1*13fbcb42Sjoerg //===- UsedDeclVisitor.h - ODR-used declarations visitor --------*- C++ -*-===//
2*13fbcb42Sjoerg //
3*13fbcb42Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*13fbcb42Sjoerg // See https://llvm.org/LICENSE.txt for license information.
5*13fbcb42Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*13fbcb42Sjoerg //===----------------------------------------------------------------------===//
7*13fbcb42Sjoerg //
8*13fbcb42Sjoerg //  This file defines UsedDeclVisitor, a CRTP class which visits all the
9*13fbcb42Sjoerg //  declarations that are ODR-used by an expression or statement.
10*13fbcb42Sjoerg //
11*13fbcb42Sjoerg //===----------------------------------------------------------------------===//
12*13fbcb42Sjoerg 
13*13fbcb42Sjoerg #ifndef LLVM_CLANG_LIB_SEMA_USEDDECLVISITOR_H
14*13fbcb42Sjoerg #define LLVM_CLANG_LIB_SEMA_USEDDECLVISITOR_H
15*13fbcb42Sjoerg 
16*13fbcb42Sjoerg #include "clang/AST/EvaluatedExprVisitor.h"
17*13fbcb42Sjoerg #include "clang/Sema/SemaInternal.h"
18*13fbcb42Sjoerg 
19*13fbcb42Sjoerg namespace clang {
20*13fbcb42Sjoerg template <class Derived>
21*13fbcb42Sjoerg class UsedDeclVisitor : public EvaluatedExprVisitor<Derived> {
22*13fbcb42Sjoerg protected:
23*13fbcb42Sjoerg   Sema &S;
24*13fbcb42Sjoerg 
25*13fbcb42Sjoerg public:
26*13fbcb42Sjoerg   typedef EvaluatedExprVisitor<Derived> Inherited;
27*13fbcb42Sjoerg 
UsedDeclVisitor(Sema & S)28*13fbcb42Sjoerg   UsedDeclVisitor(Sema &S) : Inherited(S.Context), S(S) {}
29*13fbcb42Sjoerg 
asImpl()30*13fbcb42Sjoerg   Derived &asImpl() { return *static_cast<Derived *>(this); }
31*13fbcb42Sjoerg 
VisitDeclRefExpr(DeclRefExpr * E)32*13fbcb42Sjoerg   void VisitDeclRefExpr(DeclRefExpr *E) {
33*13fbcb42Sjoerg     auto *D = E->getDecl();
34*13fbcb42Sjoerg     if (isa<FunctionDecl>(D) || isa<VarDecl>(D)) {
35*13fbcb42Sjoerg       asImpl().visitUsedDecl(E->getLocation(), D);
36*13fbcb42Sjoerg     }
37*13fbcb42Sjoerg   }
38*13fbcb42Sjoerg 
VisitMemberExpr(MemberExpr * E)39*13fbcb42Sjoerg   void VisitMemberExpr(MemberExpr *E) {
40*13fbcb42Sjoerg     auto *D = E->getMemberDecl();
41*13fbcb42Sjoerg     if (isa<FunctionDecl>(D) || isa<VarDecl>(D)) {
42*13fbcb42Sjoerg       asImpl().visitUsedDecl(E->getMemberLoc(), D);
43*13fbcb42Sjoerg     }
44*13fbcb42Sjoerg     asImpl().Visit(E->getBase());
45*13fbcb42Sjoerg   }
46*13fbcb42Sjoerg 
VisitCapturedStmt(CapturedStmt * Node)47*13fbcb42Sjoerg   void VisitCapturedStmt(CapturedStmt *Node) {
48*13fbcb42Sjoerg     asImpl().visitUsedDecl(Node->getBeginLoc(), Node->getCapturedDecl());
49*13fbcb42Sjoerg     Inherited::VisitCapturedStmt(Node);
50*13fbcb42Sjoerg   }
51*13fbcb42Sjoerg 
VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr * E)52*13fbcb42Sjoerg   void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) {
53*13fbcb42Sjoerg     asImpl().visitUsedDecl(
54*13fbcb42Sjoerg         E->getBeginLoc(),
55*13fbcb42Sjoerg         const_cast<CXXDestructorDecl *>(E->getTemporary()->getDestructor()));
56*13fbcb42Sjoerg     asImpl().Visit(E->getSubExpr());
57*13fbcb42Sjoerg   }
58*13fbcb42Sjoerg 
VisitCXXNewExpr(CXXNewExpr * E)59*13fbcb42Sjoerg   void VisitCXXNewExpr(CXXNewExpr *E) {
60*13fbcb42Sjoerg     if (E->getOperatorNew())
61*13fbcb42Sjoerg       asImpl().visitUsedDecl(E->getBeginLoc(), E->getOperatorNew());
62*13fbcb42Sjoerg     if (E->getOperatorDelete())
63*13fbcb42Sjoerg       asImpl().visitUsedDecl(E->getBeginLoc(), E->getOperatorDelete());
64*13fbcb42Sjoerg     Inherited::VisitCXXNewExpr(E);
65*13fbcb42Sjoerg   }
66*13fbcb42Sjoerg 
VisitCXXDeleteExpr(CXXDeleteExpr * E)67*13fbcb42Sjoerg   void VisitCXXDeleteExpr(CXXDeleteExpr *E) {
68*13fbcb42Sjoerg     if (E->getOperatorDelete())
69*13fbcb42Sjoerg       asImpl().visitUsedDecl(E->getBeginLoc(), E->getOperatorDelete());
70*13fbcb42Sjoerg     QualType DestroyedOrNull = E->getDestroyedType();
71*13fbcb42Sjoerg     if (!DestroyedOrNull.isNull()) {
72*13fbcb42Sjoerg       QualType Destroyed = S.Context.getBaseElementType(DestroyedOrNull);
73*13fbcb42Sjoerg       if (const RecordType *DestroyedRec = Destroyed->getAs<RecordType>()) {
74*13fbcb42Sjoerg         CXXRecordDecl *Record = cast<CXXRecordDecl>(DestroyedRec->getDecl());
75*13fbcb42Sjoerg         asImpl().visitUsedDecl(E->getBeginLoc(), S.LookupDestructor(Record));
76*13fbcb42Sjoerg       }
77*13fbcb42Sjoerg     }
78*13fbcb42Sjoerg 
79*13fbcb42Sjoerg     Inherited::VisitCXXDeleteExpr(E);
80*13fbcb42Sjoerg   }
81*13fbcb42Sjoerg 
VisitCXXConstructExpr(CXXConstructExpr * E)82*13fbcb42Sjoerg   void VisitCXXConstructExpr(CXXConstructExpr *E) {
83*13fbcb42Sjoerg     asImpl().visitUsedDecl(E->getBeginLoc(), E->getConstructor());
84*13fbcb42Sjoerg     Inherited::VisitCXXConstructExpr(E);
85*13fbcb42Sjoerg   }
86*13fbcb42Sjoerg 
VisitCXXDefaultArgExpr(CXXDefaultArgExpr * E)87*13fbcb42Sjoerg   void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) {
88*13fbcb42Sjoerg     asImpl().Visit(E->getExpr());
89*13fbcb42Sjoerg   }
90*13fbcb42Sjoerg 
visitUsedDecl(SourceLocation Loc,Decl * D)91*13fbcb42Sjoerg   void visitUsedDecl(SourceLocation Loc, Decl *D) {
92*13fbcb42Sjoerg     if (auto *CD = dyn_cast<CapturedDecl>(D)) {
93*13fbcb42Sjoerg       if (auto *S = CD->getBody()) {
94*13fbcb42Sjoerg         asImpl().Visit(S);
95*13fbcb42Sjoerg       }
96*13fbcb42Sjoerg     } else if (auto *CD = dyn_cast<BlockDecl>(D)) {
97*13fbcb42Sjoerg       if (auto *S = CD->getBody()) {
98*13fbcb42Sjoerg         asImpl().Visit(S);
99*13fbcb42Sjoerg       }
100*13fbcb42Sjoerg     }
101*13fbcb42Sjoerg   }
102*13fbcb42Sjoerg };
103*13fbcb42Sjoerg } // end namespace clang
104*13fbcb42Sjoerg 
105*13fbcb42Sjoerg #endif // LLVM_CLANG_LIB_SEMA_USEDDECLVISITOR_H
106