1//===- UsedDeclVisitor.h - ODR-used declarations 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// This file defines UsedDeclVisitor, a CRTP class which visits all the
9// declarations that are ODR-used by an expression or statement.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_CLANG_LIB_SEMA_USEDDECLVISITOR_H
14#define LLVM_CLANG_LIB_SEMA_USEDDECLVISITOR_H
15
16#include "clang/AST/EvaluatedExprVisitor.h"
17#include "clang/Sema/SemaInternal.h"
18
19namespace clang {
20template <class Derived>
21class UsedDeclVisitor : public EvaluatedExprVisitor<Derived> {
22protected:
23 Sema &S;
24
25public:
26 typedef EvaluatedExprVisitor<Derived> Inherited;
27
28 UsedDeclVisitor(Sema &S) : Inherited(S.Context), S(S) {}
29
30 Derived &asImpl() { return *static_cast<Derived *>(this); }
31
32 void VisitDeclRefExpr(DeclRefExpr *E) {
33 auto *D = E->getDecl();
34 if (isa<FunctionDecl>(Val: D) || isa<VarDecl>(Val: D)) {
35 asImpl().visitUsedDecl(E->getLocation(), D);
36 }
37 }
38
39 void VisitMemberExpr(MemberExpr *E) {
40 auto *D = E->getMemberDecl();
41 if (isa<FunctionDecl>(Val: D) || isa<VarDecl>(Val: D)) {
42 asImpl().visitUsedDecl(E->getMemberLoc(), D);
43 }
44 asImpl().Visit(E->getBase());
45 }
46
47 void VisitCapturedStmt(CapturedStmt *Node) {
48 asImpl().visitUsedDecl(Node->getBeginLoc(), Node->getCapturedDecl());
49 Inherited::VisitCapturedStmt(Node);
50 }
51
52 void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) {
53 asImpl().visitUsedDecl(
54 E->getBeginLoc(),
55 const_cast<CXXDestructorDecl *>(E->getTemporary()->getDestructor()));
56 asImpl().Visit(E->getSubExpr());
57 }
58
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);
65 }
66
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(QT: DestroyedOrNull);
73 if (auto *Record = Destroyed->getAsCXXRecordDecl();
74 Record &&
75 (Record->isBeingDefined() || Record->isCompleteDefinition()))
76 asImpl().visitUsedDecl(E->getBeginLoc(), S.LookupDestructor(Class: Record));
77 }
78
79 Inherited::VisitCXXDeleteExpr(E);
80 }
81
82 void VisitCXXConstructExpr(CXXConstructExpr *E) {
83 asImpl().visitUsedDecl(E->getBeginLoc(), E->getConstructor());
84 CXXConstructorDecl *D = E->getConstructor();
85 for (const CXXCtorInitializer *Init : D->inits()) {
86 if (Init->isInClassMemberInitializer())
87 asImpl().Visit(Init->getInit());
88 }
89 Inherited::VisitCXXConstructExpr(E);
90 }
91
92 void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) {
93 asImpl().Visit(E->getExpr());
94 Inherited::VisitCXXDefaultArgExpr(E);
95 }
96
97 void VisitCXXDefaultInitExpr(CXXDefaultInitExpr *E) {
98 asImpl().Visit(E->getExpr());
99 Inherited::VisitCXXDefaultInitExpr(E);
100 }
101
102 void VisitInitListExpr(InitListExpr *ILE) {
103 if (ILE->hasArrayFiller())
104 asImpl().Visit(ILE->getArrayFiller());
105 Inherited::VisitInitListExpr(ILE);
106 }
107
108 void visitUsedDecl(SourceLocation Loc, Decl *D) {
109 if (auto *CD = dyn_cast<CapturedDecl>(Val: D)) {
110 if (auto *S = CD->getBody()) {
111 asImpl().Visit(S);
112 }
113 } else if (auto *CD = dyn_cast<BlockDecl>(Val: D)) {
114 if (auto *S = CD->getBody()) {
115 asImpl().Visit(S);
116 }
117 }
118 }
119};
120} // end namespace clang
121
122#endif // LLVM_CLANG_LIB_SEMA_USEDDECLVISITOR_H
123