From 8967ab042f1362ba911a2b662aab026407d2117a Mon Sep 17 00:00:00 2001 From: Ilya Biryukov Date: Wed, 25 Sep 2019 15:46:04 +0000 Subject: [PATCH] Re-land r372863: [AST] Extract Decl::printNestedNameSpecifier helper from Decl::printQualifiedName Reverted in r372880 due to the test failure. Also contains a fix that adjusts printQualifiedName to return the same results as before in case of anonymous function locals and parameters. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@372889 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/Decl.h | 8 +++ lib/AST/Decl.cpp | 27 +++++++--- unittests/AST/NamedDeclPrinterTest.cpp | 70 +++++++++++++++++++++----- 3 files changed, 85 insertions(+), 20 deletions(-) diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 096df484cb..6b6a8abc3a 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -310,6 +310,14 @@ public: void printQualifiedName(raw_ostream &OS) const; void printQualifiedName(raw_ostream &OS, const PrintingPolicy &Policy) const; + /// Print only the nested name specifier part of a fully-qualified name, + /// including the '::' at the end. E.g. + /// when `printQualifiedName(D)` prints "A::B::i", + /// this function prints "A::B::". + void printNestedNameSpecifier(raw_ostream &OS) const; + void printNestedNameSpecifier(raw_ostream &OS, + const PrintingPolicy &Policy) const; + // FIXME: Remove string version. std::string getQualifiedNameAsString() const; diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index b27ac907b8..135b5f71c7 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -1558,6 +1558,24 @@ void NamedDecl::printQualifiedName(raw_ostream &OS) const { void NamedDecl::printQualifiedName(raw_ostream &OS, const PrintingPolicy &P) const { + if (getDeclContext()->isFunctionOrMethod()) { + // We do not print '(anonymous)' for function parameters without name. + printName(OS); + return; + } + printNestedNameSpecifier(OS, P); + if (getDeclName() || isa(this)) + OS << *this; + else + OS << "(anonymous)"; +} + +void NamedDecl::printNestedNameSpecifier(raw_ostream &OS) const { + printNestedNameSpecifier(OS, getASTContext().getPrintingPolicy()); +} + +void NamedDecl::printNestedNameSpecifier(raw_ostream &OS, + const PrintingPolicy &P) const { const DeclContext *Ctx = getDeclContext(); // For ObjC methods and properties, look through categories and use the @@ -1571,10 +1589,8 @@ void NamedDecl::printQualifiedName(raw_ostream &OS, Ctx = ID; } - if (Ctx->isFunctionOrMethod()) { - printName(OS); + if (Ctx->isFunctionOrMethod()) return; - } using ContextsTy = SmallVector; ContextsTy Contexts; @@ -1644,11 +1660,6 @@ void NamedDecl::printQualifiedName(raw_ostream &OS, } OS << "::"; } - - if (getDeclName() || isa(this)) - OS << *this; - else - OS << "(anonymous)"; } void NamedDecl::getNameForDiagnostic(raw_ostream &OS, diff --git a/unittests/AST/NamedDeclPrinterTest.cpp b/unittests/AST/NamedDeclPrinterTest.cpp index a50626517f..a5c3e19055 100644 --- a/unittests/AST/NamedDeclPrinterTest.cpp +++ b/unittests/AST/NamedDeclPrinterTest.cpp @@ -16,9 +16,12 @@ //===----------------------------------------------------------------------===// #include "clang/AST/ASTContext.h" +#include "clang/AST/Decl.h" +#include "clang/AST/PrettyPrinter.h" #include "clang/ASTMatchers/ASTMatchFinder.h" #include "clang/Tooling/Tooling.h" #include "llvm/ADT/SmallString.h" +#include "llvm/Support/raw_ostream.h" #include "gtest/gtest.h" using namespace clang; @@ -30,11 +33,12 @@ namespace { class PrintMatch : public MatchFinder::MatchCallback { SmallString<1024> Printed; unsigned NumFoundDecls; - bool SuppressUnwrittenScope; + std::function Printer; public: - explicit PrintMatch(bool suppressUnwrittenScope) - : NumFoundDecls(0), SuppressUnwrittenScope(suppressUnwrittenScope) {} + explicit PrintMatch( + std::function Printer) + : NumFoundDecls(0), Printer(std::move(Printer)) {} void run(const MatchFinder::MatchResult &Result) override { const NamedDecl *ND = Result.Nodes.getNodeAs("id"); @@ -45,9 +49,7 @@ public: return; llvm::raw_svector_ostream Out(Printed); - PrintingPolicy Policy = Result.Context->getPrintingPolicy(); - Policy.SuppressUnwrittenScope = SuppressUnwrittenScope; - ND->printQualifiedName(Out, Policy); + Printer(Out, ND); } StringRef getPrinted() const { @@ -59,12 +61,12 @@ public: } }; -::testing::AssertionResult -PrintedNamedDeclMatches(StringRef Code, const std::vector &Args, - bool SuppressUnwrittenScope, - const DeclarationMatcher &NodeMatch, - StringRef ExpectedPrinted, StringRef FileName) { - PrintMatch Printer(SuppressUnwrittenScope); +::testing::AssertionResult PrintedDeclMatches( + StringRef Code, const std::vector &Args, + const DeclarationMatcher &NodeMatch, StringRef ExpectedPrinted, + StringRef FileName, + std::function Print) { + PrintMatch Printer(std::move(Print)); MatchFinder Finder; Finder.addMatcher(NodeMatch, &Printer); std::unique_ptr Factory = @@ -91,6 +93,21 @@ PrintedNamedDeclMatches(StringRef Code, const std::vector &Args, return ::testing::AssertionSuccess(); } +::testing::AssertionResult +PrintedNamedDeclMatches(StringRef Code, const std::vector &Args, + bool SuppressUnwrittenScope, + const DeclarationMatcher &NodeMatch, + StringRef ExpectedPrinted, StringRef FileName) { + return PrintedDeclMatches(Code, Args, NodeMatch, ExpectedPrinted, FileName, + [=](llvm::raw_ostream &Out, const NamedDecl *ND) { + auto Policy = + ND->getASTContext().getPrintingPolicy(); + Policy.SuppressUnwrittenScope = + SuppressUnwrittenScope; + ND->printQualifiedName(Out, Policy); + }); +} + ::testing::AssertionResult PrintedNamedDeclCXX98Matches(StringRef Code, StringRef DeclName, StringRef ExpectedPrinted) { @@ -127,6 +144,17 @@ PrintedWrittenPropertyDeclObjCMatches(StringRef Code, StringRef DeclName, "input.m"); } +::testing::AssertionResult +PrintedNestedNameSpecifierMatches(StringRef Code, StringRef DeclName, + StringRef ExpectedPrinted) { + std::vector Args{"-std=c++11"}; + return PrintedDeclMatches(Code, Args, namedDecl(hasName(DeclName)).bind("id"), + ExpectedPrinted, "input.cc", + [](llvm::raw_ostream &Out, const NamedDecl *D) { + D->printNestedNameSpecifier(Out); + }); +} + } // unnamed namespace TEST(NamedDeclPrinter, TestNamespace1) { @@ -223,3 +251,21 @@ R"( "property", "Obj::property")); } + +TEST(NamedDeclPrinter, NestedNameSpecifierSimple) { + const char *Code = + R"( + namespace foo { namespace bar { void func(); } } +)"; + ASSERT_TRUE(PrintedNestedNameSpecifierMatches(Code, "func", "foo::bar::")); +} + +TEST(NamedDeclPrinter, NestedNameSpecifierTemplateArgs) { + const char *Code = + R"( + template struct vector; + template <> struct vector { int method(); }; +)"; + ASSERT_TRUE( + PrintedNestedNameSpecifierMatches(Code, "method", "vector::")); +} -- 2.40.0