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