[cfe-commits] r138960 - in /cfe/trunk: include/clang/Basic/SourceManager.h lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp lib/ARCMigrate/Transforms.cpp lib/ARCMigrate/Transforms.h test/ARCMT/cxx-rewrite.mm test/ARCMT/remove-statements.m

Argyrios Kyrtzidis akyrtzi at gmail.com
Thu Sep 1 13:53:18 PDT 2011


Author: akirtzidis
Date: Thu Sep  1 15:53:18 2011
New Revision: 138960

URL: http://llvm.org/viewvc/llvm-project?rev=138960&view=rev
Log:
[arcmt] Fix test/ARCMT/remove-statements.m regression due to
Objective-C method buffering(rdar://10056942)

Turned out the same issue existed for C++ inline methods.

Modified:
    cfe/trunk/include/clang/Basic/SourceManager.h
    cfe/trunk/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp
    cfe/trunk/lib/ARCMigrate/Transforms.cpp
    cfe/trunk/lib/ARCMigrate/Transforms.h
    cfe/trunk/test/ARCMT/cxx-rewrite.mm
    cfe/trunk/test/ARCMT/remove-statements.m

Modified: cfe/trunk/include/clang/Basic/SourceManager.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/SourceManager.h?rev=138960&r1=138959&r2=138960&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/SourceManager.h (original)
+++ cfe/trunk/include/clang/Basic/SourceManager.h Thu Sep  1 15:53:18 2011
@@ -1116,6 +1116,19 @@
   /// \returns true if LHS source location comes before RHS, false otherwise.
   bool isBeforeInTranslationUnit(SourceLocation LHS, SourceLocation RHS) const;
 
+  /// \brief Comparison function class.
+  class LocBeforeThanCompare : public std::binary_function<SourceLocation,
+                                                         SourceLocation, bool> {
+    SourceManager &SM;
+
+  public:
+    explicit LocBeforeThanCompare(SourceManager &SM) : SM(SM) { }
+
+    bool operator()(SourceLocation LHS, SourceLocation RHS) const {
+      return SM.isBeforeInTranslationUnit(LHS, RHS);
+    }
+  };
+
   /// \brief Determines the order of 2 source locations in the "source location
   /// address space".
   bool isBeforeInSLocAddrSpace(SourceLocation LHS, SourceLocation RHS) const {

Modified: cfe/trunk/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp?rev=138960&r1=138959&r2=138960&view=diff
==============================================================================
--- cfe/trunk/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp (original)
+++ cfe/trunk/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp Thu Sep  1 15:53:18 2011
@@ -22,25 +22,68 @@
 #include "Transforms.h"
 #include "Internals.h"
 #include "clang/AST/StmtVisitor.h"
+#include "clang/Basic/SourceManager.h"
 
 using namespace clang;
 using namespace arcmt;
 using namespace trans;
 
+static bool isEmptyARCMTMacroStatement(NullStmt *S,
+                                       std::vector<SourceLocation> &MacroLocs,
+                                       ASTContext &Ctx) {
+  if (!S->hasLeadingEmptyMacro())
+    return false;
+
+  SourceLocation SemiLoc = S->getSemiLoc();
+  if (SemiLoc.isInvalid() || SemiLoc.isMacroID())
+    return false;
+
+  if (MacroLocs.empty())
+    return false;
+
+  SourceManager &SM = Ctx.getSourceManager();
+  std::vector<SourceLocation>::iterator
+    I = std::upper_bound(MacroLocs.begin(), MacroLocs.end(), SemiLoc,
+                         SourceManager::LocBeforeThanCompare(SM));
+  --I;
+  SourceLocation
+      AfterMacroLoc = I->getFileLocWithOffset(getARCMTMacroName().size());
+  assert(AfterMacroLoc.isFileID());
+
+  if (AfterMacroLoc == SemiLoc)
+    return true;
+
+  int RelOffs = 0;
+  if (!SM.isInSameSLocAddrSpace(AfterMacroLoc, SemiLoc, &RelOffs))
+    return false;
+  if (RelOffs < 0)
+    return false;
+
+  // We make the reasonable assumption that a semicolon after 100 characters
+  // means that it is not the next token after our macro. If this assumption
+  // fails it is not critical, we will just fail to clear out, e.g., an empty
+  // 'if'.
+  if (RelOffs - getARCMTMacroName().size() > 100)
+    return false;
+
+  SourceLocation AfterMacroSemiLoc = findSemiAfterLocation(AfterMacroLoc, Ctx);
+  return AfterMacroSemiLoc == SemiLoc;
+}
+
 namespace {
 
 /// \brief Returns true if the statement became empty due to previous
 /// transformations.
 class EmptyChecker : public StmtVisitor<EmptyChecker, bool> {
   ASTContext &Ctx;
-  llvm::DenseSet<unsigned> &MacroLocs;
+  std::vector<SourceLocation> &MacroLocs;
 
 public:
-  EmptyChecker(ASTContext &ctx, llvm::DenseSet<unsigned> &macroLocs)
+  EmptyChecker(ASTContext &ctx, std::vector<SourceLocation> &macroLocs)
     : Ctx(ctx), MacroLocs(macroLocs) { }
 
   bool VisitNullStmt(NullStmt *S) {
-    return isMacroLoc(S->getLeadingEmptyMacroLoc());
+    return isEmptyARCMTMacroStatement(S, MacroLocs, Ctx);
   }
   bool VisitCompoundStmt(CompoundStmt *S) {
     if (S->body_empty())
@@ -102,23 +145,14 @@
       return false;
     return Visit(S->getSubStmt());
   }
-
-private:
-  bool isMacroLoc(SourceLocation loc) {
-    if (loc.isInvalid()) return false;
-    return MacroLocs.count(loc.getRawEncoding());
-  }
 };
 
 class EmptyStatementsRemover :
                             public RecursiveASTVisitor<EmptyStatementsRemover> {
   MigrationPass &Pass;
-  llvm::DenseSet<unsigned> &MacroLocs;
 
 public:
-  EmptyStatementsRemover(MigrationPass &pass,
-                         llvm::DenseSet<unsigned> &macroLocs)
-    : Pass(pass), MacroLocs(macroLocs) { }
+  EmptyStatementsRemover(MigrationPass &pass) : Pass(pass) { }
 
   bool TraverseStmtExpr(StmtExpr *E) {
     CompoundStmt *S = E->getSubStmt();
@@ -138,17 +172,12 @@
     return true;
   }
 
-  bool isMacroLoc(SourceLocation loc) {
-    if (loc.isInvalid()) return false;
-    return MacroLocs.count(loc.getRawEncoding());
-  }
-
   ASTContext &getContext() { return Pass.Ctx; }
 
 private:
   void check(Stmt *S) {
     if (!S) return;
-    if (EmptyChecker(Pass.Ctx, MacroLocs).Visit(S)) {
+    if (EmptyChecker(Pass.Ctx, Pass.ARCMTMacroLocs).Visit(S)) {
       Transaction Trans(Pass.TA);
       Pass.TA.removeStmt(S);
     }
@@ -157,8 +186,8 @@
 
 } // anonymous namespace
 
-static bool isBodyEmpty(CompoundStmt *body,
-                        ASTContext &Ctx, llvm::DenseSet<unsigned> &MacroLocs) {
+static bool isBodyEmpty(CompoundStmt *body, ASTContext &Ctx,
+                        std::vector<SourceLocation> &MacroLocs) {
   for (CompoundStmt::body_iterator
          I = body->body_begin(), E = body->body_end(); I != E; ++I)
     if (!EmptyChecker(Ctx, MacroLocs).Visit(*I))
@@ -167,8 +196,7 @@
   return true;
 }
 
-static void removeDeallocMethod(MigrationPass &pass,
-                                llvm::DenseSet<unsigned> &MacroLocs) {
+static void removeDeallocMethod(MigrationPass &pass) {
   ASTContext &Ctx = pass.Ctx;
   TransformActions &TA = pass.TA;
   DeclContext *DC = Ctx.getTranslationUnitDecl();
@@ -183,7 +211,7 @@
       ObjCMethodDecl *MD = *MI;
       if (MD->getMethodFamily() == OMF_dealloc) {
         if (MD->hasBody() &&
-            isBodyEmpty(MD->getCompoundBody(), Ctx, MacroLocs)) {
+            isBodyEmpty(MD->getCompoundBody(), Ctx, pass.ARCMTMacroLocs)) {
           Transaction Trans(TA);
           TA.remove(MD->getSourceRange());
         }
@@ -194,14 +222,9 @@
 }
 
 void trans::removeEmptyStatementsAndDealloc(MigrationPass &pass) {
-  llvm::DenseSet<unsigned> MacroLocs;
-  for (unsigned i = 0, e = pass.ARCMTMacroLocs.size(); i != e; ++i)
-    MacroLocs.insert(pass.ARCMTMacroLocs[i].getRawEncoding());
-
-  EmptyStatementsRemover(pass, MacroLocs)
-    .TraverseDecl(pass.Ctx.getTranslationUnitDecl());
+  EmptyStatementsRemover(pass).TraverseDecl(pass.Ctx.getTranslationUnitDecl());
 
-  removeDeallocMethod(pass, MacroLocs);
+  removeDeallocMethod(pass);
 
   for (unsigned i = 0, e = pass.ARCMTMacroLocs.size(); i != e; ++i) {
     Transaction Trans(pass.TA);

Modified: cfe/trunk/lib/ARCMigrate/Transforms.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ARCMigrate/Transforms.cpp?rev=138960&r1=138959&r2=138960&view=diff
==============================================================================
--- cfe/trunk/lib/ARCMigrate/Transforms.cpp (original)
+++ cfe/trunk/lib/ARCMigrate/Transforms.cpp Thu Sep  1 15:53:18 2011
@@ -91,6 +91,18 @@
 /// source location will be invalid.
 SourceLocation trans::findLocationAfterSemi(SourceLocation loc,
                                             ASTContext &Ctx) {
+  SourceLocation SemiLoc = findSemiAfterLocation(loc, Ctx);
+  if (SemiLoc.isInvalid())
+    return SourceLocation();
+  return SemiLoc.getFileLocWithOffset(1);
+}
+
+/// \brief \arg Loc is the end of a statement range. This returns the location
+/// of the semicolon following the statement.
+/// If no semicolon is found or the location is inside a macro, the returned
+/// source location will be invalid.
+SourceLocation trans::findSemiAfterLocation(SourceLocation loc,
+                                            ASTContext &Ctx) {
   SourceManager &SM = Ctx.getSourceManager();
   if (loc.isMacroID()) {
     if (!Lexer::isAtEndOfMacroExpansion(loc, SM, Ctx.getLangOptions()))
@@ -119,7 +131,7 @@
   if (tok.isNot(tok::semi))
     return SourceLocation();
 
-  return tok.getLocation().getFileLocWithOffset(1);
+  return tok.getLocation();
 }
 
 bool trans::hasSideEffects(Expr *E, ASTContext &Ctx) {

Modified: cfe/trunk/lib/ARCMigrate/Transforms.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ARCMigrate/Transforms.h?rev=138960&r1=138959&r2=138960&view=diff
==============================================================================
--- cfe/trunk/lib/ARCMigrate/Transforms.h (original)
+++ cfe/trunk/lib/ARCMigrate/Transforms.h Thu Sep  1 15:53:18 2011
@@ -54,6 +54,12 @@
 /// source location will be invalid.
 SourceLocation findLocationAfterSemi(SourceLocation loc, ASTContext &Ctx);
 
+/// \brief \arg Loc is the end of a statement range. This returns the location
+/// of the semicolon following the statement.
+/// If no semicolon is found or the location is inside a macro, the returned
+/// source location will be invalid.
+SourceLocation findSemiAfterLocation(SourceLocation loc, ASTContext &Ctx);
+
 bool hasSideEffects(Expr *E, ASTContext &Ctx);
 bool isGlobalVar(Expr *E);
 /// \brief Returns "nil" or "0" if 'nil' macro is not actually defined.

Modified: cfe/trunk/test/ARCMT/cxx-rewrite.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ARCMT/cxx-rewrite.mm?rev=138960&r1=138959&r2=138960&view=diff
==============================================================================
--- cfe/trunk/test/ARCMT/cxx-rewrite.mm (original)
+++ cfe/trunk/test/ARCMT/cxx-rewrite.mm Thu Sep  1 15:53:18 2011
@@ -14,6 +14,8 @@
         NSAutoreleasePool *pool = [NSAutoreleasePool new];
         [[[NSString string] retain] release];
         [pool drain];
+        if (s)
+          [s release];
     }
     ~foo(){ [s release]; }
 private:

Modified: cfe/trunk/test/ARCMT/remove-statements.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ARCMT/remove-statements.m?rev=138960&r1=138959&r2=138960&view=diff
==============================================================================
--- cfe/trunk/test/ARCMT/remove-statements.m (original)
+++ cfe/trunk/test/ARCMT/remove-statements.m Thu Sep  1 15:53:18 2011
@@ -1,7 +1,6 @@
 // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-nonfragile-abi -fsyntax-only -fobjc-arc -x objective-c %s.result
 // RUN: arcmt-test --args -triple x86_64-apple-darwin10 -fobjc-nonfragile-abi -fsyntax-only -x objective-c %s > %t
 // RUN: diff %t %s.result
-// XFAIL: *
 
 #include "Common.h"
 





More information about the cfe-commits mailing list