Changes based on review.

  - Include file sorted.
  - Order of comparion with constants fixed.
  - CHECK line fixed.
  - Addressed the question when macro caller is a macro id.
  - Added more testcases.

Hi klimek, revane,

http://llvm-reviews.chandlerc.com/D549

CHANGE SINCE LAST DIFF
  http://llvm-reviews.chandlerc.com/D549?vs=1307&id=1310#toc

Files:
  cpp11-migrate/UseNullptr/NullptrActions.cpp
  test/cpp11-migrate/UseNullptr/basic.cpp
  test/cpp11-migrate/UseNullptr/macros.cpp
Index: cpp11-migrate/UseNullptr/NullptrActions.cpp
===================================================================
--- cpp11-migrate/UseNullptr/NullptrActions.cpp
+++ cpp11-migrate/UseNullptr/NullptrActions.cpp
@@ -20,13 +20,15 @@
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/RecursiveASTVisitor.h"
 
+#include "clang/Lex/Lexer.h"
+
 using namespace clang::ast_matchers;
 using namespace clang::tooling;
 using namespace clang;
 
 namespace {
 
-/// \brief Replaces the provided range with the text "nullptr", but only if 
+/// \brief Replaces the provided range with the text "nullptr", but only if
 /// the start and end location are both in main file.
 /// Returns true if and only if a replacement was made.
 bool ReplaceWithNullptr(tooling::Replacements &Replace, SourceManager &SM,
@@ -114,13 +116,32 @@
   const CastExpr *Cast = Result.Nodes.getNodeAs<CastExpr>(ImplicitCastNode);
   if (Cast) {
     const Expr *E = Cast->IgnoreParenImpCasts();
-
     SourceLocation StartLoc = E->getLocStart();
     SourceLocation EndLoc = E->getLocEnd();
 
-    // If the start/end location is a macro, get the expansion location.
-    StartLoc = SM.getFileLoc(StartLoc);
-    EndLoc = SM.getFileLoc(EndLoc);
+    // If the start/end location is a macro argument expansion, get the
+    // expansion location. If its a macro body expansion, check to see if its
+    // coming from a macro called NULL.
+    if (SM.isMacroArgExpansion(StartLoc) && SM.isMacroArgExpansion(EndLoc)) {
+      StartLoc = SM.getFileLoc(StartLoc);
+      EndLoc = SM.getFileLoc(EndLoc);
+    } else if (SM.isMacroBodyExpansion(StartLoc) &&
+               SM.isMacroBodyExpansion(EndLoc)) {
+      llvm::StringRef ImmediateMacroName = clang::Lexer::getImmediateMacroName(
+          StartLoc, SM, Result.Context->getLangOpts());
+      if (ImmediateMacroName != "NULL")
+        return;
+
+      SourceLocation MacroCallerStartLoc =
+          SM.getImmediateMacroCallerLoc(StartLoc);
+      SourceLocation MacroCallerEndLoc = SM.getImmediateMacroCallerLoc(EndLoc);
+
+      if (MacroCallerStartLoc.isFileID() && MacroCallerEndLoc.isFileID()) {
+        StartLoc = SM.getFileLoc(StartLoc);
+        EndLoc = SM.getFileLoc(EndLoc);
+      } else
+        return;
+    }
 
     AcceptedChanges +=
         ReplaceWithNullptr(Replace, SM, StartLoc, EndLoc) ? 1 : 0;
Index: test/cpp11-migrate/UseNullptr/basic.cpp
===================================================================
--- test/cpp11-migrate/UseNullptr/basic.cpp
+++ test/cpp11-migrate/UseNullptr/basic.cpp
@@ -8,6 +8,7 @@
 
 const unsigned int g_null = 0;
 #define NULL 0
+// CHECK: #define NULL 0
 
 void test_assignment() {
   int *p1 = 0;
@@ -179,32 +180,6 @@
   // CHECK: return g_null;
 }
 
-// Test function-like macros where the parameter to the macro (expression)
-// results in a nullptr.
-void __dummy_assert_fail() {}
-
-void test_function_like_macro1() {
-  // This tests that the CastSequenceVisitor is working properly.
-#define my_assert(expr) \
-  ((expr) ? static_cast<void>(expr) : __dummy_assert_fail())
-
-  int *p;
-  my_assert(p != 0);
-  // CHECK: my_assert(p != nullptr);
-#undef my_assert
-}
-
-void test_function_like_macro2() {
-  // This tests that the implicit cast is working properly.
-#define my_macro(expr) \
-  (expr)
-
-  int *p;
-  my_macro(p != 0);
-  // CHECK: my_macro(p != nullptr);
-#undef my_macro
-}
-
 // Test parentheses expressions resulting in a nullptr.
 int *test_parentheses_expression1() {
   return(0);
Index: test/cpp11-migrate/UseNullptr/macros.cpp
===================================================================
--- /dev/null
+++ test/cpp11-migrate/UseNullptr/macros.cpp
@@ -0,0 +1,93 @@
+// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
+// RUN: cpp11-migrate -use-nullptr %t.cpp -- -I %S
+// RUN: FileCheck -input-file=%t.cpp %s
+
+#define NULL 0
+// CHECK: #define NULL 0
+
+void dummy(int*) {}
+void side_effect() {}
+
+#define MACRO_EXPANSION_HAS_NULL \
+  void foo() { \
+    dummy(0); \
+    dummy(NULL); \
+    side_effect(); \
+  }
+  // CHECK: void foo() { \
+  // CHECK-NEXT:   dummy(0); \
+  // CHECK-NEXT:   dummy(NULL); \
+
+MACRO_EXPANSION_HAS_NULL;
+// CHECK: MACRO_EXPANSION_HAS_NULL;
+#undef MACRO_EXPANSION_HAS_NULL
+
+
+void test_macro_expansion1() {
+#define MACRO_EXPANSION_HAS_NULL \
+  dummy(NULL); \
+  side_effect();
+  // CHECK: dummy(NULL); \
+  // CHECK-NEXT: side_effect();
+
+  MACRO_EXPANSION_HAS_NULL;
+  // CHECK: MACRO_EXPANSION_HAS_NULL;
+
+#undef MACRO_EXPANSION_HAS_NULL
+}
+
+void test_macro_expansion2() {
+#define MACRO_EXPANSION_HAS_NULL \
+  dummy(NULL); \
+  side_effect();
+  // CHECK: dummy(NULL); \
+  // CHECK-NEXT: side_effect();
+
+#define OUTER_MACRO \
+  MACRO_EXPANSION_HAS_NULL; \
+  side_effect();
+
+  OUTER_MACRO;
+  // CHECK: OUTER_MACRO;
+
+#undef OUTER_MACRO
+#undef MACRO_EXPANSION_HAS_NULL
+}
+
+void test_macro_expansion3() {
+#define MY_NULL NULL
+  // TODO: Eventually we should fix the transform to detect cases like this so
+  // that we can replace MY_NULL with nullptr.
+  int *p = MY_NULL;
+  // CHECK: int *p = MY_NULL;
+#undef MY_NULL
+}
+
+// Test function-like macros where the parameter to the macro (expression)
+// results in a nullptr.
+void __dummy_assert_fail() {}
+
+void test_function_like_macro1() {
+  // This tests that the CastSequenceVisitor is working properly.
+#define my_assert(expr) \
+  ((expr) ? static_cast<void>(expr) : __dummy_assert_fail())
+  // CHECK: ((expr) ? static_cast<void>(expr) : __dummy_assert_fail())
+
+  int *p;
+  my_assert(p != 0);
+  // CHECK: my_assert(p != nullptr);
+#undef my_assert
+}
+
+void test_function_like_macro2() {
+  // This tests that the implicit cast is working properly.
+#define my_macro(expr) \
+  (expr)
+
+  int *p;
+  my_macro(p != 0);
+  // CHECK: my_macro(p != nullptr);
+#undef my_macro
+}
+
+
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to