r372863 - [AST] Extract Decl::printNestedNameSpecifier helper from Decl::printQualifiedName

Ilya Biryukov via cfe-commits cfe-commits at lists.llvm.org
Wed Sep 25 06:09:10 PDT 2019


Author: ibiryukov
Date: Wed Sep 25 06:09:10 2019
New Revision: 372863

URL: http://llvm.org/viewvc/llvm-project?rev=372863&view=rev
Log:
[AST] Extract Decl::printNestedNameSpecifier helper from Decl::printQualifiedName

Summary:
To be used in clangd, e.g. in D66647.
Currently the alternative to this function is doing string manipulation on results of `printQualifiedName`, which is
hard-to-impossible to get right in presence of template arguments.

Reviewers: kadircet, aaron.ballman

Reviewed By: kadircet, aaron.ballman

Subscribers: aaron.ballman, usaxena95, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D67825

Modified:
    cfe/trunk/include/clang/AST/Decl.h
    cfe/trunk/lib/AST/Decl.cpp
    cfe/trunk/unittests/AST/NamedDeclPrinterTest.cpp

Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=372863&r1=372862&r2=372863&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Wed Sep 25 06:09:10 2019
@@ -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;
 

Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=372863&r1=372862&r2=372863&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Wed Sep 25 06:09:10 2019
@@ -1558,6 +1558,19 @@ void NamedDecl::printQualifiedName(raw_o
 
 void NamedDecl::printQualifiedName(raw_ostream &OS,
                                    const PrintingPolicy &P) const {
+  printNestedNameSpecifier(OS, P);
+  if (getDeclName() || isa<DecompositionDecl>(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 +1584,8 @@ void NamedDecl::printQualifiedName(raw_o
         Ctx = ID;
   }
 
-  if (Ctx->isFunctionOrMethod()) {
-    printName(OS);
+  if (Ctx->isFunctionOrMethod())
     return;
-  }
 
   using ContextsTy = SmallVector<const DeclContext *, 8>;
   ContextsTy Contexts;
@@ -1644,11 +1655,6 @@ void NamedDecl::printQualifiedName(raw_o
     }
     OS << "::";
   }
-
-  if (getDeclName() || isa<DecompositionDecl>(this))
-    OS << *this;
-  else
-    OS << "(anonymous)";
 }
 
 void NamedDecl::getNameForDiagnostic(raw_ostream &OS,

Modified: cfe/trunk/unittests/AST/NamedDeclPrinterTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/AST/NamedDeclPrinterTest.cpp?rev=372863&r1=372862&r2=372863&view=diff
==============================================================================
--- cfe/trunk/unittests/AST/NamedDeclPrinterTest.cpp (original)
+++ cfe/trunk/unittests/AST/NamedDeclPrinterTest.cpp Wed Sep 25 06:09:10 2019
@@ -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<void(llvm::raw_ostream &OS, const NamedDecl *)> Printer;
 
 public:
-  explicit PrintMatch(bool suppressUnwrittenScope)
-    : NumFoundDecls(0), SuppressUnwrittenScope(suppressUnwrittenScope) {}
+  explicit PrintMatch(
+      std::function<void(llvm::raw_ostream &OS, const NamedDecl *)> Printer)
+      : NumFoundDecls(0), Printer(std::move(Printer)) {}
 
   void run(const MatchFinder::MatchResult &Result) override {
     const NamedDecl *ND = Result.Nodes.getNodeAs<NamedDecl>("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<std::string> &Args,
-                        bool SuppressUnwrittenScope,
-                        const DeclarationMatcher &NodeMatch,
-                        StringRef ExpectedPrinted, StringRef FileName) {
-  PrintMatch Printer(SuppressUnwrittenScope);
+::testing::AssertionResult PrintedDeclMatches(
+    StringRef Code, const std::vector<std::string> &Args,
+    const DeclarationMatcher &NodeMatch, StringRef ExpectedPrinted,
+    StringRef FileName,
+    std::function<void(llvm::raw_ostream &, const NamedDecl *)> Print) {
+  PrintMatch Printer(std::move(Print));
   MatchFinder Finder;
   Finder.addMatcher(NodeMatch, &Printer);
   std::unique_ptr<FrontendActionFactory> Factory =
@@ -92,6 +94,21 @@ PrintedNamedDeclMatches(StringRef Code,
 }
 
 ::testing::AssertionResult
+PrintedNamedDeclMatches(StringRef Code, const std::vector<std::string> &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) {
   std::vector<std::string> Args(1, "-std=c++98");
@@ -127,6 +144,17 @@ PrintedWrittenPropertyDeclObjCMatches(St
                                  "input.m");
 }
 
+::testing::AssertionResult
+PrintedNestedNameSpecifierMatches(StringRef Code, StringRef DeclName,
+                                  StringRef ExpectedPrinted) {
+  std::vector<std::string> 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 <class T> struct vector;
+        template <> struct vector<int> { int method(); };
+)";
+  ASSERT_TRUE(
+      PrintedNestedNameSpecifierMatches(Code, "method", "vector<int>::"));
+}




More information about the cfe-commits mailing list