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 19 namespace clang { 20 template <class Derived> 21 class UsedDeclVisitor : public EvaluatedExprVisitor<Derived> { 22 protected: 23 Sema &S; 24 25 public: 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