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 IgnoreExprNodes(const_cast<Expr *>(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 *IgnoreElidableImplicitConstructorSingleStep(Expr *E) { 125 auto *CCE = dyn_cast<CXXConstructExpr>(E); 126 if (CCE && CCE->isElidable() && !isa<CXXTemporaryObjectExpr>(CCE)) { 127 unsigned NumArgs = CCE->getNumArgs(); 128 if ((NumArgs == 1 || 129 (NumArgs > 1 && CCE->getArg(1)->isDefaultArgument())) && 130 !CCE->getArg(0)->isDefaultArgument() && !CCE->isListInitialization()) 131 return CCE->getArg(0); 132 } 133 return E; 134 } 135 136 inline Expr *IgnoreImplicitAsWrittenSingleStep(Expr *E) { 137 if (auto *ICE = dyn_cast<ImplicitCastExpr>(E)) 138 return ICE->getSubExprAsWritten(); 139 140 return IgnoreImplicitSingleStep(E); 141 } 142 143 inline Expr *IgnoreParensOnlySingleStep(Expr *E) { 144 if (auto *PE = dyn_cast<ParenExpr>(E)) 145 return PE->getSubExpr(); 146 return E; 147 } 148 149 inline Expr *IgnoreParensSingleStep(Expr *E) { 150 if (auto *PE = dyn_cast<ParenExpr>(E)) 151 return PE->getSubExpr(); 152 153 if (auto *UO = dyn_cast<UnaryOperator>(E)) { 154 if (UO->getOpcode() == UO_Extension) 155 return UO->getSubExpr(); 156 } 157 158 else if (auto *GSE = dyn_cast<GenericSelectionExpr>(E)) { 159 if (!GSE->isResultDependent()) 160 return GSE->getResultExpr(); 161 } 162 163 else if (auto *CE = dyn_cast<ChooseExpr>(E)) { 164 if (!CE->isConditionDependent()) 165 return CE->getChosenSubExpr(); 166 } 167 168 return E; 169 } 170 171 } // namespace clang 172 173 #endif // LLVM_CLANG_AST_IGNOREEXPR_H 174