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