1 //===--- AST.cpp - Utility AST functions -----------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "AST.h" 11 12 #include "clang/AST/ASTContext.h" 13 #include "clang/AST/Decl.h" 14 #include "clang/Basic/SourceLocation.h" 15 #include "clang/Basic/SourceManager.h" 16 #include "clang/Index/USRGeneration.h" 17 18 using namespace llvm; 19 namespace clang { 20 namespace clangd { 21 22 // Returns true if the complete name of decl \p D is spelled in the source code. 23 // This is not the case for symbols formed via macro concatenation. 24 // (We used to attempt to treat names spelled on the command-line this way too, 25 // but the preamble doesn't preserve the required information). 26 bool isSpelledInSourceCode(const Decl *D) { 27 const auto &SM = D->getASTContext().getSourceManager(); 28 auto Loc = D->getLocation(); 29 // FIXME: Revisit the strategy, the heuristic is limitted when handling 30 // macros, we should use the location where the whole definition occurs. 31 if (Loc.isMacroID()) { 32 std::string PrintLoc = SM.getSpellingLoc(Loc).printToString(SM); 33 if (StringRef(PrintLoc).startswith("<scratch")) 34 return false; 35 } 36 return true; 37 } 38 39 bool isImplementationDetail(const Decl *D) { return !isSpelledInSourceCode(D); } 40 41 SourceLocation findNameLoc(const clang::Decl* D) { 42 const auto &SM = D->getASTContext().getSourceManager(); 43 if (!isSpelledInSourceCode(D)) 44 // Use the expansion location as spelling location is not interesting. 45 return SM.getExpansionRange(D->getLocation()).getBegin(); 46 return SM.getSpellingLoc(D->getLocation()); 47 } 48 49 std::string printQualifiedName(const NamedDecl &ND) { 50 std::string QName; 51 raw_string_ostream OS(QName); 52 PrintingPolicy Policy(ND.getASTContext().getLangOpts()); 53 // Note that inline namespaces are treated as transparent scopes. This 54 // reflects the way they're most commonly used for lookup. Ideally we'd 55 // include them, but at query time it's hard to find all the inline 56 // namespaces to query: the preamble doesn't have a dedicated list. 57 Policy.SuppressUnwrittenScope = true; 58 ND.printQualifiedName(OS, Policy); 59 OS.flush(); 60 assert(!StringRef(QName).startswith("::")); 61 return QName; 62 } 63 64 std::string printNamespaceScope(const DeclContext &DC) { 65 for (const auto *Ctx = &DC; Ctx != nullptr; Ctx = Ctx->getParent()) 66 if (const auto *NS = dyn_cast<NamespaceDecl>(Ctx)) 67 if (!NS->isAnonymousNamespace() && !NS->isInlineNamespace()) 68 return printQualifiedName(*NS) + "::"; 69 return ""; 70 } 71 72 Optional<SymbolID> getSymbolID(const Decl *D) { 73 SmallString<128> USR; 74 if (index::generateUSRForDecl(D, USR)) 75 return None; 76 return SymbolID(USR); 77 } 78 79 Optional<SymbolID> getSymbolID(const IdentifierInfo &II, const MacroInfo *MI, 80 const SourceManager &SM) { 81 if (MI == nullptr) 82 return None; 83 SmallString<128> USR; 84 if (index::generateUSRForMacro(II.getName(), MI->getDefinitionLoc(), SM, USR)) 85 return None; 86 return SymbolID(USR); 87 } 88 89 } // namespace clangd 90 } // namespace clang 91