//===- UsedDeclVisitor.h - ODR-used declarations visitor --------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception //===----------------------------------------------------------------------===// // // This file defines UsedDeclVisitor, a CRTP class which visits all the // declarations that are ODR-used by an expression or statement. // //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_LIB_SEMA_USEDDECLVISITOR_H #define LLVM_CLANG_LIB_SEMA_USEDDECLVISITOR_H #include "clang/AST/EvaluatedExprVisitor.h" #include "clang/Sema/SemaInternal.h" namespace clang { template class UsedDeclVisitor : public EvaluatedExprVisitor { protected: Sema &S; public: typedef EvaluatedExprVisitor Inherited; UsedDeclVisitor(Sema &S) : Inherited(S.Context), S(S) {} Derived &asImpl() { return *static_cast(this); } void VisitDeclRefExpr(DeclRefExpr *E) { auto *D = E->getDecl(); if (isa(D) || isa(D)) { asImpl().visitUsedDecl(E->getLocation(), D); } } void VisitMemberExpr(MemberExpr *E) { auto *D = E->getMemberDecl(); if (isa(D) || isa(D)) { asImpl().visitUsedDecl(E->getMemberLoc(), D); } asImpl().Visit(E->getBase()); } void VisitCapturedStmt(CapturedStmt *Node) { asImpl().visitUsedDecl(Node->getBeginLoc(), Node->getCapturedDecl()); Inherited::VisitCapturedStmt(Node); } void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) { asImpl().visitUsedDecl( E->getBeginLoc(), const_cast(E->getTemporary()->getDestructor())); asImpl().Visit(E->getSubExpr()); } void VisitCXXNewExpr(CXXNewExpr *E) { if (E->getOperatorNew()) asImpl().visitUsedDecl(E->getBeginLoc(), E->getOperatorNew()); if (E->getOperatorDelete()) asImpl().visitUsedDecl(E->getBeginLoc(), E->getOperatorDelete()); Inherited::VisitCXXNewExpr(E); } void VisitCXXDeleteExpr(CXXDeleteExpr *E) { if (E->getOperatorDelete()) asImpl().visitUsedDecl(E->getBeginLoc(), E->getOperatorDelete()); QualType DestroyedOrNull = E->getDestroyedType(); if (!DestroyedOrNull.isNull()) { QualType Destroyed = S.Context.getBaseElementType(DestroyedOrNull); if (const RecordType *DestroyedRec = Destroyed->getAs()) { CXXRecordDecl *Record = cast(DestroyedRec->getDecl()); if (Record->getDefinition()) asImpl().visitUsedDecl(E->getBeginLoc(), S.LookupDestructor(Record)); } } Inherited::VisitCXXDeleteExpr(E); } void VisitCXXConstructExpr(CXXConstructExpr *E) { asImpl().visitUsedDecl(E->getBeginLoc(), E->getConstructor()); Inherited::VisitCXXConstructExpr(E); } void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) { asImpl().Visit(E->getExpr()); } void visitUsedDecl(SourceLocation Loc, Decl *D) { if (auto *CD = dyn_cast(D)) { if (auto *S = CD->getBody()) { asImpl().Visit(S); } } else if (auto *CD = dyn_cast(D)) { if (auto *S = CD->getBody()) { asImpl().Visit(S); } } } }; } // end namespace clang #endif // LLVM_CLANG_LIB_SEMA_USEDDECLVISITOR_H