]> granicus.if.org Git - clang/commitdiff
[DeclPrinter] Allow printing fully qualified name of function declaration
authorSerge Pavlov <sepavloff@gmail.com>
Thu, 23 Nov 2017 05:38:20 +0000 (05:38 +0000)
committerSerge Pavlov <sepavloff@gmail.com>
Thu, 23 Nov 2017 05:38:20 +0000 (05:38 +0000)
When requesting a tooltip for a function call in an IDE, the fully
qualified name helps to remove ambiguity in the function signature.

Patch by Nikolai Kosjar!

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

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@318896 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/PrettyPrinter.h
lib/AST/DeclPrinter.cpp
unittests/AST/DeclPrinterTest.cpp

index 2c0564335b736a23252a9662f989910aa26449cc..e831b903cbae6985633307c1a4707df957927a12 100644 (file)
@@ -51,7 +51,8 @@ struct PrintingPolicy {
       TerseOutput(false), PolishForDeclaration(false),
       Half(LO.Half), MSWChar(LO.MicrosoftExt && !LO.WChar),
       IncludeNewlines(true), MSVCFormatting(false),
-      ConstantsAsWritten(false), SuppressImplicitBase(false) { }
+      ConstantsAsWritten(false), SuppressImplicitBase(false),
+      FullyQualifiedName(false) { }
 
   /// Adjust this printing policy for cases where it's known that we're
   /// printing C++ code (for instance, if AST dumping reaches a C++-only
@@ -220,6 +221,10 @@ struct PrintingPolicy {
 
   /// When true, don't print the implicit 'self' or 'this' expressions.
   bool SuppressImplicitBase : 1;
+
+  /// When true, print the fully qualified name of function declarations.
+  /// This is the opposite of SuppressScope and thus overrules it.
+  bool FullyQualifiedName : 1;
 };
 
 } // end namespace clang
index b810dd74738473399006298da45a0a6410386ced..b792c5920a5536cdc2b5b56d281b54f3ff678bdc 100644 (file)
@@ -580,13 +580,19 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
   PrintingPolicy SubPolicy(Policy);
   SubPolicy.SuppressSpecifiers = false;
   std::string Proto;
-  if (!Policy.SuppressScope) {
-    if (const NestedNameSpecifier *NS = D->getQualifier()) {
-      llvm::raw_string_ostream OS(Proto);
-      NS->print(OS, Policy);
+
+  if (Policy.FullyQualifiedName) {
+    Proto += D->getQualifiedNameAsString();
+  } else {
+    if (!Policy.SuppressScope) {
+      if (const NestedNameSpecifier *NS = D->getQualifier()) {
+        llvm::raw_string_ostream OS(Proto);
+        NS->print(OS, Policy);
+      }
     }
+    Proto += D->getNameInfo().getAsString();
   }
-  Proto += D->getNameInfo().getAsString();
+
   if (GuideDecl)
     Proto = GuideDecl->getDeducedTemplate()->getDeclName().getAsString();
   if (const TemplateArgumentList *TArgs = D->getTemplateSpecializationArgs()) {
index dc1977d87689bac9c23ecf257c67f0c3cdf35f52..4cf8bce20ea29da9ddc967495b434f1a0ea54f1d 100644 (file)
@@ -104,15 +104,17 @@ PrintedDeclMatches(StringRef Code, const std::vector<std::string> &Args,
   return ::testing::AssertionSuccess();
 }
 
-::testing::AssertionResult PrintedDeclCXX98Matches(StringRef Code,
-                                                   StringRef DeclName,
-                                                   StringRef ExpectedPrinted) {
+::testing::AssertionResult
+PrintedDeclCXX98Matches(StringRef Code, StringRef DeclName,
+                        StringRef ExpectedPrinted,
+                        PrintingPolicyModifier PolicyModifier = nullptr) {
   std::vector<std::string> Args(1, "-std=c++98");
   return PrintedDeclMatches(Code,
                             Args,
                             namedDecl(hasName(DeclName)).bind("id"),
                             ExpectedPrinted,
-                            "input.cc");
+                            "input.cc",
+                            PolicyModifier);
 }
 
 ::testing::AssertionResult
@@ -350,6 +352,47 @@ TEST(DeclPrinter, TestFunctionDecl1) {
     "void A()"));
 }
 
+TEST(DeclPrinter, TestFreeFunctionDecl_FullyQualifiedName) {
+    ASSERT_TRUE(PrintedDeclCXX98Matches(
+      "void A();",
+      "A",
+      "void A()",
+      [](PrintingPolicy &Policy){ Policy.FullyQualifiedName = true; }));
+}
+
+TEST(DeclPrinter, TestFreeFunctionDeclInNamespace_FullyQualifiedName) {
+    ASSERT_TRUE(PrintedDeclCXX98Matches(
+      "namespace X { void A(); };",
+      "A",
+      "void X::A()",
+      [](PrintingPolicy &Policy){ Policy.FullyQualifiedName = true; }));
+}
+
+TEST(DeclPrinter, TestMemberFunction_FullyQualifiedName) {
+    ASSERT_TRUE(PrintedDeclCXX98Matches(
+      "struct X { void A(); };",
+      "A",
+      "void X::A()",
+      [](PrintingPolicy &Policy){ Policy.FullyQualifiedName = true; }));
+}
+
+TEST(DeclPrinter, TestMemberFunctionInNamespace_FullyQualifiedName) {
+    ASSERT_TRUE(PrintedDeclCXX98Matches(
+      "namespace Z { struct X { void A(); }; }",
+      "A",
+      "void Z::X::A()",
+      [](PrintingPolicy &Policy){ Policy.FullyQualifiedName = true; }));
+}
+
+TEST(DeclPrinter, TestMemberFunctionOutside_FullyQualifiedName) {
+    ASSERT_TRUE(PrintedDeclCXX98Matches(
+      "struct X { void A(); };"
+       "void X::A() {}",
+      functionDecl(hasName("A"), isDefinition()).bind("id"),
+      "void X::A()",
+      [](PrintingPolicy &Policy){ Policy.FullyQualifiedName = true; }));
+}
+
 TEST(DeclPrinter, TestFunctionDecl2) {
   ASSERT_TRUE(PrintedDeclCXX98Matches(
     "void A() {}",