- Updating test case to test #undef behaviour.

Hi tareqsiraj, arielbernal,

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

CHANGE SINCE LAST DIFF
  http://llvm-reviews.chandlerc.com/D896?vs=2198&id=2199#toc

Files:
  cpp11-migrate/AddOverride/AddOverride.cpp
  cpp11-migrate/AddOverride/AddOverride.h
  cpp11-migrate/AddOverride/AddOverrideActions.cpp
  cpp11-migrate/AddOverride/AddOverrideActions.h
  cpp11-migrate/Core/Transform.cpp
  cpp11-migrate/Core/Transform.h
  cpp11-migrate/Core/Transforms.cpp
  cpp11-migrate/Core/Transforms.h
  cpp11-migrate/LoopConvert/LoopConvert.cpp
  cpp11-migrate/LoopConvert/LoopConvert.h
  cpp11-migrate/UseAuto/UseAuto.cpp
  cpp11-migrate/UseAuto/UseAuto.h
  cpp11-migrate/UseNullptr/UseNullptr.cpp
  cpp11-migrate/UseNullptr/UseNullptr.h
  cpp11-migrate/tool/Cpp11Migrate.cpp
  test/cpp11-migrate/AddOverride/basic.cpp
  unittests/cpp11-migrate/TransformTest.cpp
Index: cpp11-migrate/AddOverride/AddOverride.cpp
===================================================================
--- cpp11-migrate/AddOverride/AddOverride.cpp
+++ cpp11-migrate/AddOverride/AddOverride.cpp
@@ -16,15 +16,21 @@
 #include "AddOverride.h"
 #include "AddOverrideActions.h"
 #include "AddOverrideMatchers.h"
+#include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/FrontendActions.h"
 #include "clang/Rewrite/Core/Rewriter.h"
 #include "clang/Tooling/Refactoring.h"
 #include "clang/Tooling/Tooling.h"
+#include "llvm/Support/CommandLine.h"
 
 using clang::ast_matchers::MatchFinder;
 using namespace clang::tooling;
 using namespace clang;
 
+static llvm::cl::opt<bool> DetectMacros(
+    "override-macros",
+    llvm::cl::desc("Detect and use macros that expand to the 'override' keyword."));
+
 int AddOverrideTransform::apply(const FileContentsByPath &InputStates,
                                 RiskLevel MaxRisk,
                                 const CompilationDatabase &Database,
@@ -41,11 +47,15 @@
   unsigned AcceptedChanges = 0;
 
   MatchFinder Finder;
-  AddOverrideFixer Fixer(AddOverrideTool.getReplacements(), AcceptedChanges);
+  AddOverrideFixer Fixer(AddOverrideTool.getReplacements(), AcceptedChanges,
+                         DetectMacros);
+  // Make Fixer available to handleBeginSource().
+  this->Fixer = &Fixer;
 
   Finder.addMatcher(makeCandidateForOverrideAttrMatcher(), &Fixer);
 
-  if (int result = AddOverrideTool.run(newFrontendActionFactory(&Finder))) {
+  if (int result = AddOverrideTool.run(
+          newFrontendActionFactory(&Finder, /*Callbacks=*/ this))) {
     llvm::errs() << "Error encountered during translation.\n";
     return result;
   }
@@ -61,3 +71,10 @@
 
   return 0;
 }
+
+bool AddOverrideTransform::handleBeginSource(clang::CompilerInstance &CI,
+                                             llvm::StringRef Filename) {
+  assert(Fixer != NULL && "Fixer must be set");
+  Fixer->setPreprocessor(CI.getPreprocessor());
+  return Transform::handleBeginSource(CI, Filename);
+}
Index: cpp11-migrate/AddOverride/AddOverride.h
===================================================================
--- cpp11-migrate/AddOverride/AddOverride.h
+++ cpp11-migrate/AddOverride/AddOverride.h
@@ -20,18 +20,27 @@
 #include "Core/Transform.h"
 #include "llvm/Support/Compiler.h"
 
+class AddOverrideFixer;
+
 /// \brief Subclass of Transform that adds the C++11 override keyword to
 /// member functions overriding base class virtual functions.
 class AddOverrideTransform : public Transform {
 public:
-  AddOverrideTransform() : Transform("AddOverride") {}
+  AddOverrideTransform(bool EnableTiming)
+      : Transform("AddOverride", EnableTiming) {}
 
   /// \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;
+
+  virtual bool handleBeginSource(clang::CompilerInstance &CI,
+                                 llvm::StringRef Filename) LLVM_OVERRIDE;
+
+private:
+  AddOverrideFixer *Fixer;
 };
 
 #endif // LLVM_TOOLS_CLANG_TOOLS_EXTRA_CPP11_MIGRATE_ADD_OVERRIDE_H
Index: cpp11-migrate/AddOverride/AddOverrideActions.cpp
===================================================================
--- cpp11-migrate/AddOverride/AddOverrideActions.cpp
+++ cpp11-migrate/AddOverride/AddOverrideActions.cpp
@@ -21,6 +21,7 @@
 #include "clang/AST/Attr.h"
 #include "clang/AST/RecursiveASTVisitor.h"
 #include "clang/Lex/Lexer.h"
+#include "clang/Lex/Preprocessor.h"
 
 using namespace clang::ast_matchers;
 using namespace clang::tooling;
@@ -85,6 +86,15 @@
     StartLoc = SM.getSpellingLoc(M->getLocEnd());
     StartLoc = Lexer::getLocForEndOfToken(StartLoc, 0, SM, LangOptions());
   }
