blob: ec1862cd73db4430276ad7d43c40958fef71c94f [file] [log] [blame]
//===--- AST.cpp - Utility AST functions -----------------------*- C++ -*-===//
// The LLVM Compiler Infrastructure
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
#include "AST.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/Basic/SourceManager.h"
namespace clang {
namespace clangd {
using namespace llvm;
SourceLocation findNameLoc(const clang::Decl* D) {
const auto& SM = D->getASTContext().getSourceManager();
// FIXME: Revisit the strategy, the heuristic is limitted when handling
// macros, we should use the location where the whole definition occurs.
SourceLocation SpellingLoc = SM.getSpellingLoc(D->getLocation());
if (D->getLocation().isMacroID()) {
std::string PrintLoc = SpellingLoc.printToString(SM);
if (llvm::StringRef(PrintLoc).startswith("<scratch") ||
llvm::StringRef(PrintLoc).startswith("<command line>")) {
// We use the expansion location for the following symbols, as spelling
// locations of these symbols are not interesting to us:
// * symbols formed via macro concatenation, the spelling location will
// be "<scratch space>"
// * symbols controlled and defined by a compile command-line option
// `-DName=foo`, the spelling location will be "<command line>".
SpellingLoc = SM.getExpansionRange(D->getLocation()).getBegin();
return SpellingLoc;
std::string printQualifiedName(const NamedDecl &ND) {
std::string QName;
llvm::raw_string_ostream OS(QName);
PrintingPolicy Policy(ND.getASTContext().getLangOpts());
// Note that inline namespaces are treated as transparent scopes. This
// reflects the way they're most commonly used for lookup. Ideally we'd
// include them, but at query time it's hard to find all the inline
// namespaces to query: the preamble doesn't have a dedicated list.
Policy.SuppressUnwrittenScope = true;
ND.printQualifiedName(OS, Policy);
return QName;
} // namespace clangd
} // namespace clang