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>(D) || isa<VarDecl>(D)) {
35      asImpl().visitUsedDecl(E->getLocation(), D);
36    }
37  }
38
39  void VisitMemberExpr(MemberExpr *E) {
40    auto *D = E->getMemberDecl();
41    if (isa<FunctionDecl>(D) || isa<VarDecl>(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(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));
77      }
78    }
79
80    Inherited::VisitCXXDeleteExpr(E);
81  }
82
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());
89    }
90    Inherited::VisitCXXConstructExpr(E);
91  }
92
93  void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) {
94    asImpl().Visit(E->getExpr());
95    Inherited::VisitCXXDefaultArgExpr(E);
96  }
97
98  void VisitCXXDefaultInitExpr(CXXDefaultInitExpr *E) {
99    asImpl().Visit(E->getExpr());
100    Inherited::VisitCXXDefaultInitExpr(E);
101  }
102
103  void VisitInitListExpr(InitListExpr *ILE) {
104    if (ILE->hasArrayFiller())
105      asImpl().Visit(ILE->getArrayFiller());
106    Inherited::VisitInitListExpr(ILE);
107  }
108
109  void visitUsedDecl(SourceLocation Loc, Decl *D) {
110    if (auto *CD = dyn_cast<CapturedDecl>(D)) {
111      if (auto *S = CD->getBody()) {
112        asImpl().Visit(S);
113      }
114    } else if (auto *CD = dyn_cast<BlockDecl>(D)) {
115      if (auto *S = CD->getBody()) {
116        asImpl().Visit(S);
117      }
118    }
119  }
120};
121} // end namespace clang
122
123#endif // LLVM_CLANG_LIB_SEMA_USEDDECLVISITOR_H
124