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