diff options
| author | Kadir Cetinkaya <kadircet@google.com> | 2019-04-12 10:09:14 +0000 |
|---|---|---|
| committer | Kadir Cetinkaya <kadircet@google.com> | 2019-04-12 10:09:14 +0000 |
| commit | a80a52283cb7d8ee4d44c08030c44c39b3481d36 (patch) | |
| tree | 94f5736d88a8e3c97d64f1e771c84c108d4ce00a /clang-tools-extra/clangd/AST.cpp | |
| parent | 2446f843aeeae6c0fff3620b90bab9cdcc47ec8a (diff) | |
| download | bcm5719-llvm-a80a52283cb7d8ee4d44c08030c44c39b3481d36.tar.gz bcm5719-llvm-a80a52283cb7d8ee4d44c08030c44c39b3481d36.zip | |
[clangd] Print template arguments helper
Summary:
Prepares ground for printing template arguments as written in the
source code, part of re-landing rC356541 with D59599 applied.
Reviewers: ioeric, ilya-biryukov
Subscribers: mgorny, MaskRay, jkorous, arphaman, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D59639
llvm-svn: 358272
Diffstat (limited to 'clang-tools-extra/clangd/AST.cpp')
| -rw-r--r-- | clang-tools-extra/clangd/AST.cpp | 66 |
1 files changed, 52 insertions, 14 deletions
diff --git a/clang-tools-extra/clangd/AST.cpp b/clang-tools-extra/clangd/AST.cpp index 47559c10d36..113069a09eb 100644 --- a/clang-tools-extra/clangd/AST.cpp +++ b/clang-tools-extra/clangd/AST.cpp @@ -11,15 +11,37 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclTemplate.h" +#include "clang/AST/TemplateBase.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" #include "clang/Index/USRGeneration.h" +#include "llvm/ADT/Optional.h" #include "llvm/Support/Casting.h" #include "llvm/Support/ScopedPrinter.h" +#include "llvm/Support/raw_ostream.h" namespace clang { namespace clangd { +namespace { +llvm::Optional<llvm::ArrayRef<TemplateArgumentLoc>> +getTemplateSpecializationArgLocs(const NamedDecl &ND) { + if (auto *Func = llvm::dyn_cast<FunctionDecl>(&ND)) { + if (const ASTTemplateArgumentListInfo *Args = + Func->getTemplateSpecializationArgsAsWritten()) + return Args->arguments(); + } else if (auto *Cls = + llvm::dyn_cast<ClassTemplatePartialSpecializationDecl>(&ND)) { + if (auto *Args = Cls->getTemplateArgsAsWritten()) + return Args->arguments(); + } else if (auto *Var = llvm::dyn_cast<VarTemplateSpecializationDecl>(&ND)) + return Var->getTemplateArgsInfo().arguments(); + // We return None for ClassTemplateSpecializationDecls because it does not + // contain TemplateArgumentLoc information. + return llvm::None; +} +} // namespace + // Returns true if the complete name of decl \p D is spelled in the source code. // This is not the case for: // * symbols formed via macro concatenation, the spelling location will @@ -65,17 +87,6 @@ std::string printQualifiedName(const NamedDecl &ND) { return QName; } -static const TemplateArgumentList * -getTemplateSpecializationArgs(const NamedDecl &ND) { - if (auto *Func = llvm::dyn_cast<FunctionDecl>(&ND)) - return Func->getTemplateSpecializationArgs(); - if (auto *Cls = llvm::dyn_cast<ClassTemplateSpecializationDecl>(&ND)) - return &Cls->getTemplateInstantiationArgs(); - if (auto *Var = llvm::dyn_cast<VarTemplateSpecializationDecl>(&ND)) - return &Var->getTemplateInstantiationArgs(); - return nullptr; -} - std::string printName(const ASTContext &Ctx, const NamedDecl &ND) { std::string Name; llvm::raw_string_ostream Out(Name); @@ -90,9 +101,7 @@ std::string printName(const ASTContext &Ctx, const NamedDecl &ND) { } ND.getDeclName().print(Out, PP); if (!Out.str().empty()) { - // FIXME(ibiryukov): do not show args not explicitly written by the user. - if (auto *ArgList = getTemplateSpecializationArgs(ND)) - printTemplateArgumentList(Out, ArgList->asArray(), PP); + Out << printTemplateSpecializationArgs(ND); return Out.str(); } // The name was empty, so present an anonymous entity. @@ -105,6 +114,35 @@ std::string printName(const ASTContext &Ctx, const NamedDecl &ND) { return "(anonymous)"; } +std::string printTemplateSpecializationArgs(const NamedDecl &ND) { + std::string TemplateArgs; + llvm::raw_string_ostream OS(TemplateArgs); + PrintingPolicy Policy(ND.getASTContext().getLangOpts()); + if (llvm::Optional<llvm::ArrayRef<TemplateArgumentLoc>> Args = + getTemplateSpecializationArgLocs(ND)) { + printTemplateArgumentList(OS, *Args, Policy); + } else if (auto *Cls = llvm::dyn_cast<ClassTemplateSpecializationDecl>(&ND)) { + if (const TypeSourceInfo *TSI = Cls->getTypeAsWritten()) { + // ClassTemplateSpecializationDecls do not contain + // TemplateArgumentTypeLocs, they only have TemplateArgumentTypes. So we + // create a new argument location list from TypeSourceInfo. + auto STL = TSI->getTypeLoc().getAs<TemplateSpecializationTypeLoc>(); + llvm::SmallVector<TemplateArgumentLoc, 8> ArgLocs; + ArgLocs.reserve(STL.getNumArgs()); + for (unsigned I = 0; I < STL.getNumArgs(); ++I) + ArgLocs.push_back(STL.getArgLoc(I)); + printTemplateArgumentList(OS, ArgLocs, Policy); + } else { + // FIXME: Fix cases when getTypeAsWritten returns null inside clang AST, + // e.g. friend decls. Currently we fallback to Template Arguments without + // location information. + printTemplateArgumentList(OS, Cls->getTemplateArgs().asArray(), Policy); + } + } + OS.flush(); + return TemplateArgs; +} + std::string printNamespaceScope(const DeclContext &DC) { for (const auto *Ctx = &DC; Ctx != nullptr; Ctx = Ctx->getParent()) if (const auto *NS = dyn_cast<NamespaceDecl>(Ctx)) |

