1 //===--- IgnoreExpr.h - Ignore intermediate Expressions -----------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file defines common functions to ignore intermediate expression nodes 10 // 11 //===----------------------------------------------------------------------===// 12 13 #ifndef LLVM_CLANG_AST_IGNOREEXPR_H 14 #define LLVM_CLANG_AST_IGNOREEXPR_H 15 16 #include "clang/AST/Expr.h" 17 #include "clang/AST/ExprCXX.h" 18 19 namespace clang { 20 namespace detail { 21 /// Given an expression E and functions Fn_1,...,Fn_n : Expr * -> Expr *, 22 /// Return Fn_n(...(Fn_1(E))) 23 inline Expr *IgnoreExprNodesImpl(Expr *E) { return E; } 24 template <typename FnTy, typename... FnTys> 25 Expr *IgnoreExprNodesImpl(Expr *E, FnTy &&Fn, FnTys &&... Fns) { 26 return IgnoreExprNodesImpl(Fn(E), std::forward<FnTys>(Fns)...); 27 } 28 } // namespace detail 29 30 /// Given an expression E and functions Fn_1,...,Fn_n : Expr * -> Expr *, 31 /// Recursively apply each of the functions to E until reaching a fixed point. 32 /// Note that a null E is valid; in this case nothing is done. 33 template <typename... FnTys> Expr *IgnoreExprNodes(Expr *E, FnTys &&... Fns) { 34 Expr *LastE = nullptr; 35 while (E != LastE) { 36 LastE = E; 37 E = detail::IgnoreExprNodesImpl(E, std::forward<FnTys>(Fns)...); 38 } 39 return E; 40 } 41 42 template <typename... FnTys> 43 const Expr *IgnoreExprNodes(const Expr *E, FnTys &&...Fns) { 44 return const_cast<Expr *>(IgnoreExprNodes(E, std::forward<FnTys>(Fns)...)); 45 } 46 47 inline Expr *IgnoreImplicitCastsSingleStep(Expr *E) { 48 if (auto *ICE = dyn_cast<ImplicitCastExpr>(E)) 49 return ICE->getSubExpr(); 50 51 if (auto *FE = dyn_cast<FullExpr>(E)) 52 return FE->getSubExpr(); 53 54 return E; 55 } 56 57 inline Expr *IgnoreImplicitCastsExtraSingleStep(Expr *E) { 58 // FIXME: Skip MaterializeTemporaryExpr and SubstNonTypeTemplateParmExpr in 59 // addition to what IgnoreImpCasts() skips to account for the current 60 // behaviour of IgnoreParenImpCasts(). 61 Expr *SubE = IgnoreImplicitCastsSingleStep(E); 62 if (SubE != E) 63 return SubE; 64 65 if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E)) 66 return MTE->getSubExpr(); 67 68 if (auto *NTTP = dyn_cast<SubstNonTypeTemplateParmExpr>(E)) 69 return NTTP->getReplacement(); 70 71 return E; 72 } 73 74 inline Expr *IgnoreCastsSingleStep(Expr *E) { 75 if (auto *CE = dyn_cast<CastExpr>(E)) 76 return CE->getSubExpr(); 77 78 if (auto *FE = dyn_cast<FullExpr>(E)) 79 return FE->getSubExpr(); 80 81 if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E)) 82 return MTE->getSubExpr(); 83 84 if (auto *NTTP = dyn_cast<SubstNonTypeTemplateParmExpr>(E)) 85 return NTTP->getReplacement(); 86 87 return E; 88 } 89 90 inline Expr *IgnoreLValueCastsSingleStep(Expr *E) { 91 // Skip what IgnoreCastsSingleStep skips, except that only 92 // lvalue-to-rvalue casts are skipped. 93 if (auto *CE = dyn_cast<CastExpr>(E)) 94 if (CE->getCastKind() != CK_LValueToRValue) 95 return E; 96 97 return IgnoreCastsSingleStep(E); 98 } 99 100 inline Expr *IgnoreBaseCastsSingleStep(Expr *E) { 101 if (auto *CE = dyn_cast<CastExpr>(E)) 102 if (CE->getCastKind() == CK_DerivedToBase || 103 CE->getCastKind() == CK_UncheckedDerivedToBase || 104 CE->getCastKind() == CK_NoOp) 105 return CE->getSubExpr(); 106 107 return E; 108 } 109 110 inline Expr *IgnoreImplicitSingleStep(Expr *E) { 111 Expr *SubE = IgnoreImplicitCastsSingleStep(E); 112 if (SubE != E) 113 return SubE; 114 115 if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E)) 116 return MTE->getSubExpr(); 117 118 if (auto *BTE = dyn_cast<CXXBindTemporaryExpr>(E)) 119 return BTE->getSubExpr(); 120 121 return E; 122 } 123 124 inline Expr *IgnoreImplicitAsWrittenSingleStep(Expr *E) { 125 if (auto *ICE = dyn_cast<ImplicitCastExpr>(E)) 126 return ICE->getSubExprAsWritten(); 127 128 return IgnoreImplicitSingleStep(E); 129 } 130 131 inline Expr *IgnoreParensOnlySingleStep(Expr *E) { 132 if (auto *PE = dyn_cast<ParenExpr>(E)) 133 return PE->getSubExpr(); 134 return E; 135 } 136 137 inline Expr *IgnoreParensSingleStep(Expr *E) { 138 if (auto *PE = dyn_cast<ParenExpr>(E)) 139 return PE->getSubExpr(); 140 141 if (auto *UO = dyn_cast<UnaryOperator>(E)) { 142 if (UO->getOpcode() == UO_Extension) 143 return UO->getSubExpr(); 144 } 145 146 else if (auto *GSE = dyn_cast<GenericSelectionExpr>(E)) { 147 if (!GSE->isResultDependent()) 148 return GSE->getResultExpr(); 149 } 150 151 else if (auto *CE = dyn_cast<ChooseExpr>(E)) { 152 if (!CE->isConditionDependent()) 153 return CE->getChosenSubExpr(); 154 } 155 156 return E; 157 } 158 159 } // namespace clang 160 161 #endif // LLVM_CLANG_AST_IGNOREEXPR_H 162