-  Replace.insert(tooling::Replacement(SM, StartLoc, 0, " override"));
+
+  std::string ReplacementText = " override";
+  if (DetectMacros) {
+    assert(PP != 0 && "No access to Preprocessor object for macro detection");
+    clang::TokenValue Tokens[] = { PP->getIdentifierInfo("override") };
+    llvm::StringRef MacroName = PP->getLastMacroWithSpelling(StartLoc, Tokens);
+    if (!MacroName.empty())
+      ReplacementText = (" " + MacroName).str();
+  }
+  Replace.insert(tooling::Replacement(SM, StartLoc, 0, ReplacementText));
   ++AcceptedChanges;
 }
Index: cpp11-migrate/AddOverride/AddOverrideActions.h
===================================================================
--- cpp11-migrate/AddOverride/AddOverrideActions.h
+++ cpp11-migrate/AddOverride/AddOverrideActions.h
@@ -24,15 +24,20 @@
 class AddOverrideFixer : public clang::ast_matchers::MatchFinder::MatchCallback {
 public:
   AddOverrideFixer(clang::tooling::Replacements &Replace,
-                   unsigned &AcceptedChanges) :
-    Replace(Replace), AcceptedChanges(AcceptedChanges) {}
+                   unsigned &AcceptedChanges, bool DetectMacros)
+      : Replace(Replace), AcceptedChanges(AcceptedChanges),
+        DetectMacros(DetectMacros) {}
 
   /// \brief Entry point to the callback called when matches are made.
   virtual void run(const clang::ast_matchers::MatchFinder::MatchResult &Result);
 
+  void setPreprocessor(clang::Preprocessor &PP) { this->PP = &PP; }
+
 private:
+  clang::Preprocessor *PP;
   clang::tooling::Replacements &Replace;
   unsigned &AcceptedChanges;
+  bool DetectMacros;
 };
 
 #endif // LLVM_TOOLS_CLANG_TOOLS_EXTRA_CPP11_MIGRATE_ADD_OVERRIDE_ACTIONS_H
Index: cpp11-migrate/Core/Transform.cpp
===================================================================
--- cpp11-migrate/Core/Transform.cpp
+++ cpp11-migrate/Core/Transform.cpp
@@ -35,3 +35,19 @@
     Results[Entry->getName()] = ResultBuf;
   }
 }
