13 #include "clang/AST/ASTContext.h" 14 #include "clang/AST/ASTTypeTraits.h" 15 #include "clang/AST/Decl.h" 16 #include "clang/AST/DeclBase.h" 17 #include "clang/AST/DeclCXX.h" 18 #include "clang/AST/DeclTemplate.h" 19 #include "clang/AST/DeclarationName.h" 20 #include "clang/AST/NestedNameSpecifier.h" 21 #include "clang/AST/PrettyPrinter.h" 22 #include "clang/AST/RecursiveASTVisitor.h" 23 #include "clang/AST/TemplateBase.h" 24 #include "clang/Basic/SourceLocation.h" 25 #include "clang/Basic/SourceManager.h" 26 #include "clang/Basic/Specifiers.h" 27 #include "clang/Index/USRGeneration.h" 28 #include "clang/Lex/Lexer.h" 29 #include "llvm/ADT/ArrayRef.h" 30 #include "llvm/ADT/Optional.h" 31 #include "llvm/ADT/STLExtras.h" 32 #include "llvm/ADT/StringRef.h" 33 #include "llvm/Support/Casting.h" 34 #include "llvm/Support/ScopedPrinter.h" 35 #include "llvm/Support/raw_ostream.h" 43 llvm::Optional<llvm::ArrayRef<TemplateArgumentLoc>>
44 getTemplateSpecializationArgLocs(
const NamedDecl &ND) {
45 if (
auto *Func = llvm::dyn_cast<FunctionDecl>(&ND)) {
46 if (
const ASTTemplateArgumentListInfo *Args =
47 Func->getTemplateSpecializationArgsAsWritten())
48 return Args->arguments();
49 }
else if (
auto *Cls =
50 llvm::dyn_cast<ClassTemplatePartialSpecializationDecl>(&ND)) {
51 if (
auto *Args = Cls->getTemplateArgsAsWritten())
52 return Args->arguments();
53 }
else if (
auto *Var =
54 llvm::dyn_cast<VarTemplatePartialSpecializationDecl>(&ND)) {
55 if (
auto *Args = Var->getTemplateArgsAsWritten())
56 return Args->arguments();
57 }
else if (
auto *Var = llvm::dyn_cast<VarTemplateSpecializationDecl>(&ND))
58 return Var->getTemplateArgsInfo().arguments();
65 bool isTemplateSpecializationKind(
const NamedDecl *D,
66 TemplateSpecializationKind
Kind) {
67 if (
const auto *TD = dyn_cast<T>(D))
68 return TD->getTemplateSpecializationKind() ==
Kind;
72 bool isTemplateSpecializationKind(
const NamedDecl *D,
73 TemplateSpecializationKind Kind) {
74 return isTemplateSpecializationKind<FunctionDecl>(D,
Kind) ||
75 isTemplateSpecializationKind<CXXRecordDecl>(D, Kind) ||
76 isTemplateSpecializationKind<VarDecl>(D,
Kind);
81 llvm::DenseSet<const NamespaceDecl *>
82 getUsingNamespaceDirectives(
const DeclContext *DestContext,
83 SourceLocation Until) {
84 const auto &SM = DestContext->getParentASTContext().getSourceManager();
85 llvm::DenseSet<const NamespaceDecl *> VisibleNamespaceDecls;
86 for (
const auto *DC = DestContext; DC; DC = DC->getLookupParent()) {
87 for (
const auto *D : DC->decls()) {
88 if (!SM.isWrittenInSameFile(D->getLocation(), Until) ||
89 !SM.isBeforeInTranslationUnit(D->getLocation(), Until))
91 if (
auto *UDD = llvm::dyn_cast<UsingDirectiveDecl>(D))
92 VisibleNamespaceDecls.insert(
93 UDD->getNominatedNamespace()->getCanonicalDecl());
96 return VisibleNamespaceDecls;
106 const DeclContext *SourceContext,
107 llvm::function_ref<
bool(NestedNameSpecifier *)> IsVisible) {
108 std::vector<const NestedNameSpecifier *>
Parents;
109 bool ReachedNS =
false;
110 for (
const DeclContext *CurContext = SourceContext; CurContext;
111 CurContext = CurContext->getLookupParent()) {
113 if (CurContext->Encloses(DestContext))
116 NestedNameSpecifier *NNS =
nullptr;
117 if (
auto *TD = llvm::dyn_cast<TagDecl>(CurContext)) {
120 NNS = NestedNameSpecifier::Create(Context,
nullptr,
false,
121 TD->getTypeForDecl());
124 auto *NSD = llvm::cast<NamespaceDecl>(CurContext);
125 NNS = NestedNameSpecifier::Create(Context,
nullptr, NSD);
128 if (NSD->isAnonymousNamespace() || NSD->isInlineNamespace())
135 Parents.push_back(NNS);
141 llvm::raw_string_ostream OS(Result);
142 for (
const auto *
Parent : llvm::reverse(Parents))
143 Parent->print(OS, Context.getPrintingPolicy());
150 return isTemplateSpecializationKind(D, TSK_ImplicitInstantiation);
154 return isTemplateSpecializationKind(D, TSK_ExplicitSpecialization);
159 D->getASTContext().getSourceManager());
163 auto L = D.getLocation();
165 return SM.getSpellingLoc(L);
166 return SM.getExpansionLoc(L);
171 llvm::raw_string_ostream OS(QName);
172 PrintingPolicy Policy(ND.getASTContext().getLangOpts());
177 Policy.SuppressUnwrittenScope =
true;
178 ND.printQualifiedName(OS, Policy);
180 assert(!StringRef(QName).startswith(
"::"));
185 return N.isIdentifier() && !N.getAsIdentifierInfo();
189 if (
auto *V = llvm::dyn_cast<DeclaratorDecl>(&ND))
190 return V->getQualifierLoc();
191 if (
auto *T = llvm::dyn_cast<TagDecl>(&ND))
192 return T->getQualifierLoc();
193 return NestedNameSpecifierLoc();
197 const UsingDirectiveDecl &D) {
198 PrintingPolicy
PP(Ctx.getLangOpts());
200 llvm::raw_string_ostream Out(Name);
202 if (
auto *Qual = D.getQualifier())
203 Qual->print(Out,
PP);
204 D.getNominatedNamespaceAsWritten()->printName(Out);
210 llvm::raw_string_ostream Out(Name);
211 PrintingPolicy
PP(Ctx.getLangOpts());
213 PP.SuppressTemplateArgsInCXXConstructors =
true;
216 if (
auto *UD = llvm::dyn_cast<UsingDirectiveDecl>(&ND)) {
217 Out <<
"using namespace ";
218 if (
auto *Qual = UD->getQualifier())
219 Qual->print(Out,
PP);
220 UD->getNominatedNamespaceAsWritten()->printName(Out);
226 if (isa<NamespaceDecl>(ND))
227 return "(anonymous namespace)";
228 if (
auto *Cls = llvm::dyn_cast<RecordDecl>(&ND)) {
231 return (
"(anonymous " + Cls->getKindName() +
")").str();
233 if (isa<EnumDecl>(ND))
234 return "(anonymous enum)";
235 return "(anonymous)";
240 Qualifier->print(Out,
PP);
242 ND.getDeclName().print(Out,
PP);
250 std::string TemplateArgs;
251 llvm::raw_string_ostream OS(TemplateArgs);
252 PrintingPolicy Policy(ND.getASTContext().getLangOpts());
253 if (llvm::Optional<llvm::ArrayRef<TemplateArgumentLoc>> Args =
254 getTemplateSpecializationArgLocs(ND)) {
255 printTemplateArgumentList(OS, *Args, Policy);
256 }
else if (
auto *Cls = llvm::dyn_cast<ClassTemplateSpecializationDecl>(&ND)) {
257 if (
const TypeSourceInfo *TSI = Cls->getTypeAsWritten()) {
261 auto STL = TSI->getTypeLoc().getAs<TemplateSpecializationTypeLoc>();
262 llvm::SmallVector<TemplateArgumentLoc, 8> ArgLocs;
263 ArgLocs.reserve(STL.getNumArgs());
264 for (
unsigned I = 0; I < STL.getNumArgs(); ++I)
265 ArgLocs.push_back(STL.getArgLoc(I));
266 printTemplateArgumentList(OS, ArgLocs, Policy);
271 printTemplateArgumentList(OS, Cls->getTemplateArgs().asArray(), Policy);
279 for (
const auto *
Ctx = &DC;
Ctx !=
nullptr;
Ctx =
Ctx->getParent())
280 if (
const auto *NS = dyn_cast<NamespaceDecl>(
Ctx))
281 if (!NS->isAnonymousNamespace() && !NS->isInlineNamespace())
287 llvm::SmallString<128> USR;
288 if (index::generateUSRForDecl(D, USR))
293 llvm::Optional<SymbolID>
getSymbolID(
const llvm::StringRef MacroName,
295 const SourceManager &SM) {
298 llvm::SmallString<128> USR;
299 if (index::generateUSRForMacro(MacroName, MI->getDefinitionLoc(), SM, USR))
305 std::string
printType(
const QualType QT,
const DeclContext &CurContext) {
307 llvm::raw_string_ostream OS(Result);
313 llvm::ArrayRef<std::string>{});
314 PrintingPolicy
PP(CurContext.getParentASTContext().getPrintingPolicy());
315 PP.SuppressScope =
true;
316 PP.SuppressTagKeyword =
true;
322 if (
const auto *CTSD = llvm::dyn_cast<ClassTemplateSpecializationDecl>(D))
323 if (
const auto *TSI = CTSD->getTypeAsWritten())
324 return TSI->getType();
325 return D->getASTContext().getTypeDeclType(D);
337 class DeducedTypeVisitor :
public RecursiveASTVisitor<DeducedTypeVisitor> {
338 SourceLocation SearchedLocation;
341 DeducedTypeVisitor(SourceLocation SearchedLocation)
342 : SearchedLocation(SearchedLocation) {}
349 bool VisitDeclaratorDecl(DeclaratorDecl *D) {
350 if (!D->getTypeSourceInfo() ||
351 D->getTypeSourceInfo()->getTypeLoc().getBeginLoc() != SearchedLocation)
354 if (
auto *AT = D->getType()->getContainedAutoType()) {
355 if (!AT->getDeducedType().isNull())
367 bool VisitFunctionDecl(FunctionDecl *D) {
368 if (!D->getTypeSourceInfo())
371 auto CurLoc = D->getReturnTypeSourceRange().getBegin();
373 if (CurLoc.isInvalid() && dyn_cast<CXXConversionDecl>(D))
374 CurLoc = D->getTypeSourceInfo()->getTypeLoc().getBeginLoc();
376 if (CurLoc.isInvalid())
377 CurLoc = D->getSourceRange().getBegin();
378 if (CurLoc != SearchedLocation)
381 const AutoType *AT = D->getReturnType()->getContainedAutoType();
382 if (AT && !AT->getDeducedType().isNull()) {
384 }
else if (
auto DT = dyn_cast<DecltypeType>(D->getReturnType())) {
387 if (!DT->getUnderlyingType().isNull())
389 }
else if (!D->getReturnType().isNull()) {
398 bool VisitDecltypeTypeLoc(DecltypeTypeLoc TL) {
399 if (TL.getBeginLoc() != SearchedLocation)
406 const DecltypeType *DT = dyn_cast<DecltypeType>(TL.getTypePtr());
407 while (DT && !DT->getUnderlyingType().isNull()) {
409 DT = dyn_cast<DecltypeType>(
DeducedType.getTypePtr());
419 SourceLocation
Loc) {
422 if (!Loc.isValid() ||
423 Lexer::getRawToken(Loc, Tok, ASTCtx.getSourceManager(),
424 ASTCtx.getLangOpts(),
false) ||
425 !Tok.is(tok::raw_identifier) ||
426 !(Tok.getRawIdentifier() ==
"auto" ||
427 Tok.getRawIdentifier() ==
"decltype")) {
430 DeducedTypeVisitor V(Loc);
431 V.TraverseAST(ASTCtx);
432 if (V.DeducedType.isNull())
434 return V.DeducedType;
438 const DeclContext *DestContext,
440 const NamedDecl *ND) {
441 auto VisibleNamespaceDecls =
442 getUsingNamespaceDirectives(DestContext, InsertionPoint);
444 Context, DestContext, ND->getDeclContext(),
445 [&](NestedNameSpecifier *NNS) {
448 const auto *CanonNSD = NNS->getAsNamespace()->getCanonicalDecl();
449 return llvm::any_of(VisibleNamespaceDecls,
450 [CanonNSD](
const NamespaceDecl *NSD) {
451 return NSD->getCanonicalDecl() == CanonNSD;
457 const DeclContext *DestContext,
459 llvm::ArrayRef<std::string> VisibleNamespaces) {
460 for (llvm::StringRef NS : VisibleNamespaces) {
461 assert(NS.endswith(
"::"));
465 Context, DestContext, ND->getDeclContext(),
466 [&](NestedNameSpecifier *NNS) {
467 return llvm::any_of(VisibleNamespaces, [&](llvm::StringRef
Namespace) {
469 llvm::raw_string_ostream OS(NS);
470 NNS->print(OS, Context.getPrintingPolicy());
SourceLocation Loc
'#' location in the include directive
std::string printName(const ASTContext &Ctx, const NamedDecl &ND)
Prints unqualified name of the decl for the purpose of displaying it to the user. ...
const FunctionDecl * Decl
std::string printQualifiedName(const NamedDecl &ND)
Returns the qualified name of ND.
SourceLocation nameLocation(const clang::Decl &D, const SourceManager &SM)
Find the source location of the identifier for D.
llvm::Optional< QualType > getDeducedType(ASTContext &ASTCtx, SourceLocation Loc)
Retrieves the deduced type at a given location (auto, decltype).
llvm::Optional< SymbolID > getSymbolID(const Decl *D)
Gets the symbol ID for a declaration, if possible.
std::string printUsingNamespaceName(const ASTContext &Ctx, const UsingDirectiveDecl &D)
Returns the name of the namespace inside the 'using namespace' directive, as written in the code...
std::string printNamespaceScope(const DeclContext &DC)
Returns the first enclosing namespace scope starting from DC.
NestedNameSpecifierLoc getQualifierLoc(const NamedDecl &ND)
Returns a nested name specifier loc of ND if it was present in the source, e.g.
Documents should not be synced at all.
std::string printTemplateSpecializationArgs(const NamedDecl &ND)
Prints template arguments of a decl as written in the source code, including enclosing '<' and '>'...
bool isSpelledInSource(SourceLocation Loc, const SourceManager &SM)
Returns true if the token at Loc is spelled in the source code.
This declaration is an alias that was referred to.
std::string printType(const QualType QT, const DeclContext &CurContext)
Returns a QualType as string.
llvm::SmallVector< const NamedDecl *, 1 > explicitReferenceTargets(DynTypedNode N, DeclRelationSet Mask)
std::string getQualification(ASTContext &Context, const DeclContext *DestContext, SourceLocation InsertionPoint, const NamedDecl *ND)
Gets the nested name specifier necessary for spelling ND in DestContext, at InsertionPoint.
QualType declaredType(const TypeDecl *D)
bool isImplicitTemplateInstantiation(const NamedDecl *D)
Indicates if D is a template instantiation implicitly generated by the compiler, e.g.
static constexpr llvm::StringLiteral Name
A context is an immutable container for per-request data that must be propagated through layers that ...
bool isExplicitTemplateSpecialization(const NamedDecl *D)
Indicates if D is an explicit template specialization, e.g.
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
static bool isAnonymous(const DeclarationName &N)
llvm::SmallDenseMap< const NamedDecl *, RelSet > Decls
bool isImplementationDetail(const Decl *D)
Returns true if the declaration is considered implementation detail based on heuristics.
std::array< uint8_t, 20 > SymbolID