blob: 661c6aaf4032a479c5fe111b78f3ec3ec7922775 [file] [log] [blame]
Haojian Wu5f100262018-03-09 14:00:34 +00001//===--- 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/SourceManager.h"
Haojian Wuc6ddb462018-08-07 08:57:52 +000015#include "clang/Index/USRGeneration.h"
Haojian Wu5f100262018-03-09 14:00:34 +000016
17namespace clang {
18namespace clangd {
19using namespace llvm;
20
21SourceLocation findNameLoc(const clang::Decl* D) {
22 const auto& SM = D->getASTContext().getSourceManager();
23 // FIXME: Revisit the strategy, the heuristic is limitted when handling
24 // macros, we should use the location where the whole definition occurs.
25 SourceLocation SpellingLoc = SM.getSpellingLoc(D->getLocation());
26 if (D->getLocation().isMacroID()) {
27 std::string PrintLoc = SpellingLoc.printToString(SM);
28 if (llvm::StringRef(PrintLoc).startswith("<scratch") ||
29 llvm::StringRef(PrintLoc).startswith("<command line>")) {
30 // We use the expansion location for the following symbols, as spelling
31 // locations of these symbols are not interesting to us:
32 // * symbols formed via macro concatenation, the spelling location will
33 // be "<scratch space>"
34 // * symbols controlled and defined by a compile command-line option
35 // `-DName=foo`, the spelling location will be "<command line>".
Richard Smith4bb15ab2018-04-30 05:26:07 +000036 SpellingLoc = SM.getExpansionRange(D->getLocation()).getBegin();
Haojian Wu5f100262018-03-09 14:00:34 +000037 }
38 }
39 return SpellingLoc;
40}
41
Eric Liu7ad16962018-06-22 10:46:59 +000042std::string printQualifiedName(const NamedDecl &ND) {
43 std::string QName;
44 llvm::raw_string_ostream OS(QName);
45 PrintingPolicy Policy(ND.getASTContext().getLangOpts());
46 // Note that inline namespaces are treated as transparent scopes. This
47 // reflects the way they're most commonly used for lookup. Ideally we'd
48 // include them, but at query time it's hard to find all the inline
49 // namespaces to query: the preamble doesn't have a dedicated list.
50 Policy.SuppressUnwrittenScope = true;
51 ND.printQualifiedName(OS, Policy);
52 OS.flush();
53 assert(!StringRef(QName).startswith("::"));
54 return QName;
55}
56
Haojian Wuc6ddb462018-08-07 08:57:52 +000057llvm::Optional<SymbolID> getSymbolID(const Decl *D) {
58 llvm::SmallString<128> USR;
59 if (index::generateUSRForDecl(D, USR))
60 return None;
61 return SymbolID(USR);
62}
63
Eric Liud25f1212018-09-06 09:59:37 +000064llvm::Optional<SymbolID> getSymbolID(const IdentifierInfo &II,
65 const MacroInfo *MI,
66 const SourceManager &SM) {
67 if (MI == nullptr)
68 return None;
69 llvm::SmallString<128> USR;
70 if (index::generateUSRForMacro(II.getName(), MI->getDefinitionLoc(), SM, USR))
71 return None;
72 return SymbolID(USR);
73}
74
Haojian Wu5f100262018-03-09 14:00:34 +000075} // namespace clangd
76} // namespace clang