1*13fbcb42Sjoerg //===- UsedDeclVisitor.h - ODR-used declarations visitor --------*- C++ -*-===// 2*13fbcb42Sjoerg // 3*13fbcb42Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*13fbcb42Sjoerg // See https://llvm.org/LICENSE.txt for license information. 5*13fbcb42Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*13fbcb42Sjoerg //===----------------------------------------------------------------------===// 7*13fbcb42Sjoerg // 8*13fbcb42Sjoerg // This file defines UsedDeclVisitor, a CRTP class which visits all the 9*13fbcb42Sjoerg // declarations that are ODR-used by an expression or statement. 10*13fbcb42Sjoerg // 11*13fbcb42Sjoerg //===----------------------------------------------------------------------===// 12*13fbcb42Sjoerg 13*13fbcb42Sjoerg #ifndef LLVM_CLANG_LIB_SEMA_USEDDECLVISITOR_H 14*13fbcb42Sjoerg #define LLVM_CLANG_LIB_SEMA_USEDDECLVISITOR_H 15*13fbcb42Sjoerg 16*13fbcb42Sjoerg #include "clang/AST/EvaluatedExprVisitor.h" 17*13fbcb42Sjoerg #include "clang/Sema/SemaInternal.h" 18*13fbcb42Sjoerg 19*13fbcb42Sjoerg namespace clang { 20*13fbcb42Sjoerg template <class Derived> 21*13fbcb42Sjoerg class UsedDeclVisitor : public EvaluatedExprVisitor<Derived> { 22*13fbcb42Sjoerg protected: 23*13fbcb42Sjoerg Sema &S; 24*13fbcb42Sjoerg 25*13fbcb42Sjoerg public: 26*13fbcb42Sjoerg typedef EvaluatedExprVisitor<Derived> Inherited; 27*13fbcb42Sjoerg UsedDeclVisitor(Sema & S)28*13fbcb42Sjoerg UsedDeclVisitor(Sema &S) : Inherited(S.Context), S(S) {} 29*13fbcb42Sjoerg asImpl()30*13fbcb42Sjoerg Derived &asImpl() { return *static_cast<Derived *>(this); } 31*13fbcb42Sjoerg VisitDeclRefExpr(DeclRefExpr * E)32*13fbcb42Sjoerg void VisitDeclRefExpr(DeclRefExpr *E) { 33*13fbcb42Sjoerg auto *D = E->getDecl(); 34*13fbcb42Sjoerg if (isa<FunctionDecl>(D) || isa<VarDecl>(D)) { 35*13fbcb42Sjoerg asImpl().visitUsedDecl(E->getLocation(), D); 36*13fbcb42Sjoerg } 37*13fbcb42Sjoerg } 38*13fbcb42Sjoerg VisitMemberExpr(MemberExpr * E)39*13fbcb42Sjoerg void VisitMemberExpr(MemberExpr *E) { 40*13fbcb42Sjoerg auto *D = E->getMemberDecl(); 41*13fbcb42Sjoerg if (isa<FunctionDecl>(D) || isa<VarDecl>(D)) { 42*13fbcb42Sjoerg asImpl().visitUsedDecl(E->getMemberLoc(), D); 43*13fbcb42Sjoerg } 44*13fbcb42Sjoerg asImpl().Visit(E->getBase()); 45*13fbcb42Sjoerg } 46*13fbcb42Sjoerg VisitCapturedStmt(CapturedStmt * Node)47*13fbcb42Sjoerg void VisitCapturedStmt(CapturedStmt *Node) { 48*13fbcb42Sjoerg asImpl().visitUsedDecl(Node->getBeginLoc(), Node->getCapturedDecl()); 49*13fbcb42Sjoerg Inherited::VisitCapturedStmt(Node); 50*13fbcb42Sjoerg } 51*13fbcb42Sjoerg VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr * E)52*13fbcb42Sjoerg void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) { 53*13fbcb42Sjoerg asImpl().visitUsedDecl( 54*13fbcb42Sjoerg E->getBeginLoc(), 55*13fbcb42Sjoerg const_cast<CXXDestructorDecl *>(E->getTemporary()->getDestructor())); 56*13fbcb42Sjoerg asImpl().Visit(E->getSubExpr()); 57*13fbcb42Sjoerg } 58*13fbcb42Sjoerg VisitCXXNewExpr(CXXNewExpr * E)59*13fbcb42Sjoerg void VisitCXXNewExpr(CXXNewExpr *E) { 60*13fbcb42Sjoerg if (E->getOperatorNew()) 61*13fbcb42Sjoerg asImpl().visitUsedDecl(E->getBeginLoc(), E->getOperatorNew()); 62*13fbcb42Sjoerg if (E->getOperatorDelete()) 63*13fbcb42Sjoerg asImpl().visitUsedDecl(E->getBeginLoc(), E->getOperatorDelete()); 64*13fbcb42Sjoerg Inherited::VisitCXXNewExpr(E); 65*13fbcb42Sjoerg } 66*13fbcb42Sjoerg VisitCXXDeleteExpr(CXXDeleteExpr * E)67*13fbcb42Sjoerg void VisitCXXDeleteExpr(CXXDeleteExpr *E) { 68*13fbcb42Sjoerg if (E->getOperatorDelete()) 69*13fbcb42Sjoerg asImpl().visitUsedDecl(E->getBeginLoc(), E->getOperatorDelete()); 70*13fbcb42Sjoerg QualType DestroyedOrNull = E->getDestroyedType(); 71*13fbcb42Sjoerg if (!DestroyedOrNull.isNull()) { 72*13fbcb42Sjoerg QualType Destroyed = S.Context.getBaseElementType(DestroyedOrNull); 73*13fbcb42Sjoerg if (const RecordType *DestroyedRec = Destroyed->getAs<RecordType>()) { 74*13fbcb42Sjoerg CXXRecordDecl *Record = cast<CXXRecordDecl>(DestroyedRec->getDecl()); 75*13fbcb42Sjoerg asImpl().visitUsedDecl(E->getBeginLoc(), S.LookupDestructor(Record)); 76*13fbcb42Sjoerg } 77*13fbcb42Sjoerg } 78*13fbcb42Sjoerg 79*13fbcb42Sjoerg Inherited::VisitCXXDeleteExpr(E); 80*13fbcb42Sjoerg } 81*13fbcb42Sjoerg VisitCXXConstructExpr(CXXConstructExpr * E)82*13fbcb42Sjoerg void VisitCXXConstructExpr(CXXConstructExpr *E) { 83*13fbcb42Sjoerg asImpl().visitUsedDecl(E->getBeginLoc(), E->getConstructor()); 84*13fbcb42Sjoerg Inherited::VisitCXXConstructExpr(E); 85*13fbcb42Sjoerg } 86*13fbcb42Sjoerg VisitCXXDefaultArgExpr(CXXDefaultArgExpr * E)87*13fbcb42Sjoerg void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) { 88*13fbcb42Sjoerg asImpl().Visit(E->getExpr()); 89*13fbcb42Sjoerg } 90*13fbcb42Sjoerg visitUsedDecl(SourceLocation Loc,Decl * D)91*13fbcb42Sjoerg void visitUsedDecl(SourceLocation Loc, Decl *D) { 92*13fbcb42Sjoerg if (auto *CD = dyn_cast<CapturedDecl>(D)) { 93*13fbcb42Sjoerg if (auto *S = CD->getBody()) { 94*13fbcb42Sjoerg asImpl().Visit(S); 95*13fbcb42Sjoerg } 96*13fbcb42Sjoerg } else if (auto *CD = dyn_cast<BlockDecl>(D)) { 97*13fbcb42Sjoerg if (auto *S = CD->getBody()) { 98*13fbcb42Sjoerg asImpl().Visit(S); 99*13fbcb42Sjoerg } 100*13fbcb42Sjoerg } 101*13fbcb42Sjoerg } 102*13fbcb42Sjoerg }; 103*13fbcb42Sjoerg } // end namespace clang 104*13fbcb42Sjoerg 105*13fbcb42Sjoerg #endif // LLVM_CLANG_LIB_SEMA_USEDDECLVISITOR_H 106