r316631 - Allow StmtPrinter to supress implicit 'this' and 'self' base expressions

Alex Lorenz via cfe-commits cfe-commits at lists.llvm.org
Wed Oct 25 17:56:54 PDT 2017


Author: arphaman
Date: Wed Oct 25 17:56:54 2017
New Revision: 316631

URL: http://llvm.org/viewvc/llvm-project?rev=316631&view=rev
Log:
Allow StmtPrinter to supress implicit 'this' and 'self' base expressions

This will be useful for certain refactoring actions.

rdar://34202062

Modified:
    cfe/trunk/include/clang/AST/PrettyPrinter.h
    cfe/trunk/lib/AST/StmtPrinter.cpp
    cfe/trunk/unittests/AST/StmtPrinterTest.cpp

Modified: cfe/trunk/include/clang/AST/PrettyPrinter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/PrettyPrinter.h?rev=316631&r1=316630&r2=316631&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/PrettyPrinter.h (original)
+++ cfe/trunk/include/clang/AST/PrettyPrinter.h Wed Oct 25 17:56:54 2017
@@ -51,7 +51,7 @@ struct PrintingPolicy {
       TerseOutput(false), PolishForDeclaration(false),
       Half(LO.Half), MSWChar(LO.MicrosoftExt && !LO.WChar),
       IncludeNewlines(true), MSVCFormatting(false),
-      ConstantsAsWritten(false) { }
+      ConstantsAsWritten(false), SuppressImplicitBase(false) { }
 
   /// \brief Adjust this printing policy for cases where it's known that
   /// we're printing C++ code (for instance, if AST dumping reaches a
@@ -218,7 +218,10 @@ struct PrintingPolicy {
   /// 0x10
   /// 2.5e3
   /// \endcode
-  bool ConstantsAsWritten;
+  bool ConstantsAsWritten : 1;
+
+  /// \brief When true, don't print the implicit 'self' or 'this' expressions.
+  bool SuppressImplicitBase : 1;
 };
 
 } // end namespace clang

Modified: cfe/trunk/lib/AST/StmtPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtPrinter.cpp?rev=316631&r1=316630&r2=316631&view=diff
==============================================================================
--- cfe/trunk/lib/AST/StmtPrinter.cpp (original)
+++ cfe/trunk/lib/AST/StmtPrinter.cpp Wed Oct 25 17:56:54 2017
@@ -1346,10 +1346,25 @@ void StmtPrinter::VisitUnresolvedLookupE
         OS, Node->template_arguments(), Policy);
 }
 
+static bool isImplicitSelf(const Expr *E) {
+  if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
+    if (const ImplicitParamDecl *PD =
+            dyn_cast<ImplicitParamDecl>(DRE->getDecl())) {
+      if (PD->getParameterKind() == ImplicitParamDecl::ObjCSelf &&
+          DRE->getLocStart().isInvalid())
+        return true;
+    }
+  }
+  return false;
+}
+
 void StmtPrinter::VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node) {
   if (Node->getBase()) {
-    PrintExpr(Node->getBase());
-    OS << (Node->isArrow() ? "->" : ".");
+    if (!Policy.SuppressImplicitBase ||
+        !isImplicitSelf(Node->getBase()->IgnoreImpCasts())) {
+      PrintExpr(Node->getBase());
+      OS << (Node->isArrow() ? "->" : ".");
+    }
   }
   OS << *Node->getDecl();
 }
@@ -1670,16 +1685,25 @@ void StmtPrinter::VisitCallExpr(CallExpr
   PrintCallArgs(Call);
   OS << ")";
 }
