Add use-nullptr transform to cpp11-migrate

This transform converts the usage of null pointer constants (e.g. NULL, 0,
etc.) in legacy C++ code and converts them to use the new C++11 nullptr
keyword.
- Added use-nullptr transform.
- Added C++11 support to the final syntax check. Used ArgumentAdjuster class to
  add -std=c++11 option to the command line options.
- Added tests for use-nullptr transform.
- Added tests that exercises both loop-convert and use-nullptr in the source
  file.

TODO: There's a known bug when using both -loop-convert and -use-nullptr at the
      same time.

Author: Tareq A Siraj <tareq.a.siraj@intel.com>
Reviewers: klimek, gribozavr
llvm-svn: 173178
diff --git a/clang-tools-extra/cpp11-migrate/UseNullptr/NullptrActions.cpp b/clang-tools-extra/cpp11-migrate/UseNullptr/NullptrActions.cpp
new file mode 100644
index 0000000..54ea3e8
--- /dev/null
+++ b/clang-tools-extra/cpp11-migrate/UseNullptr/NullptrActions.cpp
@@ -0,0 +1,115 @@
+//===-- nullptr-convert/NullptrActions.cpp - Matcher callback -------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+///  \file
+///  \brief This file contains the definition of the NullptrFixer class which is
+///  used as an ASTMatcher callback. Also within this file is a helper AST
+///  visitor class used to identify sequences of explicit casts.
+///
+//===----------------------------------------------------------------------===//
+
+#include "NullptrActions.h"
+#include "NullptrMatchers.h"
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+
+
+using namespace clang::ast_matchers;
+using namespace clang::tooling;
+using namespace clang;
+
+/// \brief Looks for a sequences of 0 or more explicit casts with an implicit
+/// null-to-pointer cast within.
+///
+/// The matcher this visitor is used with will find a top-most explicit cast
+/// (i.e. it has no explicit casts as an ancestor) where an implicit cast is
+/// nested within. However, there is no guarantee that only explicit casts
+/// exist between the found top-most explicit cast and the possibly more than
+/// one nested implicit cast. This visitor finds all cast sequences with an
+/// implicit cast to null within and creates a replacement.
+class CastSequenceVisitor : public RecursiveASTVisitor<CastSequenceVisitor> {
+public:
+  CastSequenceVisitor(tooling::Replacements &R, SourceManager &SM,
+                      unsigned &AcceptedChanges) :
+    Replace(R), SM(SM), AcceptedChanges(AcceptedChanges), FirstCast(0) {}
+
+  // Only VisitStmt is overridden as we shouldn't find other base AST types
+  // within a cast expression.
+  bool VisitStmt(Stmt *S) {
+    CastExpr *C = dyn_cast<CastExpr>(S);
+
+    if (!C) {
+      ResetFirstCast();
+      return true;
+    } else if (!FirstCast) {
+      FirstCast = C;
+    }
+
+    if (C->getCastKind() == CK_NullToPointer ||
+        C->getCastKind() == CK_NullToMemberPointer) {
+      SourceLocation StartLoc = FirstCast->getLocStart();
+      SourceLocation EndLoc = FirstCast->getLocEnd();
+
+      if (SM.getFileID(StartLoc) == SM.getFileID(EndLoc) &&
+          SM.isFromMainFile(StartLoc) && SM.isFromMainFile(EndLoc)) {
+        CharSourceRange Range(SourceRange(StartLoc, EndLoc), true);
+        Replace.insert(tooling::Replacement(SM, Range, "nullptr"));
+        ++AcceptedChanges;
+      }
+      ResetFirstCast();
+    }
+
+    return true;
+  }
+
+private:
+  void ResetFirstCast() { FirstCast = 0; }
+
+private:
+  tooling::Replacements &Replace;
+  SourceManager &SM;
+  unsigned &AcceptedChanges;
+  CastExpr *FirstCast;
+};
+
+
+void NullptrFixer::run(const ast_matchers::MatchFinder::MatchResult &Result) {
+  SourceManager &SM = *Result.SourceManager;
+
+  const CastExpr *NullCast = Result.Nodes.getNodeAs<CastExpr>(CastSequence);
+  if (NullCast) {
+    // Given an explicit cast with an implicit null-to-pointer cast within
+    // use CastSequenceVisitor to identify sequences of explicit casts that can
+    // be converted into 'nullptr'.
+    CastSequenceVisitor Visitor(Replace, SM, AcceptedChanges);
+    Visitor.TraverseStmt(const_cast<CastExpr*>(NullCast));
+  }
+
+  const CastExpr *Cast = Result.Nodes.getNodeAs<CastExpr>(ImplicitCastNode);
+  if (Cast) {
+    SourceLocation StartLoc = Cast->getLocStart();
+    SourceLocation EndLoc = Cast->getLocEnd();
+
+    if (SM.getFileID(StartLoc) != SM.getFileID(EndLoc))
+      return;
+
+    if (StartLoc.isMacroID())
+      StartLoc = SM.getExpansionLoc(StartLoc);
+    if (EndLoc.isMacroID())
+      EndLoc = SM.getExpansionLoc(EndLoc);
+
+    if (!SM.isFromMainFile(StartLoc) || !SM.isFromMainFile(EndLoc))
+      return;
+
+    CharSourceRange Range(SourceRange(StartLoc, EndLoc), true);
+    Replace.insert(tooling::Replacement(SM, Range, "nullptr"));
+    ++AcceptedChanges;
+  }
+}
diff --git a/clang-tools-extra/cpp11-migrate/UseNullptr/NullptrActions.h b/clang-tools-extra/cpp11-migrate/UseNullptr/NullptrActions.h
new file mode 100644
index 0000000..b1086ee
--- /dev/null
+++ b/clang-tools-extra/cpp11-migrate/UseNullptr/NullptrActions.h
@@ -0,0 +1,40 @@
+//===-- nullptr-convert/NullptrActions.h - Matcher callback ------*- C++ -*-==//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+///  \file
+///  \brief This file contains the declaration of the NullptrFixer class which
+///  is used as a ASTMatcher callback.
+///
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_TOOLS_CLANG_TOOLS_EXTRA_CPP11_MIGRATE_NULLPTR_ACTIONS_H
+#define LLVM_TOOLS_CLANG_TOOLS_EXTRA_CPP11_MIGRATE_NULLPTR_ACTIONS_H
+
+#include "Transform.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Tooling/Refactoring.h"
+
+/// \brief The callback to be used for nullptr migration matchers.
+///
+class NullptrFixer : public clang::ast_matchers::MatchFinder::MatchCallback {
+public:
+  NullptrFixer(clang::tooling::Replacements &Replace,
+               unsigned &AcceptedChanges,
+               RiskLevel) :
+  Replace(Replace),
+  AcceptedChanges(AcceptedChanges) { }
+
+  /// \brief Entry point to the callback called when matches are made.
+  virtual void run(const clang::ast_matchers::MatchFinder::MatchResult &Result);
+
+private:
+  clang::tooling::Replacements &Replace;
+  unsigned &AcceptedChanges;
+};
+
+#endif // LLVM_TOOLS_CLANG_TOOLS_EXTRA_CPP11_MIGRATE_NULLPTR_ACTIONS_H
diff --git a/clang-tools-extra/cpp11-migrate/UseNullptr/NullptrMatchers.cpp b/clang-tools-extra/cpp11-migrate/UseNullptr/NullptrMatchers.cpp
new file mode 100644
index 0000000..a6522a1
--- /dev/null
+++ b/clang-tools-extra/cpp11-migrate/UseNullptr/NullptrMatchers.cpp
@@ -0,0 +1,53 @@
+//===-- nullptr-convert/Matchers.cpp - Matchers for null casts ------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+///  \file
+///  \brief This file contains the definitions for matcher-generating functions
+///  and a custom AST_MATCHER for identifying casts of type CK_NullTo*.
+///
+//===----------------------------------------------------------------------===//
+#include "NullptrMatchers.h"
+#include "clang/AST/ASTContext.h"
+
+using namespace clang::ast_matchers;
+using namespace clang;
+
+const char *ImplicitCastNode = "cast";
+const char *CastSequence = "sequence";
+
+namespace clang {
+namespace ast_matchers {
+/// \brief Matches cast expressions that have a cast kind of CK_NullToPointer
+/// or CK_NullToMemberPointer.
+///
+/// Given
+/// \code
+///   int *p = 0;
+/// \endcode
+/// implicitCastExpr(isNullToPointer()) matches the implicit cast clang adds
+/// around \c 0.
+AST_MATCHER(CastExpr, isNullToPointer) {
+  return Node.getCastKind() == CK_NullToPointer ||
+    Node.getCastKind() == CK_NullToMemberPointer;
+}
+
+} // end namespace ast_matchers
+} // end namespace clang
+
+StatementMatcher makeImplicitCastMatcher() {
+  return implicitCastExpr(allOf(unless(hasAncestor(explicitCastExpr())),
+                                isNullToPointer())).bind(ImplicitCastNode);
+}
+
+StatementMatcher makeCastSequenceMatcher() {
+  return explicitCastExpr(
+            allOf(unless(hasAncestor(explicitCastExpr())),
+                  hasDescendant(implicitCastExpr(isNullToPointer())))
+            ).bind(CastSequence);
+}
diff --git a/clang-tools-extra/cpp11-migrate/UseNullptr/NullptrMatchers.h b/clang-tools-extra/cpp11-migrate/UseNullptr/NullptrMatchers.h
new file mode 100644
index 0000000..e6d2317
--- /dev/null
+++ b/clang-tools-extra/cpp11-migrate/UseNullptr/NullptrMatchers.h
@@ -0,0 +1,38 @@
+//===-- nullptr-convert/Matchers.h - Matchers for null casts ---*- C++ -*--===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+///  \file
+///  \brief This file contains the declarations for matcher-generating functions
+///  and names for bound nodes found by AST matchers.
+///
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_TOOLS_CLANG_TOOLS_EXTRA_CPP11_MIGRATE_USE_NULLPTR_MATCHERS_H
+#define LLVM_TOOLS_CLANG_TOOLS_EXTRA_CPP11_MIGRATE_USE_NULLPTR_MATCHERS_H
+
+#include "clang/ASTMatchers/ASTMatchers.h"
+
+// Names to bind with matched expressions.
+extern const char *ImplicitCastNode;
+extern const char *CastSequence;
+
+/// \brief Create a matcher to find the implicit casts clang inserts
+/// when writing null to a pointer.
+///
+/// However, don't match those implicit casts that have explicit casts as
+/// an ancestor. Explicit casts are handled by makeCastSequenceMatcher().
+clang::ast_matchers::StatementMatcher makeImplicitCastMatcher();
+
+/// \brief Create a matcher that finds the head of a sequence of nested explicit
+/// casts that have an implicit cast to null within.
+///
+/// This matcher is necessary so that an entire sequence of explicit casts can
+/// be replaced instead of just the inner-most implicit cast.
+clang::ast_matchers::StatementMatcher makeCastSequenceMatcher();
+
+#endif // LLVM_TOOLS_CLANG_TOOLS_EXTRA_CPP11_MIGRATE_USE_NULLPTR_MATCHERS_H
diff --git a/clang-tools-extra/cpp11-migrate/UseNullptr/UseNullptr.cpp b/clang-tools-extra/cpp11-migrate/UseNullptr/UseNullptr.cpp
new file mode 100644
index 0000000..aaf5bf1
--- /dev/null
+++ b/clang-tools-extra/cpp11-migrate/UseNullptr/UseNullptr.cpp
@@ -0,0 +1,68 @@
+//===-- LoopConvert/LoopConvert.cpp - C++11 for-loop migration --*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief This file provides the implementation of the UseNullptrTransform
+/// class.
+///
+//===----------------------------------------------------------------------===//
+
+#include "UseNullptr.h"
+#include "NullptrActions.h"
+#include "NullptrMatchers.h"
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/Rewrite/Core/Rewriter.h"
+#include "clang/Tooling/Refactoring.h"
+#include "clang/Tooling/Tooling.h"
+
+using clang::ast_matchers::MatchFinder;
+using namespace clang::tooling;
+using namespace clang;
+
+int UseNullptrTransform::apply(const FileContentsByPath &InputStates,
+                               RiskLevel MaxRisk,
+                               const CompilationDatabase &Database,
+                               const std::vector<std::string> &SourcePaths,
+                               FileContentsByPath &ResultStates) {
+  RefactoringTool UseNullptrTool(Database, SourcePaths);
+
+  for (FileContentsByPath::const_iterator I = InputStates.begin(),
+       E = InputStates.end();
+       I != E; ++I) {
+    UseNullptrTool.mapVirtualFile(I->first, I->second);
+  }
+
+  unsigned AcceptedChanges = 0;
+
+  MatchFinder Finder;
+  NullptrFixer Fixer(UseNullptrTool.getReplacements(),
+                     AcceptedChanges,
+                     MaxRisk);
+
+  Finder.addMatcher(makeImplicitCastMatcher(), &Fixer);
+  Finder.addMatcher(makeCastSequenceMatcher(), &Fixer);
+
+  if (int result = UseNullptrTool.run(newFrontendActionFactory(&Finder))) {
+    llvm::errs() << "Error encountered during translation.\n";
+    return result;
+  }
+
+  RewriterContainer Rewrite(UseNullptrTool.getFiles());
+
+  // FIXME: Do something if some replacements didn't get applied?
+  UseNullptrTool.applyAllReplacements(Rewrite.getRewriter());
+
+  collectResults(Rewrite.getRewriter(), ResultStates);
+
+  if (AcceptedChanges > 0) {
+    setChangesMade();
+  }
+
+  return 0;
+}
diff --git a/clang-tools-extra/cpp11-migrate/UseNullptr/UseNullptr.h b/clang-tools-extra/cpp11-migrate/UseNullptr/UseNullptr.h
new file mode 100644
index 0000000..c62ed84
--- /dev/null
+++ b/clang-tools-extra/cpp11-migrate/UseNullptr/UseNullptr.h
@@ -0,0 +1,34 @@
+//===-- LoopConvert/LoopConvert.h - C++11 for-loop migration ----*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief This file provides the definition of the UseNullptrTransform
+/// class which is the main interface to the use-nullptr transform
+/// that tries to make use of nullptr where possible.
+///
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_TOOLS_CLANG_TOOLS_EXTRA_CPP11_MIGRATE_USE_NULLPTR_H
+#define LLVM_TOOLS_CLANG_TOOLS_EXTRA_CPP11_MIGRATE_USE_NULLPTR_H
+
+#include "Transform.h"
+#include "llvm/Support/Compiler.h" // For LLVM_OVERRIDE
+
+/// \brief Subclass of Transform that transforms null pointer constants into
+/// C++11's nullptr keyword where possible.
+class UseNullptrTransform : public Transform {
+public:
+  /// \see Transform::run().
+  virtual int apply(const FileContentsByPath &InputStates,
+                    RiskLevel MaxRiskLEvel,
+                    const clang::tooling::CompilationDatabase &Database,
+                    const std::vector<std::string> &SourcePaths,
+                    FileContentsByPath &ResultStates) LLVM_OVERRIDE;
+};
+
+#endif // LLVM_TOOLS_CLANG_TOOLS_EXTRA_CPP11_MIGRATE_USE_NULLPTR_H