clang-tools 10.0.0

AST.cpp
Go to the documentation of this file.
1 //===--- AST.cpp - Utility AST functions -----------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "AST.h"
10
11 #include "FindTarget.h"
12 #include "SourceCode.h"
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"
36 #include <string>
37 #include <vector>
38
39 namespace clang {
40 namespace clangd {
41
42 namespace {
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();
59 // We return None for ClassTemplateSpecializationDecls because it does not
60 // contain TemplateArgumentLoc information.
61 return llvm::None;
62 }
63
64 template <class T>
65 bool isTemplateSpecializationKind(const NamedDecl *D,
66 TemplateSpecializationKind Kind) {
67 if (const auto *TD = dyn_cast<T>(D))
68 return TD->getTemplateSpecializationKind() == Kind;
69 return false;
70 }
71
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);
77 }
78
79 // Store all UsingDirectiveDecls in parent contexts of DestContext, that were
80 // introduced before InsertionPoint.
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))
90 continue;
91 if (auto *UDD = llvm::dyn_cast<UsingDirectiveDecl>(D))
92 VisibleNamespaceDecls.insert(
93 UDD->getNominatedNamespace()->getCanonicalDecl());
94 }
95 }
96 return VisibleNamespaceDecls;
97 }
98
99 // Goes over all parents of SourceContext until we find a comman ancestor for
100 // DestContext and SourceContext. Any qualifier including and above common
101 // ancestor is redundant, therefore we stop at lowest common ancestor.
102 // In addition to that stops early whenever IsVisible returns true. This can be
103 // used to implement support for "using namespace" decls.
104 std::string
105 getQualification(ASTContext &Context, const DeclContext *DestContext,
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()) {
112 // Stop once we reach a common ancestor.
113 if (CurContext->Encloses(DestContext))
114 break;
115
116 NestedNameSpecifier *NNS = nullptr;
117 if (auto *TD = llvm::dyn_cast<TagDecl>(CurContext)) {
118 // There can't be any more tag parents after hitting a namespace.
119 assert(!ReachedNS);
120 NNS = NestedNameSpecifier::Create(Context, nullptr, false,
121 TD->getTypeForDecl());
122 } else {
123 ReachedNS = true;
124 auto *NSD = llvm::cast<NamespaceDecl>(CurContext);
125 NNS = NestedNameSpecifier::Create(Context, nullptr, NSD);
126 // Anonymous and inline namespace names are not spelled while qualifying a
127 // name, so skip those.
128 if (NSD->isAnonymousNamespace() || NSD->isInlineNamespace())
129 continue;
130 }
131 // Stop if this namespace is already visible at DestContext.
132 if (IsVisible(NNS))
133 break;
134
135 Parents.push_back(NNS);
136 }
137
138 // Go over name-specifiers in reverse order to create necessary qualification,
139 // since we stored inner-most parent first.
140 std::string Result;
141 llvm::raw_string_ostream OS(Result);
142 for (const auto *Parent : llvm::reverse(Parents))
143 Parent->print(OS, Context.getPrintingPolicy());
144 return OS.str();
145 }
146
147 } // namespace
148
149 bool isImplicitTemplateInstantiation(const NamedDecl *D) {
150 return isTemplateSpecializationKind(D, TSK_ImplicitInstantiation);
151 }
152
153 bool isExplicitTemplateSpecialization(const NamedDecl *D) {
154 return isTemplateSpecializationKind(D, TSK_ExplicitSpecialization);
155 }
156
157 bool isImplementationDetail(const Decl *D) {
158 return !isSpelledInSource(D->getLocation(),
159 D->getASTContext().getSourceManager());
160 }
161
162 SourceLocation nameLocation(const clang::Decl &D, const SourceManager &SM) {
163 auto L = D.getLocation();
164 if (isSpelledInSource(L, SM))
165 return SM.getSpellingLoc(L);
166 return SM.getExpansionLoc(L);
167 }
168
169 std::string printQualifiedName(const NamedDecl &ND) {
170 std::string QName;
171 llvm::raw_string_ostream OS(QName);
172 PrintingPolicy Policy(ND.getASTContext().getLangOpts());
173 // Note that inline namespaces are treated as transparent scopes. This
174 // reflects the way they're most commonly used for lookup. Ideally we'd
175 // include them, but at query time it's hard to find all the inline
176 // namespaces to query: the preamble doesn't have a dedicated list.
177 Policy.SuppressUnwrittenScope = true;
178 ND.printQualifiedName(OS, Policy);
179 OS.flush();
180 assert(!StringRef(QName).startswith("::"));
181 return QName;
182 }
183
184 static bool isAnonymous(const DeclarationName &N) {
185 return N.isIdentifier() && !N.getAsIdentifierInfo();
186 }
187
188 NestedNameSpecifierLoc getQualifierLoc(const NamedDecl &ND) {
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();
194 }
195
196 std::string printUsingNamespaceName(const ASTContext &Ctx,
197 const UsingDirectiveDecl &D) {
198 PrintingPolicy PP(Ctx.getLangOpts());
199 std::string Name;
200 llvm::raw_string_ostream Out(Name);
201
202 if (auto *Qual = D.getQualifier())
203 Qual->print(Out, PP);
204 D.getNominatedNamespaceAsWritten()->printName(Out);
205 return Out.str();
206 }
207
208 std::string printName(const ASTContext &Ctx, const NamedDecl &ND) {
209 std::string Name;
210 llvm::raw_string_ostream Out(Name);
211 PrintingPolicy PP(Ctx.getLangOpts());
212 // We don't consider a class template's args part of the constructor name.
213 PP.SuppressTemplateArgsInCXXConstructors = true;
214
215 // Handle 'using namespace'. They all have the same name - <using-directive>.
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);
221 return Out.str();
222 }
223
224 if (isAnonymous(ND.getDeclName())) {
225 // Come up with a presentation for an anonymous entity.
226 if (isa<NamespaceDecl>(ND))
227 return "(anonymous namespace)";
228 if (auto *Cls = llvm::dyn_cast<RecordDecl>(&ND)) {
229 if (Cls->isLambda())
230 return "(lambda)";
231 return ("(anonymous " + Cls->getKindName() + ")").str();
232 }
233 if (isa<EnumDecl>(ND))
234 return "(anonymous enum)";
235 return "(anonymous)";
236 }
237
238 // Print nested name qualifier if it was written in the source code.
239 if (auto *Qualifier = getQualifierLoc(ND).getNestedNameSpecifier())
240 Qualifier->print(Out, PP);
241 // Print the name itself.
242 ND.getDeclName().print(Out, PP);
243 // Print template arguments.
244 Out << printTemplateSpecializationArgs(ND);
245
246 return Out.str();
247 }
248
249 std::string printTemplateSpecializationArgs(const NamedDecl &ND) {
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()) {
258 // ClassTemplateSpecializationDecls do not contain
259 // TemplateArgumentTypeLocs, they only have TemplateArgumentTypes. So we
260 // create a new argument location list from TypeSourceInfo.
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);
267 } else {
268 // FIXME: Fix cases when getTypeAsWritten returns null inside clang AST,
269 // e.g. friend decls. Currently we fallback to Template Arguments without
270 // location information.
271 printTemplateArgumentList(OS, Cls->getTemplateArgs().asArray(), Policy);
272 }
273 }
274 OS.flush();
275 return TemplateArgs;
276 }
277
278 std::string printNamespaceScope(const DeclContext &DC) {
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())
282 return printQualifiedName(*NS) + "::";
283 return "";
284 }
285
286 llvm::Optional<SymbolID> getSymbolID(const Decl *D) {
287 llvm::SmallString<128> USR;
288 if (index::generateUSRForDecl(D, USR))
289 return None;
290 return SymbolID(USR);
291 }
292
293 llvm::Optional<SymbolID> getSymbolID(const llvm::StringRef MacroName,
294 const MacroInfo *MI,
295 const SourceManager &SM) {
296 if (MI == nullptr)
297 return None;
298 llvm::SmallString<128> USR;
299 if (index::generateUSRForMacro(MacroName, MI->getDefinitionLoc(), SM, USR))
300 return None;
301 return SymbolID(USR);
302 }
303
304 // FIXME: This should be handled while printing underlying decls instead.
305 std::string printType(const QualType QT, const DeclContext &CurContext) {
306 std::string Result;
307 llvm::raw_string_ostream OS(Result);
308 auto Decls = explicitReferenceTargets(
309 ast_type_traits::DynTypedNode::create(QT), DeclRelation::Alias);
310 if (!Decls.empty())
311 OS << getQualification(CurContext.getParentASTContext(), &CurContext,
312 Decls.front(),
313 /*VisibleNamespaces=*/llvm::ArrayRef<std::string>{});
314 PrintingPolicy PP(CurContext.getParentASTContext().getPrintingPolicy());
315 PP.SuppressScope = true;
316 PP.SuppressTagKeyword = true;
317 QT.print(OS, PP);
318 return OS.str();
319 }
320
321 QualType declaredType(const TypeDecl *D) {
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);
326 }
327
328 namespace {
329 /// Computes the deduced type at a given location by visiting the relevant
330 /// nodes. We use this to display the actual type when hovering over an "auto"
331 /// keyword or "decltype()" expression.
332 /// FIXME: This could have been a lot simpler by visiting AutoTypeLocs but it
333 /// seems that the AutoTypeLocs that can be visited along with their AutoType do
334 /// not have the deduced type set. Instead, we have to go to the appropriate
335 /// DeclaratorDecl/FunctionDecl and work our back to the AutoType that does have
336 /// a deduced type set. The AST should be improved to simplify this scenario.
337 class DeducedTypeVisitor : public RecursiveASTVisitor<DeducedTypeVisitor> {
338 SourceLocation SearchedLocation;
339
340 public:
341 DeducedTypeVisitor(SourceLocation SearchedLocation)
342 : SearchedLocation(SearchedLocation) {}
343
344 // Handle auto initializers:
345 //- auto i = 1;
346 //- decltype(auto) i = 1;
347 //- auto& i = 1;
348 //- auto* i = &a;
349 bool VisitDeclaratorDecl(DeclaratorDecl *D) {
350 if (!D->getTypeSourceInfo() ||
351 D->getTypeSourceInfo()->getTypeLoc().getBeginLoc() != SearchedLocation)
352 return true;
353
354 if (auto *AT = D->getType()->getContainedAutoType()) {
355 if (!AT->getDeducedType().isNull())
356 DeducedType = AT->getDeducedType();
357 }
358 return true;
359 }
360
361 // Handle auto return types:
362 //- auto foo() {}
363 //- auto& foo() {}
364 //- auto foo() -> int {}
365 //- auto foo() -> decltype(1+1) {}
366 //- operator auto() const { return 10; }
367 bool VisitFunctionDecl(FunctionDecl *D) {
368 if (!D->getTypeSourceInfo())
369 return true;
370 // Loc of auto in return type (c++14).
371 auto CurLoc = D->getReturnTypeSourceRange().getBegin();
372 // Loc of "auto" in operator auto()
373 if (CurLoc.isInvalid() && dyn_cast<CXXConversionDecl>(D))
374 CurLoc = D->getTypeSourceInfo()->getTypeLoc().getBeginLoc();
375 // Loc of "auto" in function with trailing return type (c++11).
376 if (CurLoc.isInvalid())
377 CurLoc = D->getSourceRange().getBegin();
378 if (CurLoc != SearchedLocation)
379 return true;
380
381 const AutoType *AT = D->getReturnType()->getContainedAutoType();
382 if (AT && !AT->getDeducedType().isNull()) {
383 DeducedType = AT->getDeducedType();
384 } else if (auto DT = dyn_cast<DecltypeType>(D->getReturnType())) {
385 // auto in a trailing return type just points to a DecltypeType and
386 // getContainedAutoType does not unwrap it.
387 if (!DT->getUnderlyingType().isNull())
388 DeducedType = DT->getUnderlyingType();
389 } else if (!D->getReturnType().isNull()) {
390 DeducedType = D->getReturnType();
391 }
392 return true;
393 }
394
395 // Handle non-auto decltype, e.g.:
396 // - auto foo() -> decltype(expr) {}
397 // - decltype(expr);
398 bool VisitDecltypeTypeLoc(DecltypeTypeLoc TL) {
399 if (TL.getBeginLoc() != SearchedLocation)
400 return true;
401
402 // A DecltypeType's underlying type can be another DecltypeType! E.g.
403 // int I = 0;
404 // decltype(I) J = I;
405 // decltype(J) K = J;
406 const DecltypeType *DT = dyn_cast<DecltypeType>(TL.getTypePtr());
407 while (DT && !DT->getUnderlyingType().isNull()) {
408 DeducedType = DT->getUnderlyingType();
409 DT = dyn_cast<DecltypeType>(DeducedType.getTypePtr());
410 }
411 return true;
412 }
413
414 QualType DeducedType;
415 };
416 } // namespace
417
418 llvm::Optional<QualType> getDeducedType(ASTContext &ASTCtx,
419 SourceLocation Loc) {
420 Token Tok;
421 // Only try to find a deduced type if the token is auto or decltype.
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")) {
428 return {};
429 }
430 DeducedTypeVisitor V(Loc);
431 V.TraverseAST(ASTCtx);
432 if (V.DeducedType.isNull())
433 return llvm::None;
434 return V.DeducedType;
435 }
436
437 std::string getQualification(ASTContext &Context,
438 const DeclContext *DestContext,
439 SourceLocation InsertionPoint,
440 const NamedDecl *ND) {
441 auto VisibleNamespaceDecls =
442 getUsingNamespaceDirectives(DestContext, InsertionPoint);
443 return getQualification(
444 Context, DestContext, ND->getDeclContext(),
445 [&](NestedNameSpecifier *NNS) {
446 if (NNS->getKind() != NestedNameSpecifier::Namespace)
447 return false;
448 const auto *CanonNSD = NNS->getAsNamespace()->getCanonicalDecl();
449 return llvm::any_of(VisibleNamespaceDecls,
450 [CanonNSD](const NamespaceDecl *NSD) {
451 return NSD->getCanonicalDecl() == CanonNSD;
452 });
453 });
454 }
455
456 std::string getQualification(ASTContext &Context,
457 const DeclContext *DestContext,
458 const NamedDecl *ND,
459 llvm::ArrayRef<std::string> VisibleNamespaces) {
460 for (llvm::StringRef NS : VisibleNamespaces) {
461 assert(NS.endswith("::"));
462 (void)NS;
463 }
464 return getQualification(
465 Context, DestContext, ND->getDeclContext(),
466 [&](NestedNameSpecifier *NNS) {
467 return llvm::any_of(VisibleNamespaces, [&](llvm::StringRef Namespace) {
468 std::string NS;
469 llvm::raw_string_ostream OS(NS);
470 NNS->print(OS, Context.getPrintingPolicy());
471 return OS.str() == Namespace;
472 });
473 });
474 }
475
476 } // namespace clangd
477 } // namespace clang
Loc
SourceLocation Loc
&#39;#&#39; location in the include directive
Definition: IncludeOrderCheck.cpp:37
clang::clangd::printName
std::string printName(const ASTContext &Ctx, const NamedDecl &ND)
Prints unqualified name of the decl for the purpose of displaying it to the user. ...
Definition: AST.cpp:208
DeducedType
QualType DeducedType
Definition: AST.cpp:414
Decl
const FunctionDecl * Decl
Definition: AvoidBindCheck.cpp:93
clang::clangd::TypeHierarchyDirection::Parents
AST.h
clang::clangd::printQualifiedName
std::string printQualifiedName(const NamedDecl &ND)
Returns the qualified name of ND.
Definition: AST.cpp:169
clang::clangd::nameLocation
SourceLocation nameLocation(const clang::Decl &D, const SourceManager &SM)
Find the source location of the identifier for D.
Definition: AST.cpp:162
clang::clangd::getDeducedType
llvm::Optional< QualType > getDeducedType(ASTContext &ASTCtx, SourceLocation Loc)
Retrieves the deduced type at a given location (auto, decltype).
Definition: AST.cpp:418
clang::clangd::getSymbolID
llvm::Optional< SymbolID > getSymbolID(const Decl *D)
Gets the symbol ID for a declaration, if possible.
Definition: AST.cpp:286
clang::clangd::printUsingNamespaceName
std::string printUsingNamespaceName(const ASTContext &Ctx, const UsingDirectiveDecl &D)
Returns the name of the namespace inside the &#39;using namespace&#39; directive, as written in the code...
Definition: AST.cpp:196
Parent
const Node * Parent
Definition: ExtractFunction.cpp:148
clang::clangd::printNamespaceScope
std::string printNamespaceScope(const DeclContext &DC)
Returns the first enclosing namespace scope starting from DC.
Definition: AST.cpp:278
SourceCode.h
clang::clangd::getQualifierLoc
NestedNameSpecifierLoc getQualifierLoc(const NamedDecl &ND)
Returns a nested name specifier loc of ND if it was present in the source, e.g.
Definition: AST.cpp:188
clang::clangd::TextDocumentSyncKind::None
Documents should not be synced at all.
clang::clangd::printTemplateSpecializationArgs
std::string printTemplateSpecializationArgs(const NamedDecl &ND)
Prints template arguments of a decl as written in the source code, including enclosing &#39;<&#39; and &#39;>&#39;...
Definition: AST.cpp:249
clang::clangd::isSpelledInSource
bool isSpelledInSource(SourceLocation Loc, const SourceManager &SM)
Returns true if the token at Loc is spelled in the source code.
Definition: SourceCode.cpp:217
clang::clangd::DeclRelation::Alias
This declaration is an alias that was referred to.
clang::clangd::printType
std::string printType(const QualType QT, const DeclContext &CurContext)
Returns a QualType as string.
Definition: AST.cpp:305
Kind
BindArgumentKind Kind
Definition: AvoidBindCheck.cpp:57
Ctx
Context Ctx
Definition: TUScheduler.cpp:237
QName
std::string QName
Definition: DiagnosticsTests.cpp:523
clang::clangd::explicitReferenceTargets
llvm::SmallVector< const NamedDecl *, 1 > explicitReferenceTargets(DynTypedNode N, DeclRelationSet Mask)
Definition: FindTarget.cpp:519
clang::clangd::getQualification
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.
Definition: AST.cpp:437
clang::clangd::declaredType
QualType declaredType(const TypeDecl *D)
Definition: AST.cpp:321
clang::clangd::isImplicitTemplateInstantiation
bool isImplicitTemplateInstantiation(const NamedDecl *D)
Indicates if D is a template instantiation implicitly generated by the compiler, e.g.
Definition: AST.cpp:149
InsertionPoint
SourceLocation InsertionPoint
Definition: ExtractFunction.cpp:305
Name
static constexpr llvm::StringLiteral Name
Definition: UppercaseLiteralSuffixCheck.cpp:27
clang::clangd::Context
A context is an immutable container for per-request data that must be propagated through layers that ...
Definition: Context.h:69
clang::clangd::isExplicitTemplateSpecialization
bool isExplicitTemplateSpecialization(const NamedDecl *D)
Indicates if D is an explicit template specialization, e.g.
Definition: AST.cpp:153
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ApplyReplacements.h:27
clang::clangd::isAnonymous
static bool isAnonymous(const DeclarationName &N)
Definition: AST.cpp:184
FindTarget.h
clang::tidy::bugprone::PP
static Preprocessor * PP
Definition: BadSignalToKillThreadCheck.cpp:28
clang::clangd::SymbolKind::Namespace
clang::clangd::isImplementationDetail
bool isImplementationDetail(const Decl *D)
Returns true if the declaration is considered implementation detail based on heuristics.
Definition: AST.cpp:157
clang::doc::SymbolID
std::array< uint8_t, 20 > SymbolID
Definition: Representation.h:30