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 asImpl().visitUsedDecl(E->getBeginLoc(), S.LookupDestructor(Record)); 76 } 77 } 78 79 Inherited::VisitCXXDeleteExpr(E); 80 } 81 82 void VisitCXXConstructExpr(CXXConstructExpr *E) { 83 asImpl().visitUsedDecl(E->getBeginLoc(), E->getConstructor()); 84 Inherited::VisitCXXConstructExpr(E); 85 } 86 87 void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) { 88 asImpl().Visit(E->getExpr()); 89 } 90 91 void visitUsedDecl(SourceLocation Loc, Decl *D) { 92 if (auto *CD = dyn_cast<CapturedDecl>(D)) { 93 if (auto *S = CD->getBody()) { 94 asImpl().Visit(S); 95 } 96 } else if (auto *CD = dyn_cast<BlockDecl>(D)) { 97 if (auto *S = CD->getBody()) { 98 asImpl().Visit(S); 99 } 100 } 101 } 102 }; 103 } // end namespace clang 104 105 #endif // LLVM_CLANG_LIB_SEMA_USEDDECLVISITOR_H 106