1 | //===--- EvaluatedExprVisitor.h - Evaluated expression visitor --*- C++ -*-===// |
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 the EvaluatedExprVisitor class template, which visits |
10 | // the potentially-evaluated subexpressions of a potentially-evaluated |
11 | // expression. |
12 | // |
13 | //===----------------------------------------------------------------------===// |
14 | #ifndef LLVM_CLANG_AST_EVALUATEDEXPRVISITOR_H |
15 | #define LLVM_CLANG_AST_EVALUATEDEXPRVISITOR_H |
16 | |
17 | #include "clang/AST/DeclCXX.h" |
18 | #include "clang/AST/Expr.h" |
19 | #include "clang/AST/ExprCXX.h" |
20 | #include "clang/AST/StmtVisitor.h" |
21 | #include "llvm/ADT/STLExtras.h" |
22 | |
23 | namespace clang { |
24 | |
25 | class ASTContext; |
26 | |
27 | /// Given a potentially-evaluated expression, this visitor visits all |
28 | /// of its potentially-evaluated subexpressions, recursively. |
29 | template<template <typename> class Ptr, typename ImplClass> |
30 | class EvaluatedExprVisitorBase : public StmtVisitorBase<Ptr, ImplClass, void> { |
31 | protected: |
32 | const ASTContext &Context; |
33 | |
34 | public: |
35 | // Return whether this visitor should recurse into discarded statements for a |
36 | // 'constexpr-if'. |
37 | bool shouldVisitDiscardedStmt() const { return true; } |
38 | #define PTR(CLASS) typename Ptr<CLASS>::type |
39 | |
40 | explicit EvaluatedExprVisitorBase(const ASTContext &Context) : Context(Context) { } |
41 | |
42 | // Expressions that have no potentially-evaluated subexpressions (but may have |
43 | // other sub-expressions). |
44 | void VisitDeclRefExpr(PTR(DeclRefExpr) E) { } |
45 | void VisitOffsetOfExpr(PTR(OffsetOfExpr) E) { } |
46 | void VisitUnaryExprOrTypeTraitExpr(PTR(UnaryExprOrTypeTraitExpr) E) { } |
47 | void VisitExpressionTraitExpr(PTR(ExpressionTraitExpr) E) { } |
48 | void VisitBlockExpr(PTR(BlockExpr) E) { } |
49 | void VisitCXXUuidofExpr(PTR(CXXUuidofExpr) E) { } |
50 | void VisitCXXNoexceptExpr(PTR(CXXNoexceptExpr) E) { } |
51 | |
52 | void VisitMemberExpr(PTR(MemberExpr) E) { |
53 | // Only the base matters. |
54 | return this->Visit(E->getBase()); |
55 | } |
56 | |
57 | void VisitChooseExpr(PTR(ChooseExpr) E) { |
58 | // Don't visit either child expression if the condition is dependent. |
59 | if (E->getCond()->isValueDependent()) |
60 | return; |
61 | // Only the selected subexpression matters; the other one is not evaluated. |
62 | return this->Visit(E->getChosenSubExpr()); |
63 | } |
64 | |
65 | void VisitGenericSelectionExpr(PTR(GenericSelectionExpr) E) { |
66 | // The controlling expression of a generic selection is not evaluated. |
67 | |
68 | // Don't visit either child expression if the condition is type-dependent. |
69 | if (E->isResultDependent()) |
70 | return; |
71 | // Only the selected subexpression matters; the other subexpressions and the |
72 | // controlling expression are not evaluated. |
73 | return this->Visit(E->getResultExpr()); |
74 | } |
75 | |
76 | void VisitDesignatedInitExpr(PTR(DesignatedInitExpr) E) { |
77 | // Only the actual initializer matters; the designators are all constant |
78 | // expressions. |
79 | return this->Visit(E->getInit()); |
80 | } |
81 | |
82 | void VisitCXXTypeidExpr(PTR(CXXTypeidExpr) E) { |
83 | if (E->isPotentiallyEvaluated()) |
84 | return this->Visit(E->getExprOperand()); |
85 | } |
86 | |
87 | void VisitCallExpr(PTR(CallExpr) CE) { |
88 | if (!CE->isUnevaluatedBuiltinCall(Context)) |
89 | return getDerived().VisitExpr(CE); |
90 | } |
91 | |
92 | void VisitLambdaExpr(PTR(LambdaExpr) LE) { |
93 | // Only visit the capture initializers, and not the body. |
94 | for (LambdaExpr::const_capture_init_iterator I = LE->capture_init_begin(), |
95 | E = LE->capture_init_end(); |
96 | I != E; ++I) |
97 | if (*I) |
98 | this->Visit(*I); |
99 | } |
100 | |
101 | /// The basis case walks all of the children of the statement or |
102 | /// expression, assuming they are all potentially evaluated. |
103 | void VisitStmt(PTR(Stmt) S) { |
104 | for (auto *SubStmt : S->children()) |
105 | if (SubStmt) |
106 | this->Visit(SubStmt); |
107 | } |
108 | |
109 | void VisitIfStmt(PTR(IfStmt) If) { |
110 | if (!getDerived().shouldVisitDiscardedStmt()) { |
111 | if (auto SubStmt = If->getNondiscardedCase(Context)) { |
112 | if (*SubStmt) |
113 | this->Visit(*SubStmt); |
114 | return; |
115 | } |
116 | } |
117 | |
118 | getDerived().VisitStmt(If); |
119 | } |
120 | |
121 | ImplClass &getDerived() { return *static_cast<ImplClass *>(this); } |
122 | |
123 | #undef PTR |
124 | }; |
125 | |
126 | /// EvaluatedExprVisitor - This class visits 'Expr *'s |
127 | template <typename ImplClass> |
128 | class EvaluatedExprVisitor |
129 | : public EvaluatedExprVisitorBase<std::add_pointer, ImplClass> { |
130 | public: |
131 | explicit EvaluatedExprVisitor(const ASTContext &Context) |
132 | : EvaluatedExprVisitorBase<std::add_pointer, ImplClass>(Context) {} |
133 | }; |
134 | |
135 | /// ConstEvaluatedExprVisitor - This class visits 'const Expr *'s. |
136 | template <typename ImplClass> |
137 | class ConstEvaluatedExprVisitor |
138 | : public EvaluatedExprVisitorBase<llvm::make_const_ptr, ImplClass> { |
139 | public: |
140 | explicit ConstEvaluatedExprVisitor(const ASTContext &Context) |
141 | : EvaluatedExprVisitorBase<llvm::make_const_ptr, ImplClass>(Context) {} |
142 | }; |
143 | } |
144 | |
145 | #endif // LLVM_CLANG_AST_EVALUATEDEXPRVISITOR_H |
146 | |