[clang-tools-extra] r178243 - Allow users to specify NULL like macros to be replaced

Tareq A. Siraj tareq.a.sriaj at intel.com
Thu Mar 28 09:06:59 PDT 2013


Author: tasiraj
Date: Thu Mar 28 11:06:59 2013
New Revision: 178243

URL: http://llvm.org/viewvc/llvm-project?rev=178243&view=rev
Log:
Allow users to specify NULL like macros to be replaced

-use-nullptr only replaced macro named NULL and ignored any user defined
macros that behaved like NULL. This patch introduces -user-null-macros
command line option to let users specify their custom NULL like macros.

- Added a -user-null-macros command line option that takes a
  comma-separated list of user-defined macros to be replaced when using
  the -use-nullptr transform.
- Added documentation.
- Updated testcase to reflect current behavior.
- Whitespace fixes.

Reviewers: revane, klimek, gribozavr


Modified:
    clang-tools-extra/trunk/cpp11-migrate/Transforms.h
    clang-tools-extra/trunk/cpp11-migrate/UseNullptr/NullptrActions.cpp
    clang-tools-extra/trunk/cpp11-migrate/UseNullptr/NullptrActions.h
    clang-tools-extra/trunk/docs/UseNullptrTransform.rst
    clang-tools-extra/trunk/docs/cpp11-migrate.rst
    clang-tools-extra/trunk/test/cpp11-migrate/UseNullptr/macros.cpp

Modified: clang-tools-extra/trunk/cpp11-migrate/Transforms.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/cpp11-migrate/Transforms.h?rev=178243&r1=178242&r2=178243&view=diff
==============================================================================
--- clang-tools-extra/trunk/cpp11-migrate/Transforms.h (original)
+++ clang-tools-extra/trunk/cpp11-migrate/Transforms.h Thu Mar 28 11:06:59 2013
@@ -37,7 +37,7 @@ public:
   typedef TransformVec::const_iterator const_iterator;
 
 public:
- 
+
   ~Transforms();
 
   /// \brief Create command line options using LLVM's command line library.

Modified: clang-tools-extra/trunk/cpp11-migrate/UseNullptr/NullptrActions.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/cpp11-migrate/UseNullptr/NullptrActions.cpp?rev=178243&r1=178242&r2=178243&view=diff
==============================================================================
--- clang-tools-extra/trunk/cpp11-migrate/UseNullptr/NullptrActions.cpp (original)
+++ clang-tools-extra/trunk/cpp11-migrate/UseNullptr/NullptrActions.cpp Thu Mar 28 11:06:59 2013
@@ -28,6 +28,13 @@ using namespace clang;
 
 namespace {
 
+const char *NullMacroName = "NULL";
+
+static llvm::cl::opt<std::string> UserNullMacroNames(
+    "user-null-macros", llvm::cl::desc("Comma-separated list of user-defined "
+                                       "macro names that behave like NULL"),
+    llvm::cl::init(""));
+
 /// \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.
@@ -41,6 +48,25 @@ bool ReplaceWithNullptr(tooling::Replace
     return false;
 }
 
+/// \brief Returns the name of the outermost macro.
+///
+/// Given
+/// \code
+/// #define MY_NULL NULL
+/// \endcode
+/// If \p Loc points to NULL, this function will return the name MY_NULL.
+llvm::StringRef GetOutermostMacroName(
+    SourceLocation Loc, const SourceManager &SM, const LangOptions &LO) {
+  assert(Loc.isMacroID());
+  SourceLocation OutermostMacroLoc;
+
+  while (Loc.isMacroID()) {
+    OutermostMacroLoc = Loc;
+    Loc = SM.getImmediateMacroCallerLoc(Loc);
+  }
+
+  return clang::Lexer::getImmediateMacroName(OutermostMacroLoc, SM, LO);
+}
 }
 
 /// \brief Looks for a sequences of 0 or more explicit casts with an implicit
@@ -101,6 +127,16 @@ private:
   Expr *FirstSubExpr;
 };
 
+NullptrFixer::NullptrFixer(clang::tooling::Replacements &Replace,
+                           unsigned &AcceptedChanges, RiskLevel)
+    : Replace(Replace), AcceptedChanges(AcceptedChanges) {
+  if (!UserNullMacroNames.empty()) {
+    llvm::StringRef S = UserNullMacroNames;
+    S.split(UserNullMacros, ",");
+  }
+  UserNullMacros.insert(UserNullMacros.begin(), llvm::StringRef(NullMacroName));
+}
+
 void NullptrFixer::run(const ast_matchers::MatchFinder::MatchResult &Result) {
   SourceManager &SM = *Result.SourceManager;
 
@@ -127,20 +163,19 @@ void NullptrFixer::run(const ast_matcher
       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;
+      llvm::StringRef OutermostMacroName =
+          GetOutermostMacroName(StartLoc, SM, Result.Context->getLangOpts());
+
+      // Check to see if the user wants to replace the macro being expanded.
+      bool ReplaceNullMacro =
+          std::find(UserNullMacros.begin(), UserNullMacros.end(),
+                    OutermostMacroName) != UserNullMacros.end();
 
-      SourceLocation MacroCallerStartLoc =
-          SM.getImmediateMacroCallerLoc(StartLoc);
-      SourceLocation MacroCallerEndLoc = SM.getImmediateMacroCallerLoc(EndLoc);
-
-      if (MacroCallerStartLoc.isFileID() && MacroCallerEndLoc.isFileID()) {
-        StartLoc = SM.getFileLoc(StartLoc);
-        EndLoc = SM.getFileLoc(EndLoc);
-      } else
+      if (!ReplaceNullMacro)
         return;
+
+      StartLoc = SM.getFileLoc(StartLoc);
+      EndLoc = SM.getFileLoc(EndLoc);
     }
 
     AcceptedChanges +=

Modified: clang-tools-extra/trunk/cpp11-migrate/UseNullptr/NullptrActions.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/cpp11-migrate/UseNullptr/NullptrActions.h?rev=178243&r1=178242&r2=178243&view=diff
==============================================================================
--- clang-tools-extra/trunk/cpp11-migrate/UseNullptr/NullptrActions.h (original)
+++ clang-tools-extra/trunk/cpp11-migrate/UseNullptr/NullptrActions.h Thu Mar 28 11:06:59 2013
@@ -25,9 +25,7 @@ class NullptrFixer : public clang::ast_m
 public:
   NullptrFixer(clang::tooling::Replacements &Replace,
                unsigned &AcceptedChanges,
-               RiskLevel) :
-  Replace(Replace),
-  AcceptedChanges(AcceptedChanges) { }
+               RiskLevel);
 
   /// \brief Entry point to the callback called when matches are made.
   virtual void run(const clang::ast_matchers::MatchFinder::MatchResult &Result);
