1 //===- UsedDeclVisitor.h - ODR-used declarations visitor --------*- C++ -*-===//
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 //===----------------------------------------------------------------------===//
8 // This file defines UsedDeclVisitor, a CRTP class which visits all the
9 // declarations that are ODR-used by an expression or statement.
11 //===----------------------------------------------------------------------===//
13 #ifndef LLVM_CLANG_LIB_SEMA_USEDDECLVISITOR_H
14 #define LLVM_CLANG_LIB_SEMA_USEDDECLVISITOR_H
16 #include "clang/AST/EvaluatedExprVisitor.h"
17 #include "clang/Sema/SemaInternal.h"
20 template <class Derived
>
21 class UsedDeclVisitor
: public EvaluatedExprVisitor
<Derived
> {
26 typedef EvaluatedExprVisitor
<Derived
> Inherited
;
28 UsedDeclVisitor(Sema
&S
) : Inherited(S
.Context
), S(S
) {}
30 Derived
&asImpl() { return *static_cast<Derived
*>(this); }
32 void VisitDeclRefExpr(DeclRefExpr
*E
) {
33 auto *D
= E
->getDecl();
34 if (isa
<FunctionDecl
>(D
) || isa
<VarDecl
>(D
)) {
35 asImpl().visitUsedDecl(E
->getLocation(), D
);
39 void VisitMemberExpr(MemberExpr
*E
) {
40 auto *D
= E
->getMemberDecl();
41 if (isa
<FunctionDecl
>(D
) || isa
<VarDecl
>(D
)) {
42 asImpl().visitUsedDecl(E
->getMemberLoc(), D
);
44 asImpl().Visit(E
->getBase());
47 void VisitCapturedStmt(CapturedStmt
*Node
) {
48 asImpl().visitUsedDecl(Node
->getBeginLoc(), Node
->getCapturedDecl());
49 Inherited::VisitCapturedStmt(Node
);
52 void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr
*E
) {
53 asImpl().visitUsedDecl(
55 const_cast<CXXDestructorDecl
*>(E
->getTemporary()->getDestructor()));
56 asImpl().Visit(E
->getSubExpr());
59 void VisitCXXNewExpr(CXXNewExpr
*E
) {
60 if (E
->getOperatorNew())
61 asImpl().visitUsedDecl(E
->getBeginLoc(), E
->getOperatorNew());
62 if (E
->getOperatorDelete())
63 asImpl().visitUsedDecl(E
->getBeginLoc(), E
->getOperatorDelete());
64 Inherited::VisitCXXNewExpr(E
);
67 void VisitCXXDeleteExpr(CXXDeleteExpr
*E
) {
68 if (E
->getOperatorDelete())
69 asImpl().visitUsedDecl(E
->getBeginLoc(), E
->getOperatorDelete());
70 QualType DestroyedOrNull
= E
->getDestroyedType();
71 if (!DestroyedOrNull
.isNull()) {
72 QualType Destroyed
= S
.Context
.getBaseElementType(DestroyedOrNull
);
73 if (const RecordType
*DestroyedRec
= Destroyed
->getAs
<RecordType
>()) {
74 CXXRecordDecl
*Record
= cast
<CXXRecordDecl
>(DestroyedRec
->getDecl());
75 if (Record
->getDefinition())
76 asImpl().visitUsedDecl(E
->getBeginLoc(), S
.LookupDestructor(Record
));
80 Inherited::VisitCXXDeleteExpr(E
);
83 void VisitCXXConstructExpr(CXXConstructExpr
*E
) {
84 asImpl().visitUsedDecl(E
->getBeginLoc(), E
->getConstructor());
85 CXXConstructorDecl
*D
= E
->getConstructor();
86 for (const CXXCtorInitializer
*Init
: D
->inits()) {
87 if (Init
->isInClassMemberInitializer())
88 asImpl().Visit(Init
->getInit());
90 Inherited::VisitCXXConstructExpr(E
);
93 void VisitCXXDefaultArgExpr(CXXDefaultArgExpr
*E
) {
94 asImpl().Visit(E
->getExpr());
95 Inherited::VisitCXXDefaultArgExpr(E
);
98 void VisitCXXDefaultInitExpr(CXXDefaultInitExpr
*E
) {
99 asImpl().Visit(E
->getExpr());
100 Inherited::VisitCXXDefaultInitExpr(E
);
103 void VisitInitListExpr(InitListExpr
*ILE
) {
104 if (ILE
->hasArrayFiller())
105 asImpl().Visit(ILE
->getArrayFiller());
106 Inherited::VisitInitListExpr(ILE
);
109 void visitUsedDecl(SourceLocation Loc
, Decl
*D
) {
110 if (auto *CD
= dyn_cast
<CapturedDecl
>(D
)) {
111 if (auto *S
= CD
->getBody()) {
114 } else if (auto *CD
= dyn_cast
<BlockDecl
>(D
)) {
115 if (auto *S
= CD
->getBody()) {
121 } // end namespace clang
123 #endif // LLVM_CLANG_LIB_SEMA_USEDDECLVISITOR_H