+
+bool Transform::handleBeginSource(CompilerInstance &CI, StringRef Filename) {
+  if (!EnableTiming)
+    return true;
+
+  Timings.push_back(std::make_pair(Filename.str(), llvm::TimeRecord()));
+  Timings.back().second -= llvm::TimeRecord::getCurrentTime(true);
+  return true;
+}
+
+void Transform::handleEndSource() {
+  if (!EnableTiming)
+    return;
+
+  Timings.back().second += llvm::TimeRecord::getCurrentTime(false);
+}
Index: cpp11-migrate/Core/Transform.h
===================================================================
--- cpp11-migrate/Core/Transform.h
+++ cpp11-migrate/Core/Transform.h
@@ -17,6 +17,8 @@
 
 #include <string>
 #include <vector>
+#include "clang/Tooling/Tooling.h"
+#include "llvm/Support/Timer.h"
 
 // For RewriterContainer
 #include "clang/Rewrite/Core/Rewriter.h"
@@ -104,9 +106,23 @@
 };
 
 /// \brief Abstract base class for all C++11 migration transforms.
-class Transform {
+///
+/// Per-source performance timing is handled by the callbacks
+/// handleBeginSource() and handleEndSource() if timing is enabled. See
+/// clang::tooling::newFrontendActionFactory() for how to register
+/// a Transform object for callbacks.
+class Transform : public clang::tooling::SourceFileCallbacks {
 public:
-  Transform(llvm::StringRef Name) : Name(Name) {
+  /// \brief Constructor
+  /// \param Name Name of the transform for human-readable purposes (e.g. -help
+  /// text)
+  /// \param EnableTiming Enable the timing of the duration between calls to
+  /// handleBeginSource() and handleEndSource(). When a Transform object is
+  /// registered for FrontendAction source file callbacks, this behaviour can
+  /// be used to time the application of a MatchFinder by subclasses. Durations
+  /// are automatically stored in a TimingVec.
+  Transform(llvm::StringRef Name, bool EnableTiming)
+      : Name(Name), EnableTiming(EnableTiming) {
     Reset();
   }
 
@@ -156,7 +172,31 @@
     DeferredChanges = 0;
   }
 
+  /// \brief Callback for notification of the start of processing of a source
+  /// file by a FrontendAction. Starts a performance timer if timing was
+  /// enabled.
+  virtual bool handleBeginSource(clang::CompilerInstance &CI,
+                                 llvm::StringRef Filename) LLVM_OVERRIDE;
+
+  /// \brief Callback for notification of the end of processing of a source
+  /// file by a FrontendAction. Stops a performance timer if timing was enabled
+  /// and records the elapsed time. For a given source, handleBeginSource() and
+  /// handleEndSource() are expected to be called in pairs.
+  virtual void handleEndSource() LLVM_OVERRIDE;
+
+  /// \brief Performance timing data is stored as a vector of pairs. Pairs are
+  /// formed of:
+  /// \li Name of source file.
+  /// \li Elapsed time.
+  typedef std::vector<std::pair<std::string, llvm::TimeRecord> > TimingVec;
+
+  /// \brief Return an iterator to the start of collected timing data.
+  TimingVec::const_iterator timing_begin() const { return Timings.begin(); }
+  /// \brief Return an iterator to the start of collected timing data.
+  TimingVec::const_iterator timing_end() const { return Timings.end(); }
+
 protected:
+
   void setAcceptedChanges(unsigned Changes) {
     AcceptedChanges = Changes;
   }
@@ -169,6 +209,8 @@
 
 private:
   const std::string Name;
+  bool EnableTiming;
+  TimingVec Timings;
   unsigned AcceptedChanges;
   unsigned RejectedChanges;
   unsigned DeferredChanges;
Index: cpp11-migrate/Core/Transforms.cpp
===================================================================
--- cpp11-migrate/Core/Transforms.cpp
+++ cpp11-migrate/Core/Transforms.cpp
@@ -35,11 +35,11 @@
       new cl::opt<bool>(OptName.data(), cl::desc(Description.data())), Creator));
 }
 
-void Transforms::createSelectedTransforms() {
+void Transforms::createSelectedTransforms(bool EnableTiming) {
   for (OptionVec::iterator I = Options.begin(),
        E = Options.end(); I != E; ++I) {
     if (*I->first) {
-      ChosenTransforms.push_back(I->second());
+      ChosenTransforms.push_back(I->second(EnableTiming));
     }
   }
 }
Index: cpp11-migrate/Core/Transforms.h
===================================================================
--- cpp11-migrate/Core/Transforms.h
+++ cpp11-migrate/Core/Transforms.h
@@ -28,10 +28,10 @@
 } // namespace llvm
 class Transform;
 
