• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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>>
getTemplateSpecializationArgLocs(const NamedDecl & ND)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>
isTemplateSpecializationKind(const NamedDecl * D,TemplateSpecializationKind Kind)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 
isTemplateSpecializationKind(const NamedDecl * D,TemplateSpecializationKind Kind)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 *>
getUsingNamespaceDirectives(const DeclContext * DestContext,SourceLocation Until)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
getQualification(ASTContext & Context,const DeclContext * DestContext,const DeclContext * SourceContext,llvm::function_ref<bool (NestedNameSpecifier *)> IsVisible)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 
isImplicitTemplateInstantiation(const NamedDecl * D)148 bool isImplicitTemplateInstantiation(const NamedDecl *D) {
149   return isTemplateSpecializationKind(D, TSK_ImplicitInstantiation);
150 }
151 
isExplicitTemplateSpecialization(const NamedDecl * D)152 bool isExplicitTemplateSpecialization(const NamedDecl *D) {
153   return isTemplateSpecializationKind(D, TSK_ExplicitSpecialization);
154 }
155 
isImplementationDetail(const Decl * D)156 bool isImplementationDetail(const Decl *D) {
157   return !isSpelledInSource(D->getLocation(),
158                             D->getASTContext().getSourceManager());
159 }
160 
nameLocation(const clang::Decl & D,const SourceManager & SM)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 
printQualifiedName(const NamedDecl & ND)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 
isAnonymous(const DeclarationName & N)183 static bool isAnonymous(const DeclarationName &N) {
184   return N.isIdentifier() && !N.getAsIdentifierInfo();
185 }
186 
getQualifierLoc(const NamedDecl & ND)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 
printUsingNamespaceName(const ASTContext & Ctx,const UsingDirectiveDecl & D)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 
printName(const ASTContext & Ctx,const NamedDecl & ND)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.
243   Out << printTemplateSpecializationArgs(ND);
244 
245   return Out.str();
246 }
247 
printTemplateSpecializationArgs(const NamedDecl & ND)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 
printNamespaceScope(const DeclContext & DC)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 
getSymbolID(const Decl * D)285 SymbolID getSymbolID(const Decl *D) {
286   llvm::SmallString<128> USR;
287   if (index::generateUSRForDecl(D, USR))
288     return {};
289   return SymbolID(USR);
290 }
291 
getSymbolID(const llvm::StringRef MacroName,const MacroInfo * MI,const SourceManager & SM)292 SymbolID getSymbolID(const llvm::StringRef MacroName, const MacroInfo *MI,
293                      const SourceManager &SM) {
294   if (MI == nullptr)
295     return {};
296   llvm::SmallString<128> USR;
297   if (index::generateUSRForMacro(MacroName, MI->getDefinitionLoc(), SM, USR))
298     return {};
299   return SymbolID(USR);
300 }
301 
302 // FIXME: This should be handled while printing underlying decls instead.
printType(const QualType QT,const DeclContext & CurContext)303 std::string printType(const QualType QT, const DeclContext &CurContext) {
304   std::string Result;
305   llvm::raw_string_ostream OS(Result);
306   auto Decls = explicitReferenceTargets(
307       ast_type_traits::DynTypedNode::create(QT), DeclRelation::Alias);
308   if (!Decls.empty())
309     OS << getQualification(CurContext.getParentASTContext(), &CurContext,
310                            Decls.front(),
311                            /*VisibleNamespaces=*/llvm::ArrayRef<std::string>{});
312   PrintingPolicy PP(CurContext.getParentASTContext().getPrintingPolicy());
313   PP.SuppressScope = true;
314   PP.SuppressTagKeyword = true;
315   QT.print(OS, PP);
316   return OS.str();
317 }
318 
declaredType(const TypeDecl * D)319 QualType declaredType(const TypeDecl *D) {
320   if (const auto *CTSD = llvm::dyn_cast<ClassTemplateSpecializationDecl>(D))
321     if (const auto *TSI = CTSD->getTypeAsWritten())
322       return TSI->getType();
323   return D->getASTContext().getTypeDeclType(D);
324 }
325 
326 namespace {
327 /// Computes the deduced type at a given location by visiting the relevant
328 /// nodes. We use this to display the actual type when hovering over an "auto"
329 /// keyword or "decltype()" expression.
330 /// FIXME: This could have been a lot simpler by visiting AutoTypeLocs but it
331 /// seems that the AutoTypeLocs that can be visited along with their AutoType do
332 /// not have the deduced type set. Instead, we have to go to the appropriate
333 /// DeclaratorDecl/FunctionDecl and work our back to the AutoType that does have
334 /// a deduced type set. The AST should be improved to simplify this scenario.
335 class DeducedTypeVisitor : public RecursiveASTVisitor<DeducedTypeVisitor> {
336   SourceLocation SearchedLocation;
337 
338 public:
DeducedTypeVisitor(SourceLocation SearchedLocation)339   DeducedTypeVisitor(SourceLocation SearchedLocation)
340       : SearchedLocation(SearchedLocation) {}
341 
342   // Handle auto initializers:
343   //- auto i = 1;
344   //- decltype(auto) i = 1;
345   //- auto& i = 1;
346   //- auto* i = &a;
VisitDeclaratorDecl(DeclaratorDecl * D)347   bool VisitDeclaratorDecl(DeclaratorDecl *D) {
348     if (!D->getTypeSourceInfo() ||
349         D->getTypeSourceInfo()->getTypeLoc().getBeginLoc() != SearchedLocation)
350       return true;
351 
352     if (auto *AT = D->getType()->getContainedAutoType()) {
353       if (!AT->getDeducedType().isNull())
354         DeducedType = AT->getDeducedType();
355     }
356     return true;
357   }
358 
359   // Handle auto return types:
360   //- auto foo() {}
361   //- auto& foo() {}
362   //- auto foo() -> int {}
363   //- auto foo() -> decltype(1+1) {}
364   //- operator auto() const { return 10; }
VisitFunctionDecl(FunctionDecl * D)365   bool VisitFunctionDecl(FunctionDecl *D) {
366     if (!D->getTypeSourceInfo())
367       return true;
368     // Loc of auto in return type (c++14).
369     auto CurLoc = D->getReturnTypeSourceRange().getBegin();
370     // Loc of "auto" in operator auto()
371     if (CurLoc.isInvalid() && dyn_cast<CXXConversionDecl>(D))
372       CurLoc = D->getTypeSourceInfo()->getTypeLoc().getBeginLoc();
373     // Loc of "auto" in function with trailing return type (c++11).
374     if (CurLoc.isInvalid())
375       CurLoc = D->getSourceRange().getBegin();
376     if (CurLoc != SearchedLocation)
377       return true;
378 
379     const AutoType *AT = D->getReturnType()->getContainedAutoType();
380     if (AT && !AT->getDeducedType().isNull()) {
381       DeducedType = AT->getDeducedType();
382     } else if (auto DT = dyn_cast<DecltypeType>(D->getReturnType())) {
383       // auto in a trailing return type just points to a DecltypeType and
384       // getContainedAutoType does not unwrap it.
385       if (!DT->getUnderlyingType().isNull())
386         DeducedType = DT->getUnderlyingType();
387     } else if (!D->getReturnType().isNull()) {
388       DeducedType = D->getReturnType();
389     }
390     return true;
391   }
392 
393   // Handle non-auto decltype, e.g.:
394   // - auto foo() -> decltype(expr) {}
395   // - decltype(expr);
VisitDecltypeTypeLoc(DecltypeTypeLoc TL)396   bool VisitDecltypeTypeLoc(DecltypeTypeLoc TL) {
397     if (TL.getBeginLoc() != SearchedLocation)
398       return true;
399 
400     // A DecltypeType's underlying type can be another DecltypeType! E.g.
401     //  int I = 0;
402     //  decltype(I) J = I;
403     //  decltype(J) K = J;
404     const DecltypeType *DT = dyn_cast<DecltypeType>(TL.getTypePtr());
405     while (DT && !DT->getUnderlyingType().isNull()) {
406       DeducedType = DT->getUnderlyingType();
407       DT = dyn_cast<DecltypeType>(DeducedType.getTypePtr());
408     }
409     return true;
410   }
411 
412   QualType DeducedType;
413 };
414 } // namespace
415 
getDeducedType(ASTContext & ASTCtx,SourceLocation Loc)416 llvm::Optional<QualType> getDeducedType(ASTContext &ASTCtx,
417                                         SourceLocation Loc) {
418   if (!Loc.isValid())
419     return {};
420   DeducedTypeVisitor V(Loc);
421   V.TraverseAST(ASTCtx);
422   if (V.DeducedType.isNull())
423     return llvm::None;
424   return V.DeducedType;
425 }
426 
getQualification(ASTContext & Context,const DeclContext * DestContext,SourceLocation InsertionPoint,const NamedDecl * ND)427 std::string getQualification(ASTContext &Context,
428                              const DeclContext *DestContext,
429                              SourceLocation InsertionPoint,
430                              const NamedDecl *ND) {
431   auto VisibleNamespaceDecls =
432       getUsingNamespaceDirectives(DestContext, InsertionPoint);
433   return getQualification(
434       Context, DestContext, ND->getDeclContext(),
435       [&](NestedNameSpecifier *NNS) {
436         if (NNS->getKind() != NestedNameSpecifier::Namespace)
437           return false;
438         const auto *CanonNSD = NNS->getAsNamespace()->getCanonicalDecl();
439         return llvm::any_of(VisibleNamespaceDecls,
440                             [CanonNSD](const NamespaceDecl *NSD) {
441                               return NSD->getCanonicalDecl() == CanonNSD;
442                             });
443       });
444 }
445 
getQualification(ASTContext & Context,const DeclContext * DestContext,const NamedDecl * ND,llvm::ArrayRef<std::string> VisibleNamespaces)446 std::string getQualification(ASTContext &Context,
447                              const DeclContext *DestContext,
448                              const NamedDecl *ND,
449                              llvm::ArrayRef<std::string> VisibleNamespaces) {
450   for (llvm::StringRef NS : VisibleNamespaces) {
451     assert(NS.endswith("::"));
452     (void)NS;
453   }
454   return getQualification(
455       Context, DestContext, ND->getDeclContext(),
456       [&](NestedNameSpecifier *NNS) {
457         return llvm::any_of(VisibleNamespaces, [&](llvm::StringRef Namespace) {
458           std::string NS;
459           llvm::raw_string_ostream OS(NS);
460           NNS->print(OS, Context.getPrintingPolicy());
461           return OS.str() == Namespace;
462         });
463       });
464 }
465 
hasUnstableLinkage(const Decl * D)466 bool hasUnstableLinkage(const Decl *D) {
467   // Linkage of a ValueDecl depends on the type.
468   // If that's not deduced yet, deducing it may change the linkage.
469   auto *VD = llvm::dyn_cast_or_null<ValueDecl>(D);
470   return VD && !VD->getType().isNull() && VD->getType()->isUndeducedType();
471 }
472 
473 } // namespace clangd
474 } // namespace clang
475