Home | History | Annotate | Line # | Download | only in AST
      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