-typedef Transform *(*TransformCreator)();
+typedef Transform *(*TransformCreator)(bool);
 template <typename T>
-Transform *ConstructTransform() {
-  return new T();
+Transform *ConstructTransform(bool EnableTiming) {
+  return new T(EnableTiming);
 }
 
 /// \brief Class encapsulating the creation of command line bool options
@@ -55,7 +55,7 @@
   /// \brief Instantiate all transforms that were selected on the command line.
   ///
   /// Call *after* parsing options.
-  void createSelectedTransforms();
+  void createSelectedTransforms(bool EnableTiming);
 
   /// \brief Return an iterator to the start of a container of instantiated
   /// transforms.
Index: cpp11-migrate/LoopConvert/LoopConvert.cpp
===================================================================
--- cpp11-migrate/LoopConvert/LoopConvert.cpp
+++ cpp11-migrate/LoopConvert/LoopConvert.cpp
@@ -64,7 +64,8 @@
                                   MaxRisk, LFK_PseudoArray);
   Finder.addMatcher(makePseudoArrayLoopMatcher(), &PseudoarrrayLoopFixer);
 
-  if (int result = LoopTool.run(newFrontendActionFactory(&Finder))) {
+  if (int result = LoopTool.run(
+          newFrontendActionFactory(&Finder, /*Callbacks=*/ this))) {
     llvm::errs() << "Error encountered during translation.\n";
     return result;
   }
Index: cpp11-migrate/LoopConvert/LoopConvert.h
===================================================================
--- cpp11-migrate/LoopConvert/LoopConvert.h
+++ cpp11-migrate/LoopConvert/LoopConvert.h
@@ -23,7 +23,8 @@
 /// for-loops where possible.
 class LoopConvertTransform : public Transform {
 public:
-  LoopConvertTransform() : Transform("LoopConvert") {}
+  LoopConvertTransform(bool EnableTiming)
+      : Transform("LoopConvert", EnableTiming) {}
 
   /// \see Transform::run().
   virtual int apply(const FileContentsByPath &InputStates,
Index: cpp11-migrate/UseAuto/UseAuto.cpp
===================================================================
--- cpp11-migrate/UseAuto/UseAuto.cpp
+++ cpp11-migrate/UseAuto/UseAuto.cpp
@@ -43,7 +43,8 @@
   Finder.addMatcher(makeIteratorDeclMatcher(), &ReplaceIterators);
   Finder.addMatcher(makeDeclWithNewMatcher(), &ReplaceNew);
 
-  if (int Result = UseAutoTool.run(newFrontendActionFactory(&Finder))) {
+  if (int Result = UseAutoTool.run(
+          newFrontendActionFactory(&Finder, /*Callbacks=*/ this))) {
     llvm::errs() << "Error encountered during translation.\n";
     return Result;
   }
Index: cpp11-migrate/UseAuto/UseAuto.h
===================================================================
--- cpp11-migrate/UseAuto/UseAuto.h
+++ cpp11-migrate/UseAuto/UseAuto.h
@@ -29,7 +29,7 @@
 /// p2 are not handled by this transform.
 class UseAutoTransform : public Transform {
 public:
-  UseAutoTransform() : Transform("UseAuto") {}
+  UseAutoTransform(bool EnableTiming) : Transform("UseAuto", EnableTiming) {}
 
   /// \see Transform::run().
   virtual int apply(const FileContentsByPath &InputStates,
Index: cpp11-migrate/UseNullptr/UseNullptr.cpp
===================================================================
--- cpp11-migrate/UseNullptr/UseNullptr.cpp
+++ cpp11-migrate/UseNullptr/UseNullptr.cpp
@@ -47,7 +47,8 @@
 
   Finder.addMatcher(makeCastSequenceMatcher(), &Fixer);
 
-  if (int result = UseNullptrTool.run(newFrontendActionFactory(&Finder))) {
+  if (int result = UseNullptrTool.run(
+          newFrontendActionFactory(&Finder, /*Callbacks=*/ this))) {
     llvm::errs() << "Error encountered during translation.\n";
     return result;
   }
Index: cpp11-migrate/UseNullptr/UseNullptr.h
===================================================================
--- cpp11-migrate/UseNullptr/UseNullptr.h
+++ cpp11-migrate/UseNullptr/UseNullptr.h
@@ -23,7 +23,8 @@
 /// C++11's nullptr keyword where possible.
 class UseNullptrTransform : public Transform {
 public:
-  UseNullptrTransform() : Transform("UseNullptr") {}
+  UseNullptrTransform(bool EnableTiming)
+      : Transform("UseNullptr", EnableTiming) {}
 
   /// \see Transform::run().
   virtual int apply(const FileContentsByPath &InputStates,
Index: cpp11-migrate/tool/Cpp11Migrate.cpp
===================================================================
--- cpp11-migrate/tool/Cpp11Migrate.cpp
+++ cpp11-migrate/tool/Cpp11Migrate.cpp
@@ -99,7 +99,7 @@
   // This causes options to be parsed.
   CommonOptionsParser OptionsParser(argc, argv);
 
-  TransformManager.createSelectedTransforms();
+  TransformManager.createSelectedTransforms(/*EnableTiming=*/false);
 
   if (TransformManager.begin() == TransformManager.end()) {
     llvm::errs() << "No selected transforms\n";
Index: test/cpp11-migrate/AddOverride/basic.cpp
===================================================================
--- test/cpp11-migrate/AddOverride/basic.cpp
+++ test/cpp11-migrate/AddOverride/basic.cpp
@@ -1,9 +1,11 @@
 // RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
 // RUN: cpp11-migrate -add-override %t.cpp -- -I %S -std=c++11
 // RUN: FileCheck -input-file=%t.cpp %s
+// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
+// RUN: cpp11-migrate -add-override -override-macros %t.cpp -- -I %S -std=c++11
+// RUN: FileCheck --check-prefix=MACRO --input-file=%t.cpp %s
 
-class A {
-public:
+struct A {
   virtual ~A();
   // CHECK: virtual ~A();
   void f();
@@ -14,103 +16,109 @@
 };
 
 // Test that override isn't added to non-virtual functions.
-class B : public A {
-public:
+struct B : public A {
   void f();
-  // CHECK: class B
-  // CHECK: void f();
+  // CHECK: struct B
+  // CHECK-NEXT: void f();
 };
 
 // Test that override is added to functions that override virtual functions.
-class C : public A {
-public:
+struct C : public A {
   void h() const;
-  // CHECK: class C
-  // CHECK: void h() const override;
+  // CHECK: struct C
+  // CHECK-NEXT: void h() const override;
+  // MACRO: struct C
+  // MACRO-NEXT: void h() const override;
 };
 
 // Test that override isn't add to functions that overload but not override.
-class D : public A {
-public:
+struct D : public A {
   void h();
-  // CHECK: class D
-  // CHECK: void h();
+  // CHECK: struct D
+  // CHECK-NEXT: void h();
 };
 
 // Test that override isn't added again to functions that already have it.
-class E : public A {
-public:
+struct E : public A {
   void h() const override;
-  // CHECK: class E
-  // CHECK: void h() const override;
+  // CHECK: struct E
+  // CHECK-NEXT: void h() const override;
+  // MACRO: struct E
+  // MACRO-NEXT: void h() const override;
 };
 
 // Test that override isn't added to the destructor.
-class F : public A {
-public:
+struct F : public A {
   virtual ~F();
-  // CHECK: class F
-  // CHECK: virtual ~F();
+  // CHECK: struct F
+  // CHECK-NEXT: virtual ~F();
 };
 
 // Test that override is placed before any end of line comments.
-class G : public A {
-public:
+struct G : public A {
   void h() const; // comment
   void i() // comment
   {}
-  // CHECK: class G
-  // CHECK: void h() const override; // comment
-  // CHECK: void i() override // comment
+  // CHECK: struct G
+  // CHECK-NEXT: void h() const override; // comment
+  // CHECK-NEXT: void i() override // comment
   // CHECK-NEXT: {}
 };
 
 // Test that override is placed correctly if there is an inline body.
-class H : public A {
-public:
+struct H : public A {
   void h() const { }
-  // CHECK: class H
-  // CHECK: void h() const override { }
+  // CHECK: struct H
+  // CHECK-NEXT: void h() const override { }
 };
 
 // Test that override is placed correctly if there is a body on the next line.
-class I : public A {
-public:
+struct I : public A {
   void h() const
   { }
-  // CHECK: class I
-  // CHECK: void h() const override
-  // CHECK: { }
+  // CHECK: struct I
+  // CHECK-NEXT: void h() const override
+  // CHECK-NEXT: { }
 };
 
 // Test that override is placed correctly if there is a body outside the class.
-class J : public A {
-public:
+struct J : public A {
   void h() const;
-  // CHECK: class J
-  // CHECK: void h() const override;
+  // CHECK: struct J
+  // CHECK-NEXT: void h() const override;
 };
 
 void J::h() const {
   // CHECK: void J::h() const {
 }
 
 // Test that override is placed correctly if there is a trailing return type.
-class K : public A {
-public:
+struct K : public A {
   auto h() const -> void;
-  // CHECK: class K
-  // CHECK: auto h() const -> void override;
+  // CHECK: struct K
+  // CHECK-NEXT: auto h() const -> void override;
 };
 
-// Test that override isn't added if it is already specified via a macro.
-class L : public A {
-public:
 #define LLVM_OVERRIDE override
+
+// Test that override isn't added if it is already specified via a macro.
+struct L : public A {
   void h() const LLVM_OVERRIDE;
-  // CHECK: class L
-  // CHECK: void h() const LLVM_OVERRIDE;
+  // CHECK: struct L
+  // CHECK-NEXT: void h() const LLVM_OVERRIDE;
+  // MACRO: struct L
+  // MACRO-NEXT: void h() const LLVM_OVERRIDE;
+};
+
+template <typename T>
+struct M : public A {
+  virtual void i();
+  // CHECK: struct M
+  // CHECK-NEXT: virtual void i() override;
+  // MACRO: struct M
+  // MACRO-NEXT: virtual void i() LLVM_OVERRIDE;
 };
+M<int> b;
 
 // Test that override isn't added at the wrong place for "pure overrides"
 struct APure {
@@ -137,16 +145,17 @@
 template<typename T> struct Derived : T {
   void f(); // adding 'override' here will break instantiation of Derived<Base2>
   // CHECK: struct Derived
-  // CHECK: void f();
+  // CHECK-NEXT: void f();
 };
 Derived<Base1> d1;
 Derived<Base2> d2;
 
-template <typename T>
-class M : public A {
-public:
-  virtual void i();
-  // CHECK: class M : public A {
-  // CHECK: virtual void i() override;
+#undef LLVM_OVERRIDE
+
+struct N : public A {
+  void h() const;
+  // CHECK: struct N
+  // CHECK-NEXT: void h() const override;
+  // MACRO: struct N
+  // MACRO-NEXT: void h() const override;
 };
-M<int> b;
Index: unittests/cpp11-migrate/TransformTest.cpp
===================================================================
--- unittests/cpp11-migrate/TransformTest.cpp
+++ unittests/cpp11-migrate/TransformTest.cpp
@@ -1,13 +1,20 @@
 #include "gtest/gtest.h"
 #include "Core/Transform.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/DeclGroup.h"
+#include "llvm/Support/Process.h"
+#include "llvm/Support/Path.h"
+
+using namespace clang;
 
 class DummyTransform : public Transform {
 public:
-  DummyTransform(llvm::StringRef Name) : Transform(Name) {}
+  DummyTransform(llvm::StringRef Name, bool EnableTiming)
+      : Transform(Name, EnableTiming) {}
 
   virtual int apply(const FileContentsByPath &,
                     RiskLevel ,
-                    const clang::tooling::CompilationDatabase &,
+                    const tooling::CompilationDatabase &,
                     const std::vector<std::string> &,
                     FileContentsByPath &) { return 0; }
 
@@ -23,7 +30,7 @@
 };
 
 TEST(Transform, Interface) {
-  DummyTransform T("my_transform");
+  DummyTransform T("my_transform", /*EnableTiming=*/false);
   ASSERT_EQ("my_transform", T.getName());
   ASSERT_EQ(0u, T.getAcceptedChanges());
   ASSERT_EQ(0u, T.getRejectedChanges());
@@ -48,3 +55,83 @@
   T.setRejectedChanges(1);
   ASSERT_TRUE(T.getChangesNotMade());
 }
+
+class FindTopLevelDeclConsumer : public ASTConsumer {
+public:
+  FindTopLevelDeclConsumer(bool *Called) : Called(Called) {}
+
+  virtual bool HandleTopLevelDecl(DeclGroupRef DeclGroup) {
+    llvm::sys::TimeValue UserStart;
+    llvm::sys::TimeValue SystemStart;
+    llvm::sys::TimeValue UserNow;
+    llvm::sys::TimeValue SystemNow;
+    llvm::sys::TimeValue Wall;
+
+    // Busy-wait until the user/system time combined is more than 1ms
+    llvm::sys::TimeValue OneMS(0, 1000000);
+    llvm::sys::Process::GetTimeUsage(Wall, UserStart, SystemStart);
+    do {
+      llvm::sys::Process::GetTimeUsage(Wall, UserNow, SystemNow);
+    } while (UserNow - UserStart + SystemNow - SystemStart < OneMS);
+    *Called = true;
+    return true;
+  }
+  bool *Called;
+};
+
+struct ConsumerFactory {
+  ASTConsumer *newASTConsumer() {
+    return new FindTopLevelDeclConsumer(&Called);
+  }
+  bool Called;
+};
+
+TEST(Transform, Timings) {
+  DummyTransform T("timing_transform", /*EnableTiming=*/true);
+
+  // All the path stuff is to make the test work independently of OS.
+
+  // The directory used is not important since the path gets mapped to a virtual
+  // file anyway. What is important is that we have an absolute path with which
+  // to use with mapVirtualFile().
+  llvm::sys::Path FileA = llvm::sys::Path::GetCurrentDirectory();
+  std::string CurrentDir = FileA.str();
+  FileA.appendComponent("a.cc");
+  std::string FileAName = FileA.str();
+  llvm::sys::Path FileB = llvm::sys::Path::GetCurrentDirectory();
+  FileB.appendComponent("b.cc");
+  std::string FileBName = FileB.str();
+
+  tooling::FixedCompilationDatabase Compilations(CurrentDir, std::vector<std::string>());
+  std::vector<std::string> Sources;
+  Sources.push_back(FileAName);
+  Sources.push_back(FileBName);
+  tooling::ClangTool Tool(Compilations, Sources);
+
+  Tool.mapVirtualFile(FileAName, "void a() {}");
+  Tool.mapVirtualFile(FileBName, "void b() {}");
+
+  ConsumerFactory Factory;
+  Tool.run(newFrontendActionFactory(&Factory, &T));
+
+  EXPECT_TRUE(Factory.Called);
+  Transform::TimingVec::const_iterator I = T.timing_begin();
+  EXPECT_GT(I->second.getProcessTime(), 0.0);
+
+  // The success of the test shouldn't depend on the order of iteration through
+  // timers.
+  llvm::sys::Path FirstFile(I->first);
+  if (FileA == FirstFile) {
+    ++I;
+    EXPECT_EQ(FileB, llvm::sys::Path(I->first));
+    EXPECT_GT(I->second.getProcessTime(), 0.0);
+  } else if (FileB == FirstFile) {
+    ++I;
+    EXPECT_EQ(FileA, llvm::sys::Path(I->first));
+    EXPECT_GT(I->second.getProcessTime(), 0.0);
+  } else {
+    FAIL() << "Unexpected file name " << I->first << " in timing data.";
+  }
+  ++I;
+  EXPECT_EQ(T.timing_end(), I);
+}
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to