summaryrefslogtreecommitdiff
path: root/clang/lib/Sema/UsedDeclVisitor.h
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema/UsedDeclVisitor.h')
-rw-r--r--clang/lib/Sema/UsedDeclVisitor.h102
1 files changed, 102 insertions, 0 deletions
diff --git a/clang/lib/Sema/UsedDeclVisitor.h b/clang/lib/Sema/UsedDeclVisitor.h
new file mode 100644
index 000000000000..d207e07f451a
--- /dev/null
+++ b/clang/lib/Sema/UsedDeclVisitor.h
@@ -0,0 +1,102 @@
+//===- 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 Derived>
+class UsedDeclVisitor : public EvaluatedExprVisitor<Derived> {
+protected:
+ Sema &S;
+
+public:
+ typedef EvaluatedExprVisitor<Derived> Inherited;
+
+ UsedDeclVisitor(Sema &S) : Inherited(S.Context), S(S) {}
+
+ Derived &asImpl() { return *static_cast<Derived *>(this); }
+
+ void VisitDeclRefExpr(DeclRefExpr *E) {
+ auto *D = E->getDecl();
+ if (isa<FunctionDecl>(D) || isa<VarDecl>(D)) {
+ asImpl().visitUsedDecl(E->getLocation(), D);
+ }
+ }
+
+ void VisitMemberExpr(MemberExpr *E) {
+ auto *D = E->getMemberDecl();
+ if (isa<FunctionDecl>(D) || isa<VarDecl>(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<CXXDestructorDecl *>(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 Destroyed = S.Context.getBaseElementType(E->getDestroyedType());
+ if (const RecordType *DestroyedRec = Destroyed->getAs<RecordType>()) {
+ CXXRecordDecl *Record = cast<CXXRecordDecl>(DestroyedRec->getDecl());
+ 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<CapturedDecl>(D)) {
+ if (auto *S = CD->getBody()) {
+ asImpl().Visit(S);
+ }
+ } else if (auto *CD = dyn_cast<BlockDecl>(D)) {
+ if (auto *S = CD->getBody()) {
+ asImpl().Visit(S);
+ }
+ }
+ }
+};
+} // end namespace clang
+
+#endif // LLVM_CLANG_LIB_SEMA_USEDDECLVISITOR_H