@@ -35,6 +33,7 @@ public:
 private:
   clang::tooling::Replacements &Replace;
   unsigned &AcceptedChanges;
+  llvm::SmallVector<llvm::StringRef, 1> UserNullMacros;
 };
 
 #endif // LLVM_TOOLS_CLANG_TOOLS_EXTRA_CPP11_MIGRATE_NULLPTR_ACTIONS_H

Modified: clang-tools-extra/trunk/docs/UseNullptrTransform.rst
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/UseNullptrTransform.rst?rev=178243&r1=178242&r2=178243&view=diff
==============================================================================
--- clang-tools-extra/trunk/docs/UseNullptrTransform.rst (original)
+++ clang-tools-extra/trunk/docs/UseNullptrTransform.rst Thu Mar 28 11:06:59 2013
@@ -38,3 +38,45 @@ transforms to:
   int *ret_ptr() {
     return nullptr;
   }
+
+
+User defined macros
+===================
+
+By default this transform will only replace the ``NULL`` macro and will skip any
+user-defined macros that behaves like ``NULL``. The user can use the
+:option:`-user-null-macros` option to specify a comma-separated list of macro
+names that will be transformed along with ``NULL``.
+
+Example
+-------
+
+.. code-block:: c++
+
+  #define MY_NULL (void*)0
+  void assignment() {
+    void *p = MY_NULL;
+  }
+
+
+using the command-line
+
+.. code-block:: bash
+
+  cpp11-migrate -use-nullptr -user-null-macros=MY_NULL foo.cpp
+
+
+transforms to:
+
+.. code-block:: c++
+
+  #define MY_NULL NULL
+  void assignment() {
+    int *p = nullptr;
+  }
+
+
+Risk
+====
+
+:option:`-risk` has no effect in this transform.

Modified: clang-tools-extra/trunk/docs/cpp11-migrate.rst
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/cpp11-migrate.rst?rev=178243&r1=178242&r2=178243&view=diff
==============================================================================
--- clang-tools-extra/trunk/docs/cpp11-migrate.rst (original)
+++ clang-tools-extra/trunk/docs/cpp11-migrate.rst Thu Mar 28 11:06:59 2013
@@ -40,6 +40,12 @@ Command Line Options
   Makes use of the new C++11 keyword ``nullptr`` where possible.
   See :doc:`UseNullptrTransform`.
 
+.. option:: -user-null-macros=<string>
+
+  ``<string>`` is a comma-separated list of user-defined macros that behave like
+  the ``NULL`` macro. The :option:`-use-nullptr` transform will replace these
+  macros along with ``NULL``. See :doc:`UseNullptrTransform`.
+
 .. option:: -use-auto
 
   Replace the type specifier of variable declarations with the ``auto`` type
@@ -76,7 +82,7 @@ Command Line Options
   :ref:`transform documentation <transforms>` for details.
 
 .. option:: -final-syntax-check
- 
+
   After applying the final transform to a file, parse the file to ensure the
   last transform did not introduce syntax errors. Syntax errors introduced by
   earlier transforms are already caught when subsequent transforms parse the

Modified: clang-tools-extra/trunk/test/cpp11-migrate/UseNullptr/macros.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/cpp11-migrate/UseNullptr/macros.cpp?rev=178243&r1=178242&r2=178243&view=diff
==============================================================================
--- clang-tools-extra/trunk/test/cpp11-migrate/UseNullptr/macros.cpp (original)
+++ clang-tools-extra/trunk/test/cpp11-migrate/UseNullptr/macros.cpp Thu Mar 28 11:06:59 2013
@@ -1,6 +1,9 @@
 // RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
 // RUN: cpp11-migrate -use-nullptr %t.cpp -- -I %S
 // RUN: FileCheck -input-file=%t.cpp %s
+// RUN: grep -Ev "// *[A-Z-]+:" %s > %t2.cpp
+// RUN: cpp11-migrate -use-nullptr -user-null-macros=MY_NULL %t2.cpp -- -I %S
+// RUN: FileCheck -check-prefix=USER-SUPPLIED-NULL -input-file=%t2.cpp %s
 
 #define NULL 0
 // CHECK: #define NULL 0
@@ -56,10 +59,9 @@ void test_macro_expansion2() {
 
 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;
+  // USER-SUPPLIED-NULL: int *p = nullptr;
 #undef MY_NULL
 }
 





More information about the cfe-commits mailing list