khuttun created this revision.
khuttun added reviewers: sepavloff, alexfh.
Herald added a subscriber: cfe-commits.

The purpose of this addition is to be able to write AST matchers that match 
class template member functions by fully qualified name, without the need to 
explicitly specify the template arguments in the name.

For example, to match the call to `S::f` here

  template <typename T>
  struct S {
    void f();
  };
  
  void foo() {
    S<int> s;
    s.f();
  }

the matcher currently needs to specify the template arguments:

  callExpr(callee(functionDecl(hasName("::S<int>::f"))))

With the help of this change, it's possible to create a version of `hasName` 
that ignores the template arguments. The matcher could then be written as

  callExpr(callee(functionDecl(hasNameIgnoringTemplateArgs("::S::f"))))

The motivation for this change is to be able to add checking of class template 
member functions to clang-tidy checker bugprone-unused-return-value: 
http://clang.llvm.org/extra/clang-tidy/checks/bugprone-unused-return-value.html

The discussion about this can be found in the code review for the checker: 
https://reviews.llvm.org/D41655?id=130461#inline-374438


Repository:
  rC Clang

https://reviews.llvm.org/D45161

Files:
  include/clang/AST/PrettyPrinter.h
  lib/AST/TypePrinter.cpp
  unittests/AST/NamedDeclPrinterTest.cpp

Index: unittests/AST/NamedDeclPrinterTest.cpp
===================================================================
--- unittests/AST/NamedDeclPrinterTest.cpp
+++ unittests/AST/NamedDeclPrinterTest.cpp
@@ -28,14 +28,19 @@
 
 namespace {
 
+using PrintingPolicyModifier = void (*)(PrintingPolicy &policy);
+
 class PrintMatch : public MatchFinder::MatchCallback {
   SmallString<1024> Printed;
   unsigned NumFoundDecls;
   bool SuppressUnwrittenScope;
+  PrintingPolicyModifier PolicyModifier;
 
 public:
-  explicit PrintMatch(bool suppressUnwrittenScope)
-    : NumFoundDecls(0), SuppressUnwrittenScope(suppressUnwrittenScope) {}
+  explicit PrintMatch(bool suppressUnwrittenScope,
+                      PrintingPolicyModifier PolicyModifier)
+      : NumFoundDecls(0), SuppressUnwrittenScope(suppressUnwrittenScope),
+        PolicyModifier(PolicyModifier) {}
 
   void run(const MatchFinder::MatchResult &Result) override {
     const NamedDecl *ND = Result.Nodes.getNodeAs<NamedDecl>("id");
@@ -48,6 +53,8 @@
     llvm::raw_svector_ostream Out(Printed);
     PrintingPolicy Policy = Result.Context->getPrintingPolicy();
     Policy.SuppressUnwrittenScope = SuppressUnwrittenScope;
+    if (PolicyModifier)
+      PolicyModifier(Policy);
     ND->printQualifiedName(Out, Policy);
   }
 
@@ -64,8 +71,9 @@
 PrintedNamedDeclMatches(StringRef Code, const std::vector<std::string> &Args,
                         bool SuppressUnwrittenScope,
                         const DeclarationMatcher &NodeMatch,
-                        StringRef ExpectedPrinted, StringRef FileName) {
-  PrintMatch Printer(SuppressUnwrittenScope);
+                        StringRef ExpectedPrinted, StringRef FileName,
+                        PrintingPolicyModifier PolicyModifier) {
+  PrintMatch Printer(SuppressUnwrittenScope, PolicyModifier);
   MatchFinder Finder;
   Finder.addMatcher(NodeMatch, &Printer);
   std::unique_ptr<FrontendActionFactory> Factory =
@@ -94,26 +102,30 @@
 
 ::testing::AssertionResult
 PrintedNamedDeclCXX98Matches(StringRef Code, StringRef DeclName,
-                             StringRef ExpectedPrinted) {
+                             StringRef ExpectedPrinted,
+                             PrintingPolicyModifier PolicyModifier = nullptr) {
   std::vector<std::string> Args(1, "-std=c++98");
   return PrintedNamedDeclMatches(Code,
                                  Args,
                                  /*SuppressUnwrittenScope*/ false,
                                  namedDecl(hasName(DeclName)).bind("id"),
                                  ExpectedPrinted,
-                                 "input.cc");
+                                 "input.cc",
+                                 PolicyModifier);
 }
 
 ::testing::AssertionResult
-PrintedWrittenNamedDeclCXX11Matches(StringRef Code, StringRef DeclName,
-                                    StringRef ExpectedPrinted) {
+PrintedWrittenNamedDeclCXX11Matches(
+    StringRef Code, StringRef DeclName, StringRef ExpectedPrinted,
+    PrintingPolicyModifier PolicyModifier = nullptr) {
   std::vector<std::string> Args(1, "-std=c++11");
   return PrintedNamedDeclMatches(Code,
                                  Args,
                                  /*SuppressUnwrittenScope*/ true,
                                  namedDecl(hasName(DeclName)).bind("id"),
                                  ExpectedPrinted,
-                                 "input.cc");
+                                 "input.cc",
+                                 PolicyModifier);
 }
 
 } // unnamed namespace
@@ -180,3 +192,20 @@
     "A",
     "X::A"));
 }
+
+TEST(NamedDeclPrinter, TestClassTemplateMemberFunction) {
+  ASSERT_TRUE(PrintedNamedDeclCXX98Matches(
+    "template <typename T> struct X { void A(); };"
+    "void Y() { X<int> x; x.A(); }",
+    "::X<int>::A",
+    "X<int>::A"));
+}
+
+TEST(NamedDeclPrinter, TestClassTemplateMemberFunction_SuppressTemplateArgs) {
+  ASSERT_TRUE(PrintedNamedDeclCXX98Matches(
+    "template <typename T> struct X { void A(); };"
+    "void Y() { X<int> x; x.A(); }",
+    "::X<int>::A",
+    "X::A",
+    [](PrintingPolicy &Policy){ Policy.SuppressTemplateArgs = true; }));
+}
Index: lib/AST/TypePrinter.cpp
===================================================================
--- lib/AST/TypePrinter.cpp
+++ lib/AST/TypePrinter.cpp
@@ -1538,6 +1538,9 @@
 template<typename TA>
 static void printTo(raw_ostream &OS, ArrayRef<TA> Args,
                     const PrintingPolicy &Policy, bool SkipBrackets) {
+  if (Policy.SuppressTemplateArgs)
+    return;
+
   const char *Comma = Policy.MSVCFormatting ? "," : ", ";
   if (!SkipBrackets)
     OS << '<';
Index: include/clang/AST/PrettyPrinter.h
===================================================================
--- include/clang/AST/PrettyPrinter.h
+++ include/clang/AST/PrettyPrinter.h
@@ -52,7 +52,7 @@
       Half(LO.Half), MSWChar(LO.MicrosoftExt && !LO.WChar),
       IncludeNewlines(true), MSVCFormatting(false),
       ConstantsAsWritten(false), SuppressImplicitBase(false),
-      FullyQualifiedName(false) { }
+      FullyQualifiedName(false), SuppressTemplateArgs(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
@@ -225,6 +225,9 @@
   /// When true, print the fully qualified name of function declarations.
   /// This is the opposite of SuppressScope and thus overrules it.
   bool FullyQualifiedName : 1;
+
+  /// When true, suppresses printing template arguments
+  bool SuppressTemplateArgs : 1;
 };
 
 } // end namespace clang
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
  • [PATCH] D45161: [AST] Add n... Kalle Huttunen via Phabricator via cfe-commits

Reply via email to