+
+static bool isImplicitThis(const Expr *E) {
+  if (const auto *TE = dyn_cast<CXXThisExpr>(E))
+    return TE->isImplicit();
+  return false;
+}
+
 void StmtPrinter::VisitMemberExpr(MemberExpr *Node) {
-  // FIXME: Suppress printing implicit bases (like "this")
-  PrintExpr(Node->getBase());
+  if (!Policy.SuppressImplicitBase || !isImplicitThis(Node->getBase())) {
+    PrintExpr(Node->getBase());
 
-  MemberExpr *ParentMember = dyn_cast<MemberExpr>(Node->getBase());
-  FieldDecl  *ParentDecl   = ParentMember
-    ? dyn_cast<FieldDecl>(ParentMember->getMemberDecl()) : nullptr;
+    MemberExpr *ParentMember = dyn_cast<MemberExpr>(Node->getBase());
+    FieldDecl *ParentDecl =
+        ParentMember ? dyn_cast<FieldDecl>(ParentMember->getMemberDecl())
+                     : nullptr;
 
-  if (!ParentDecl || !ParentDecl->isAnonymousStructOrUnion())
-    OS << (Node->isArrow() ? "->" : ".");
+    if (!ParentDecl || !ParentDecl->isAnonymousStructOrUnion())
+      OS << (Node->isArrow() ? "->" : ".");
+  }
 
   if (FieldDecl *FD = dyn_cast<FieldDecl>(Node->getMemberDecl()))
     if (FD->isAnonymousStructOrUnion())

Modified: cfe/trunk/unittests/AST/StmtPrinterTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/AST/StmtPrinterTest.cpp?rev=316631&r1=316630&r2=316631&view=diff
==============================================================================
--- cfe/trunk/unittests/AST/StmtPrinterTest.cpp (original)
+++ cfe/trunk/unittests/AST/StmtPrinterTest.cpp Wed Oct 25 17:56:54 2017
@@ -31,18 +31,26 @@ using namespace tooling;
 
 namespace {
 
-void PrintStmt(raw_ostream &Out, const ASTContext *Context, const Stmt *S) {
+using PolicyAdjusterType =
+    Optional<llvm::function_ref<void(PrintingPolicy &Policy)>>;
+
+void PrintStmt(raw_ostream &Out, const ASTContext *Context, const Stmt *S,
+               PolicyAdjusterType PolicyAdjuster) {
   assert(S != nullptr && "Expected non-null Stmt");
   PrintingPolicy Policy = Context->getPrintingPolicy();
+  if (PolicyAdjuster)
+    (*PolicyAdjuster)(Policy);
   S->printPretty(Out, /*Helper*/ nullptr, Policy);
 }
 
 class PrintMatch : public MatchFinder::MatchCallback {
   SmallString<1024> Printed;
   unsigned NumFoundStmts;
+  PolicyAdjusterType PolicyAdjuster;
 
 public:
-  PrintMatch() : NumFoundStmts(0) {}
+  PrintMatch(PolicyAdjusterType PolicyAdjuster)
+      : NumFoundStmts(0), PolicyAdjuster(PolicyAdjuster) {}
 
   void run(const MatchFinder::MatchResult &Result) override {
     const Stmt *S = Result.Nodes.getNodeAs<Stmt>("id");
@@ -53,7 +61,7 @@ public:
       return;
 
     llvm::raw_svector_ostream Out(Printed);
-    PrintStmt(Out, Result.Context, S);
+    PrintStmt(Out, Result.Context, S, PolicyAdjuster);
   }
 
   StringRef getPrinted() const {
@@ -68,9 +76,10 @@ public:
 template <typename T>
 ::testing::AssertionResult
 PrintedStmtMatches(StringRef Code, const std::vector<std::string> &Args,
-                   const T &NodeMatch, StringRef ExpectedPrinted) {
+                   const T &NodeMatch, StringRef ExpectedPrinted,
+                   PolicyAdjusterType PolicyAdjuster = None) {
 
-  PrintMatch Printer;
+  PrintMatch Printer(PolicyAdjuster);
   MatchFinder Finder;
   Finder.addMatcher(NodeMatch, &Printer);
   std::unique_ptr<FrontendActionFactory> Factory(
@@ -122,11 +131,13 @@ PrintedStmtCXX98Matches(StringRef Code,
 
 ::testing::AssertionResult
 PrintedStmtCXX11Matches(StringRef Code, const StatementMatcher &NodeMatch,
-                        StringRef ExpectedPrinted) {
+                        StringRef ExpectedPrinted,
+                        PolicyAdjusterType PolicyAdjuster = None) {
   std::vector<std::string> Args;
   Args.push_back("-std=c++11");
   Args.push_back("-Wno-unused-value");
-  return PrintedStmtMatches(Code, Args, NodeMatch, ExpectedPrinted);
+  return PrintedStmtMatches(Code, Args, NodeMatch, ExpectedPrinted,
+                            PolicyAdjuster);
 }
 
 ::testing::AssertionResult PrintedStmtMSMatches(
@@ -146,6 +157,17 @@ PrintedStmtCXX11Matches(StringRef Code,
                             ExpectedPrinted);
 }
 
+::testing::AssertionResult
+PrintedStmtObjCMatches(StringRef Code, const StatementMatcher &NodeMatch,
+                       StringRef ExpectedPrinted,
+                       PolicyAdjusterType PolicyAdjuster = None) {
+  std::vector<std::string> Args;
+  Args.push_back("-ObjC");
+  Args.push_back("-fobjc-runtime=macosx-10.12.0");
+  return PrintedStmtMatches(Code, Args, NodeMatch, ExpectedPrinted,
+                            PolicyAdjuster);
+}
+
 } // unnamed namespace
 
 TEST(StmtPrinter, TestIntegerLiteral) {
@@ -214,3 +236,41 @@ TEST(StmtPrinter, TestCXXConversionDeclE
     "(a & b)"));
     // WRONG; Should be: (a & b).operator void *()
 }
+
+TEST(StmtPrinter, TestNoImplicitBases) {
+  const char *CPPSource = R"(
+class A {
+  int field;
+  int member() { return field; }
+};
+)";
+  // No implicit 'this'.
+  ASSERT_TRUE(PrintedStmtCXX11Matches(
+      CPPSource, memberExpr(anything()).bind("id"), "field",
+      PolicyAdjusterType(
+          [](PrintingPolicy &PP) { PP.SuppressImplicitBase = true; })));
+  // Print implicit 'this'.
+  ASSERT_TRUE(PrintedStmtCXX11Matches(
+      CPPSource, memberExpr(anything()).bind("id"), "this->field"));
+
+  const char *ObjCSource = R"(
+ at interface I {
+   int ivar;
+}
+ at end
+ at implementation I
+- (int) method {
+  return ivar;
+}
+ at end
+      )";
+  // No implicit 'self'.
+  ASSERT_TRUE(PrintedStmtObjCMatches(ObjCSource, returnStmt().bind("id"),
+                                     "return ivar;\n",
+                                     PolicyAdjusterType([](PrintingPolicy &PP) {
+                                       PP.SuppressImplicitBase = true;
+                                     })));
+  // Print implicit 'self'.
+  ASSERT_TRUE(PrintedStmtObjCMatches(ObjCSource, returnStmt().bind("id"),
+                                     "return self->ivar;\n"));
+}




More information about the cfe-commits mailing list