1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287
|
//===- CursorVisitor.h - CursorVisitor interface ----------------*- 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
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TOOLS_LIBCLANG_CURSORVISITOR_H
#define LLVM_CLANG_TOOLS_LIBCLANG_CURSORVISITOR_H
#include "CXCursor.h"
#include "CXTranslationUnit.h"
#include "Index_Internal.h"
#include "clang/AST/DeclVisitor.h"
#include "clang/AST/TypeLocVisitor.h"
namespace clang {
class PreprocessingRecord;
class ASTUnit;
namespace concepts {
class Requirement;
}
namespace cxcursor {
class VisitorJob {
public:
enum Kind {
DeclVisitKind,
StmtVisitKind,
MemberExprPartsKind,
TypeLocVisitKind,
OverloadExprPartsKind,
DeclRefExprPartsKind,
LabelRefVisitKind,
ExplicitTemplateArgsVisitKind,
NestedNameSpecifierLocVisitKind,
DeclarationNameInfoVisitKind,
MemberRefVisitKind,
SizeOfPackExprPartsKind,
LambdaExprPartsKind,
ConceptSpecializationExprVisitKind,
RequiresExprVisitKind,
PostChildrenVisitKind
};
protected:
const void *data[3];
CXCursor parent;
Kind K;
VisitorJob(CXCursor C, Kind k, const void *d1, const void *d2 = nullptr,
const void *d3 = nullptr)
: parent(C), K(k) {
data[0] = d1;
data[1] = d2;
data[2] = d3;
}
public:
Kind getKind() const { return K; }
const CXCursor &getParent() const { return parent; }
};
typedef SmallVector<VisitorJob, 10> VisitorWorkList;
// Cursor visitor.
class CursorVisitor : public DeclVisitor<CursorVisitor, bool>,
public TypeLocVisitor<CursorVisitor, bool> {
public:
/// Callback called after child nodes of a cursor have been visited.
/// Return true to break visitation or false to continue.
typedef bool (*PostChildrenVisitorTy)(CXCursor cursor,
CXClientData client_data);
private:
/// The translation unit we are traversing.
CXTranslationUnit TU;
ASTUnit *AU;
/// The parent cursor whose children we are traversing.
CXCursor Parent;
/// The declaration that serves at the parent of any statement or
/// expression nodes.
const Decl *StmtParent;
/// The visitor function.
CXCursorVisitor Visitor;
PostChildrenVisitorTy PostChildrenVisitor;
/// The opaque client data, to be passed along to the visitor.
CXClientData ClientData;
/// Whether we should visit the preprocessing record entries last,
/// after visiting other declarations.
bool VisitPreprocessorLast;
/// Whether we should visit declarations or preprocessing record
/// entries that are #included inside the \arg RegionOfInterest.
bool VisitIncludedEntities;
/// When valid, a source range to which the cursor should restrict
/// its search.
SourceRange RegionOfInterest;
/// Whether we should only visit declarations and not preprocessing
/// record entries.
bool VisitDeclsOnly;
// FIXME: Eventually remove. This part of a hack to support proper
// iteration over all Decls contained lexically within an ObjC container.
DeclContext::decl_iterator *DI_current;
DeclContext::decl_iterator DE_current;
SmallVectorImpl<Decl *>::iterator *FileDI_current;
SmallVectorImpl<Decl *>::iterator FileDE_current;
// Cache of pre-allocated worklists for data-recursion walk of Stmts.
SmallVector<VisitorWorkList *, 5> WorkListFreeList;
SmallVector<VisitorWorkList *, 5> WorkListCache;
using DeclVisitor<CursorVisitor, bool>::Visit;
using TypeLocVisitor<CursorVisitor, bool>::Visit;
/// Determine whether this particular source range comes before, comes
/// after, or overlaps the region of interest.
///
/// \param R a half-open source range retrieved from the abstract syntax tree.
RangeComparisonResult CompareRegionOfInterest(SourceRange R);
bool visitDeclsFromFileRegion(FileID File, unsigned Offset, unsigned Length);
class SetParentRAII {
CXCursor &Parent;
const Decl *&StmtParent;
CXCursor OldParent;
public:
SetParentRAII(CXCursor &Parent, const Decl *&StmtParent, CXCursor NewParent)
: Parent(Parent), StmtParent(StmtParent), OldParent(Parent) {
Parent = NewParent;
if (clang_isDeclaration(Parent.kind))
StmtParent = getCursorDecl(Parent);
}
~SetParentRAII() {
Parent = OldParent;
if (clang_isDeclaration(Parent.kind))
StmtParent = getCursorDecl(Parent);
}
};
public:
CursorVisitor(CXTranslationUnit TU, CXCursorVisitor Visitor,
CXClientData ClientData, bool VisitPreprocessorLast,
bool VisitIncludedPreprocessingEntries = false,
SourceRange RegionOfInterest = SourceRange(),
bool VisitDeclsOnly = false,
PostChildrenVisitorTy PostChildrenVisitor = nullptr)
: TU(TU), AU(cxtu::getASTUnit(TU)), Visitor(Visitor),
PostChildrenVisitor(PostChildrenVisitor), ClientData(ClientData),
VisitPreprocessorLast(VisitPreprocessorLast),
VisitIncludedEntities(VisitIncludedPreprocessingEntries),
RegionOfInterest(RegionOfInterest), VisitDeclsOnly(VisitDeclsOnly),
DI_current(nullptr), FileDI_current(nullptr) {
Parent.kind = CXCursor_NoDeclFound;
Parent.data[0] = nullptr;
Parent.data[1] = nullptr;
Parent.data[2] = nullptr;
StmtParent = nullptr;
}
~CursorVisitor() {
// Free the pre-allocated worklists for data-recursion.
for (SmallVectorImpl<VisitorWorkList *>::iterator I = WorkListCache.begin(),
E = WorkListCache.end();
I != E; ++I) {
delete *I;
}
}
ASTUnit *getASTUnit() const { return AU; }
CXTranslationUnit getTU() const { return TU; }
bool Visit(CXCursor Cursor, bool CheckedRegionOfInterest = false);
/// Visit declarations and preprocessed entities for the file region
/// designated by \see RegionOfInterest.
bool visitFileRegion();
bool visitPreprocessedEntitiesInRegion();
bool shouldVisitIncludedEntities() const { return VisitIncludedEntities; }
template <typename InputIterator>
bool visitPreprocessedEntities(InputIterator First, InputIterator Last,
PreprocessingRecord &PPRec,
FileID FID = FileID());
bool VisitChildren(CXCursor Parent);
// Declaration visitors
bool VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D);
bool VisitTypeAliasDecl(TypeAliasDecl *D);
bool VisitAttributes(Decl *D);
bool VisitBlockDecl(BlockDecl *B);
bool VisitCXXRecordDecl(CXXRecordDecl *D);
Optional<bool> shouldVisitCursor(CXCursor C);
bool VisitDeclContext(DeclContext *DC);
bool VisitTranslationUnitDecl(TranslationUnitDecl *D);
bool VisitTypedefDecl(TypedefDecl *D);
bool VisitTagDecl(TagDecl *D);
bool VisitClassTemplateSpecializationDecl(ClassTemplateSpecializationDecl *D);
bool VisitClassTemplatePartialSpecializationDecl(
ClassTemplatePartialSpecializationDecl *D);
bool VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D);
bool VisitEnumConstantDecl(EnumConstantDecl *D);
bool VisitDeclaratorDecl(DeclaratorDecl *DD);
bool VisitFunctionDecl(FunctionDecl *ND);
bool VisitFieldDecl(FieldDecl *D);
bool VisitVarDecl(VarDecl *);
bool VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
bool VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
bool VisitClassTemplateDecl(ClassTemplateDecl *D);
bool VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
bool VisitObjCTypeParamDecl(ObjCTypeParamDecl *D);
bool VisitObjCMethodDecl(ObjCMethodDecl *ND);
bool VisitObjCContainerDecl(ObjCContainerDecl *D);
bool VisitObjCCategoryDecl(ObjCCategoryDecl *ND);
bool VisitObjCProtocolDecl(ObjCProtocolDecl *PID);
bool VisitObjCPropertyDecl(ObjCPropertyDecl *PD);
bool VisitObjCTypeParamList(ObjCTypeParamList *typeParamList);
bool VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
bool VisitObjCImplDecl(ObjCImplDecl *D);
bool VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D);
bool VisitObjCImplementationDecl(ObjCImplementationDecl *D);
// FIXME: ObjCCompatibleAliasDecl requires aliased-class locations.
bool VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *PD);
bool VisitLinkageSpecDecl(LinkageSpecDecl *D);
bool VisitNamespaceDecl(NamespaceDecl *D);
bool VisitNamespaceAliasDecl(NamespaceAliasDecl *D);
bool VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
bool VisitUsingDecl(UsingDecl *D);
bool VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
bool VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
bool VisitStaticAssertDecl(StaticAssertDecl *D);
bool VisitFriendDecl(FriendDecl *D);
bool VisitDecompositionDecl(DecompositionDecl *D);
bool VisitConceptDecl(ConceptDecl *D);
bool VisitTypeConstraint(const TypeConstraint &TC);
bool VisitConceptRequirement(const concepts::Requirement &R);
// Name visitor
bool VisitDeclarationNameInfo(DeclarationNameInfo Name);
bool VisitNestedNameSpecifier(NestedNameSpecifier *NNS, SourceRange Range);
bool VisitNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS);
// Template visitors
bool VisitTemplateParameters(const TemplateParameterList *Params);
bool VisitTemplateName(TemplateName Name, SourceLocation Loc);
bool VisitTemplateArgumentLoc(const TemplateArgumentLoc &TAL);
// Type visitors
#define ABSTRACT_TYPELOC(CLASS, PARENT)
#define TYPELOC(CLASS, PARENT) bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc);
#include "clang/AST/TypeLocNodes.def"
bool VisitTagTypeLoc(TagTypeLoc TL);
bool VisitArrayTypeLoc(ArrayTypeLoc TL);
bool VisitFunctionTypeLoc(FunctionTypeLoc TL, bool SkipResultType = false);
// Data-recursive visitor functions.
bool IsInRegionOfInterest(CXCursor C);
bool RunVisitorWorkList(VisitorWorkList &WL);
void EnqueueWorkList(VisitorWorkList &WL, const Stmt *S);
LLVM_ATTRIBUTE_NOINLINE bool Visit(const Stmt *S);
private:
Optional<bool> handleDeclForVisitation(const Decl *D);
};
} // namespace cxcursor
} // namespace clang
#endif
|