[PATCH] D15606: Remove clang-modernize.
Justin Bogner via cfe-commits
cfe-commits at lists.llvm.org
Thu Dec 17 12:47:09 PST 2015
Alexander Kornienko via cfe-commits <cfe-commits at lists.llvm.org> writes:
> alexfh created this revision.
> alexfh added a reviewer: klimek.
> alexfh added a subscriber: cfe-commits.
>
> clang-modernize transforms have moved to clang-tidy. Removing
> the old tool now.
Please add a note to the release notes mentioning this.
> http://reviews.llvm.org/D15606
>
> Files:
> CMakeLists.txt
> Makefile
> clang-modernize/
> clang-modernize/AddOverride/
> clang-modernize/AddOverride/AddOverride.cpp
> clang-modernize/AddOverride/AddOverride.h
> clang-modernize/AddOverride/AddOverrideActions.cpp
> clang-modernize/AddOverride/AddOverrideActions.h
> clang-modernize/AddOverride/AddOverrideMatchers.cpp
> clang-modernize/AddOverride/AddOverrideMatchers.h
> clang-modernize/CMakeLists.txt
> clang-modernize/Core/
> clang-modernize/Core/CMakeLists.txt
> clang-modernize/Core/CustomMatchers.h
> clang-modernize/Core/IncludeDirectives.cpp
> clang-modernize/Core/IncludeDirectives.h
> clang-modernize/Core/IncludeExcludeInfo.cpp
> clang-modernize/Core/IncludeExcludeInfo.h
> clang-modernize/Core/Makefile
> clang-modernize/Core/PerfSupport.cpp
> clang-modernize/Core/PerfSupport.h
> clang-modernize/Core/Refactoring.h
> clang-modernize/Core/ReplacementHandling.cpp
> clang-modernize/Core/ReplacementHandling.h
> clang-modernize/Core/Transform.cpp
> clang-modernize/Core/Transform.h
> clang-modernize/Core/Transforms.cpp
> clang-modernize/Core/Transforms.h
> clang-modernize/LoopConvert/
> clang-modernize/LoopConvert/LoopActions.cpp
> clang-modernize/LoopConvert/LoopActions.h
> clang-modernize/LoopConvert/LoopConvert.cpp
> clang-modernize/LoopConvert/LoopConvert.h
> clang-modernize/LoopConvert/LoopMatchers.cpp
> clang-modernize/LoopConvert/LoopMatchers.h
> clang-modernize/LoopConvert/StmtAncestor.cpp
> clang-modernize/LoopConvert/StmtAncestor.h
> clang-modernize/LoopConvert/VariableNaming.cpp
> clang-modernize/LoopConvert/VariableNaming.h
> clang-modernize/Makefile
> clang-modernize/PassByValue/
> clang-modernize/PassByValue/PassByValue.cpp
> clang-modernize/PassByValue/PassByValue.h
> clang-modernize/PassByValue/PassByValueActions.cpp
> clang-modernize/PassByValue/PassByValueActions.h
> clang-modernize/PassByValue/PassByValueMatchers.cpp
> clang-modernize/PassByValue/PassByValueMatchers.h
> clang-modernize/ReplaceAutoPtr/
> clang-modernize/ReplaceAutoPtr/ReplaceAutoPtr.cpp
> clang-modernize/ReplaceAutoPtr/ReplaceAutoPtr.h
> clang-modernize/ReplaceAutoPtr/ReplaceAutoPtrActions.cpp
> clang-modernize/ReplaceAutoPtr/ReplaceAutoPtrActions.h
> clang-modernize/ReplaceAutoPtr/ReplaceAutoPtrMatchers.cpp
> clang-modernize/ReplaceAutoPtr/ReplaceAutoPtrMatchers.h
> clang-modernize/UseAuto/
> clang-modernize/UseAuto/UseAuto.cpp
> clang-modernize/UseAuto/UseAuto.h
> clang-modernize/UseAuto/UseAutoActions.cpp
> clang-modernize/UseAuto/UseAutoActions.h
> clang-modernize/UseAuto/UseAutoMatchers.cpp
> clang-modernize/UseAuto/UseAutoMatchers.h
> clang-modernize/UseNullptr/
> clang-modernize/UseNullptr/NullptrActions.cpp
> clang-modernize/UseNullptr/NullptrActions.h
> clang-modernize/UseNullptr/NullptrMatchers.cpp
> clang-modernize/UseNullptr/NullptrMatchers.h
> clang-modernize/UseNullptr/UseNullptr.cpp
> clang-modernize/UseNullptr/UseNullptr.h
> clang-modernize/tool/
> clang-modernize/tool/CMakeLists.txt
> clang-modernize/tool/ClangModernize.cpp
> clang-modernize/tool/Makefile
> docs/AddOverrideTransform.rst
> docs/LoopConvertTransform.rst
> docs/MigratorUsage.rst
> docs/ModernizerUsage.rst
> docs/PassByValueTransform.rst
> docs/ReplaceAutoPtrTransform.rst
> docs/UseAutoTransform.rst
> docs/UseNullptrTransform.rst
> docs/clang-modernize.rst
> docs/cpp11-migrate.rst
> docs/index.rst
> test/CMakeLists.txt
> test/clang-modernize/
> test/clang-modernize/AddOverride/
> test/clang-modernize/AddOverride/basic.cpp
> test/clang-modernize/AddOverride/pure_specifier_fail.cpp
> test/clang-modernize/Combined/
> test/clang-modernize/Combined/combined.cpp
> test/clang-modernize/Combined/compilers.cpp
> test/clang-modernize/Compilations/
> test/clang-modernize/Compilations/Inputs/
> test/clang-modernize/Compilations/Inputs/compilations.cpp
> test/clang-modernize/Compilations/Inputs/compilations_expected.cpp
> test/clang-modernize/Compilations/Inputs/compile_commands.json
> test/clang-modernize/Compilations/Inputs/cpp11.cpp
> test/clang-modernize/Compilations/Inputs/cpp11_expected.cpp
> test/clang-modernize/Compilations/compilation_inc.cpp
> test/clang-modernize/Compilations/compilation_inc_sources.cpp
> test/clang-modernize/Compilations/compilation_not_inc.cpp
> test/clang-modernize/Compilations/detect_from_path.cpp
> test/clang-modernize/Compilations/detect_from_source.cpp
> test/clang-modernize/Compilations/fixed_comp.cpp
> test/clang-modernize/Compilations/fixed_comp_inc.cpp
> test/clang-modernize/Compilations/no_compilation.cpp
> test/clang-modernize/Core/
> test/clang-modernize/Core/Inputs/
> test/clang-modernize/Core/Inputs/.clang-format
> test/clang-modernize/Core/Reformatting.cpp
> test/clang-modernize/HeaderReplacements/
> test/clang-modernize/HeaderReplacements/Inputs/
> test/clang-modernize/HeaderReplacements/Inputs/no_yaml.h
> test/clang-modernize/HeaderReplacements/common.cpp
> test/clang-modernize/HeaderReplacements/common.h
> test/clang-modernize/HeaderReplacements/common_expected.yaml
> test/clang-modernize/HeaderReplacements/main.cpp
> test/clang-modernize/HeaderReplacements/main_expected.yaml
> test/clang-modernize/HeaderReplacements/no_yaml.cpp
> test/clang-modernize/LoopConvert/
> test/clang-modernize/LoopConvert/Inputs/
> test/clang-modernize/LoopConvert/Inputs/macro_problem.h
> test/clang-modernize/LoopConvert/Inputs/negative-header.h
> test/clang-modernize/LoopConvert/Inputs/structures.h
> test/clang-modernize/LoopConvert/array.cpp
> test/clang-modernize/LoopConvert/confidence.cpp
> test/clang-modernize/LoopConvert/dependency.cpp
> test/clang-modernize/LoopConvert/free_begin_end_fail.cpp
> test/clang-modernize/LoopConvert/iterator.cpp
> test/clang-modernize/LoopConvert/macro_problem.cpp
> test/clang-modernize/LoopConvert/naming-alias.cpp
> test/clang-modernize/LoopConvert/naming-conflict.cpp
> test/clang-modernize/LoopConvert/negative-iterator.cpp
> test/clang-modernize/LoopConvert/negative-multi-end-call.cpp
> test/clang-modernize/LoopConvert/negative-pseudoarray-extra.cpp
> test/clang-modernize/LoopConvert/negative-pseudoarray.cpp
> test/clang-modernize/LoopConvert/negative.cpp
> test/clang-modernize/LoopConvert/nesting.cpp
> test/clang-modernize/LoopConvert/nocompile.cpp
> test/clang-modernize/LoopConvert/pseudoarray.cpp
> test/clang-modernize/LoopConvert/single-iterator.cpp
> test/clang-modernize/PassByValue/
> test/clang-modernize/PassByValue/basic.cpp
> test/clang-modernize/PassByValue/basic.h
> test/clang-modernize/ReplaceAutoPtr/
> test/clang-modernize/ReplaceAutoPtr/Inputs/
> test/clang-modernize/ReplaceAutoPtr/Inputs/basic.h
> test/clang-modernize/ReplaceAutoPtr/Inputs/memory_stub.h
> test/clang-modernize/ReplaceAutoPtr/basic.cpp
> test/clang-modernize/ReplaceAutoPtr/move.cpp
> test/clang-modernize/ReplaceAutoPtr/template_fail.cpp
> test/clang-modernize/UseAuto/
> test/clang-modernize/UseAuto/Inputs/
> test/clang-modernize/UseAuto/Inputs/test_std_container.h
> test/clang-modernize/UseAuto/basic_iterator_tests.cpp
> test/clang-modernize/UseAuto/iterator.cpp
> test/clang-modernize/UseAuto/new.cpp
> test/clang-modernize/UseAuto/new_cv_failing.cpp
> test/clang-modernize/UseNullptr/
> test/clang-modernize/UseNullptr/Inputs/
> test/clang-modernize/UseNullptr/Inputs/basic.h
> test/clang-modernize/UseNullptr/basic.cpp
> test/clang-modernize/UseNullptr/basic_failing.cpp
> test/clang-modernize/UseNullptr/macros.cpp
> test/clang-modernize/UseNullptr/nullptr_t.cpp
> unittests/CMakeLists.txt
> unittests/Makefile
> unittests/clang-modernize/
> unittests/clang-modernize/CMakeLists.txt
> unittests/clang-modernize/IncludeDirectivesTest.cpp
> unittests/clang-modernize/IncludeExcludeTest.cpp
> unittests/clang-modernize/Makefile
> unittests/clang-modernize/PerfSupportTest.cpp
> unittests/clang-modernize/TransformTest.cpp
> unittests/clang-modernize/UniqueHeaderNameTest.cpp
> unittests/include/common/Utility.h
>
> Index: unittests/include/common/Utility.h
> ===================================================================
> --- unittests/include/common/Utility.h
> +++ /dev/null
> @@ -1,25 +0,0 @@
> -//=-- clang-modernize/Utility.h - Utility functions and macros---*- C++ -*-===//
> -//
> -// The LLVM Compiler Infrastructure
> -//
> -// This file is distributed under the University of Illinois Open Source
> -// License. See LICENSE.TXT for details.
> -//
> -//===----------------------------------------------------------------------===//
> -
> -#ifndef CLANG_MODERNIZE_UNITTESTS_UTILITY_H
> -#define CLANG_MODERNIZE_UNITTESTS_UTILITY_H
> -
> -// FIXME: copied from unittests/Support/Path.cpp
> -#define ASSERT_NO_ERROR(x) \
> - if (std::error_code ASSERT_NO_ERROR_ec = x) { \
> - llvm::SmallString<128> MessageStorage; \
> - llvm::raw_svector_ostream Message(MessageStorage); \
> - Message << #x ": did not return errc::success.\n" \
> - << "error number: " << ASSERT_NO_ERROR_ec.value() << "\n" \
> - << "error message: " << ASSERT_NO_ERROR_ec.message() << "\n"; \
> - GTEST_FATAL_FAILURE_(MessageStorage.c_str()); \
> - } else { \
> - }
> -
> -#endif // CLANG_MODERNIZE_UNITTESTS_UTILITY_H
> Index: unittests/clang-modernize/UniqueHeaderNameTest.cpp
> ===================================================================
> --- unittests/clang-modernize/UniqueHeaderNameTest.cpp
> +++ /dev/null
> @@ -1,61 +0,0 @@
> -//===- unittests/clang-modernize/UniqueHeaderNameTest.cpp -----------------===//
> -//
> -// The LLVM Compiler Infrastructure
> -//
> -// This file is distributed under the University of Illinois Open Source
> -// License. See LICENSE.TXT for details.
> -//
> -//===----------------------------------------------------------------------===//
> -//
> -// Test for the generateReplacementsFileName() in FileOverrides.h
> -//
> -//===----------------------------------------------------------------------===//
> -
> -#include "gtest/gtest.h"
> -#include "Core/ReplacementHandling.h"
> -#include "llvm/Support/FileSystem.h"
> -#include "llvm/Support/Path.h"
> -#include "llvm/Support/Regex.h"
> -#include <system_error>
> -
> -TEST(UniqueHeaderName, testUniqueHeaderName) {
> - using namespace llvm::sys::path;
> -
> - llvm::SmallString<32> TmpDir;
> - system_temp_directory(true, TmpDir);
> -
> - llvm::SmallString<128> SourceFile(TmpDir);
> - append(SourceFile, "project/lib/feature.cpp");
> - native(SourceFile.str().str(), SourceFile);
> -
> - llvm::SmallString<128> DestDir(TmpDir);
> - append(DestDir, "replacements");
> -
> - llvm::SmallString<128> FullActualPath;
> - llvm::SmallString<128> Error;
> - bool Result = ReplacementHandling::generateReplacementsFileName(
> - DestDir, SourceFile, FullActualPath, Error);
> -
> - ASSERT_TRUE(Result);
> - EXPECT_TRUE(Error.empty());
> -
> - // We need to check the directory name and filename separately since on
> - // Windows, the path separator is '\' which is a regex escape character.
> - llvm::SmallString<128> ExpectedPath =
> - llvm::sys::path::parent_path(SourceFile);
> - llvm::SmallString<128> ActualPath =
> - llvm::sys::path::parent_path(FullActualPath);
> - llvm::SmallString<128> ActualName =
> - llvm::sys::path::filename(FullActualPath);
> -
> - EXPECT_STREQ(DestDir.c_str(), ActualPath.c_str());
> -
> - llvm::StringRef ExpectedName =
> - "^feature.cpp_[0-9a-f]{2}_[0-9a-f]{2}_[0-9a-f]{2}_[0-9a-f]{2}_["
> - "0-9a-f]{2}_[0-9a-f]{2}.yaml$";
> - llvm::Regex R(ExpectedName);
> - ASSERT_TRUE(R.match(ActualName))
> - << "ExpectedName: " << ExpectedName.data()
> - << "\nActualName: " << ActualName.c_str();
> - ASSERT_TRUE(Error.empty()) << "Error: " << Error.c_str();
> -}
> Index: unittests/clang-modernize/TransformTest.cpp
> ===================================================================
> --- unittests/clang-modernize/TransformTest.cpp
> +++ /dev/null
> @@ -1,299 +0,0 @@
> -//===- clang-modernize/TransformTest.cpp - Transform unit tests -----------===//
> -//
> -// The LLVM Compiler Infrastructure
> -//
> -// This file is distributed under the University of Illinois Open Source
> -// License. See LICENSE.TXT for details.
> -//
> -//===----------------------------------------------------------------------===//
> -
> -#include "gtest/gtest.h"
> -#include "Core/Transform.h"
> -#include "clang/AST/ASTConsumer.h"
> -#include "clang/AST/DeclGroup.h"
> -#include "clang/ASTMatchers/ASTMatchFinder.h"
> -#include "clang/ASTMatchers/ASTMatchers.h"
> -#include "llvm/Support/FileSystem.h"
> -#include "llvm/Support/Path.h"
> -#include "llvm/Support/Process.h"
> -
> -using namespace clang;
> -using namespace ast_matchers;
> -
> -class DummyTransform : public Transform {
> -public:
> - DummyTransform(llvm::StringRef Name, const TransformOptions &Options)
> - : Transform(Name, Options) {}
> -
> - int apply(const tooling::CompilationDatabase &,
> - const std::vector<std::string> &) override {
> - return 0;
> - }
> -
> - void setAcceptedChanges(unsigned Changes) {
> - Transform::setAcceptedChanges(Changes);
> - }
> - void setRejectedChanges(unsigned Changes) {
> - Transform::setRejectedChanges(Changes);
> - }
> - void setDeferredChanges(unsigned Changes) {
> - Transform::setDeferredChanges(Changes);
> - }
> -
> -};
> -
> -TEST(Transform, Interface) {
> - TransformOptions Options;
> - DummyTransform T("my_transform", Options);
> -
> - ASSERT_EQ("my_transform", T.getName());
> - ASSERT_EQ(0u, T.getAcceptedChanges());
> - ASSERT_EQ(0u, T.getRejectedChanges());
> - ASSERT_EQ(0u, T.getDeferredChanges());
> - ASSERT_FALSE(T.getChangesMade());
> - ASSERT_FALSE(T.getChangesNotMade());
> -
> - T.setAcceptedChanges(1);
> - ASSERT_TRUE(T.getChangesMade());
> -
> - T.setDeferredChanges(1);
> - ASSERT_TRUE(T.getChangesNotMade());
> -
> - T.setRejectedChanges(1);
> - ASSERT_TRUE(T.getChangesNotMade());
> -
> - T.Reset();
> - ASSERT_EQ(0u, T.getAcceptedChanges());
> - ASSERT_EQ(0u, T.getRejectedChanges());
> - ASSERT_EQ(0u, T.getDeferredChanges());
> -
> - T.setRejectedChanges(1);
> - ASSERT_TRUE(T.getChangesNotMade());
> -}
> -
> -class TimePassingASTConsumer : public ASTConsumer {
> -public:
> - TimePassingASTConsumer(bool *Called) : Called(Called) {}
> -
> - bool HandleTopLevelDecl(DeclGroupRef DeclGroup) override {
> - 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 {
> - std::unique_ptr<ASTConsumer> newASTConsumer() {
> - return llvm::make_unique<TimePassingASTConsumer>(&Called);
> - }
> - bool Called;
> -};
> -
> -struct CallbackForwarder : public clang::tooling::SourceFileCallbacks {
> - CallbackForwarder(Transform &Callee) : Callee(Callee) {}
> -
> - bool handleBeginSource(CompilerInstance &CI, StringRef Filename) override {
> - return Callee.handleBeginSource(CI, Filename);
> - }
> -
> - void handleEndSource() override { Callee.handleEndSource(); }
> -
> - Transform &Callee;
> -};
> -
> -TEST(Transform, Timings) {
> - TransformOptions Options;
> - Options.EnableTiming = true;
> - DummyTransform T("timing_transform", Options);
> -
> - // 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().
> - SmallString<128> CurrentDir;
> - std::error_code EC = llvm::sys::fs::current_path(CurrentDir);
> - assert(!EC);
> - (void)EC;
> -
> - SmallString<128> FileA = CurrentDir;
> - llvm::sys::path::append(FileA, "a.cc");
> -
> - SmallString<128> FileB = CurrentDir;
> - llvm::sys::path::append(FileB, "b.cc");
> -
> - tooling::FixedCompilationDatabase Compilations(CurrentDir.str(),
> - std::vector<std::string>());
> - std::vector<std::string> Sources;
> - Sources.push_back(FileA.str());
> - Sources.push_back(FileB.str());
> - tooling::ClangTool Tool(Compilations, Sources);
> -
> - Tool.mapVirtualFile(FileA, "void a() {}");
> - Tool.mapVirtualFile(FileB, "void b() {}");
> -
> - // Factory to create TimePassingASTConsumer for each source file the tool
> - // runs on.
> - ConsumerFactory Factory;
> -
> - // We don't care about any of Transform's functionality except to get it to
> - // record timings. For that, we need to forward handleBeginSource() and
> - // handleEndSource() calls to it.
> - CallbackForwarder Callbacks(T);
> -
> - Tool.run(
> - clang::tooling::newFrontendActionFactory(&Factory, &Callbacks).get());
> -
> - 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.
> - StringRef FirstFile = I->first;
> - if (FileA == FirstFile) {
> - ++I;
> - EXPECT_EQ(FileB, I->first);
> - EXPECT_GT(I->second.getProcessTime(), 0.0);
> - } else if (FileB == FirstFile) {
> - ++I;
> - EXPECT_EQ(FileA, 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);
> -}
> -
> -class ModifiableCallback
> - : public clang::ast_matchers::MatchFinder::MatchCallback {
> -public:
> - ModifiableCallback(const Transform &Owner)
> - : Owner(Owner) {}
> -
> - void
> - run(const clang::ast_matchers::MatchFinder::MatchResult &Result) override {
> - const VarDecl *Decl = Result.Nodes.getNodeAs<VarDecl>("decl");
> - ASSERT_TRUE(Decl != nullptr);
> -
> - const SourceManager &SM = *Result.SourceManager;
> -
> - // Decl 'a' comes from the main source file. This test should always pass.
> - if (Decl->getName().equals("a"))
> - EXPECT_TRUE(Owner.isFileModifiable(SM, Decl->getLocStart()));
> -
> - // Decl 'c' comes from an excluded header. This test should never pass.
> - else if (Decl->getName().equals("c"))
> - EXPECT_FALSE(Owner.isFileModifiable(SM, Decl->getLocStart()));
> -
> - // Decl 'b' comes from an included header.
> - else if (Decl->getName().equals("b"))
> - EXPECT_TRUE(Owner.isFileModifiable(SM, Decl->getLocStart()));
> -
> - // Make sure edge cases are handled gracefully (they should never be
> - // allowed).
> - SourceLocation DummyLoc;
> - EXPECT_FALSE(Owner.isFileModifiable(SM, DummyLoc));
> - }
> -
> -private:
> - const Transform &Owner;
> -};
> -
> -TEST(Transform, isFileModifiable) {
> - TransformOptions Options;
> -
> - ///
> - /// SETUP
> - ///
> - /// To test Transform::isFileModifiable() we need a SourceManager primed with
> - /// actual files and SourceLocations to test. Easiest way to accomplish this
> - /// is to use Tooling classes.
> - ///
> - /// 1) Simulate a source file that includes two headers, one that is allowed
> - /// to be modified and the other that is not allowed. Each of the three
> - /// files involved will declare a single variable with a different name.
> - /// 2) A matcher is created to find VarDecls.
> - /// 3) A MatchFinder callback calls Transform::isFileModifiable() with the
> - /// SourceLocations of found VarDecls and thus tests the function.
> - ///
> -
> - // 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().
> - SmallString<128> CurrentDir;
> - std::error_code EC = llvm::sys::fs::current_path(CurrentDir);
> - assert(!EC);
> - (void)EC;
> -
> - SmallString<128> SourceFile = CurrentDir;
> - llvm::sys::path::append(SourceFile, "a.cc");
> -
> - SmallString<128> HeaderFile = CurrentDir;
> - llvm::sys::path::append(HeaderFile, "a.h");
> -
> - SmallString<128> HeaderBFile = CurrentDir;
> - llvm::sys::path::append(HeaderBFile, "temp");
> - llvm::sys::path::append(HeaderBFile, "b.h");
> -
> - StringRef ExcludeDir = llvm::sys::path::parent_path(HeaderBFile);
> -
> - IncludeExcludeInfo IncInfo;
> - Options.ModifiableFiles.readListFromString(CurrentDir, ExcludeDir);
> -
> - tooling::FixedCompilationDatabase Compilations(CurrentDir.str(),
> - std::vector<std::string>());
> - std::vector<std::string> Sources;
> - Sources.push_back(SourceFile.str());
> - tooling::ClangTool Tool(Compilations, Sources);
> -
> - Tool.mapVirtualFile(SourceFile,
> - "#include \"a.h\"\n"
> - "#include \"temp/b.h\"\n"
> - "int a;");
> - Tool.mapVirtualFile(HeaderFile, "int b;");
> - Tool.mapVirtualFile(HeaderBFile, "int c;");
> -
> - DummyTransform T("dummy", Options);
> - MatchFinder Finder;
> - ModifiableCallback Callback(T);
> - Finder.addMatcher(varDecl().bind("decl"), &Callback);
> - Tool.run(tooling::newFrontendActionFactory(&Finder).get());
> -}
> -
> -TEST(VersionTest, Interface) {
> - Version V;
> -
> - ASSERT_TRUE(V.isNull());
> - ASSERT_TRUE(Version(1) < Version(1, 1));
> - ASSERT_TRUE(Version(1) < Version(2));
> - ASSERT_TRUE(Version(1, 1) < Version(2));
> - ASSERT_TRUE(Version(1, 1) == Version(1, 1));
> - ASSERT_EQ(Version(1).getMajor(), unsigned(1));
> - ASSERT_EQ(Version(1).getMinor(), unsigned(0));
> - ASSERT_EQ(Version(1, 2).getMinor(), unsigned(2));
> -}
> -
> -TEST(VersionTest, getFromString) {
> - ASSERT_EQ(Version(1), Version::getFromString("1"));
> - ASSERT_EQ(Version(1, 2), Version::getFromString("1.2"));
> - ASSERT_TRUE(Version::getFromString("foo").isNull());
> - ASSERT_TRUE(Version::getFromString("1bar").isNull());
> - // elements after major.minor are ignored
> - ASSERT_EQ(Version(1, 2), Version::getFromString("1.2.3"));
> -}
> Index: unittests/clang-modernize/PerfSupportTest.cpp
> ===================================================================
> --- unittests/clang-modernize/PerfSupportTest.cpp
> +++ /dev/null
> @@ -1,97 +0,0 @@
> -//===- clang-modernize/PerfSupportTest.cpp - PerfSupport unit tests -------===//
> -//
> -// The LLVM Compiler Infrastructure
> -//
> -// This file is distributed under the University of Illinois Open Source
> -// License. See LICENSE.TXT for details.
> -//
> -//===----------------------------------------------------------------------===//
> -
> -#include "gtest/gtest.h"
> -#include "Core/PerfSupport.h"
> -
> -using namespace llvm;
> -using namespace clang;
> -
> -class TransformA : public Transform {
> -public:
> - TransformA(const TransformOptions &Options)
> - : Transform("TransformA", Options) {}
> -
> - int apply(const tooling::CompilationDatabase &,
> - const std::vector<std::string> &) override {
> - return 0;
> - }
> -
> - void addTiming(StringRef Label, TimeRecord Duration) {
> - Transform::addTiming(Label, Duration);
> - }
> -};
> -
> -class TransformB : public Transform {
> -public:
> - TransformB(const TransformOptions &Options)
> - : Transform("TransformB", Options) {}
> -
> - int apply(const tooling::CompilationDatabase &,
> - const std::vector<std::string> &) override {
> - return 0;
> - }
> -
> - void addTiming(StringRef Label, TimeRecord Duration) {
> - Transform::addTiming(Label, Duration);
> - }
> -};
> -
> -struct ExpectedResults {
> - const char *SourceName;
> - unsigned DataCount;
> - struct Datum {
> - const char *Label;
> - float Duration;
> - } Data[2];
> -};
> -
> -TEST(PerfSupport, collectSourcePerfData) {
> - TransformOptions Options;
> - TransformA A(Options);
> - TransformB B(Options);
> -
> - // The actual durations don't matter. Below only their relative ordering is
> - // tested to ensure times, labels, and sources all stay together properly.
> - A.addTiming("FileA.cpp", TimeRecord::getCurrentTime(/*Start=*/true));
> - A.addTiming("FileC.cpp", TimeRecord::getCurrentTime(/*Start=*/true));
> - B.addTiming("FileC.cpp", TimeRecord::getCurrentTime(/*Start=*/true));
> - B.addTiming("FileB.cpp", TimeRecord::getCurrentTime(/*Start=*/true));
> -
> - SourcePerfData PerfData;
> - collectSourcePerfData(A, PerfData);
> -
> - SourcePerfData::const_iterator FileAI = PerfData.find("FileA.cpp");
> - EXPECT_NE(FileAI, PerfData.end());
> - SourcePerfData::const_iterator FileCI = PerfData.find("FileC.cpp");
> - EXPECT_NE(FileCI, PerfData.end());
> - EXPECT_EQ(2u, PerfData.size());
> -
> - EXPECT_EQ(1u, FileAI->second.size());
> - EXPECT_EQ("TransformA", FileAI->second[0].Label);
> - EXPECT_EQ(1u, FileCI->second.size());
> - EXPECT_EQ("TransformA", FileCI->second[0].Label);
> - EXPECT_LE(FileAI->second[0].Duration, FileCI->second[0].Duration);
> -
> - collectSourcePerfData(B, PerfData);
> -
> - SourcePerfData::const_iterator FileBI = PerfData.find("FileB.cpp");
> - EXPECT_NE(FileBI, PerfData.end());
> - EXPECT_EQ(3u, PerfData.size());
> -
> - EXPECT_EQ(1u, FileAI->second.size());
> - EXPECT_EQ("TransformA", FileAI->second[0].Label);
> - EXPECT_EQ(2u, FileCI->second.size());
> - EXPECT_EQ("TransformA", FileCI->second[0].Label);
> - EXPECT_EQ("TransformB", FileCI->second[1].Label);
> - EXPECT_LE(FileCI->second[0].Duration, FileCI->second[1].Duration);
> - EXPECT_EQ(1u, FileBI->second.size());
> - EXPECT_EQ("TransformB", FileBI->second[0].Label);
> - EXPECT_LE(FileCI->second[1].Duration, FileBI->second[0].Duration);
> -}
> Index: unittests/clang-modernize/Makefile
> ===================================================================
> --- unittests/clang-modernize/Makefile
> +++ /dev/null
> @@ -1,27 +0,0 @@
> -##===- unittests/clang-modernize/Makefile ------------------*- Makefile -*-===##
> -#
> -# The LLVM Compiler Infrastructure
> -#
> -# This file is distributed under the University of Illinois Open Source
> -# License. See LICENSE.TXT for details.
> -#
> -##===----------------------------------------------------------------------===##
> -
> -CLANG_LEVEL = ../../../..
> -include $(CLANG_LEVEL)/../../Makefile.config
> -
> -TESTNAME = ClangModernizeTests
> -LINK_COMPONENTS := asmparser bitreader support MC MCParser option \
> - TransformUtils
> -USEDLIBS = modernizeCore.a clangFormat.a clangApplyReplacements.a \
> - clangTooling.a clangToolingCore.a clangFrontend.a \
> - clangSerialization.a clangDriver.a clangRewriteFrontend.a \
> - clangRewrite.a clangParse.a clangSema.a clangAnalysis.a \
> - clangAST.a clangASTMatchers.a clangEdit.a clangLex.a \
> - clangBasic.a
> -
> -include $(CLANG_LEVEL)/Makefile
> -MAKEFILE_UNITTEST_NO_INCLUDE_COMMON := 1
> -CPP.Flags += -I$(PROJ_SRC_DIR)/../../clang-modernize -I$(PROJ_SRC_DIR)/../../clang-apply-replacements/include \
> - -I$(PROJ_SRC_DIR)/../include
> -include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest
> Index: unittests/clang-modernize/IncludeExcludeTest.cpp
> ===================================================================
> --- unittests/clang-modernize/IncludeExcludeTest.cpp
> +++ /dev/null
> @@ -1,149 +0,0 @@
> -//===- clang-modernize/IncludeExcludeTest.cpp - IncludeExclude unit tests -===//
> -//
> -// The LLVM Compiler Infrastructure
> -//
> -// This file is distributed under the University of Illinois Open Source
> -// License. See LICENSE.TXT for details.
> -//
> -//===----------------------------------------------------------------------===//
> -
> -#include "common/Utility.h"
> -#include "Core/IncludeExcludeInfo.h"
> -#include "llvm/Support/FileSystem.h"
> -#include "llvm/Support/Path.h"
> -#include "gtest/gtest.h"
> -#include <fstream>
> -
> -TEST(IncludeExcludeTest, ParseString) {
> - IncludeExcludeInfo IEManager;
> - std::error_code Err = IEManager.readListFromString(
> - /*include=*/ "a,b/b2,c/c2,d/../d2/../d3",
> - /*exclude=*/ "a/af.cpp,a/a2,b/b2/b2f.cpp,c/c2");
> -
> - ASSERT_EQ(Err, std::error_code());
> -
> - // If the file does not appear on the include list then it is not safe to
> - // transform. Files are not safe to transform by default.
> - EXPECT_FALSE(IEManager.isFileIncluded("f.cpp"));
> - EXPECT_FALSE(IEManager.isFileIncluded("b/dir/f.cpp"));
> - EXPECT_FALSE(IEManager.isFileIncluded("d/f.cpp"));
> - EXPECT_FALSE(IEManager.isFileIncluded("d2/f.cpp"));
> -
> - // If the file appears on only the include list then it is safe to transform.
> - EXPECT_TRUE(IEManager.isFileIncluded("a/f.cpp"));
> - EXPECT_TRUE(IEManager.isFileIncluded("a/dir/f.cpp"));
> - EXPECT_TRUE(IEManager.isFileIncluded("b/b2/f.cpp"));
> - EXPECT_TRUE(IEManager.isFileIncluded("d3/f.cpp"));
> -
> - // If the file appears on both the include or exclude list then it is not
> - // safe to transform.
> - EXPECT_FALSE(IEManager.isFileIncluded("a/af.cpp"));
> - EXPECT_FALSE(IEManager.isFileIncluded("a/a2/f.cpp"));
> - EXPECT_FALSE(IEManager.isFileIncluded("a/a2/dir/f.cpp"));
> - EXPECT_FALSE(IEManager.isFileIncluded("b/b2/b2f.cpp"));
> - EXPECT_FALSE(IEManager.isFileIncluded("c/c2/c3/f.cpp"));
> -
> -#ifdef LLVM_ON_WIN32
> - // Check for cases when the path separators are different between the path
> - // that was read and the path that we are checking for. This can happen on
> - // windows where lit provides "\" and the test has "/".
> - ASSERT_NO_ERROR(IEManager.readListFromString(
> - /*include=*/ "C:\\foo,a\\b/c,a/../b\\c/..\\d",
> - /*exclude=*/ "C:\\bar"
> - ));
> - EXPECT_TRUE(IEManager.isFileIncluded("C:/foo/code.h"));
> - EXPECT_FALSE(IEManager.isFileIncluded("C:/bar/code.h"));
> - EXPECT_TRUE(IEManager.isFileIncluded("a/b\\c/code.h"));
> - EXPECT_FALSE(IEManager.isFileIncluded("b\\c/code.h"));
> - EXPECT_TRUE(IEManager.isFileIncluded("b/d\\code.h"));
> -#endif
> -}
> -
> -TEST(IncludeExcludeTest, ParseStringCases) {
> - IncludeExcludeInfo IEManager;
> - std::error_code Err = IEManager.readListFromString(
> - /*include=*/ "a/.,b/b2/,c/c2/c3/../../c4/,d/d2/./d3/,/e/e2/.",
> - /*exclude=*/ "");
> -
> - ASSERT_EQ(Err, std::error_code());
> -
> - EXPECT_TRUE(IEManager.isFileIncluded("a/f.cpp"));
> - EXPECT_TRUE(IEManager.isFileIncluded("b/b2/f.cpp"));
> - EXPECT_TRUE(IEManager.isFileIncluded("c/c4/f.cpp"));
> - EXPECT_TRUE(IEManager.isFileIncluded("d/d2/d3/f.cpp"));
> - EXPECT_TRUE(IEManager.isFileIncluded("/e/e2/f.cpp"));
> -
> - EXPECT_FALSE(IEManager.isFileIncluded("c/c2/c3/f.cpp"));
> -}
> -
> -// Utility for creating and filling files with data for IncludeExcludeFileTest
> -// tests.
> -struct InputFiles {
> -
> - // This function uses fatal assertions. The caller is responsible for making
> - // sure fatal assertions propagate.
> - void CreateFiles(bool UnixMode) {
> - llvm::SmallString<128> Path;
> - int FD;
> -
> - ASSERT_NO_ERROR(
> - llvm::sys::fs::createTemporaryFile("include", "", FD, Path));
> - IncludeDataPath = Path.str();
> - {
> - llvm::raw_fd_ostream IncludeDataFile(FD, true);
> - for (unsigned i = 0; i < sizeof(IncludeData) / sizeof(char *); ++i) {
> - IncludeDataFile << IncludeData[i] << (UnixMode ? "\n" : "\r\n");
> - }
> - }
> -
> - ASSERT_NO_ERROR(
> - llvm::sys::fs::createTemporaryFile("exclude", "", FD, Path));
> - ExcludeDataPath = Path.str();
> - {
> - llvm::raw_fd_ostream ExcludeDataFile(FD, true);
> - for (unsigned i = 0; i < sizeof(ExcludeData) / sizeof(char *); ++i) {
> - ExcludeDataFile << ExcludeData[i] << (UnixMode ? "\n" : "\r\n");
> - }
> - }
> - }
> -
> - static const char *IncludeData[3];
> - static const char *ExcludeData[4];
> -
> - std::string IncludeDataPath;
> - std::string ExcludeDataPath;
> -};
> -
> -const char *InputFiles::IncludeData[3] = { "a", "b/b2", "c/c2" };
> -const char *InputFiles::ExcludeData[4] = { "a/af.cpp", "a/a2", "b/b2/b2f.cpp",
> - "c/c2" };
> -
> -TEST(IncludeExcludeFileTest, UNIXFile) {
> - InputFiles UnixFiles;
> - ASSERT_NO_FATAL_FAILURE(UnixFiles.CreateFiles(/* UnixMode= */true));
> -
> - IncludeExcludeInfo IEManager;
> - std::error_code Err = IEManager.readListFromFile(
> - UnixFiles.IncludeDataPath.c_str(), UnixFiles.ExcludeDataPath.c_str());
> -
> - ASSERT_EQ(Err, std::error_code());
> -
> - EXPECT_FALSE(IEManager.isFileIncluded("f.cpp"));
> - EXPECT_TRUE(IEManager.isFileIncluded("a/f.cpp"));
> - EXPECT_FALSE(IEManager.isFileIncluded("a/af.cpp"));
> -}
> -
> -TEST(IncludeExcludeFileTest, DOSFile) {
> - InputFiles DOSFiles;
> - ASSERT_NO_FATAL_FAILURE(DOSFiles.CreateFiles(/* UnixMode= */false));
> -
> - IncludeExcludeInfo IEManager;
> - std::error_code Err = IEManager.readListFromFile(
> - DOSFiles.IncludeDataPath.c_str(), DOSFiles.ExcludeDataPath.c_str());
> -
> - ASSERT_EQ(Err, std::error_code());
> -
> - EXPECT_FALSE(IEManager.isFileIncluded("f.cpp"));
> - EXPECT_TRUE(IEManager.isFileIncluded("a/f.cpp"));
> - EXPECT_FALSE(IEManager.isFileIncluded("a/af.cpp"));
> -}
> Index: unittests/clang-modernize/IncludeDirectivesTest.cpp
> ===================================================================
> --- unittests/clang-modernize/IncludeDirectivesTest.cpp
> +++ /dev/null
> @@ -1,410 +0,0 @@
> -//===- clang-modernize/IncludeDirectivesTest.cpp --------------------------===//
> -//
> -// The LLVM Compiler Infrastructure
> -//
> -// This file is distributed under the University of Illinois Open Source
> -// License. See LICENSE.TXT for details.
> -//
> -//===----------------------------------------------------------------------===//
> -
> -#include "Core/IncludeDirectives.h"
> -#include "common/VirtualFileHelper.h"
> -#include "clang/Frontend/CompilerInstance.h"
> -#include "clang/Frontend/FrontendActions.h"
> -#include "llvm/Support/Path.h"
> -#include "gtest/gtest.h"
> -
> -using namespace llvm;
> -using namespace clang;
> -
> -/// \brief A convenience method around \c tooling::runToolOnCodeWithArgs() that
> -/// adds the current directory to the include search paths.
> -static void applyActionOnCode(FrontendAction *ToolAction, StringRef Code) {
> - SmallString<128> CurrentDir;
> - ASSERT_FALSE(llvm::sys::fs::current_path(CurrentDir));
> -
> - // Add the current directory to the header search paths so angled includes can
> - // find them.
> - std::vector<std::string> Args;
> - Args.push_back("-I");
> - Args.push_back(CurrentDir.str().str());
> -
> - // mapVirtualFile() needs absolute path for the input file as well.
> - SmallString<128> InputFile(CurrentDir);
> - sys::path::append(InputFile, "input.cc");
> -
> - ASSERT_TRUE(
> - tooling::runToolOnCodeWithArgs(ToolAction, Code, Args, InputFile.str()));
> -}
> -
> -namespace {
> -class TestAddIncludeAction : public PreprocessOnlyAction {
> -public:
> - TestAddIncludeAction(StringRef Include, tooling::Replacements &Replaces,
> - const char *HeaderToModify = nullptr)
> - : Include(Include), Replaces(Replaces), HeaderToModify(HeaderToModify) {
> - // some headers that the tests can include
> - mapVirtualHeader("foo-inner.h", "#pragma once\n");
> - mapVirtualHeader("foo.h", "#pragma once\n"
> - "#include <foo-inner.h>\n");
> - mapVirtualHeader("bar-inner.h", "#pragma once\n");
> - mapVirtualHeader("bar.h", "#pragma once\n"
> - "#include <bar-inner.h>\n");
> - mapVirtualHeader("xmacro.def", "X(Val1)\n"
> - "X(Val2)\n"
> - "X(Val3)\n");
> - }
> -
> - /// \brief Make \p FileName an absolute path.
> - ///
> - /// Header files are mapped in the current working directory. The current
> - /// working directory is used because it's important to map files with
> - /// absolute paths.
> - ///
> - /// When used in conjunction with \c applyActionOnCode() (which adds the
> - /// current working directory to the header search paths) it is possible to
> - /// refer to the headers by using '\<FileName\>'.
> - std::string makeHeaderFileName(StringRef FileName) const {
> - SmallString<128> Path;
> - std::error_code EC = llvm::sys::fs::current_path(Path);
> - assert(!EC);
> - (void)EC;
> -
> - sys::path::append(Path, FileName);
> - return Path.str().str();
> - }
> -
> - /// \brief Map additional header files.
> - ///
> - /// \sa makeHeaderFileName()
> - void mapVirtualHeader(StringRef FileName, StringRef Content) {
> - VFHelper.mapFile(makeHeaderFileName(FileName), Content);
> - }
> -
> -private:
> - bool BeginSourceFileAction(CompilerInstance &CI,
> - StringRef FileName) override {
> - if (!PreprocessOnlyAction::BeginSourceFileAction(CI, FileName))
> - return false;
> - VFHelper.mapVirtualFiles(CI.getSourceManager());
> -
> - FileToModify =
> - HeaderToModify ? makeHeaderFileName(HeaderToModify) : FileName.str();
> -
> - FileIncludes.reset(new IncludeDirectives(CI));
> - return true;
> - }
> -
> - void EndSourceFileAction() override {
> - const tooling::Replacement &Replace =
> - FileIncludes->addAngledInclude(FileToModify, Include);
> - if (Replace.isApplicable())
> - Replaces.insert(Replace);
> - }
> -
> - StringRef Include;
> - VirtualFileHelper VFHelper;
> - tooling::Replacements &Replaces;
> - std::unique_ptr<IncludeDirectives> FileIncludes;
> - std::string FileToModify;
> - // if non-null, add the include directives in this file instead of the main
> - // file.
> - const char *HeaderToModify;
> -};
> -
> -std::string addIncludeInCode(StringRef Include, StringRef Code) {
> - tooling::Replacements Replaces;
> -
> - applyActionOnCode(new TestAddIncludeAction(Include, Replaces), Code);
> -
> - if (::testing::Test::HasFailure())
> - return "<<unexpected error from applyActionOnCode()>>";
> -
> - return tooling::applyAllReplacements(Code, Replaces);
> -}
> -} // end anonymous namespace
> -
> -TEST(IncludeDirectivesTest2, endOfLinesVariants) {
> - EXPECT_EQ("#include <foo.h>\n"
> - "#include <bar>\n",
> - addIncludeInCode("bar", "#include <foo.h>\n"));
> - EXPECT_EQ("#include <foo.h>\r\n"
> - "#include <bar>\r\n",
> - addIncludeInCode("bar", "#include <foo.h>\r\n"));
> - EXPECT_EQ("#include <foo.h>\r"
> - "#include <bar>\r",
> - addIncludeInCode("bar", "#include <foo.h>\r"));
> -}
> -
> -TEST(IncludeDirectivesTest, ppToken) {
> - EXPECT_EQ("#define FOO <foo.h>\n"
> - "#include FOO\n"
> - "#include <bar>\n"
> - "int i;\n",
> - addIncludeInCode("bar", "#define FOO <foo.h>\n"
> - "#include FOO\n"
> - "int i;\n"));
> -}
> -
> -TEST(IncludeDirectivesTest, noFileHeader) {
> - EXPECT_EQ("#include <bar>\n"
> - "\n"
> - "int foo;\n",
> - addIncludeInCode("bar", "int foo;\n"));
> -}
> -
> -TEST(IncludeDirectivesTest, commentBeforeTopMostCode) {
> - EXPECT_EQ("#include <bar>\n"
> - "\n"
> - "// Foo\n"
> - "int foo;\n",
> - addIncludeInCode("bar", "// Foo\n"
> - "int foo;\n"));
> -}
> -
> -TEST(IncludeDirectivesTest, multiLineComment) {
> - EXPECT_EQ("#include <foo.h> /* \n */\n"
> - "#include <bar>\n",
> - addIncludeInCode("bar", "#include <foo.h> /* \n */\n"));
> - EXPECT_EQ("#include <foo.h> /* \n */"
> - "\n#include <bar>",
> - addIncludeInCode("bar", "#include <foo.h> /* \n */"));
> -}
> -
> -TEST(IncludeDirectivesTest, multilineCommentWithTrailingSpace) {
> - EXPECT_EQ("#include <foo.h> /*\n*/ \n"
> - "#include <bar>\n",
> - addIncludeInCode("bar", "#include <foo.h> /*\n*/ \n"));
> - EXPECT_EQ("#include <foo.h> /*\n*/ "
> - "\n#include <bar>",
> - addIncludeInCode("bar", "#include <foo.h> /*\n*/ "));
> -}
> -
> -TEST(IncludeDirectivesTest, fileHeaders) {
> - EXPECT_EQ("// this is a header\n"
> - "// some license stuff here\n"
> - "\n"
> - "#include <bar>\n"
> - "\n"
> - "/// \\brief Foo\n"
> - "int foo;\n",
> - addIncludeInCode("bar", "// this is a header\n"
> - "// some license stuff here\n"
> - "\n"
> - "/// \\brief Foo\n"
> - "int foo;\n"));
> -}
> -
> -TEST(IncludeDirectivesTest, preferablyAngledNextToAngled) {
> - EXPECT_EQ("#include <foo.h>\n"
> - "#include <bar>\n"
> - "#include \"bar.h\"\n",
> - addIncludeInCode("bar", "#include <foo.h>\n"
> - "#include \"bar.h\"\n"));
> - EXPECT_EQ("#include \"foo.h\"\n"
> - "#include \"bar.h\"\n"
> - "#include <bar>\n",
> - addIncludeInCode("bar", "#include \"foo.h\"\n"
> - "#include \"bar.h\"\n"));
> -}
> -
> -TEST(IncludeDirectivesTest, avoidDuplicates) {
> - EXPECT_EQ("#include <foo.h>\n",
> - addIncludeInCode("foo.h", "#include <foo.h>\n"));
> -}
> -
> -// Tests includes in the middle of the code are ignored.
> -TEST(IncludeDirectivesTest, ignoreHeadersMeantForMultipleInclusion) {
> - std::string Expected = "#include \"foo.h\"\n"
> - "#include <bar>\n"
> - "\n"
> - "enum Kind {\n"
> - "#define X(A) K_##A,\n"
> - "#include \"xmacro.def\"\n"
> - "#undef X\n"
> - " K_NUM_KINDS\n"
> - "};\n";
> - std::string Result = addIncludeInCode("bar", "#include \"foo.h\"\n"
> - "\n"
> - "enum Kind {\n"
> - "#define X(A) K_##A,\n"
> - "#include \"xmacro.def\"\n"
> - "#undef X\n"
> - " K_NUM_KINDS\n"
> - "};\n");
> - EXPECT_EQ(Expected, Result);
> -}
> -
> -namespace {
> -TestAddIncludeAction *makeIndirectTestsAction(const char *HeaderToModify,
> - tooling::Replacements &Replaces) {
> - StringRef IncludeToAdd = "c.h";
> - TestAddIncludeAction *TestAction =
> - new TestAddIncludeAction(IncludeToAdd, Replaces, HeaderToModify);
> - TestAction->mapVirtualHeader("c.h", "#pragma once\n");
> - TestAction->mapVirtualHeader("a.h", "#pragma once\n"
> - "#include <c.h>\n");
> - TestAction->mapVirtualHeader("b.h", "#pragma once\n");
> - return TestAction;
> -}
> -} // end anonymous namespace
> -
> -TEST(IncludeDirectivesTest, indirectIncludes) {
> - // In TestAddIncludeAction 'foo.h' includes 'foo-inner.h'. Check that we
> - // aren't including foo-inner.h again.
> - EXPECT_EQ("#include <foo.h>\n",
> - addIncludeInCode("foo-inner.h", "#include <foo.h>\n"));
> -
> - tooling::Replacements Replaces;
> - StringRef Code = "#include <a.h>\n"
> - "#include <b.h>\n";
> -
> - // a.h already includes c.h
> - {
> - FrontendAction *Action = makeIndirectTestsAction("a.h", Replaces);
> - ASSERT_NO_FATAL_FAILURE(applyActionOnCode(Action, Code));
> - EXPECT_EQ(unsigned(0), Replaces.size());
> - }
> -
> - // c.h is included before b.h but b.h doesn't include c.h directly, so check
> - // that it will be inserted.
> - {
> - FrontendAction *Action = makeIndirectTestsAction("b.h", Replaces);
> - ASSERT_NO_FATAL_FAILURE(applyActionOnCode(Action, Code));
> - EXPECT_EQ("#include <c.h>\n\n\n",
> - tooling::applyAllReplacements("\n", Replaces));
> - }
> -}
> -
> -/// \brief Convenience method to test header guards detection implementation.
> -static std::string addIncludeInGuardedHeader(StringRef IncludeToAdd,
> - StringRef GuardedHeaderCode) {
> - const char *GuardedHeaderName = "guarded.h";
> - tooling::Replacements Replaces;
> - TestAddIncludeAction *TestAction =
> - new TestAddIncludeAction(IncludeToAdd, Replaces, GuardedHeaderName);
> - TestAction->mapVirtualHeader(GuardedHeaderName, GuardedHeaderCode);
> -
> - applyActionOnCode(TestAction, "#include <guarded.h>\n");
> - if (::testing::Test::HasFailure())
> - return "<<unexpected error from applyActionOnCode()>>";
> -
> - return tooling::applyAllReplacements(GuardedHeaderCode, Replaces);
> -}
> -
> -TEST(IncludeDirectivesTest, insertInsideIncludeGuard) {
> - EXPECT_EQ("#ifndef GUARD_H\n"
> - "#define GUARD_H\n"
> - "\n"
> - "#include <foo>\n"
> - "\n"
> - "struct foo {};\n"
> - "\n"
> - "#endif // GUARD_H\n",
> - addIncludeInGuardedHeader("foo", "#ifndef GUARD_H\n"
> - "#define GUARD_H\n"
> - "\n"
> - "struct foo {};\n"
> - "\n"
> - "#endif // GUARD_H\n"));
> -}
> -
> -TEST(IncludeDirectivesTest, guardAndHeader) {
> - EXPECT_EQ("// File header\n"
> - "\n"
> - "#ifndef GUARD_H\n"
> - "#define GUARD_H\n"
> - "\n"
> - "#include <foo>\n"
> - "\n"
> - "struct foo {};\n"
> - "\n"
> - "#endif // GUARD_H\n",
> - addIncludeInGuardedHeader("foo", "// File header\n"
> - "\n"
> - "#ifndef GUARD_H\n"
> - "#define GUARD_H\n"
> - "\n"
> - "struct foo {};\n"
> - "\n"
> - "#endif // GUARD_H\n"));
> -}
> -
> -TEST(IncludeDirectivesTest, fullHeaderFitsAsAPreamble) {
> - EXPECT_EQ("#ifndef GUARD_H\n"
> - "#define GUARD_H\n"
> - "\n"
> - "#include <foo>\n"
> - "\n"
> - "#define FOO 1\n"
> - "\n"
> - "#endif // GUARD_H\n",
> - addIncludeInGuardedHeader("foo", "#ifndef GUARD_H\n"
> - "#define GUARD_H\n"
> - "\n"
> - "#define FOO 1\n"
> - "\n"
> - "#endif // GUARD_H\n"));
> -}
> -
> -TEST(IncludeDirectivesTest, codeBeforeIfndef) {
> - EXPECT_EQ("#include <foo>\n"
> - "\n"
> - "int bar;\n"
> - "\n"
> - "#ifndef GUARD_H\n"
> - "#define GUARD_H\n"
> - "\n"
> - "struct foo;"
> - "\n"
> - "#endif // GUARD_H\n",
> - addIncludeInGuardedHeader("foo", "int bar;\n"
> - "\n"
> - "#ifndef GUARD_H\n"
> - "#define GUARD_H\n"
> - "\n"
> - "struct foo;"
> - "\n"
> - "#endif // GUARD_H\n"));
> -}
> -
> -TEST(IncludeDirectivesTest, codeAfterEndif) {
> - EXPECT_EQ("#include <foo>\n"
> - "\n"
> - "#ifndef GUARD_H\n"
> - "#define GUARD_H\n"
> - "\n"
> - "struct foo;"
> - "\n"
> - "#endif // GUARD_H\n"
> - "\n"
> - "int bar;\n",
> - addIncludeInGuardedHeader("foo", "#ifndef GUARD_H\n"
> - "#define GUARD_H\n"
> - "\n"
> - "struct foo;"
> - "\n"
> - "#endif // GUARD_H\n"
> - "\n"
> - "int bar;\n"));
> -}
> -
> -TEST(IncludeDirectivesTest, headerGuardWithInclude) {
> - EXPECT_EQ("#ifndef GUARD_H\n"
> - "#define GUARD_H\n"
> - "\n"
> - "#include <bar.h>\n"
> - "#include <foo>\n"
> - "\n"
> - "struct foo;\n"
> - "\n"
> - "#endif // GUARD_H\n",
> - addIncludeInGuardedHeader("foo", "#ifndef GUARD_H\n"
> - "#define GUARD_H\n"
> - "\n"
> - "#include <bar.h>\n"
> - "\n"
> - "struct foo;\n"
> - "\n"
> - "#endif // GUARD_H\n"));
> -}
> Index: unittests/clang-modernize/CMakeLists.txt
> ===================================================================
> --- unittests/clang-modernize/CMakeLists.txt
> +++ /dev/null
> @@ -1,33 +0,0 @@
> -set(LLVM_LINK_COMPONENTS
> - support
> - )
> -
> -get_filename_component(CLANG_MODERNIZE_SOURCE_DIR
> - ${CMAKE_CURRENT_SOURCE_DIR}/../../clang-modernize REALPATH)
> -get_filename_component(ClangReplaceLocation
> - "${CMAKE_CURRENT_SOURCE_DIR}/../../clang-apply-replacements/include" REALPATH)
> -get_filename_component(CommonIncLocation
> - "${CMAKE_CURRENT_SOURCE_DIR}/../include" REALPATH)
> -include_directories(
> - ${CLANG_MODERNIZE_SOURCE_DIR}
> - ${ClangReplaceLocation}
> - ${CommonIncLocation}
> - )
> -
> -add_extra_unittest(ClangModernizeTests
> - IncludeExcludeTest.cpp
> - PerfSupportTest.cpp
> - TransformTest.cpp
> - UniqueHeaderNameTest.cpp
> - IncludeDirectivesTest.cpp
> - )
> -
> -target_link_libraries(ClangModernizeTests
> - clangAST
> - clangASTMatchers
> - clangBasic
> - clangFrontend
> - clangTooling
> - clangToolingCore
> - modernizeCore
> - )
> Index: unittests/Makefile
> ===================================================================
> --- unittests/Makefile
> +++ unittests/Makefile
> @@ -10,6 +10,6 @@
> CLANG_LEVEL := ../../..
> include $(CLANG_LEVEL)/../../Makefile.config
>
> -PARALLEL_DIRS := clang-apply-replacements clang-modernize clang-query clang-tidy clang-rename
> +PARALLEL_DIRS := clang-apply-replacements clang-query clang-tidy clang-rename
>
> include $(CLANG_LEVEL)/Makefile
> Index: unittests/CMakeLists.txt
> ===================================================================
> --- unittests/CMakeLists.txt
> +++ unittests/CMakeLists.txt
> @@ -6,7 +6,6 @@
> endfunction()
>
> add_subdirectory(clang-apply-replacements)
> -add_subdirectory(clang-modernize)
> add_subdirectory(clang-rename)
> add_subdirectory(clang-query)
> add_subdirectory(clang-tidy)
> Index: test/clang-modernize/UseNullptr/nullptr_t.cpp
> ===================================================================
> --- test/clang-modernize/UseNullptr/nullptr_t.cpp
> +++ /dev/null
> @@ -1,29 +0,0 @@
> -// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
> -// RUN: clang-modernize -final-syntax-check -use-nullptr %t.cpp -- --std=c++11 -I %S
> -// RUN: FileCheck -input-file=%t.cpp %s
> -
> -namespace std {
> -
> -typedef decltype(nullptr) nullptr_t;
> -
> -} // namespace std
> -
> -// Just to make sure make_null() could have side effects.
> -void external();
> -
> -std::nullptr_t make_null() {
> - external();
> - return nullptr;
> -}
> -
> -void func() {
> - void *CallTest = make_null();
> - // CHECK: void *CallTest = make_null();
> -
> - int var = 1;
> - void *CommaTest = (var+=2, make_null());
> - // CHECK: void *CommaTest = (var+=2, make_null());
> -
> - int *CastTest = static_cast<int*>(make_null());
> - // CHECK: int *CastTest = static_cast<int*>(make_null());
> -}
> Index: test/clang-modernize/UseNullptr/macros.cpp
> ===================================================================
> --- test/clang-modernize/UseNullptr/macros.cpp
> +++ /dev/null
> @@ -1,164 +0,0 @@
> -// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
> -// RUN: clang-modernize -use-nullptr %t.cpp -- -I %S
> -// RUN: FileCheck -input-file=%t.cpp %s
> -// RUN: grep -Ev "// *[A-Z-]+:" %s > %t2.cpp
> -// RUN: clang-modernize -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
> -
> -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
> -}
> -
> -// Test macro expansion with cast sequence, PR15572
> -void test_macro_expansion2() {
> -#define MACRO_EXPANSION_HAS_NULL \
> - dummy((int*)0); \
> - side_effect();
> - // CHECK: dummy((int*)0); \
> - // CHECK-NEXT: side_effect();
> -
> - MACRO_EXPANSION_HAS_NULL;
> - // CHECK: MACRO_EXPANSION_HAS_NULL;
> -
> -#undef MACRO_EXPANSION_HAS_NULL
> -}
> -
> -void test_macro_expansion3() {
> -#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_expansion4() {
> -#define MY_NULL NULL
> - int *p = MY_NULL;
> - // CHECK: int *p = MY_NULL;
> - // USER-SUPPLIED-NULL: int *p = nullptr;
> -#undef MY_NULL
> -}
> -
> -#define IS_EQ(x, y) if (x != y) return;
> -void test_macro_args() {
> - int i = 0;
> - int *Ptr;
> -
> - IS_EQ(static_cast<int*>(0), Ptr);
> - // CHECK: IS_EQ(static_cast<int*>(nullptr), Ptr);
> - IS_EQ(0, Ptr); // literal
> - // CHECK: IS_EQ(nullptr, Ptr);
> - IS_EQ(NULL, Ptr); // macro
> - // CHECK: IS_EQ(nullptr, Ptr);
> -
> - // These are ok since the null literal is not spelled within a macro.
> -#define myassert(x) if (!(x)) return;
> - myassert(0 == Ptr);
> - // CHECK: myassert(nullptr == Ptr);
> - myassert(NULL == Ptr);
> - // CHECK: myassert(nullptr == Ptr);
> -
> - // These are bad as the null literal is buried in a macro.
> -#define BLAH(X) myassert(0 == (X));
> - // CHECK: #define BLAH(X) myassert(0 == (X));
> -#define BLAH2(X) myassert(NULL == (X));
> - // CHECK: #define BLAH2(X) myassert(NULL == (X));
> - BLAH(Ptr);
> - // CHECK: BLAH(Ptr);
> - BLAH2(Ptr);
> - // CHECK: BLAH2(Ptr);
> -
> - // Same as above but testing extra macro expansion.
> -#define EXPECT_NULL(X) IS_EQ(0, X);
> - // CHECK: #define EXPECT_NULL(X) IS_EQ(0, X);
> -#define EXPECT_NULL2(X) IS_EQ(NULL, X);
> - // CHECK: #define EXPECT_NULL2(X) IS_EQ(NULL, X);
> - EXPECT_NULL(Ptr);
> - // CHECK: EXPECT_NULL(Ptr);
> - EXPECT_NULL2(Ptr);
> - // CHECK: EXPECT_NULL2(Ptr);
> -
> - // Almost the same as above but now null literal is not in a macro so ok
> - // to transform.
> -#define EQUALS_PTR(X) IS_EQ(X, Ptr);
> - EQUALS_PTR(0);
> - EQUALS_PTR(NULL);
> -
> - // Same as above but testing extra macro expansion.
> -#define EQUALS_PTR_I(X) EQUALS_PTR(X)
> - EQUALS_PTR_I(0);
> - // CHECK: EQUALS_PTR_I(nullptr);
> - EQUALS_PTR_I(NULL);
> - // CHECK: EQUALS_PTR_I(nullptr);
> -
> - // Ok since null literal not within macro. However, now testing macro
> - // used as arg to another macro.
> -#define decorate(EXPR) side_effect(); EXPR;
> - decorate(IS_EQ(NULL, Ptr));
> - // CHECK: decorate(IS_EQ(nullptr, Ptr));
> - decorate(IS_EQ(0, Ptr));
> - // CHECK: decorate(IS_EQ(nullptr, Ptr));
> -
> - // This macro causes a NullToPointer cast to happen where 0 is assigned to z
> - // but the 0 literal cannot be replaced because it is also used as an
> - // integer in the comparison.
> -#define INT_AND_PTR_USE(X) do { int *z = X; if (X == 4) break; } while(false)
> - INT_AND_PTR_USE(0);
> - // CHECK: INT_AND_PTR_USE(0);
> -
> - // Both uses of X in this case result in NullToPointer casts so replacement
> - // is possible.
> -#define PTR_AND_PTR_USE(X) do { int *z = X; if (X != z) break; } while(false)
> - PTR_AND_PTR_USE(0);
> - // CHECK: PTR_AND_PTR_USE(nullptr);
> - PTR_AND_PTR_USE(NULL);
> - // CHECK: PTR_AND_PTR_USE(nullptr);
> -
> -#define OPTIONAL_CODE(...) __VA_ARGS__
> -#define NOT_NULL dummy(0)
> -#define CALL(X) X
> - OPTIONAL_CODE(NOT_NULL);
> - // CHECK: OPTIONAL_CODE(NOT_NULL);
> - CALL(NOT_NULL);
> - // CHECK: CALL(NOT_NULL);
> -}
> Index: test/clang-modernize/UseNullptr/basic_failing.cpp
> ===================================================================
> --- test/clang-modernize/UseNullptr/basic_failing.cpp
> +++ /dev/null
> @@ -1,27 +0,0 @@
> -// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
> -// RUN: clang-modernize -use-nullptr %t.cpp -- -I %S
> -// RUN: FileCheck -input-file=%t.cpp %s
> -// XFAIL: *
> -
> -#define NULL 0
> -
> -template <typename T>
> -class A {
> -public:
> - A(T *p = NULL) {}
> - // CHECK: A(T *p = nullptr) {}
> -
> - void f() {
> - Ptr = NULL;
> - // CHECK: Ptr = nullptr;
> - }
> -
> - T *Ptr;
> -};
> -
> -template <typename T>
> -T *f2(T *a = NULL) {
> - // CHECK: T *f2(T *a = nullptr) {
> - return a ? a : NULL;
> - // CHECK: return a ? a : nullptr;
> -}
> Index: test/clang-modernize/UseNullptr/basic.cpp
> ===================================================================
> --- test/clang-modernize/UseNullptr/basic.cpp
> +++ /dev/null
> @@ -1,291 +0,0 @@
> -// RUN: mkdir -p %T/Inputs
> -// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
> -// RUN: grep -Ev "// *[A-Z-]+:" %S/Inputs/basic.h > %T/Inputs/basic.h
> -// RUN: clang-modernize -use-nullptr -include=%T %t.cpp -- -std=c++98 -I %T -Wno-non-literal-null-conversion
> -// RUN: FileCheck -input-file=%t.cpp %s
> -// RUN: FileCheck -input-file=%T/Inputs/basic.h %S/Inputs/basic.h
> -
> -#include "Inputs/basic.h"
> -
> -const unsigned int g_null = 0;
> -#define NULL 0
> -// CHECK: #define NULL 0
> -
> -void test_assignment() {
> - int *p1 = 0;
> - // CHECK: int *p1 = nullptr;
> - p1 = 0;
> - // CHECK: p1 = nullptr;
> -
> - int *p2 = NULL;
> - // CHECK: int *p2 = nullptr;
> -
> - p2 = p1;
> - // CHECK: p2 = p1;
> -
> - const int null = 0;
> - int *p3 = null;
> - // CHECK: int *p3 = nullptr;
> -
> - p3 = NULL;
> - // CHECK: p3 = nullptr;
> -
> - int *p4 = p3;
> - // CHECK: int *p4 = p3;
> -
> - p4 = null;
> - // CHECK: p4 = nullptr;
> -
> - int i1 = 0;
> - // CHECK: int i1 = 0;
> -
> - int i2 = NULL;
> - // CHECK: int i2 = NULL;
> -
> - int i3 = null;
> - // CHECK: int i3 = null;
> -
> - int *p5, *p6, *p7;
> - p5 = p6 = p7 = NULL;
> - // CHECK: p5 = p6 = p7 = nullptr;
> -}
> -
> -struct Foo {
> - Foo(int *p = NULL) : m_p1(p) {}
> - // CHECK: Foo(int *p = nullptr) : m_p1(p) {}
> -
> - void bar(int *p = 0) {}
> - // CHECK: void bar(int *p = nullptr) {}
> -
> - void baz(int i = 0) {}
> - // CHECK: void baz(int i = 0) {}
> -
> - int *m_p1;
> - static int *m_p2;
> -};
> -
> -int *Foo::m_p2 = NULL;
> -// CHECK: int *Foo::m_p2 = nullptr;
> -
> -template <typename T>
> -struct Bar {
> - Bar(T *p) : m_p(p) {
> - m_p = static_cast<T*>(NULL);
> - // CHECK: m_p = static_cast<T*>(nullptr);
> -
> - m_p = static_cast<T*>(reinterpret_cast<int*>((void*)NULL));
> - // CHECK: m_p = static_cast<T*>(nullptr);
> -
> - m_p = static_cast<T*>(p ? p : static_cast<void*>(g_null));
> - // CHECK: m_p = static_cast<T*>(p ? p : static_cast<void*>(nullptr));
> -
> - T *p2 = static_cast<T*>(reinterpret_cast<int*>((void*)NULL));
> - // CHECK: T *p2 = static_cast<T*>(nullptr);
> -
> - m_p = NULL;
> - // CHECK: m_p = nullptr;
> -
> - int i = static_cast<int>(0.f);
> - // CHECK: int i = static_cast<int>(0.f);
> - T *i2 = static_cast<int>(0.f);
> - // CHECK: T *i2 = nullptr;
> - }
> -
> - T *m_p;
> -};
> -
> -struct Baz {
> - Baz() : i(0) {}
> - int i;
> -};
> -
> -void test_cxx_cases() {
> - Foo f(g_null);
> - // CHECK: Foo f(nullptr);
> -
> - f.bar(NULL);
> - // CHECK: f.bar(nullptr);
> -
> - f.baz(g_null);
> - // CHECK: f.baz(g_null);
> -
> - f.m_p1 = 0;
> - // CHECK: f.m_p1 = nullptr;
> -
> - Bar<int> b(g_null);
> - // CHECK: Bar<int> b(nullptr);
> -
> - Baz b2;
> - int Baz::*memptr(0);
> - // CHECK: int Baz::*memptr(nullptr);
> -
> - memptr = 0;
> - // CHECK: memptr = nullptr;
> -}
> -
> -void test_function_default_param1(void *p = 0);
> -// CHECK: void test_function_default_param1(void *p = nullptr);
> -
> -void test_function_default_param2(void *p = NULL);
> -// CHECK: void test_function_default_param2(void *p = nullptr);
> -
> -void test_function_default_param3(void *p = g_null);
> -// CHECK: void test_function_default_param3(void *p = nullptr);
> -
> -void test_function(int *p) {}
> -// CHECK: void test_function(int *p) {}
> -
> -void test_function_no_ptr_param(int i) {}
> -
> -void test_function_call() {
> - test_function(0);
> - // CHECK: test_function(nullptr);
> -
> - test_function(NULL);
> - // CHECK: test_function(nullptr);
> -
> - test_function(g_null);
> - // CHECK: test_function(nullptr);
> -
> - test_function_no_ptr_param(0);
> - // CHECK: test_function_no_ptr_param(0);
> -}
> -
> -char *test_function_return1() {
> - return 0;
> - // CHECK: return nullptr;
> -}
> -
> -void *test_function_return2() {
> - return NULL;
> - // CHECK: return nullptr;
> -}
> -
> -long *test_function_return3() {
> - return g_null;
> - // CHECK: return nullptr;
> -}
> -
> -int test_function_return4() {
> - return 0;
> - // CHECK: return 0;
> -}
> -
> -int test_function_return5() {
> - return NULL;
> - // CHECK: return NULL;
> -}
> -
> -int test_function_return6() {
> - return g_null;
> - // CHECK: return g_null;
> -}
> -
> -int *test_function_return_cast1() {
> - return(int)0;
> - // CHECK: return nullptr;
> -}
> -
> -int *test_function_return_cast2() {
> - #define RET return
> - RET(int)0;
> - // CHECK: RET nullptr;
> - #undef RET
> -}
> -
> -// Test parentheses expressions resulting in a nullptr.
> -int *test_parentheses_expression1() {
> - return(0);
> - // CHECK: return(nullptr);
> -}
> -
> -int *test_parentheses_expression2() {
> - return(int(0.f));
> - // CHECK: return(nullptr);
> -}
> -
> -int *test_nested_parentheses_expression() {
> - return((((0))));
> - // CHECK: return((((nullptr))));
> -}
> -
> -void *test_parentheses_explicit_cast() {
> - return(static_cast<void*>(0));
> - // CHECK: return(static_cast<void*>(nullptr));
> -}
> -
> -void *test_parentheses_explicit_cast_sequence1() {
> - return(static_cast<void*>(static_cast<int*>((void*)NULL)));
> - // CHECK: return(static_cast<void*>(nullptr));
> -}
> -
> -void *test_parentheses_explicit_cast_sequence2() {
> - return(static_cast<void*>(reinterpret_cast<int*>((float*)int(0.f))));
> - // CHECK: return(static_cast<void*>(nullptr));
> -}
> -
> -// Test explicit cast expressions resulting in nullptr
> -struct Bam {
> - Bam(int *a) {}
> - Bam(float *a) {}
> - Bam operator=(int *a) { return Bam(a); }
> - Bam operator=(float *a) { return Bam(a); }
> -};
> -
> -void ambiguous_function(int *a) {}
> -void ambiguous_function(float *a) {}
> -void const_ambiguous_function(const int *p) {}
> -void const_ambiguous_function(const float *p) {}
> -
> -void test_explicit_cast_ambiguous1() {
> - ambiguous_function((int*)0);
> - // CHECK: ambiguous_function((int*)nullptr);
> -}
> -
> -void test_explicit_cast_ambiguous2() {
> - ambiguous_function((int*)(0));
> - // CHECK: ambiguous_function((int*)nullptr);
> -}
> -
> -void test_explicit_cast_ambiguous3() {
> - ambiguous_function(static_cast<int*>(reinterpret_cast<int*>((float*)0)));
> - // CHECK: ambiguous_function(static_cast<int*>(nullptr));
> -}
> -
> -Bam test_explicit_cast_ambiguous4() {
> - return(((int*)(0)));
> - // CHECK: return(((int*)nullptr));
> -}
> -
> -void test_explicit_cast_ambiguous5() {
> - // Test for ambiguous overloaded constructors
> - Bam k((int*)(0));
> - // CHECK: Bam k((int*)nullptr);
> -
> - // Test for ambiguous overloaded operators
> - k = (int*)0;
> - // CHECK: k = (int*)nullptr;
> -}
> -
> -void test_const_pointers_abiguous() {
> - const_ambiguous_function((int*)0);
> - // CHECK: const_ambiguous_function((int*)nullptr);
> -}
> -
> -// Test where the implicit cast to null is surrounded by another implict cast
> -// with possible explict casts in-between.
> -void test_const_pointers() {
> - const int *const_p1 = 0;
> - // CHECK: const int *const_p1 = nullptr;
> - const int *const_p2 = NULL;
> - // CHECK: const int *const_p2 = nullptr;
> - const int *const_p3 = (int)0;
> - // CHECK: const int *const_p3 = nullptr;
> - const int *const_p4 = (int)0.0f;
> - // CHECK: const int *const_p4 = nullptr;
> - const int *const_p5 = (int*)0;
> - // CHECK: const int *const_p5 = (int*)nullptr;
> - int *t;
> - const int *const_p6 = static_cast<int*>(t ? t : static_cast<int*>(0));
> - // CHECK: const int *const_p6 = static_cast<int*>(t ? t : static_cast<int*>(nullptr));
> -}
> Index: test/clang-modernize/UseNullptr/Inputs/basic.h
> ===================================================================
> --- test/clang-modernize/UseNullptr/Inputs/basic.h
> +++ /dev/null
> @@ -1,2 +0,0 @@
> -int *global_p = 0;
> -// CHECK: int *global_p = nullptr;
> Index: test/clang-modernize/UseAuto/new_cv_failing.cpp
> ===================================================================
> --- test/clang-modernize/UseAuto/new_cv_failing.cpp
> +++ /dev/null
> @@ -1,36 +0,0 @@
> -// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
> -// RUN: clang-modernize -use-auto %t.cpp -- -std=c++11
> -// RUN: FileCheck -input-file=%t.cpp %s
> -// XFAIL: *
> -
> -// None of these tests can pass right now because TypeLoc information where CV
> -// qualifiers are concerned is not reliable/available.
> -
> -class MyType {
> -};
> -
> -int main (int argc, char **argv) {
> - const MyType *d = new MyType();
> - // CHECK: const auto *d = new MyType();
> -
> - volatile MyType *d2 = new MyType();
> - // CHECK: volatile auto *d2 = new MyType();
> -
> - const MyType * volatile e = new MyType();
> - // CHECK: const auto * volatile d = new MyType();
> -
> - volatile MyType * const f = new MyType();
> - // CHECK: volatile auto * const d2 = new MyType();
> -
> - const MyType *d5 = new const MyType();
> - // CHECK: auto d5 = new const MyType();
> -
> - volatile MyType *d6 = new volatile MyType();
> - // CHECK: auto d6 = new volatile MyType();
> -
> - const MyType * const d7 = new const MyType();
> - // CHECK: const auto d7 = new const MyType();
> -
> - volatile MyType * volatile d8 = new volatile MyType();
> - // CHECK: volatile auto d8 = new volatile MyType();
> -}
> Index: test/clang-modernize/UseAuto/new.cpp
> ===================================================================
> --- test/clang-modernize/UseAuto/new.cpp
> +++ /dev/null
> @@ -1,97 +0,0 @@
> -// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
> -// RUN: clang-modernize -use-auto %t.cpp -- -std=c++11
> -// RUN: FileCheck -input-file=%t.cpp %s
> -
> -class MyType {
> -};
> -
> -class MyDerivedType : public MyType {
> -};
> -
> -int main(int argc, char **argv) {
> - MyType *a = new MyType();
> - // CHECK: auto a = new MyType();
> -
> - static MyType *a_static = new MyType();
> - // CHECK: static auto a_static = new MyType();
> -
> - MyType *b = new MyDerivedType();
> - // CHECK: MyType *b = new MyDerivedType();
> -
> - void *c = new MyType();
> - // CHECK: void *c = new MyType();
> -
> - // CV-qualifier tests.
> - //
> - // NOTE : the form "type const" is expected here because of a deficiency in
> - // TypeLoc where CV qualifiers are not considered part of the type location
> - // info. That is, all that is being replaced in each case is "MyType *" and
> - // not "MyType * const".
> - {
> - static MyType * const d_static = new MyType();
> - // CHECK: static auto const d_static = new MyType();
> -
> - MyType * const d3 = new MyType();
> - // CHECK: auto const d3 = new MyType();
> -
> - MyType * volatile d4 = new MyType();
> - // CHECK: auto volatile d4 = new MyType();
> - }
> -
> - int (**func)(int, int) = new (int(*[5])(int,int));
> - // CHECK: int (**func)(int, int) = new (int(*[5])(int,int));
> -
> - int *e = new int[5];
> - // CHECK: auto e = new int[5];
> -
> - MyType *f(new MyType);
> - // CHECK: auto f(new MyType);
> -
> - MyType *g{new MyType};
> - // CHECK: MyType *g{new MyType};
> -
> - // Test for declaration lists.
> - {
> - MyType *a = new MyType(), *b = new MyType(), *c = new MyType();
> - // CHECK: auto a = new MyType(), b = new MyType(), c = new MyType();
> -
> - // Non-initialized declaration should not be transformed.
> - MyType *d = new MyType(), *e;
> - // CHECK: MyType *d = new MyType(), *e;
> -
> - MyType **f = new MyType*(), **g = new MyType*();
> - // CHECK: auto f = new MyType*(), g = new MyType*();
> -
> - // Mismatching types in declaration lists should not be transformed.
> - MyType *h = new MyType(), **i = new MyType*();
> - // CHECK: MyType *h = new MyType(), **i = new MyType*();
> -
> - // '*' shouldn't be removed in case of mismatching types with multiple
> - // declarations.
> - MyType *j = new MyType(), *k = new MyType(), **l = new MyType*();
> - // CHECK: MyType *j = new MyType(), *k = new MyType(), **l = new MyType*();
> - }
> -
> - // Test for typedefs.
> - {
> - typedef int * int_p;
> -
> - int_p a = new int;
> - // CHECK: auto a = new int;
> - int_p *b = new int*;
> - // CHECK: auto b = new int*;
> -
> - // Test for typedefs in declarations lists.
> - int_p c = new int, d = new int;
> - // CHECK: auto c = new int, d = new int;
> -
> - // Different types should not be transformed.
> - int_p e = new int, *f = new int_p;
> - // CHECK: int_p e = new int, *f = new int_p;
> -
> - int_p *g = new int*, *h = new int_p;
> - // CHECK: auto g = new int*, h = new int_p;
> - }
> -
> - return 0;
> -}
> Index: test/clang-modernize/UseAuto/iterator.cpp
> ===================================================================
> --- test/clang-modernize/UseAuto/iterator.cpp
> +++ /dev/null
> @@ -1,178 +0,0 @@
> -// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
> -// RUN: clang-modernize -use-auto %t.cpp -- --std=c++11 -I %S/Inputs
> -// RUN: FileCheck -input-file=%t.cpp %s
> -//
> -// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
> -// RUN: clang-modernize -use-auto %t.cpp -- --std=c++11 -I %S/Inputs \
> -// RUN: -DUSE_INLINE_NAMESPACE=1
> -// RUN: FileCheck -input-file=%t.cpp %s
> -
> -
> -#define CONTAINER array
> -#include "test_std_container.h"
> -#undef CONTAINER
> -
> -#define CONTAINER vector
> -#include "test_std_container.h"
> -#undef CONTAINER
> -
> -#define CONTAINER unordered_map
> -#define USE_BASE_CLASS_ITERATORS 1
> -#include "test_std_container.h"
> -#undef USE_BASE_CLASS_ITERATORS
> -#undef CONTAINER
> -
> -typedef std::vector<int>::iterator int_iterator;
> -
> -namespace foo {
> - template <typename T>
> - class vector {
> - public:
> - class iterator {};
> -
> - iterator begin() { return iterator(); }
> - };
> -} // namespace foo
> -
> -int main(int argc, char **argv) {
> - std::vector<int> Vec;
> - // CHECK: std::vector<int> Vec;
> -
> - std::unordered_map<int> Map;
> - // CHECK: std::unordered_map<int> Map;
> -
> - // Types with more sugar should work. Types with less should not.
> - {
> - int_iterator more_sugar = Vec.begin();
> - // CHECK: auto more_sugar = Vec.begin();
> -
> - internal::iterator_wrapper<std::vector<int>, 0> less_sugar = Vec.begin();
> - // CHECK: internal::iterator_wrapper<std::vector<int>, 0> less_sugar = Vec.begin();
> - }
> -
> - // Initialization from initializer lists isn't allowed. Using 'auto'
> - // would result in std::initializer_list being deduced for the type.
> - {
> - std::unordered_map<int>::iterator I{Map.begin()};
> - // CHECK: std::unordered_map<int>::iterator I{Map.begin()};
> -
> - std::unordered_map<int>::iterator I2 = {Map.begin()};
> - // CHECK: std::unordered_map<int>::iterator I2 = {Map.begin()};
> - }
> -
> - // Various forms of construction. Default constructors and constructors with
> - // all-default parameters shouldn't get transformed. Construction from other
> - // types is also not allowed.
> - {
> - std::unordered_map<int>::iterator copy(Map.begin());
> - // CHECK: auto copy(Map.begin());
> -
> - std::unordered_map<int>::iterator def;
> - // CHECK: std::unordered_map<int>::iterator def;
> -
> - // const_iterator has no default constructor, just one that has >0 params
> - // with defaults.
> - std::unordered_map<int>::const_iterator constI;
> - // CHECK: std::unordered_map<int>::const_iterator constI;
> -
> - // Uses iterator_provider::const_iterator's conversion constructor.
> -
> - std::unordered_map<int>::const_iterator constI2 = def;
> - // CHECK: std::unordered_map<int>::const_iterator constI2 = def;
> -
> - std::unordered_map<int>::const_iterator constI3(def);
> - // CHECK: std::unordered_map<int>::const_iterator constI3(def);
> -
> - // Explicit use of conversion constructor
> -
> - std::unordered_map<int>::const_iterator constI4 = std::unordered_map<int>::const_iterator(def);
> - // CHECK: auto constI4 = std::unordered_map<int>::const_iterator(def);
> -
> - // Uses iterator_provider::iterator's const_iterator conversion operator.
> -
> - std::unordered_map<int>::iterator I = constI;
> - // CHECK: std::unordered_map<int>::iterator I = constI;
> -
> - std::unordered_map<int>::iterator I2(constI);
> - // CHECK: std::unordered_map<int>::iterator I2(constI);
> - }
> -
> - // Weird cases of pointers and references to iterators are not transformed.
> - {
> - int_iterator I = Vec.begin();
> -
> - int_iterator *IPtr = &I;
> - // CHECK: int_iterator *IPtr = &I;
> -
> - int_iterator &IRef = I;
> - // CHECK: int_iterator &IRef = I;
> - }
> -
> - {
> - // Variable declarations in iteration statements.
> - for (std::vector<int>::iterator I = Vec.begin(); I != Vec.end(); ++I) {
> - // CHECK: for (auto I = Vec.begin(); I != Vec.end(); ++I) {
> - }
> -
> - // Range-based for loops.
> - std::array<std::vector<int>::iterator> iter_arr;
> - for (std::vector<int>::iterator I: iter_arr) {
> - // CHECK: for (auto I: iter_arr) {
> - }
> -
> - // Test with init-declarator-list.
> - for (int_iterator I = Vec.begin(),
> - E = Vec.end(); I != E; ++I) {
> - // CHECK: for (auto I = Vec.begin(),
> - // CHECK-NEXT: E = Vec.end(); I != E; ++I) {
> - }
> - }
> -
> - // Only std containers should be changed.
> - {
> - using namespace foo;
> - vector<int> foo_vec;
> - vector<int>::iterator I = foo_vec.begin();
> - // CHECK: vector<int>::iterator I = foo_vec.begin();
> - }
> -
> - // Ensure using directives don't interfere with replacement.
> - {
> - using namespace std;
> - vector<int> std_vec;
> - vector<int>::iterator I = std_vec.begin();
> - // CHECK: auto I = std_vec.begin();
> - }
> -
> - // Make sure references and cv qualifiers don't get removed (i.e. replaced
> - // with just 'auto').
> - {
> - const auto & I = Vec.begin();
> - // CHECK: const auto & I = Vec.begin();
> -
> - auto && I2 = Vec.begin();
> - // CHECK: auto && I2 = Vec.begin();
> - }
> -
> - // Passing a string as an argument to introduce a temporary object
> - // that will create an expression with cleanups. Bugzilla: 15550
> - {
> - std::unordered_map<int> MapFind;
> - std::unordered_map<int>::iterator I = MapFind.find("foo");
> - // CHECK: auto I = MapFind.find("foo");
> - }
> -
> - // Test for declaration lists
> - {
> - // Ensusre declaration lists that matches the declaration type with written
> - // no-list initializer are transformed.
> - std::vector<int>::iterator I = Vec.begin(), E = Vec.end();
> - // CHECK: auto I = Vec.begin(), E = Vec.end();
> -
> - // Declaration lists with non-initialized variables should not be
> - // transformed.
> - std::vector<int>::iterator J = Vec.begin(), K;
> - // CHECK: std::vector<int>::iterator J = Vec.begin(), K;
> - }
> - return 0;
> -}
> Index: test/clang-modernize/UseAuto/basic_iterator_tests.cpp
> ===================================================================
> --- test/clang-modernize/UseAuto/basic_iterator_tests.cpp
> +++ /dev/null
> @@ -1,123 +0,0 @@
> -// This file contains basic positive tests for the use-auto transform's ability
> -// to replace standard iterators. Variables considered:
> -// * All std container names
> -// * All std iterator names
> -// * Different patterns of defining iterators and containers
> -//
> -// // The most basic test.
> -//
> -// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
> -// RUN: clang-modernize -use-auto %t.cpp -- -DCONTAINER=array -I %S/Inputs
> -// RUN: FileCheck -input-file=%t.cpp %s
> -//
> -//
> -// Test variations on how the container and its iterators might be defined.
> -//
> -// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
> -// RUN: clang-modernize -use-auto %t.cpp -- -DCONTAINER=array \
> -// RUN: -DUSE_INLINE_NAMESPACE=1 -I %S/Inputs
> -// RUN: FileCheck -input-file=%t.cpp %s
> -//
> -// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
> -// RUN: clang-modernize -use-auto %t.cpp -- -DCONTAINER=array \
> -// RUN: -DUSE_BASE_CLASS_ITERATORS=1 -I %S/Inputs
> -// RUN: FileCheck -input-file=%t.cpp %s
> -//
> -// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
> -// RUN: clang-modernize -use-auto %t.cpp -- -DCONTAINER=array \
> -// RUN: -DUSE_INNER_CLASS_ITERATORS=1 -I %S/Inputs
> -// RUN: FileCheck -input-file=%t.cpp %s
> -//
> -//
> -// Test all of the other container names in a basic configuration.
> -//
> -// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
> -// RUN: clang-modernize -use-auto %t.cpp -- -DCONTAINER=deque -I %S/Inputs
> -// RUN: FileCheck -input-file=%t.cpp %s
> -//
> -// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
> -// RUN: clang-modernize -use-auto %t.cpp -- -DCONTAINER=forward_list -I %S/Inputs
> -// RUN: FileCheck -input-file=%t.cpp %s
> -//
> -// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
> -// RUN: clang-modernize -use-auto %t.cpp -- -DCONTAINER=list -I %S/Inputs
> -// RUN: FileCheck -input-file=%t.cpp %s
> -//
> -// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
> -// RUN: clang-modernize -use-auto %t.cpp -- -DCONTAINER=vector -I %S/Inputs
> -// RUN: FileCheck -input-file=%t.cpp %s
> -//
> -// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
> -// RUN: clang-modernize -use-auto %t.cpp -- -DCONTAINER=map -I %S/Inputs
> -// RUN: FileCheck -input-file=%t.cpp %s
> -//
> -// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
> -// RUN: clang-modernize -use-auto %t.cpp -- -DCONTAINER=multimap -I %S/Inputs
> -// RUN: FileCheck -input-file=%t.cpp %s
> -//
> -// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
> -// RUN: clang-modernize -use-auto %t.cpp -- -DCONTAINER=set -I %S/Inputs
> -// RUN: FileCheck -input-file=%t.cpp %s
> -//
> -// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
> -// RUN: clang-modernize -use-auto %t.cpp -- -DCONTAINER=multiset -I %S/Inputs
> -// RUN: FileCheck -input-file=%t.cpp %s
> -//
> -// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
> -// RUN: clang-modernize -use-auto %t.cpp -- -DCONTAINER=unordered_map -I %S/Inputs
> -// RUN: FileCheck -input-file=%t.cpp %s
> -//
> -// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
> -// RUN: clang-modernize -use-auto %t.cpp -- -DCONTAINER=unordered_multimap -I %S/Inputs
> -// RUN: FileCheck -input-file=%t.cpp %s
> -//
> -// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
> -// RUN: clang-modernize -use-auto %t.cpp -- -DCONTAINER=unordered_set -I %S/Inputs
> -// RUN: FileCheck -input-file=%t.cpp %s
> -//
> -// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
> -// RUN: clang-modernize -use-auto %t.cpp -- -DCONTAINER=unordered_multiset -I %S/Inputs
> -// RUN: FileCheck -input-file=%t.cpp %s
> -//
> -// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
> -// RUN: clang-modernize -use-auto %t.cpp -- -DCONTAINER=queue -I %S/Inputs
> -// RUN: FileCheck -input-file=%t.cpp %s
> -//
> -// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
> -// RUN: clang-modernize -use-auto %t.cpp -- -DCONTAINER=priority_queue -I %S/Inputs
> -// RUN: FileCheck -input-file=%t.cpp %s
> -//
> -// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
> -// RUN: clang-modernize -use-auto %t.cpp -- -DCONTAINER=stack -I %S/Inputs
> -// RUN: FileCheck -input-file=%t.cpp %s
> -
> -#ifndef CONTAINER
> -#error You must define CONTAINER to the name of the container for testing.
> -#endif
> -
> -#include "test_std_container.h"
> -
> -int main(int argc, char **argv) {
> - {
> - std::CONTAINER<int> C;
> - std::CONTAINER<int>::iterator I = C.begin();
> - // CHECK: auto I = C.begin();
> - }
> - {
> - std::CONTAINER<int> C;
> - std::CONTAINER<int>::reverse_iterator I = C.rbegin();
> - // CHECK: auto I = C.rbegin();
> - }
> - {
> - const std::CONTAINER<int> C;
> - std::CONTAINER<int>::const_iterator I = C.begin();
> - // CHECK: auto I = C.begin();
> - }
> - {
> - const std::CONTAINER<int> C;
> - std::CONTAINER<int>::const_reverse_iterator I = C.rbegin();
> - // CHECK: auto I = C.rbegin();
> - }
> -
> - return 0;
> -}
> Index: test/clang-modernize/UseAuto/Inputs/test_std_container.h
> ===================================================================
> --- test/clang-modernize/UseAuto/Inputs/test_std_container.h
> +++ /dev/null
> @@ -1,119 +0,0 @@
> -//===-----------------------------------------------------------*- C++ -*--===//
> -//
> -// This file contains a shell implementation of a standard container with
> -// iterators. This shell is targeted at supporting the container interfaces
> -// recognized by clang-modernize's use-auto transformation. It requires the
> -// preprocessor to parameterize the name of the container, and allows the
> -// preprocessor to parameterize various mechanisms used in the implementation
> -// of the container / iterator.
> -//
> -// Variations for how iterator types are presented:
> -// * Typedef (array, deque, forward_list, list, vector)
> -// * Nested class (map, multimap, set, multiset)
> -// * Using declaration {unordered_} X {map, multimap, set, multiset}
> -//
> -// Variations for how container types are presented:
> -// * Defined directly in namespace std
> -// * Imported into namespace std with using declarations (a la libc++).
> -//
> -//===----------------------------------------------------------------------===//
> -
> -#ifndef CONTAINER
> -#error You must define CONTAINER to the name of the desired container.
> -#endif
> -
> -// If the test code needs multiple containers, only define our helpers once.
> -#ifndef TEST_STD_CONTAINER_HELPERS
> -#define TEST_STD_CONTAINER_HELPERS
> -
> -namespace internal {
> -
> -template <typename T, int i>
> -struct iterator_wrapper {
> - iterator_wrapper() {}
> -
> - // These are required for tests using iteration statements.
> - bool operator!=(const iterator_wrapper<T, i>&) { return false; }
> - iterator_wrapper& operator++() { return *this; }
> - typename T::value_type operator*() { return typename T::value_type(); }
> -};
> -
> -template <typename T>
> -class iterator_provider {
> -public:
> - class iterator {
> - public:
> - iterator() {}
> - iterator(const iterator&) {}
> - };
> - class const_iterator {
> - public:
> - const_iterator(int i=0) {}
> - const_iterator(const iterator &) {}
> - const_iterator(const const_iterator &) {}
> - operator iterator() { return iterator(); }
> - };
> - class reverse_iterator {};
> - class const_reverse_iterator {};
> -};
> -
> -} // namespace internal
> -
> -#endif // TEST_STD_CONTAINER_HELPERS
> -
> -namespace std {
> -
> -#if USE_INLINE_NAMESPACE
> -inline namespace _1 {
> -#endif
> -
> -template <typename T>
> -class CONTAINER
> -#if USE_BASE_CLASS_ITERATORS
> - : internal::iterator_provider<CONTAINER<T> >
> -#endif
> -{
> -public:
> -
> -#if USE_BASE_CLASS_ITERATORS
> - using typename internal::iterator_provider<CONTAINER<T> >::iterator;
> - using typename internal::iterator_provider<CONTAINER<T> >::const_iterator;
> - using typename internal::iterator_provider<CONTAINER<T> >::reverse_iterator;
> - using typename internal::iterator_provider<CONTAINER<T> >::const_reverse_iterator;
> -#elif USE_INNER_CLASS_ITERATORS
> - class iterator {};
> - class const_iterator {};
> - class reverse_iterator {};
> - class const_reverse_iterator {};
> -#else
> - typedef T value_type;
> - typedef typename internal::iterator_wrapper<CONTAINER<T>, 0> iterator;
> - typedef typename internal::iterator_wrapper<CONTAINER<T>, 1> const_iterator;
> - typedef typename internal::iterator_wrapper<CONTAINER<T>, 3> reverse_iterator;
> - typedef typename internal::iterator_wrapper<CONTAINER<T>, 2> const_reverse_iterator;
> -#endif
> -
> - // Every class requires these functions.
> - CONTAINER() {}
> -
> - iterator begin() { return iterator(); }
> - iterator end() { return iterator(); }
> -
> - const_iterator begin() const { return const_iterator(); }
> - const_iterator end() const { return const_iterator(); }
> -
> - reverse_iterator rbegin() { return reverse_iterator(); }
> - reverse_iterator rend() { return reverse_iterator(); }
> -
> - const_reverse_iterator rbegin() const { return const_reverse_iterator(); }
> - const_reverse_iterator rend() const { return const_reverse_iterator(); }
> -
> - template <typename K>
> - iterator find(const K &Key) { return iterator(); }
> -};
> -
> -#if USE_INLINE_NAMESPACE
> -} // namespace _1
> -#endif
> -
> -} // namespace std
> Index: test/clang-modernize/ReplaceAutoPtr/template_fail.cpp
> ===================================================================
> --- test/clang-modernize/ReplaceAutoPtr/template_fail.cpp
> +++ /dev/null
> @@ -1,31 +0,0 @@
> -// XFAIL: *
> -//
> -// Without inline namespace:
> -//
> -// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
> -// RUN: clang-modernize -replace-auto_ptr %t.cpp -- -I %S/Inputs std=c++11
> -// RUN: FileCheck -input-file=%t.cpp %s
> -//
> -// With inline namespace:
> -//
> -// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
> -// RUN: clang-modernize -replace-auto_ptr %t.cpp -- -I %S/Inputs std=c++11 \
> -// RUN: -DUSE_INLINE_NAMESPACE=1
> -// RUN: FileCheck -input-file=%t.cpp %s
> -
> -#include "memory_stub.h"
> -
> -// Fail to modify when the template is never instantiated.
> -//
> -// This might not be an issue. If it's never used it doesn't really matter if
> -// it's changed or not. If it's a header and one of the source use it, then it
> -// will still be changed.
> -template <typename X>
> -void f() {
> - std::auto_ptr<X> p;
> - // CHECK: std::unique_ptr<X> p;
> -}
> -
> -// Alias template could be replaced if a matcher existed.
> -template <typename T> using aaaaaaaa = auto_ptr<T>;
> -// CHECK: template <typename T> using aaaaaaaa = unique_ptr<T>;
> Index: test/clang-modernize/ReplaceAutoPtr/move.cpp
> ===================================================================
> --- test/clang-modernize/ReplaceAutoPtr/move.cpp
> +++ /dev/null
> @@ -1,63 +0,0 @@
> -// Without inline namespace:
> -//
> -// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
> -// RUN: clang-modernize -replace-auto_ptr %t.cpp -- -I %S/Inputs std=c++11
> -// RUN: FileCheck -input-file=%t.cpp %s
> -//
> -// With inline namespace:
> -//
> -// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
> -// RUN: clang-modernize -replace-auto_ptr %t.cpp -- -I %S/Inputs std=c++11 \
> -// RUN: -DUSE_INLINE_NAMESPACE=1
> -// RUN: FileCheck -input-file=%t.cpp %s
> -
> -#include "memory_stub.h"
> -
> -void takes_ownership_fn(std::auto_ptr<int> x);
> -// CHECK: void takes_ownership_fn(std::unique_ptr<int> x);
> -
> -std::auto_ptr<int> get_by_value();
> -// CHECK: std::unique_ptr<int> get_by_value();
> -
> -class Wrapper {
> -public:
> - std::auto_ptr<int> &get_wrapped();
> -
> -private:
> - std::auto_ptr<int> wrapped;
> -};
> -
> -void f() {
> - std::auto_ptr<int> a, b, c;
> - // CHECK: std::unique_ptr<int> a, b, c;
> - Wrapper wrapper_a, wrapper_b;
> -
> - a = b;
> - // CHECK: a = std::move(b);
> -
> - wrapper_a.get_wrapped() = wrapper_b.get_wrapped();
> - // CHECK: wrapper_a.get_wrapped() = std::move(wrapper_b.get_wrapped());
> -
> - // Test that 'std::move()' is inserted when call to the
> - // copy-constructor are made.
> - takes_ownership_fn(c);
> - // CHECK: takes_ownership_fn(std::move(c));
> - takes_ownership_fn(wrapper_a.get_wrapped());
> - // CHECK: takes_ownership_fn(std::move(wrapper_a.get_wrapped()));
> -
> - std::auto_ptr<int> d[] = { std::auto_ptr<int>(new int(1)),
> - std::auto_ptr<int>(new int(2)) };
> - std::auto_ptr<int> e = d[0];
> - // CHECK: std::unique_ptr<int> d[] = { std::unique_ptr<int>(new int(1)),
> - // CHECK-NEXT: std::unique_ptr<int>(new int(2)) };
> - // CHECK-NEXT: std::unique_ptr<int> e = std::move(d[0]);
> -
> - // Test that std::move() is not used when assigning an rvalue
> - std::auto_ptr<int> f;
> - f = std::auto_ptr<int>(new int(0));
> - // CHECK: std::unique_ptr<int> f;
> - // CHECK-NEXT: f = std::unique_ptr<int>(new int(0));
> -
> - std::auto_ptr<int> g = get_by_value();
> - // CHECK: std::unique_ptr<int> g = get_by_value();
> -}
> Index: test/clang-modernize/ReplaceAutoPtr/basic.cpp
> ===================================================================
> --- test/clang-modernize/ReplaceAutoPtr/basic.cpp
> +++ /dev/null
> @@ -1,154 +0,0 @@
> -// RUN: mkdir -p %T/Inputs
> -//
> -// Without inline namespace:
> -//
> -// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
> -// RUN: grep -Ev "// *[A-Z-]+:" %S/Inputs/basic.h > %T/Inputs/basic.h
> -// RUN: grep -Ev "// *[A-Z-]+:" %S/Inputs/memory_stub.h > %T/Inputs/memory_stub.h
> -// RUN: clang-modernize -include=%T -replace-auto_ptr %t.cpp -- \
> -// RUN: -std=c++11 -I %T
> -// RUN: FileCheck -input-file=%t.cpp %s
> -// RUN: FileCheck -input-file=%T/Inputs/basic.h %S/Inputs/basic.h
> -//
> -// With inline namespace:
> -//
> -// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
> -// RUN: grep -Ev "// *[A-Z-]+:" %S/Inputs/basic.h > %T/Inputs/basic.h
> -// RUN: grep -Ev "// *[A-Z-]+:" %S/Inputs/memory_stub.h > %T/Inputs/memory_stub.h
> -// RUN: clang-modernize -include=%T -replace-auto_ptr %t.cpp -- \
> -// RUN: -DUSE_INLINE_NAMESPACE=1 -std=c++11 -I %T
> -// RUN: FileCheck -input-file=%t.cpp %s
> -// RUN: FileCheck -input-file=%T/Inputs/basic.h %S/Inputs/basic.h
> -
> -#include "Inputs/basic.h"
> -
> -void f_1() {
> - std::auto_ptr<int> a;
> - // CHECK: std::unique_ptr<int> a;
> -
> - // check that spaces aren't modified unnecessarily
> - std:: auto_ptr <int> b;
> - // CHECK: std:: unique_ptr <int> b;
> - std :: auto_ptr < char > c(new char());
> - // CHECK: std :: unique_ptr < char > c(new char());
> -
> - // Test construction from a temporary
> - std::auto_ptr<char> d = std::auto_ptr<char>();
> - // CHECK: std::unique_ptr<char> d = std::unique_ptr<char>();
> -
> - typedef std::auto_ptr<int> int_ptr_t;
> - // CHECK: typedef std::unique_ptr<int> int_ptr_t;
> - int_ptr_t e(new int());
> - // CHECK: int_ptr_t e(new int());
> -
> - // Test pointers
> - std::auto_ptr<int> *f;
> - // CHECK: std::unique_ptr<int> *f;
> -
> - // Test 'static' declarations
> - static std::auto_ptr<int> g;
> - // CHECK: static std::unique_ptr<int> g;
> -
> - // Test with cv-qualifiers
> - const std::auto_ptr<int> h;
> - // CHECK: const std::unique_ptr<int> h;
> - volatile std::auto_ptr<int> i;
> - // CHECK: volatile std::unique_ptr<int> i;
> - const volatile std::auto_ptr<int> j;
> - // CHECK: const volatile std::unique_ptr<int> j;
> -
> - // Test auto and initializer-list
> - auto k = std::auto_ptr<int>{};
> - // CHECK: auto k = std::unique_ptr<int>{};
> - std::auto_ptr<int> l{std::auto_ptr<int>()};
> - // CHECK: std::unique_ptr<int> l{std::unique_ptr<int>()};
> -
> - // Test interlocked auto_ptr
> - std::auto_ptr<std::auto_ptr<int> > m;
> - // CHECK: std::unique_ptr<std::unique_ptr<int> > m;
> -
> - // Test temporaries
> - std::auto_ptr<char>();
> - // CHECK: std::unique_ptr<char>();
> -
> - // Test void-specialization
> - std::auto_ptr<void> n;
> - // CHECK: std::unique_ptr<void> n;
> -
> - // Test template WITH instantiation (instantiation)
> - B<double> o;
> - std::auto_ptr<double> p(o.create());
> - // CHECK: std::unique_ptr<double> p(o.create());
> -
> - // Test 'using' in a namespace ("definition")
> - ns_1::auto_ptr<int> q;
> - // CHECK: ns_1::unique_ptr<int> q;
> -
> - // Test construction with an 'auto_ptr_ref'
> - std::auto_ptr<Base> r(create_derived_ptr());
> - // CHECK: std::unique_ptr<Base> r(create_derived_ptr());
> -}
> -
> -// Test without the nested name specifiers
> -void f_2() {
> - using namespace std;
> -
> - auto_ptr<int> a;
> - // CHECK: unique_ptr<int> a;
> -}
> -
> -// Test using declaration
> -void f_3() {
> - using std::auto_ptr;
> - // CHECK: using std::unique_ptr;
> -
> - auto_ptr<int> a;
> - // CHECK: unique_ptr<int> a;
> -}
> -
> -// Test messing-up with macros
> -void f_4() {
> -#define MACRO_1 <char>
> - std::auto_ptr MACRO_1 p(new char());
> -// CHECK: std::unique_ptr MACRO_1 p(new char());
> -#define MACRO_2 auto_ptr
> - std::MACRO_2<int> q;
> -// CHECK: #define MACRO_2 unique_ptr
> -#define MACRO_3(Type) std::auto_ptr<Type>
> - MACRO_3(float)r(new float());
> -// CHECK: #define MACRO_3(Type) std::unique_ptr<Type>
> -#define MACRO_4 std::auto_ptr
> - using MACRO_4;
> -// CHECK: #define MACRO_4 std::unique_ptr
> -#undef MACRO_1
> -#undef MACRO_2
> -#undef MACRO_3
> -#undef MACRO_4
> -}
> -
> -// Test function return values (definition)
> -std::auto_ptr<char> f_5()
> -// CHECK: std::unique_ptr<char> f_5()
> -{
> - // Test constructor
> - return std::auto_ptr<char>(new char());
> - // CHECK: return std::unique_ptr<char>(new char());
> -}
> -
> -// Test that non-std auto_ptr aren't replaced
> -void f_8() {
> - ns_2::auto_ptr<char> a;
> - // CHECK: ns_2::auto_ptr<char> a;
> - using namespace ns_2;
> - auto_ptr<int> b;
> - // CHECK: auto_ptr<int> b;
> -}
> -
> -namespace std {
> -template <typename T> using aaaaaaaa = auto_ptr<T>;
> -}
> -// We want to avoid replacing 'aaaaaaaa' by unique_ptr here. It's better to
> -// change the type alias directly.
> -// XXX: maybe another test will be more relevant to test this potential error.
> -std::aaaaaaaa<int> d;
> -// CHECK: std::aaaaaaaa<int> d;
> Index: test/clang-modernize/ReplaceAutoPtr/Inputs/memory_stub.h
> ===================================================================
> --- test/clang-modernize/ReplaceAutoPtr/Inputs/memory_stub.h
> +++ /dev/null
> @@ -1,61 +0,0 @@
> -//===-----------------------------------------------------------*- C++ -*--===//
> -//
> -// This file contains a shell implementation of the 'auto_ptr' type from the
> -// standard library. This shell aims to support the variations between standard
> -// library implementations.
> -//
> -// Variations for how 'auto_ptr' is presented:
> -// 1. Defined directly in namespace std
> -// 2. Use a versioned inline namespace in std (default on libc++).
> -//
> -// Use the preprocessor to define USE_INLINE_NAMESPACE=1 and use the second
> -// variation.
> -//
> -//===----------------------------------------------------------------------===//
> -
> -namespace std {
> -
> -#if USE_INLINE_NAMESPACE
> -inline namespace _1 {
> -#endif
> -
> -template <class Y> struct auto_ptr_ref {
> - Y *y_;
> -};
> -
> -template <class X> class auto_ptr {
> -public:
> - typedef X element_type;
> - // D.10.1.1 construct/copy/destroy:
> - explicit auto_ptr(X *p = 0) throw() {}
> - auto_ptr(auto_ptr &) throw() {}
> - template <class Y> auto_ptr(auto_ptr<Y> &) throw() {}
> - auto_ptr &operator=(auto_ptr &) throw() { return *this; }
> - template <class Y> auto_ptr &operator=(auto_ptr<Y> &) throw() {
> - return *this;
> - }
> - auto_ptr &operator=(auto_ptr_ref<X> r) throw() { return *this; }
> - ~auto_ptr() throw() {}
> - // D.10.1.3 conversions:
> - auto_ptr(auto_ptr_ref<X> r) throw() : x_(r.y_) {}
> - template <class Y> operator auto_ptr_ref<Y>() throw() {
> - auto_ptr_ref<Y> r;
> - r.y_ = x_;
> - return r;
> - }
> - template <class Y> operator auto_ptr<Y>() throw() { return auto_ptr<Y>(x_); }
> -
> -private:
> - X *x_;
> -};
> -
> -template <> class auto_ptr<void> {
> -public:
> - typedef void element_type;
> -};
> -
> -#if USE_INLINE_NAMESPACE
> -} // namespace _1
> -#endif
> -
> -} // end namespace std
> Index: test/clang-modernize/ReplaceAutoPtr/Inputs/basic.h
> ===================================================================
> --- test/clang-modernize/ReplaceAutoPtr/Inputs/basic.h
> +++ /dev/null
> @@ -1,56 +0,0 @@
> -#ifndef INPUTS_BASIC_H
> -#define INPUTS_BASIC_H
> -
> -#include "memory_stub.h"
> -
> -// Instrumentation for auto_ptr_ref test
> -// @{
> -struct Base {};
> -struct Derived : Base {};
> -std::auto_ptr<Derived> create_derived_ptr();
> -// CHECK: std::unique_ptr<Derived> create_derived_ptr();
> -// }
> -
> -// Test function return values (declaration)
> -std::auto_ptr<char> f_5();
> -// CHECK: std::unique_ptr<char> f_5()
> -
> -// Test function parameters
> -void f_6(std::auto_ptr<int>);
> -// CHECK: void f_6(std::unique_ptr<int>);
> -void f_7(const std::auto_ptr<int> &);
> -// CHECK: void f_7(const std::unique_ptr<int> &);
> -
> -// Test on record type fields
> -struct A {
> - std::auto_ptr<int> field;
> - // CHECK: std::unique_ptr<int> field;
> -
> - typedef std::auto_ptr<int> int_ptr_type;
> - // CHECK: typedef std::unique_ptr<int> int_ptr_type;
> -};
> -
> -// Test template WITH instantiation
> -template <typename T> struct B {
> - typedef typename std::auto_ptr<T> created_type;
> - // CHECK: typedef typename std::unique_ptr<T> created_type;
> -
> - created_type create() { return std::auto_ptr<T>(new T()); }
> - // CHECK: created_type create() { return std::unique_ptr<T>(new T()); }
> -};
> -
> -// Test 'using' in a namespace (declaration)
> -namespace ns_1 {
> -// Test multiple using declarations
> -using std::auto_ptr;
> -using std::auto_ptr;
> -// CHECK: using std::unique_ptr;
> -// CHECK-NEXT: using std::unique_ptr;
> -}
> -
> -namespace ns_2 {
> -template <typename T> struct auto_ptr {};
> -// CHECK: template <typename T> struct auto_ptr {};
> -}
> -
> -#endif // INPUTS_BASIC_H
> Index: test/clang-modernize/PassByValue/basic.h
> ===================================================================
> --- test/clang-modernize/PassByValue/basic.h
> +++ /dev/null
> @@ -1,23 +0,0 @@
> -#ifndef BASIC_H
> -#define BASIC_H
> -
> -// POD types are trivially move constructible
> -struct Movable {
> - int a, b, c;
> -};
> -
> -struct NotMovable {
> - NotMovable() = default;
> - NotMovable(const NotMovable &) = default;
> - NotMovable(NotMovable &&) = delete;
> - int a, b, c;
> -};
> -
> -// The test runs the migrator without header modifications enabled for this
> -// header making the constructor parameter M unmodifiable.
> -struct UnmodifiableClass {
> - UnmodifiableClass(const Movable &M);
> - Movable M;
> -};
> -
> -#endif // BASIC_H
> Index: test/clang-modernize/PassByValue/basic.cpp
> ===================================================================
> --- test/clang-modernize/PassByValue/basic.cpp
> +++ /dev/null
> @@ -1,185 +0,0 @@
> -// Since -fdelayed-template-parsing is enabled by default on Windows (as a
> -// Microsoft extension), -fno-delayed-template-parsing is used for the tests in
> -// order to have the same behavior on all systems.
> -//
> -// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
> -// RUN: clang-modernize -pass-by-value %t.cpp -- -std=c++11 -fno-delayed-template-parsing -I %S
> -// RUN: FileCheck -input-file=%t.cpp %s
> -//
> -// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
> -// RUN: clang-modernize -pass-by-value %t.cpp -- -std=c++11 -fno-delayed-template-parsing -I %S
> -// RUN: FileCheck -check-prefix=SAFE_RISK -input-file=%t.cpp %s
> -
> -#include "basic.h"
> -// CHECK: #include <utility>
> -
> -// Test that when the class declaration can't be modified we won't modify the
> -// definition either.
> -UnmodifiableClass::UnmodifiableClass(const Movable &M) : M(M) {}
> -// CHECK: UnmodifiableClass::UnmodifiableClass(const Movable &M) : M(M) {}
> -
> -struct A {
> - A(const Movable &M) : M(M) {}
> - // CHECK: A(Movable M) : M(std::move(M)) {}
> - // SAFE_RISK: A(const Movable &M) : M(M) {}
> - Movable M;
> -};
> -
> -// Test that we aren't modifying other things than a parameter
> -Movable GlobalObj;
> -struct B {
> - B(const Movable &M) : M(GlobalObj) {}
> - // CHECK: B(const Movable &M) : M(GlobalObj) {}
> - Movable M;
> -};
> -
> -// Test that a parameter with more than one reference to it won't be changed.
> -struct C {
> - // Tests extra-reference in body
> - C(const Movable &M) : M(M) { this->i = M.a; }
> - // CHECK: C(const Movable &M) : M(M) { this->i = M.a; }
> -
> - // Tests extra-reference in init-list
> - C(const Movable &M, int) : M(M), i(M.a) {}
> - // CHECK: C(const Movable &M, int) : M(M), i(M.a) {}
> - Movable M;
> - int i;
> -};
> -
> -// Test that both declaration and definition are updated
> -struct D {
> - D(const Movable &M);
> - // CHECK: D(Movable M);
> - Movable M;
> -};
> -D::D(const Movable &M) : M(M) {}
> -// CHECK: D::D(Movable M) : M(std::move(M)) {}
> -
> -// Test with default parameter
> -struct E {
> - E(const Movable &M = Movable()) : M(M) {}
> - // CHECK: E(Movable M = Movable()) : M(std::move(M)) {}
> - Movable M;
> -};
> -
> -// Test with object that can't be moved
> -struct F {
> - F(const NotMovable &NM) : NM(NM) {}
> - // CHECK: F(const NotMovable &NM) : NM(NM) {}
> - NotMovable NM;
> -};
> -
> -// Test unnamed parameter in declaration
> -struct G {
> - G(const Movable &);
> - // CHECK: G(Movable );
> - Movable M;
> -};
> -G::G(const Movable &M) : M(M) {}
> -// CHECK: G::G(Movable M) : M(std::move(M)) {}
> -
> -// Test parameter with and without qualifier
> -namespace ns_H {
> -typedef ::Movable HMovable;
> -}
> -struct H {
> - H(const ns_H::HMovable &M);
> - // CHECK: H(ns_H::HMovable M);
> - ns_H::HMovable M;
> -};
> -using namespace ns_H;
> -H::H(const HMovable &M) : M(M) {}
> -// CHECK: H(HMovable M) : M(std::move(M)) {}
> -
> -// Try messing up with macros
> -#define MOVABLE_PARAM(Name) const Movable & Name
> -// CHECK: #define MOVABLE_PARAM(Name) const Movable & Name
> -struct I {
> - I(MOVABLE_PARAM(M)) : M(M) {}
> - // CHECK: I(MOVABLE_PARAM(M)) : M(M) {}
> - Movable M;
> -};
> -#undef MOVABLE_PARAM
> -
> -// Test that templates aren't modified
> -template <typename T> struct J {
> - J(const T &M) : M(M) {}
> - // CHECK: J(const T &M) : M(M) {}
> - T M;
> -};
> -J<Movable> j1(Movable());
> -J<NotMovable> j2(NotMovable());
> -
> -struct K_Movable {
> - K_Movable() = default;
> - K_Movable(const K_Movable &) = default;
> - K_Movable(K_Movable &&o) { dummy = o.dummy; }
> - int dummy;
> -};
> -
> -// Test with movable type with an user defined move constructor.
> -struct K {
> - K(const K_Movable &M) : M(M) {}
> - // CHECK: K(K_Movable M) : M(std::move(M)) {}
> - K_Movable M;
> -};
> -
> -template <typename T> struct L {
> - L(const Movable &M) : M(M) {}
> - // CHECK: L(Movable M) : M(std::move(M)) {}
> - Movable M;
> -};
> -L<int> l(Movable());
> -
> -// Test with a non-instantiated template class
> -template <typename T> struct N {
> - N(const Movable &M) : M(M) {}
> - // CHECK: N(Movable M) : M(std::move(M)) {}
> -
> - Movable M;
> - T A;
> -};
> -
> -// Test with value parameter
> -struct O {
> - O(Movable M) : M(M) {}
> - // CHECK: O(Movable M) : M(std::move(M)) {}
> - Movable M;
> -};
> -
> -// Test with a const-value parameter
> -struct P {
> - P(const Movable M) : M(M) {}
> - // CHECK: P(const Movable M) : M(M) {}
> - Movable M;
> -};
> -
> -// Test with multiples parameters where some need to be changed and some don't
> -// need to.
> -struct Q {
> - Q(const Movable &A, const Movable &B, const Movable &C, double D)
> - : A(A), B(B), C(C), D(D) {}
> - // CHECK: Q(const Movable &A, Movable B, Movable C, double D)
> - // CHECK-NEXT: : A(A), B(std::move(B)), C(std::move(C)), D(D) {}
> - const Movable &A;
> - Movable B;
> - Movable C;
> - double D;
> -};
> -
> -// Test that value-parameters with a nested name specifier are left as-is
> -namespace ns_R {
> -typedef ::Movable RMovable;
> -}
> -struct R {
> - R(ns_R::RMovable M) : M(M) {}
> - // CHECK: R(ns_R::RMovable M) : M(std::move(M)) {}
> - ns_R::RMovable M;
> -};
> -
> -// Test with rvalue parameter
> -struct S {
> - S(Movable &&M) : M(M) {}
> - // CHECK: S(Movable &&M) : M(M) {}
> - Movable M;
> -};
> Index: test/clang-modernize/LoopConvert/single-iterator.cpp
> ===================================================================
> --- test/clang-modernize/LoopConvert/single-iterator.cpp
> +++ /dev/null
> @@ -1,152 +0,0 @@
> -// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
> -// RUN: clang-modernize -loop-convert %t.cpp -- -I %S/Inputs
> -// RUN: FileCheck -input-file=%t.cpp %s
> -
> -#include "structures.h"
> -
> -void complexContainer() {
> - X exes[5];
> - int index = 0;
> -
> - for (S::iterator i = exes[index].getS().begin(), e = exes[index].getS().end(); i != e; ++i) {
> - MutableVal k = *i;
> - MutableVal j = *i;
> - }
> - // CHECK: for (auto & elem : exes[index].getS())
> - // CHECK-NEXT: MutableVal k = elem;
> - // CHECK-NEXT: MutableVal j = elem;
> -}
> -
> -void f() {
> - /// begin()/end() - based for loops here:
> - T t;
> - for (T::iterator it = t.begin(); it != t.end(); ++it) {
> - printf("I found %d\n", *it);
> - }
> - // CHECK: for (auto & elem : t)
> - // CHECK-NEXT: printf("I found %d\n", elem);
> -
> - T *pt;
> - for (T::iterator it = pt->begin(); it != pt->end(); ++it) {
> - printf("I found %d\n", *it);
> - }
> - // CHECK: for (auto & elem : *pt)
> - // CHECK-NEXT: printf("I found %d\n", elem);
> -
> - S s;
> - for (S::iterator it = s.begin(); it != s.end(); ++it) {
> - printf("s has value %d\n", (*it).x);
> - }
> - // CHECK: for (auto & elem : s)
> - // CHECK-NEXT: printf("s has value %d\n", (elem).x);
> -
> - S *ps;
> - for (S::iterator it = ps->begin(); it != ps->end(); ++it) {
> - printf("s has value %d\n", (*it).x);
> - }
> - // CHECK: for (auto & p : *ps)
> - // CHECK-NEXT: printf("s has value %d\n", (p).x);
> -
> - for (S::iterator it = s.begin(); it != s.end(); ++it) {
> - printf("s has value %d\n", it->x);
> - }
> - // CHECK: for (auto & elem : s)
> - // CHECK-NEXT: printf("s has value %d\n", elem.x);
> -
> - for (S::iterator it = s.begin(); it != s.end(); ++it) {
> - it->x = 3;
> - }
> - // CHECK: for (auto & elem : s)
> - // CHECK-NEXT: elem.x = 3;
> -
> - for (S::iterator it = s.begin(); it != s.end(); ++it) {
> - (*it).x = 3;
> - }
> - // CHECK: for (auto & elem : s)
> - // CHECK-NEXT: (elem).x = 3;
> -
> - for (S::iterator it = s.begin(); it != s.end(); ++it) {
> - it->nonConstFun(4, 5);
> - }
> - // CHECK: for (auto & elem : s)
> - // CHECK-NEXT: elem.nonConstFun(4, 5);
> -
> - U u;
> - for (U::iterator it = u.begin(); it != u.end(); ++it) {
> - printf("s has value %d\n", it->x);
> - }
> - // CHECK: for (auto & elem : u)
> - // CHECK-NEXT: printf("s has value %d\n", elem.x);
> -
> - for (U::iterator it = u.begin(); it != u.end(); ++it) {
> - printf("s has value %d\n", (*it).x);
> - }
> - // CHECK: for (auto & elem : u)
> - // CHECK-NEXT: printf("s has value %d\n", (elem).x);
> -
> - U::iterator A;
> - for (U::iterator i = u.begin(); i != u.end(); ++i)
> - int k = A->x + i->x;
> - // CHECK: for (auto & elem : u)
> - // CHECK-NEXT: int k = A->x + elem.x;
> -
> - dependent<int> v;
> - for (dependent<int>::iterator it = v.begin();
> - it != v.end(); ++it) {
> - printf("Fibonacci number is %d\n", *it);
> - }
> - // CHECK: for (auto & elem : v) {
> - // CHECK-NEXT: printf("Fibonacci number is %d\n", elem);
> -
> - for (dependent<int>::iterator it(v.begin());
> - it != v.end(); ++it) {
> - printf("Fibonacci number is %d\n", *it);
> - }
> - // CHECK: for (auto & elem : v) {
> - // CHECK-NEXT: printf("Fibonacci number is %d\n", elem);
> -
> - doublyDependent<int,int> intmap;
> - for (doublyDependent<int,int>::iterator it = intmap.begin();
> - it != intmap.end(); ++it) {
> - printf("intmap[%d] = %d", it->first, it->second);
> - }
> - // CHECK: for (auto & elem : intmap)
> - // CHECK-NEXT: printf("intmap[%d] = %d", elem.first, elem.second);
> -}
> -
> -void different_type() {
> - // Tests to verify the proper use of auto where the init variable type and the
> - // initializer type differ or are mostly the same except for const qualifiers.
> -
> - // s.begin() returns a type 'iterator' which is just a non-const pointer and
> - // differs from const_iterator only on the const qualification.
> - S s;
> - for (S::const_iterator it = s.begin(); it != s.end(); ++it) {
> - printf("s has value %d\n", (*it).x);
> - }
> - // CHECK: for (const auto & elem : s)
> - // CHECK-NEXT: printf("s has value %d\n", (elem).x);
> -
> - S *ps;
> - for (S::const_iterator it = ps->begin(); it != ps->end(); ++it) {
> - printf("s has value %d\n", (*it).x);
> - }
> - // CHECK: for (const auto & p : *ps)
> - // CHECK-NEXT: printf("s has value %d\n", (p).x);
> -
> - // v.begin() returns a user-defined type 'iterator' which, since it's
> - // different from const_iterator, disqualifies these loops from
> - // transformation.
> - dependent<int> v;
> - for (dependent<int>::const_iterator it = v.begin(); it != v.end(); ++it) {
> - printf("Fibonacci number is %d\n", *it);
> - }
> - // CHECK: for (dependent<int>::const_iterator it = v.begin(); it != v.end(); ++it) {
> - // CHECK-NEXT: printf("Fibonacci number is %d\n", *it);
> -
> - for (dependent<int>::const_iterator it(v.begin()); it != v.end(); ++it) {
> - printf("Fibonacci number is %d\n", *it);
> - }
> - // CHECK: for (dependent<int>::const_iterator it(v.begin()); it != v.end(); ++it) {
> - // CHECK-NEXT: printf("Fibonacci number is %d\n", *it);
> -}
> Index: test/clang-modernize/LoopConvert/pseudoarray.cpp
> ===================================================================
> --- test/clang-modernize/LoopConvert/pseudoarray.cpp
> +++ /dev/null
> @@ -1,105 +0,0 @@
> -// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
> -// RUN: clang-modernize -loop-convert %t.cpp -- -I %S/Inputs -std=c++11
> -// RUN: FileCheck -input-file=%t.cpp %s
> -#include "structures.h"
> -
> -const int N = 6;
> -dependent<int> v;
> -dependent<int> *pv;
> -
> -transparent<dependent<int> > cv;
> -
> -void f() {
> - int sum = 0;
> - for (int i = 0, e = v.size(); i < e; ++i) {
> - printf("Fibonacci number is %d\n", v[i]);
> - sum += v[i] + 2;
> - }
> - // CHECK: for (auto & elem : v)
> - // CHECK-NEXT: printf("Fibonacci number is %d\n", elem);
> - // CHECK-NEXT: sum += elem + 2;
> -
> - for (int i = 0, e = v.size(); i < e; ++i) {
> - printf("Fibonacci number is %d\n", v.at(i));
> - sum += v.at(i) + 2;
> - }
> - // CHECK: for (auto & elem : v)
> - // CHECK-NEXT: printf("Fibonacci number is %d\n", elem);
> - // CHECK-NEXT: sum += elem + 2;
> -
> - for (int i = 0, e = pv->size(); i < e; ++i) {
> - printf("Fibonacci number is %d\n", pv->at(i));
> - sum += pv->at(i) + 2;
> - }
> - // CHECK: for (auto & elem : *pv)
> - // CHECK-NEXT: printf("Fibonacci number is %d\n", elem);
> - // CHECK-NEXT: sum += elem + 2;
> -
> - // This test will fail if size() isn't called repeatedly, since it
> - // returns unsigned int, and 0 is deduced to be signed int.
> - // FIXME: Insert the necessary explicit conversion, or write out the types
> - // explicitly.
> - for (int i = 0; i < pv->size(); ++i) {
> - printf("Fibonacci number is %d\n", (*pv).at(i));
> - sum += (*pv)[i] + 2;
> - }
> - // CHECK: for (auto & elem : *pv)
> - // CHECK-NEXT: printf("Fibonacci number is %d\n", elem);
> - // CHECK-NEXT: sum += elem + 2;
> -
> - for (int i = 0; i < cv->size(); ++i) {
> - printf("Fibonacci number is %d\n", cv->at(i));
> - sum += cv->at(i) + 2;
> - }
> - // CHECK: for (auto & elem : *cv)
> - // CHECK-NEXT: printf("Fibonacci number is %d\n", elem);
> - // CHECK-NEXT: sum += elem + 2;
> -}
> -
> -// Check for loops that don't mention containers
> -void noContainer() {
> - for (auto i = 0; i < v.size(); ++i) { }
> - // CHECK: for (auto & elem : v) { }
> -
> - for (auto i = 0; i < v.size(); ++i) ;
> - // CHECK: for (auto & elem : v) ;
> -}
> -
> -struct NoBeginEnd {
> - unsigned size() const;
> -};
> -
> -struct NoConstBeginEnd {
> - NoConstBeginEnd();
> - unsigned size() const;
> - unsigned begin();
> - unsigned end();
> -};
> -
> -struct ConstBeginEnd {
> - ConstBeginEnd();
> - unsigned size() const;
> - unsigned begin() const;
> - unsigned end() const;
> -};
> -
> -// Shouldn't transform pseudo-array uses if the container doesn't provide
> -// begin() and end() of the right const-ness.
> -void NoBeginEndTest() {
> - NoBeginEnd NBE;
> - for (unsigned i = 0, e = NBE.size(); i < e; ++i) {}
> - // CHECK: for (unsigned i = 0, e = NBE.size(); i < e; ++i) {}
> -
> - const NoConstBeginEnd const_NCBE;
> - for (unsigned i = 0, e = const_NCBE.size(); i < e; ++i) {}
> - // CHECK: for (unsigned i = 0, e = const_NCBE.size(); i < e; ++i) {}
> -
> - ConstBeginEnd CBE;
> - for (unsigned i = 0, e = CBE.size(); i < e; ++i) {}
> - // CHECK: for (auto & elem : CBE) {}
> -
> - const ConstBeginEnd const_CBE;
> - for (unsigned i = 0, e = const_CBE.size(); i < e; ++i) {}
> - // CHECK: for (auto & elem : const_CBE) {}
> -}
> -
> Index: test/clang-modernize/LoopConvert/nocompile.cpp
> ===================================================================
> --- test/clang-modernize/LoopConvert/nocompile.cpp
> +++ /dev/null
> @@ -1,21 +0,0 @@
> -// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
> -// RUN: not clang-modernize -loop-convert %t.cpp -- -I %S/Inputs
> -// RUN: FileCheck -input-file=%t.cpp %s
> -
> -void valid() {
> - const int arr[5];
> - int sum = 0;
> - for (int i = 0; i < 5; ++i) {
> - sum += arr[i];
> - }
> -}
> -void hasSyntaxError = 3;
> -// CHECK: void valid() {
> -// CHECK-NEXT: const int arr[5];
> -// CHECK-NEXT: int sum = 0;
> -// CHECK-NEXT: for (int i = 0; i < 5; ++i) {
> -// CHECK-NEXT: sum += arr[i];
> -// CHECK-NEXT: }
> -// CHECK-NEXT: }
> -
> -// CHECK-NEXT: void hasSyntaxError = 3;
> Index: test/clang-modernize/LoopConvert/nesting.cpp
> ===================================================================
> --- test/clang-modernize/LoopConvert/nesting.cpp
> +++ /dev/null
> @@ -1,69 +0,0 @@
> -// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
> -// RUN: clang-modernize -loop-convert %t.cpp -- -I %S/Inputs
> -// RUN: FileCheck -input-file=%t.cpp %s
> -
> -#include "structures.h"
> -
> -void f() {
> - const int N = 10;
> - const int M = 15;
> - Val Arr[N];
> - for (int i = 0; i < N; ++i) {
> - for (int j = 0; j < N; ++j) {
> - int k = Arr[i].x + Arr[j].x;
> - // The repeat is there to allow FileCheck to make sure the two variable
> - // names aren't the same.
> - int l = Arr[i].x + Arr[j].x;
> - }
> - }
> - // CHECK: for (auto & elem : Arr)
> - // CHECK-NEXT: for (auto & Arr_j : Arr)
> - // CHECK-NEXT: int k = elem.x + Arr_j.x;
> - // CHECK-NOT: int l = elem.x + elem.x;
> -
> - Val Nest[N][M];
> - for (int i = 0; i < N; ++i) {
> - for (int j = 0; j < M; ++j) {
> - printf("Got item %d", Nest[i][j].x);
> - }
> - }
> - // The inner loop is also convertible, but doesn't need to be converted
> - // immediately. Update this test when that changes!
> - // CHECK: for (auto & elem : Nest)
> - // CHECK-NEXT: for (int j = 0; j < M; ++j)
> - // CHECK-NEXT: printf("Got item %d", elem[j].x);
> -
> - // Note that the order of M and N are switched for this test.
> - for (int j = 0; j < M; ++j) {
> - for (int i = 0; i < N; ++i) {
> - printf("Got item %d", Nest[i][j].x);
> - }
> - }
> - // CHECK-NOT: for (auto & {{[a-zA-Z_]+}} : Nest[i])
> - // CHECK: for (int j = 0; j < M; ++j)
> - // CHECK-NEXT: for (auto & elem : Nest)
> - // CHECK-NEXT: printf("Got item %d", elem[j].x);
> - Nested<T> NestT;
> - for (Nested<T>::iterator I = NestT.begin(), E = NestT.end(); I != E; ++I) {
> - for (T::iterator TI = (*I).begin(), TE = (*I).end(); TI != TE; ++TI) {
> - printf("%d", *TI);
> - }
> - }
> - // The inner loop is also convertible, but doesn't need to be converted
> - // immediately. Update this test when that changes!
> - // CHECK: for (auto & elem : NestT) {
> - // CHECK-NEXT: for (T::iterator TI = (elem).begin(), TE = (elem).end(); TI != TE; ++TI) {
> - // CHECK-NEXT: printf("%d", *TI);
> -
> - Nested<S> NestS;
> - for (Nested<S>::const_iterator I = NestS.begin(), E = NestS.end(); I != E; ++I) {
> - for (S::const_iterator SI = (*I).begin(), SE = (*I).end(); SI != SE; ++SI) {
> - printf("%d", *SI);
> - }
> - }
> - // The inner loop is also convertible, but doesn't need to be converted
> - // immediately. Update this test when that changes!
> - // CHECK: for (const auto & elem : NestS) {
> - // CHECK-NEXT: for (S::const_iterator SI = (elem).begin(), SE = (elem).end(); SI != SE; ++SI) {
> - // CHECK-NEXT: printf("%d", *SI);
> -}
> Index: test/clang-modernize/LoopConvert/negative.cpp
> ===================================================================
> --- test/clang-modernize/LoopConvert/negative.cpp
> +++ /dev/null
> @@ -1,123 +0,0 @@
> -// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
> -// RUN: grep -Ev "// *[A-Z-]+:" %S/Inputs/negative-header.h > \
> -// RUN: %T/negative-header.h
> -// RUN: clang-modernize -loop-convert %t.cpp -- -I %S/Inputs/
> -// RUN: FileCheck -input-file=%t.cpp %s
> -// RUN: FileCheck -input-file=%T/negative-header.h %S/Inputs/negative-header.h
> -
> -#include "negative-header.h"
> -#include "structures.h"
> -
> -// Single FileCheck line to make sure that no loops are converted.
> -// CHECK-NOT: for ({{.*[^:]:[^:].*}})
> -
> -const int N = 6;
> -int arr[N] = {1, 2, 3, 4, 5, 6};
> -int (*pArr)[N] = &arr;
> -int sum = 0;
> -
> -// Checks for the index start and end:
> -void indexStartAndEnd() {
> - for (int i = 0; i < N + 1; ++i)
> - sum += arr[i];
> -
> - for (int i = 0; i < N - 1; ++i)
> - sum += arr[i];
> -
> - for (int i = 1; i < N; ++i)
> - sum += arr[i];
> -
> - for (int i = 1; i < N; ++i)
> - sum += arr[i];
> -
> - for (int i = 0; ; ++i)
> - sum += (*pArr)[i];
> -}
> -
> -// Checks for invalid increment steps:
> -void increment() {
> - for (int i = 0; i < N; --i)
> - sum += arr[i];
> -
> - for (int i = 0; i < N; i)
> - sum += arr[i];
> -
> - for (int i = 0; i < N;)
> - sum += arr[i];
> -
> - for (int i = 0; i < N; i += 2)
> - sum ++;
> -}
> -
> -// Checks to make sure that the index isn't used outside of the array:
> -void indexUse() {
> - for (int i = 0; i < N; ++i)
> - arr[i] += 1 + i;
> -}
> -
> -// Check for loops that don't mention arrays
> -void noArray() {
> - for (int i = 0; i < N; ++i)
> - sum += i;
> -
> - for (int i = 0; i < N; ++i) { }
> -
> - for (int i = 0; i < N; ++i) ;
> -}
> -
> -// Checks for incorrect loop variables.
> -void mixedVariables() {
> - int badIndex;
> - for (int i = 0; badIndex < N; ++i)
> - sum += arr[i];
> -
> - for (int i = 0; i < N; ++badIndex)
> - sum += arr[i];
> -
> - for (int i = 0; badIndex < N; ++badIndex)
> - sum += arr[i];
> -
> - for (int i = 0; badIndex < N; ++badIndex)
> - sum += arr[badIndex];
> -}
> -
> -// Checks for multiple arrays indexed.
> -void multipleArrays() {
> - int badArr[N];
> -
> - for (int i = 0; i < N; ++i)
> - sum += arr[i] + badArr[i];
> -
> - for (int i = 0; i < N; ++i) {
> - int k = badArr[i];
> - sum += arr[i] + k;
> - }
> -}
> -
> -struct HasArr {
> - int Arr[N];
> - Val ValArr[N];
> -};
> -
> -struct HasIndirectArr {
> - HasArr HA;
> - void implicitThis() {
> - for (int i = 0; i < N; ++i) {
> - printf("%d", HA.Arr[i]);
> - }
> -
> - for (int i = 0; i < N; ++i) {
> - printf("%d", HA.ValArr[i].x);
> - }
> - }
> -
> - void explicitThis() {
> - for (int i = 0; i < N; ++i) {
> - printf("%d", this->HA.Arr[i]);
> - }
> -
> - for (int i = 0; i < N; ++i) {
> - printf("%d", this->HA.ValArr[i].x);
> - }
> - }
> -};
> Index: test/clang-modernize/LoopConvert/negative-pseudoarray.cpp
> ===================================================================
> --- test/clang-modernize/LoopConvert/negative-pseudoarray.cpp
> +++ /dev/null
> @@ -1,129 +0,0 @@
> -// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
> -// RUN: clang-modernize -loop-convert %t.cpp -- -I %S/Inputs
> -// RUN: FileCheck -input-file=%t.cpp %s
> -
> -#include "structures.h"
> -
> -// Single FileCheck line to make sure that no loops are converted.
> -// CHECK-NOT: for ({{.*[^:]:[^:].*}})
> -
> -const int N = 6;
> -dependent<int> v;
> -dependent<int> *pv;
> -
> -transparent<dependent<int> > cv;
> -int sum = 0;
> -
> -// Checks for the index start and end:
> -void indexStartAndEnd() {
> - for (int i = 0; i < v.size() + 1; ++i)
> - sum += v[i];
> -
> - for (int i = 0; i < v.size() - 1; ++i)
> - sum += v[i];
> -
> - for (int i = 1; i < v.size(); ++i)
> - sum += v[i];
> -
> - for (int i = 1; i < v.size(); ++i)
> - sum += v[i];
> -
> - for (int i = 0; ; ++i)
> - sum += (*pv)[i];
> -}
> -
> -// Checks for invalid increment steps:
> -void increment() {
> - for (int i = 0; i < v.size(); --i)
> - sum += v[i];
> -
> - for (int i = 0; i < v.size(); i)
> - sum += v[i];
> -
> - for (int i = 0; i < v.size();)
> - sum += v[i];
> -
> - for (int i = 0; i < v.size(); i += 2)
> - sum ++;
> -}
> -
> -// Checks to make sure that the index isn't used outside of the container:
> -void indexUse() {
> - for (int i = 0; i < v.size(); ++i)
> - v[i] += 1 + i;
> -}
> -
> -// Checks for incorrect loop variables.
> -void mixedVariables() {
> - int badIndex;
> - for (int i = 0; badIndex < v.size(); ++i)
> - sum += v[i];
> -
> - for (int i = 0; i < v.size(); ++badIndex)
> - sum += v[i];
> -
> - for (int i = 0; badIndex < v.size(); ++badIndex)
> - sum += v[i];
> -
> - for (int i = 0; badIndex < v.size(); ++badIndex)
> - sum += v[badIndex];
> -}
> -
> -// Checks for an array indexed in addition to the container.
> -void multipleArrays() {
> - int badArr[N];
> -
> - for (int i = 0; i < v.size(); ++i)
> - sum += v[i] + badArr[i];
> -
> - for (int i = 0; i < v.size(); ++i)
> - sum += badArr[i];
> -
> - for (int i = 0; i < v.size(); ++i) {
> - int k = badArr[i];
> - sum += k + 2;
> - }
> -
> - for (int i = 0; i < v.size(); ++i) {
> - int k = badArr[i];
> - sum += v[i] + k;
> - }
> -}
> -
> -// Checks for multiple containers being indexed container.
> -void multipleContainers() {
> - dependent<int> badArr;
> -
> - for (int i = 0; i < v.size(); ++i)
> - sum += v[i] + badArr[i];
> -
> - for (int i = 0; i < v.size(); ++i)
> - sum += badArr[i];
> -
> - for (int i = 0; i < v.size(); ++i) {
> - int k = badArr[i];
> - sum += k + 2;
> - }
> -
> - for (int i = 0; i < v.size(); ++i) {
> - int k = badArr[i];
> - sum += v[i] + k;
> - }
> -}
> -
> -// Check to make sure that dereferenced pointers-to-containers behave nicely
> -void derefContainer() {
> - // Note the dependent<T>::operator*() returns another dependent<T>.
> - // This test makes sure that we don't allow an arbitrary number of *'s.
> - for (int i = 0; i < pv->size(); ++i)
> - sum += (**pv).at(i);
> -
> - for (int i = 0; i < pv->size(); ++i)
> - sum += (**pv)[i];
> -}
> -
> -void wrongEnd() {
> - int bad;
> - for (int i = 0, e = v.size(); i < bad; ++i)
> - sum += v[i];
> -}
> Index: test/clang-modernize/LoopConvert/negative-pseudoarray-extra.cpp
> ===================================================================
> --- test/clang-modernize/LoopConvert/negative-pseudoarray-extra.cpp
> +++ /dev/null
> @@ -1,29 +0,0 @@
> -// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
> -// RUN: clang-modernize -loop-convert %t.cpp -- -I %S/Inputs
> -// RUN: FileCheck -input-file=%t.cpp %s
> -
> -#include "structures.h"
> -
> -// Single FileCheck line to make sure that no loops are converted.
> -// CHECK-NOT: for ({{.*[^:]:[^:].*}})
> -
> -const int N = 6;
> -dependent<int> v;
> -dependent<int> *pv;
> -
> -int sum = 0;
> -
> -// Checks to see that non-const member functions are not called on the container
> -// object.
> -// These could be conceivably allowed with a lower required confidence level.
> -void memberFunctionCalled() {
> - for (int i = 0; i < v.size(); ++i) {
> - sum += v[i];
> - v.foo();
> - }
> -
> - for (int i = 0; i < v.size(); ++i) {
> - sum += v[i];
> - dependent<int>::iterator it = v.begin();
> - }
> -}
> Index: test/clang-modernize/LoopConvert/negative-multi-end-call.cpp
> ===================================================================
> --- test/clang-modernize/LoopConvert/negative-multi-end-call.cpp
> +++ /dev/null
> @@ -1,64 +0,0 @@
> -// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
> -// RUN: clang-modernize -loop-convert -risk=safe %t.cpp -- -I %S/Inputs
> -// RUN: FileCheck -input-file=%t.cpp %s
> -
> -#include "structures.h"
> -
> -// Single FileCheck line to make sure that no loops are converted.
> -// CHECK-NOT: for ({{.*[^:]:[^:].*}})
> -
> -S s;
> -T t;
> -U u;
> -
> -void multipleEnd() {
> - for (S::iterator i = s.begin(); i != s.end(); ++i)
> - MutableVal k = *i;
> -
> - for (T::iterator i = t.begin(); i != t.end(); ++i)
> - int k = *i;
> -
> - for (U::iterator i = u.begin(); i != u.end(); ++i)
> - Val k = *i;
> -}
> -
> -void f(X);
> -void f(S);
> -void f(T);
> -
> -void complexContainer() {
> - X x;
> - for (S::iterator i = x.s.begin(), e = x.s.end(); i != e; ++i) {
> - f(x);
> - MutableVal k = *i;
> - }
> -
> - for (T::iterator i = x.t.begin(), e = x.t.end(); i != e; ++i) {
> - f(x);
> - int k = *i;
> - }
> -
> - for (S::iterator i = x.s.begin(), e = x.s.end(); i != e; ++i) {
> - f(x.s);
> - MutableVal k = *i;
> - }
> -
> - for (T::iterator i = x.t.begin(), e = x.t.end(); i != e; ++i) {
> - f(x.t);
> - int k = *i;
> - }
> -
> - for (S::iterator i = x.getS().begin(), e = x.getS().end(); i != e; ++i) {
> - f(x.getS());
> - MutableVal k = *i;
> - }
> -
> - X exes[5];
> - int index = 0;
> -
> - for (S::iterator i = exes[index].getS().begin(),
> - e = exes[index].getS().end(); i != e; ++i) {
> - index++;
> - MutableVal k = *i;
> - }
> -}
> Index: test/clang-modernize/LoopConvert/negative-iterator.cpp
> ===================================================================
> --- test/clang-modernize/LoopConvert/negative-iterator.cpp
> +++ /dev/null
> @@ -1,160 +0,0 @@
> -// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
> -// RUN: clang-modernize -loop-convert %t.cpp -- -I %S/Inputs
> -// RUN: FileCheck -input-file=%t.cpp %s
> -
> -#include "structures.h"
> -
> -// Single FileCheck line to make sure that no loops are converted.
> -// CHECK-NOT: for ({{.*[^:]:[^:].*}})
> -
> -S s;
> -T t;
> -U u;
> -
> -struct BadBeginEnd : T {
> - iterator notBegin();
> - iterator notEnd();
> -};
> -
> -void notBeginOrEnd() {
> - BadBeginEnd Bad;
> - for (T::iterator i = Bad.notBegin(), e = Bad.end(); i != e; ++i)
> - int k = *i;
> -
> - for (T::iterator i = Bad.begin(), e = Bad.notEnd(); i != e; ++i)
> - int k = *i;
> -}
> -
> -void badLoopShapes() {
> - for (T::iterator i = t.begin(), e = t.end(), f = e; i != e; ++i)
> - int k = *i;
> -
> - for (T::iterator i = t.begin(), e = t.end(); i != e; )
> - int k = *i;
> -
> - for (T::iterator i = t.begin(), e = t.end(); ; ++i)
> - int k = *i;
> -
> - T::iterator outsideI;
> - T::iterator outsideE;
> -
> - for (; outsideI != outsideE ; ++outsideI)
> - int k = *outsideI;
> -}
> -
> -void iteratorArrayMix() {
> - int lower;
> - const int N = 6;
> - for (T::iterator i = t.begin(), e = t.end(); lower < N; ++i)
> - int k = *i;
> -
> - for (T::iterator i = t.begin(), e = t.end(); lower < N; ++lower)
> - int k = *i;
> -}
> -
> -struct ExtraConstructor : T::iterator {
> - ExtraConstructor(T::iterator, int);
> - explicit ExtraConstructor(T::iterator);
> -};
> -
> -void badConstructor() {
> - for (T::iterator i = ExtraConstructor(t.begin(), 0), e = t.end();
> - i != e; ++i)
> - int k = *i;
> - for (T::iterator i = ExtraConstructor(t.begin()), e = t.end(); i != e; ++i)
> - int k = *i;
> -}
> -
> -void iteratorMemberUsed() {
> - for (T::iterator i = t.begin(), e = t.end(); i != e; ++i)
> - i.x = *i;
> -
> - for (T::iterator i = t.begin(), e = t.end(); i != e; ++i)
> - int k = i.x + *i;
> -
> - for (T::iterator i = t.begin(), e = t.end(); i != e; ++i)
> - int k = e.x + *i;
> -}
> -
> -void iteratorMethodCalled() {
> - for (T::iterator i = t.begin(), e = t.end(); i != e; ++i)
> - i.insert(3);
> -
> - for (T::iterator i = t.begin(), e = t.end(); i != e; ++i)
> - if (i != i)
> - int k = 3;
> -}
> -
> -void iteratorOperatorCalled() {
> - for (T::iterator i = t.begin(), e = t.end(); i != e; ++i)
> - int k = *(++i);
> -
> - for (S::iterator i = s.begin(), e = s.end(); i != e; ++i)
> - MutableVal k = *(++i);
> -}
> -
> -void differentContainers() {
> - T other;
> - for (T::iterator i = t.begin(), e = other.end(); i != e; ++i)
> - int k = *i;
> -
> - for (T::iterator i = other.begin(), e = t.end(); i != e; ++i)
> - int k = *i;
> -
> - S otherS;
> - for (S::iterator i = s.begin(), e = otherS.end(); i != e; ++i)
> - MutableVal k = *i;
> -
> - for (S::iterator i = otherS.begin(), e = s.end(); i != e; ++i)
> - MutableVal k = *i;
> -}
> -
> -void wrongIterators() {
> - T::iterator other;
> - for (T::iterator i = t.begin(), e = t.end(); i != other; ++i)
> - int k = *i;
> -}
> -
> -struct EvilArrow : U {
> - // Please, no one ever write code like this.
> - U* operator->();
> -};
> -
> -void differentMemberAccessTypes() {
> - EvilArrow A;
> - for (EvilArrow::iterator i = A.begin(), e = A->end(); i != e; ++i)
> - Val k = *i;
> - for (EvilArrow::iterator i = A->begin(), e = A.end(); i != e; ++i)
> - Val k = *i;
> -}
> -
> -void f(const T::iterator &it, int);
> -void f(const T &it, int);
> -void g(T &it, int);
> -
> -void iteratorPassedToFunction() {
> - for (T::iterator i = t.begin(), e = t.end(); i != e; ++i)
> - f(i, *i);
> -}
> -
> -// FIXME: Disallow this except for containers passed by value and/or const
> -// reference. Or maybe this is correct enough for any container?
> -void containerPassedToFunction() {
> -// for (T::iterator i = t.begin(), e = t.end(); i != e; ++i)
> -// f(t, *i);
> -// for (T::iterator i = t.begin(), e = t.end(); i != e; ++i)
> -// g(t, *i);
> -}
> -
> -// FIXME: These tests can be removed if this tool ever does enough analysis to
> -// decide that this is a safe transformation.
> -// Until then, we don't want it applied.
> -void iteratorDefinedOutside() {
> - T::iterator theEnd = t.end();
> - for (T::iterator i = t.begin(); i != theEnd; ++i)
> - int k = *i;
> -
> - T::iterator theBegin = t.begin();
> - for (T::iterator e = t.end(); theBegin != e; ++theBegin)
> - int k = *theBegin;
> -}
> Index: test/clang-modernize/LoopConvert/naming-conflict.cpp
> ===================================================================
> --- test/clang-modernize/LoopConvert/naming-conflict.cpp
> +++ /dev/null
> @@ -1,119 +0,0 @@
> -// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
> -// RUN: clang-modernize -loop-convert %t.cpp -- -I %S/Inputs
> -// RUN: FileCheck -input-file=%t.cpp %s
> -
> -#include "structures.h"
> -
> -#define MAX(a,b) (a > b) ? a : b
> -#define DEF 5
> -
> -const int N = 10;
> -int nums[N];
> -int sum = 0;
> -
> -namespace ns {
> - struct st {
> - int x;
> - };
> -}
> -
> -void sameNames() {
> - int num = 0;
> - for (int i = 0; i < N; ++i) {
> - printf("Fibonacci number is %d\n", nums[i]);
> - sum += nums[i] + 2 + num;
> - (void) nums[i];
> - }
> - // CHECK: for (auto & nums_i : nums)
> - // CHECK-NEXT: printf("Fibonacci number is %d\n", nums_i);
> - // CHECK-NEXT: sum += nums_i + 2 + num;
> - // CHECK-NOT: (void) num;
> -}
> -
> -void macroConflict() {
> - S MAXs;
> - for (S::iterator it = MAXs.begin(), e = MAXs.end(); it != e; ++it) {
> - printf("s has value %d\n", (*it).x);
> - printf("Max of 3 and 5: %d\n", MAX(3,5));
> - }
> - // CHECK: for (auto & MAXs_it : MAXs)
> - // CHECK-NEXT: printf("s has value %d\n", (MAXs_it).x);
> - // CHECK-NEXT: printf("Max of 3 and 5: %d\n", MAX(3,5));
> -
> - for (S::const_iterator it = MAXs.begin(), e = MAXs.end(); it != e; ++it) {
> - printf("s has value %d\n", (*it).x);
> - printf("Max of 3 and 5: %d\n", MAX(3,5));
> - }
> - // CHECK: for (const auto & MAXs_it : MAXs)
> - // CHECK-NEXT: printf("s has value %d\n", (MAXs_it).x);
> - // CHECK-NEXT: printf("Max of 3 and 5: %d\n", MAX(3,5));
> -
> - T DEFs;
> - for (T::iterator it = DEFs.begin(), e = DEFs.end(); it != e; ++it) {
> - if (*it == DEF) {
> - printf("I found %d\n", *it);
> - }
> - }
> - // CHECK: for (auto & DEFs_it : DEFs)
> - // CHECK-NEXT: if (DEFs_it == DEF) {
> - // CHECK-NEXT: printf("I found %d\n", DEFs_it);
> -}
> -
> -void keywordConflict() {
> - T ints;
> - for (T::iterator it = ints.begin(), e = ints.end(); it != e; ++it) {
> - *it = 5;
> - }
> - // CHECK: for (auto & ints_it : ints)
> - // CHECK-NEXT: ints_it = 5;
> -
> - U __FUNCTION__s;
> - for (U::iterator it = __FUNCTION__s.begin(), e = __FUNCTION__s.end();
> - it != e; ++it) {
> - int __FUNCTION__s_it = (*it).x + 2;
> - }
> - // CHECK: for (auto & __FUNCTION__s_elem : __FUNCTION__s)
> - // CHECK-NEXT: int __FUNCTION__s_it = (__FUNCTION__s_elem).x + 2;
> -}
> -
> -void typeConflict() {
> - T Vals;
> - // Using the name "Val", although it is the name of an existing struct, is
> - // safe in this loop since it will only exist within this scope.
> - for (T::iterator it = Vals.begin(), e = Vals.end(); it != e; ++it) {
> - }
> - // CHECK: for (auto & Val : Vals)
> -
> - // We cannot use the name "Val" in this loop since there is a reference to
> - // it in the body of the loop.
> - for (T::iterator it = Vals.begin(), e = Vals.end(); it != e; ++it) {
> - *it = sizeof(Val);
> - }
> - // CHECK: for (auto & Vals_it : Vals)
> - // CHECK-NEXT: Vals_it = sizeof(Val);
> -
> - typedef struct Val TD;
> - U TDs;
> - // Naming the variable "TD" within this loop is safe because the typedef
> - // was never used within the loop.
> - for (U::iterator it = TDs.begin(), e = TDs.end(); it != e; ++it) {
> - }
> - // CHECK: for (auto & TD : TDs)
> -
> - // "TD" cannot be used in this loop since the typedef is being used.
> - for (U::iterator it = TDs.begin(), e = TDs.end(); it != e; ++it) {
> - TD V;
> - V.x = 5;
> - }
> - // CHECK: for (auto & TDs_it : TDs)
> - // CHECK-NEXT: TD V;
> - // CHECK-NEXT: V.x = 5;
> -
> - using ns::st;
> - T sts;
> - for (T::iterator it = sts.begin(), e = sts.end(); it != e; ++it) {
> - *it = sizeof(st);
> - }
> - // CHECK: for (auto & sts_it : sts)
> - // CHECK-NEXT: sts_it = sizeof(st);
> -}
> Index: test/clang-modernize/LoopConvert/naming-alias.cpp
> ===================================================================
> --- test/clang-modernize/LoopConvert/naming-alias.cpp
> +++ /dev/null
> @@ -1,160 +0,0 @@
> -// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
> -// RUN: clang-modernize -loop-convert %t.cpp -- -I %S/Inputs
> -// RUN: FileCheck -input-file=%t.cpp %s
> -
> -#include "structures.h"
> -
> -const int N = 10;
> -
> -Val Arr[N];
> -dependent<Val> v;
> -dependent<Val> *pv;
> -Val &func(Val &);
> -void sideEffect(int);
> -
> -void aliasing() {
> - // If the loop container is only used for a declaration of a temporary
> - // variable to hold each element, we can name the new variable for the
> - // converted range-based loop as the temporary variable's name.
> -
> - // In the following case, "t" is used as a temporary variable to hold each
> - // element, and thus we consider the name "t" aliased to the loop.
> - // The extra blank braces are left as a placeholder for after the variable
> - // declaration is deleted.
> - for (int i = 0; i < N; ++i) {
> - Val &t = Arr[i]; { }
> - int y = t.x;
> - }
> - // CHECK: for (auto & t : Arr)
> - // CHECK-NOT: Val &{{[a-z_]+}} =
> - // CHECK-NEXT: { }
> - // CHECK-NEXT: int y = t.x;
> -
> - // The container was not only used to initialize a temporary loop variable for
> - // the container's elements, so we do not alias the new loop variable.
> - for (int i = 0; i < N; ++i) {
> - Val &t = Arr[i];
> - int y = t.x;
> - int z = Arr[i].x + t.x;
> - }
> - // CHECK: for (auto & elem : Arr)
> - // CHECK-NEXT: Val &t = elem;
> - // CHECK-NEXT: int y = t.x;
> - // CHECK-NEXT: int z = elem.x + t.x;
> -
> - for (int i = 0; i < N; ++i) {
> - Val t = Arr[i];
> - int y = t.x;
> - int z = Arr[i].x + t.x;
> - }
> - // CHECK: for (auto & elem : Arr)
> - // CHECK-NEXT: Val t = elem;
> - // CHECK-NEXT: int y = t.x;
> - // CHECK-NEXT: int z = elem.x + t.x;
> -
> - // The same for pseudo-arrays like std::vector<T> (or here dependent<Val>)
> - // which provide a subscript operator[].
> - for (int i = 0; i < v.size(); ++i) {
> - Val &t = v[i]; { }
> - int y = t.x;
> - }
> - // CHECK: for (auto & t : v)
> - // CHECK-NEXT: { }
> - // CHECK-NEXT: int y = t.x;
> -
> - // The same with a call to at()
> - for (int i = 0; i < pv->size(); ++i) {
> - Val &t = pv->at(i); { }
> - int y = t.x;
> - }
> - // CHECK: for (auto & t : *pv)
> - // CHECK-NEXT: { }
> - // CHECK-NEXT: int y = t.x;
> -
> - for (int i = 0; i < N; ++i) {
> - Val &t = func(Arr[i]);
> - int y = t.x;
> - }
> - // CHECK: for (auto & elem : Arr)
> - // CHECK-NEXT: Val &t = func(elem);
> - // CHECK-NEXT: int y = t.x;
> -
> - int IntArr[N];
> - for (unsigned i = 0; i < N; ++i) {
> - if (int alias = IntArr[i]) {
> - sideEffect(alias);
> - }
> - }
> - // CHECK: for (auto alias : IntArr)
> - // CHECK-NEXT: if (alias) {
> -
> - for (unsigned i = 0; i < N; ++i) {
> - while (int alias = IntArr[i]) {
> - sideEffect(alias);
> - }
> - }
> - // CHECK: for (auto alias : IntArr)
> - // CHECK-NEXT: while (alias) {
> -
> - for (unsigned i = 0; i < N; ++i) {
> - switch (int alias = IntArr[i]) {
> - default:
> - sideEffect(alias);
> - }
> - }
> - // CHECK: for (auto alias : IntArr)
> - // CHECK-NEXT: switch (alias) {
> -
> - for (unsigned i = 0; i < N; ++i) {
> - for (int alias = IntArr[i]; alias < N; ++alias) {
> - sideEffect(alias);
> - }
> - }
> - // CHECK: for (auto alias : IntArr)
> - // CHECK-NEXT: for (; alias < N; ++alias) {
> -
> - for (unsigned i = 0; i < N; ++i) {
> - for (unsigned j = 0; int alias = IntArr[i]; ++j) {
> - sideEffect(alias);
> - }
> - }
> - // CHECK: for (auto alias : IntArr)
> - // CHECK-NEXT: for (unsigned j = 0; alias; ++j) {
> -}
> -
> -void refs_and_vals() {
> - // The following tests check that the transform correctly preserves the
> - // reference or value qualifiers of the aliased variable. That is, if the
> - // variable was declared as a value, the loop variable will be declared as a
> - // value and vice versa for references.
> -
> - S s;
> - const S s_const = s;
> -
> - for (S::const_iterator it = s_const.begin(); it != s_const.end(); ++it) {
> - MutableVal alias = *it; { }
> - alias.x = 0;
> - }
> - // CHECK: for (auto alias : s_const)
> - // CHECK-NOT: MutableVal {{[a-z_]+}} =
> - // CHECK-NEXT: { }
> - // CHECK-NEXT: alias.x = 0;
> -
> - for (S::iterator it = s.begin(), e = s.end(); it != e; ++it) {
> - MutableVal alias = *it; { }
> - alias.x = 0;
> - }
> - // CHECK: for (auto alias : s)
> - // CHECK-NOT: MutableVal {{[a-z_]+}} =
> - // CHECK-NEXT: { }
> - // CHECK-NEXT: alias.x = 0;
> -
> - for (S::iterator it = s.begin(), e = s.end(); it != e; ++it) {
> - MutableVal &alias = *it; { }
> - alias.x = 0;
> - }
> - // CHECK: for (auto & alias : s)
> - // CHECK-NOT: MutableVal &{{[a-z_]+}} =
> - // CHECK-NEXT: { }
> - // CHECK-NEXT: alias.x = 0;
> -}
> Index: test/clang-modernize/LoopConvert/macro_problem.cpp
> ===================================================================
> --- test/clang-modernize/LoopConvert/macro_problem.cpp
> +++ /dev/null
> @@ -1,22 +0,0 @@
> -// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
> -// RUN: cp %t.cpp %t.base
> -// RUN: clang-modernize -loop-convert %t.cpp -- -I %S/Inputs
> -// RUN: FileCheck -input-file=%t.cpp %s
> -//
> -// See PR15589 for why this test fails.
> -// XFAIL: *
> -
> -#include "macro_problem.h"
> -#include "structures.h"
> -
> -void side_effect(const myns::MyType &T);
> -
> -void f() {
> - TypedefDerefContainer<myns::MyType> container;
> - for (TypedefDerefContainer<myns::MyType>::iterator I = container.begin(),
> - E = container.end(); I != E; ++I) {
> - myns::MyType &alias = *I;
> - // CHECK: myns::MyType &ref = *I;
> - side_effect(ref);
> - }
> -}
> Index: test/clang-modernize/LoopConvert/iterator.cpp
> ===================================================================
> --- test/clang-modernize/LoopConvert/iterator.cpp
> +++ /dev/null
> @@ -1,244 +0,0 @@
> -// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
> -// RUN: clang-modernize -loop-convert %t.cpp -- -I %S/Inputs -std=c++11
> -// RUN: FileCheck -input-file=%t.cpp %s
> -// RUN: clang-modernize -loop-convert %t.cpp -risk=risky -- -I %S/Inputs
> -// RUN: FileCheck -check-prefix=RISKY -input-file=%t.cpp %s
> -
> -#include "structures.h"
> -
> -void f() {
> - /// begin()/end() - based for loops here:
> - T t;
> - for (T::iterator it = t.begin(), e = t.end(); it != e; ++it) {
> - printf("I found %d\n", *it);
> - }
> - // CHECK: for (auto & elem : t)
> - // CHECK-NEXT: printf("I found %d\n", elem);
> -
> - T *pt;
> - for (T::iterator it = pt->begin(), e = pt->end(); it != e; ++it) {
> - printf("I found %d\n", *it);
> - }
> - // CHECK: for (auto & elem : *pt)
> - // CHECK-NEXT: printf("I found %d\n", elem);
> -
> - S s;
> - for (S::iterator it = s.begin(), e = s.end(); it != e; ++it) {
> - printf("s has value %d\n", (*it).x);
> - }
> - // CHECK: for (auto & elem : s)
> - // CHECK-NEXT: printf("s has value %d\n", (elem).x);
> -
> - S *ps;
> - for (S::iterator it = ps->begin(), e = ps->end(); it != e; ++it) {
> - printf("s has value %d\n", (*it).x);
> - }
> - // CHECK: for (auto & p : *ps)
> - // CHECK-NEXT: printf("s has value %d\n", (p).x);
> -
> - for (S::iterator it = s.begin(), e = s.end(); it != e; ++it) {
> - printf("s has value %d\n", it->x);
> - }
> - // CHECK: for (auto & elem : s)
> - // CHECK-NEXT: printf("s has value %d\n", elem.x);
> -
> - for (S::iterator it = s.begin(), e = s.end(); it != e; ++it) {
> - it->x = 3;
> - }
> - // CHECK: for (auto & elem : s)
> - // CHECK-NEXT: elem.x = 3;
> -
> - for (S::iterator it = s.begin(), e = s.end(); it != e; ++it) {
> - (*it).x = 3;
> - }
> - // CHECK: for (auto & elem : s)
> - // CHECK-NEXT: (elem).x = 3;
> -
> - for (S::iterator it = s.begin(), e = s.end(); it != e; ++it) {
> - it->nonConstFun(4, 5);
> - }
> - // CHECK: for (auto & elem : s)
> - // CHECK-NEXT: elem.nonConstFun(4, 5);
> -
> - U u;
> - for (U::iterator it = u.begin(), e = u.end(); it != e; ++it) {
> - printf("s has value %d\n", it->x);
> - }
> - // CHECK: for (auto & elem : u)
> - // CHECK-NEXT: printf("s has value %d\n", elem.x);
> -
> - for (U::iterator it = u.begin(), e = u.end(); it != e; ++it) {
> - printf("s has value %d\n", (*it).x);
> - }
> - // CHECK: for (auto & elem : u)
> - // CHECK-NEXT: printf("s has value %d\n", (elem).x);
> -
> - U::iterator A;
> - for (U::iterator i = u.begin(), e = u.end(); i != e; ++i)
> - int k = A->x + i->x;
> - // CHECK: for (auto & elem : u)
> - // CHECK-NEXT: int k = A->x + elem.x;
> -
> - dependent<int> v;
> - for (dependent<int>::iterator it = v.begin(), e = v.end();
> - it != e; ++it) {
> - printf("Fibonacci number is %d\n", *it);
> - }
> - // CHECK: for (auto & elem : v) {
> - // CHECK-NEXT: printf("Fibonacci number is %d\n", elem);
> -
> - for (dependent<int>::iterator it(v.begin()), e = v.end();
> - it != e; ++it) {
> - printf("Fibonacci number is %d\n", *it);
> - }
> - // CHECK: for (auto & elem : v) {
> - // CHECK-NEXT: printf("Fibonacci number is %d\n", elem);
> -
> - doublyDependent<int,int> intmap;
> - for (doublyDependent<int,int>::iterator it = intmap.begin(), e = intmap.end();
> - it != e; ++it) {
> - printf("intmap[%d] = %d", it->first, it->second);
> - }
> - // CHECK: for (auto & elem : intmap)
> - // CHECK-NEXT: printf("intmap[%d] = %d", elem.first, elem.second);
> -
> - // PtrSet's iterator dereferences by value so auto & can't be used.
> - {
> - PtrSet<int*> int_ptrs;
> - for (PtrSet<int*>::iterator I = int_ptrs.begin(),
> - E = int_ptrs.end(); I != E; ++I) {
> - // CHECK: for (auto && int_ptr : int_ptrs) {
> - }
> - }
> -
> - // This container uses an iterator where the derefence type is a typedef of
> - // a reference type. Make sure non-const auto & is still used. A failure here
> - // means canonical types aren't being tested.
> - {
> - TypedefDerefContainer<int> int_ptrs;
> - for (TypedefDerefContainer<int>::iterator I = int_ptrs.begin(),
> - E = int_ptrs.end(); I != E; ++I) {
> - // CHECK: for (auto & int_ptr : int_ptrs) {
> - }
> - }
> -
> - {
> - // Iterators returning an rvalue reference should disqualify the loop from
> - // transformation.
> - RValueDerefContainer<int> container;
> - for (RValueDerefContainer<int>::iterator I = container.begin(),
> - E = container.end(); I != E; ++I) {
> - // CHECK: for (RValueDerefContainer<int>::iterator I = container.begin(),
> - // CHECK-NEXT: E = container.end(); I != E; ++I) {
> - }
> - }
> -}
> -
> -// Tests to verify the proper use of auto where the init variable type and the
> -// initializer type differ or are mostly the same except for const qualifiers.
> -void different_type() {
> - // s.begin() returns a type 'iterator' which is just a non-const pointer and
> - // differs from const_iterator only on the const qualification.
> - S s;
> - for (S::const_iterator it = s.begin(), e = s.end(); it != e; ++it) {
> - printf("s has value %d\n", (*it).x);
> - }
> - // CHECK: for (const auto & elem : s)
> - // CHECK-NEXT: printf("s has value %d\n", (elem).x);
> -
> - S *ps;
> - for (S::const_iterator it = ps->begin(), e = ps->end(); it != e; ++it) {
> - printf("s has value %d\n", (*it).x);
> - }
> - // CHECK: for (const auto & p : *ps)
> - // CHECK-NEXT: printf("s has value %d\n", (p).x);
> -
> - // v.begin() returns a user-defined type 'iterator' which, since it's
> - // different from const_iterator, disqualifies these loops from
> - // transformation.
> - dependent<int> v;
> - for (dependent<int>::const_iterator it = v.begin(), e = v.end();
> - it != e; ++it) {
> - printf("Fibonacci number is %d\n", *it);
> - }
> - // CHECK: for (dependent<int>::const_iterator it = v.begin(), e = v.end();
> - // CHECK-NEXT: it != e; ++it) {
> - // CHECK-NEXT: printf("Fibonacci number is %d\n", *it);
> -
> - for (dependent<int>::const_iterator it(v.begin()), e = v.end();
> - it != e; ++it) {
> - printf("Fibonacci number is %d\n", *it);
> - }
> - // CHECK: for (dependent<int>::const_iterator it(v.begin()), e = v.end();
> - // CHECK-NEXT: it != e; ++it) {
> - // CHECK-NEXT: printf("Fibonacci number is %d\n", *it);
> -}
> -
> -// Tests to ensure that an implicit 'this' is picked up as the container.
> -// If member calls are made to 'this' within the loop, the transform becomes
> -// risky as these calls may affect state that affects the loop.
> -class C {
> -public:
> - typedef MutableVal *iterator;
> - typedef const MutableVal *const_iterator;
> -
> - iterator begin();
> - iterator end();
> - const_iterator begin() const;
> - const_iterator end() const;
> -
> - void doSomething();
> - void doSomething() const;
> -
> - void doLoop() {
> - for (iterator I = begin(), E = end(); I != E; ++I) {
> - // CHECK: for (auto & elem : *this) {
> - }
> - for (iterator I = C::begin(), E = C::end(); I != E; ++I) {
> - // CHECK: for (auto & elem : *this) {
> - }
> - for (iterator I = begin(), E = end(); I != E; ++I) {
> - // CHECK: for (iterator I = begin(), E = end(); I != E; ++I) {
> - // RISKY: for (auto & elem : *this) {
> - doSomething();
> - }
> - for (iterator I = begin(); I != end(); ++I) {
> - // CHECK: for (auto & elem : *this) {
> - }
> - for (iterator I = begin(); I != end(); ++I) {
> - // CHECK: for (iterator I = begin(); I != end(); ++I) {
> - // RISKY: for (auto & elem : *this) {
> - doSomething();
> - }
> - }
> -
> - void doLoop() const {
> - for (const_iterator I = begin(), E = end(); I != E; ++I) {
> - // CHECK: for (auto & elem : *this) {
> - }
> - for (const_iterator I = C::begin(), E = C::end(); I != E; ++I) {
> - // CHECK: for (auto & elem : *this) {
> - }
> - for (const_iterator I = begin(), E = end(); I != E; ++I) {
> - // CHECK: for (const_iterator I = begin(), E = end(); I != E; ++I) {
> - // RISKY: for (auto & elem : *this) {
> - doSomething();
> - }
> - }
> -};
> -
> -class C2 {
> -public:
> - typedef MutableVal *iterator;
> -
> - iterator begin() const;
> - iterator end() const;
> -
> - void doLoop() {
> - // The implicit 'this' will have an Implicit cast to const C2* wrapped
> - // around it. Make sure the replacement still happens.
> - for (iterator I = begin(), E = end(); I != E; ++I) {
> - // CHECK: for (auto & elem : *this) {
> - }
> - }
> -};
> Index: test/clang-modernize/LoopConvert/free_begin_end_fail.cpp
> ===================================================================
> --- test/clang-modernize/LoopConvert/free_begin_end_fail.cpp
> +++ /dev/null
> @@ -1,32 +0,0 @@
> -// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
> -// RUN: clang-modernize -loop-convert %t.cpp -- -I %S/Inputs -std=c++11
> -// RUN: FileCheck -input-file=%t.cpp %s
> -// XFAIL: *
> -
> -struct MyArray {
> - unsigned size();
> -};
> -
> -template <typename T>
> -struct MyContainer {
> -};
> -
> -int *begin(const MyArray &Arr);
> -int *end(const MyArray &Arr);
> -
> -template <typename T>
> -T *begin(const MyContainer<T> &C);
> -template <typename T>
> -T *end(const MyContainer<T> &C);
> -
> -// The Loop Convert Transform doesn't detect free functions begin()/end() and
> -// so fails to transform these cases which it should.
> -void f() {
> - MyArray Arr;
> - for (unsigned i = 0, e = Arr.size(); i < e; ++i) {}
> - // CHECK: for (auto & elem : Arr) {}
> -
> - MyContainer<int> C;
> - for (int *I = begin(C), *E = end(C); I != E; ++I) {}
> - // CHECK: for (auto & elem : C) {}
> -}
> Index: test/clang-modernize/LoopConvert/dependency.cpp
> ===================================================================
> --- test/clang-modernize/LoopConvert/dependency.cpp
> +++ /dev/null
> @@ -1,26 +0,0 @@
> -// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
> -// RUN: clang-modernize -loop-convert %t.cpp -- && FileCheck -input-file=%t.cpp %s
> -
> -void f() {
> - const int N = 6;
> - const int M = 8;
> - int arr[N][M];
> -
> - for (int i = 0; i < N; ++i) {
> - int a = 0;
> - int b = arr[i][a];
> - }
> - // CHECK: for (auto & elem : arr) {
> - // CHECK-NEXT: int a = 0;
> - // CHECK-NEXT: int b = elem[a];
> - // CHECK-NEXT: }
> -
> - for (int j = 0; j < M; ++j) {
> - int a = 0;
> - int b = arr[a][j];
> - }
> - // CHECK: for (int j = 0; j < M; ++j) {
> - // CHECK-NEXT: int a = 0;
> - // CHECK-NEXT: int b = arr[a][j];
> - // CHECK-NEXT: }
> -}
> Index: test/clang-modernize/LoopConvert/confidence.cpp
> ===================================================================
> --- test/clang-modernize/LoopConvert/confidence.cpp
> +++ /dev/null
> @@ -1,35 +0,0 @@
> -// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
> -// RUN: clang-modernize -loop-convert %t.cpp -- -I %S/Inputs
> -// RUN: FileCheck -input-file=%t.cpp %s
> -// RUN: clang-modernize -loop-convert %t.cpp -risk=risky -- -I %S/Inputs
> -// RUN: FileCheck -check-prefix=RISKY -input-file=%t.cpp %s
> -
> -#include "structures.h"
> -
> -void f() {
> - const int N = 5;
> - const int M = 7;
> - int (*pArr)[N];
> - int Arr[N][M];
> - int sum = 0;
> -
> - for (int i = 0; i < M; ++i) {
> - sum += Arr[0][i];
> - }
> - // CHECK: for (int i = 0; i < M; ++i) {
> - // CHECK-NEXT: sum += Arr[0][i];
> - // CHECK-NEXT: }
> - // RISKY: for (auto & elem : Arr[0]) {
> - // RISKY-NEXT: sum += elem;
> - // RISKY-NEXT: }
> -
> - for (int i = 0; i < N; ++i) {
> - sum += (*pArr)[i];
> - }
> - // RISKY: for (auto & elem : *pArr) {
> - // RISKY-NEXT: sum += elem;
> - // RISKY-NEXT: }
> - // CHECK: for (int i = 0; i < N; ++i) {
> - // CHECK-NEXT: sum += (*pArr)[i];
> - // CHECK-NEXT: }
> -}
> Index: test/clang-modernize/LoopConvert/array.cpp
> ===================================================================
> --- test/clang-modernize/LoopConvert/array.cpp
> +++ /dev/null
> @@ -1,155 +0,0 @@
> -// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
> -// RUN: cp %t.cpp %t.base
> -// RUN: clang-modernize -loop-convert %t.cpp -- -I %S/Inputs
> -// RUN: FileCheck -input-file=%t.cpp %s
> -// RUN: cp %t.base %t.cpp
> -// NORUN clang-modernize -count-only . %t.cpp -- -I %S/Inputs > %T/out
> -// NORUN FileCheck -check-prefix=COUNTONLY -input-file=%T/out %s
> -// RUN: diff %t.cpp %t.base
> -
> -#include "structures.h"
> -
> -const int N = 6;
> -const int NMinusOne = N - 1;
> -int arr[N] = {1, 2, 3, 4, 5, 6};
> -int (*pArr)[N] = &arr;
> -
> -void f() {
> - int sum = 0;
> - // Update the number of correctly converted loops as this test changes:
> - // COUNTONLY: 15 converted
> - // COUNTONLY-NEXT: 0 potentially conflicting
> - // COUNTONLY-NEXT: 0 change(s) rejected
> -
> - for (int i = 0; i < N; ++i) {
> - sum += arr[i];
> - int k;
> - }
> - // CHECK: for (auto & elem : arr) {
> - // CHECK-NEXT: sum += elem;
> - // CHECK-NEXT: int k;
> - // CHECK-NEXT: }
> -
> - for (int i = 0; i < N; ++i) {
> - printf("Fibonacci number is %d\n", arr[i]);
> - sum += arr[i] + 2;
> - }
> - // CHECK: for (auto & elem : arr)
> - // CHECK-NEXT: printf("Fibonacci number is %d\n", elem);
> - // CHECK-NEXT: sum += elem + 2;
> -
> - for (int i = 0; i < N; ++i) {
> - int x = arr[i];
> - int y = arr[i] + 2;
> - }
> - // CHECK: for (auto & elem : arr)
> - // CHECK-NEXT: int x = elem;
> - // CHECK-NEXT: int y = elem + 2;
> -
> - for (int i = 0; i < N; ++i) {
> - int x = N;
> - x = arr[i];
> - }
> - // CHECK: for (auto & elem : arr)
> - // CHECK-NEXT: int x = N;
> - // CHECK-NEXT: x = elem;
> -
> - for (int i = 0; i < N; ++i) {
> - arr[i] += 1;
> - }
> - // CHECK: for (auto & elem : arr) {
> - // CHECK-NEXT: elem += 1;
> - // CHECK-NEXT: }
> -
> - for (int i = 0; i < N; ++i) {
> - int x = arr[i] + 2;
> - arr[i] ++;
> - }
> - // CHECK: for (auto & elem : arr)
> - // CHECK-NEXT: int x = elem + 2;
> - // CHECK-NEXT: elem ++;
> -
> - for (int i = 0; i < N; ++i) {
> - arr[i] = 4 + arr[i];
> - }
> - // CHECK: for (auto & elem : arr)
> - // CHECK-NEXT: elem = 4 + elem;
> -
> - for (int i = 0; i < NMinusOne + 1; ++i) {
> - sum += arr[i];
> - }
> - // CHECK: for (auto & elem : arr) {
> - // CHECK-NEXT: sum += elem;
> - // CHECK-NEXT: }
> -
> - for (int i = 0; i < N; ++i) {
> - printf("Fibonacci number %d has address %p\n", arr[i], &arr[i]);
> - sum += arr[i] + 2;
> - }
> - // CHECK: for (auto & elem : arr)
> - // CHECK-NEXT: printf("Fibonacci number %d has address %p\n", elem, &elem);
> - // CHECK-NEXT: sum += elem + 2;
> -
> - Val teas[N];
> - for (int i = 0; i < N; ++i) {
> - teas[i].g();
> - }
> - // CHECK: for (auto & tea : teas) {
> - // CHECK-NEXT: tea.g();
> - // CHECK-NEXT: }
> -}
> -
> -struct HasArr {
> - int Arr[N];
> - Val ValArr[N];
> - void implicitThis() {
> - for (int i = 0; i < N; ++i) {
> - printf("%d", Arr[i]);
> - }
> - // CHECK: for (auto & elem : Arr) {
> - // CHECK-NEXT: printf("%d", elem);
> - // CHECK-NEXT: }
> -
> - for (int i = 0; i < N; ++i) {
> - printf("%d", ValArr[i].x);
> - }
> - // CHECK: for (auto & elem : ValArr) {
> - // CHECK-NEXT: printf("%d", elem.x);
> - // CHECK-NEXT: }
> - }
> -
> - void explicitThis() {
> - for (int i = 0; i < N; ++i) {
> - printf("%d", this->Arr[i]);
> - }
> - // CHECK: for (auto & elem : this->Arr) {
> - // CHECK-NEXT: printf("%d", elem);
> - // CHECK-NEXT: }
> -
> - for (int i = 0; i < N; ++i) {
> - printf("%d", this->ValArr[i].x);
> - }
> - // CHECK: for (auto & elem : this->ValArr) {
> - // CHECK-NEXT: printf("%d", elem.x);
> - // CHECK-NEXT: }
> - }
> -};
> -
> -// Loops whose bounds are value-dependent shold not be converted.
> -template<int N>
> -void dependentExprBound() {
> - for (int i = 0; i < N; ++i)
> - arr[i] = 0;
> - // CHECK: for (int i = 0; i < N; ++i)
> - // CHECK-NEXT: arr[i] = 0;
> -}
> -template void dependentExprBound<20>();
> -
> -void memberFunctionPointer() {
> - Val v;
> - void (Val::*mfpArr[N])(void) = { &Val::g };
> - for (int i = 0; i < N; ++i)
> - (v.*mfpArr[i])();
> - // CHECK: for (auto & elem : mfpArr)
> - // CHECK-NEXT: (v.*elem)();
> -}
> Index: test/clang-modernize/LoopConvert/Inputs/structures.h
> ===================================================================
> --- test/clang-modernize/LoopConvert/Inputs/structures.h
> +++ /dev/null
> @@ -1,179 +0,0 @@
> -#ifndef STRUCTURES_H
> -#define STRUCTURES_H
> -
> -extern "C" {
> -extern int printf(const char *restrict, ...);
> -}
> -
> -struct Val {int x; void g(); };
> -
> -struct MutableVal {
> - void constFun(int) const;
> - void nonConstFun(int, int);
> - void constFun(MutableVal &) const;
> - void constParamFun(const MutableVal &) const;
> - void nonConstParamFun(const MutableVal &);
> - int x;
> -};
> -
> -struct S {
> - typedef MutableVal *iterator;
> - typedef const MutableVal *const_iterator;
> - const_iterator begin() const;
> - const_iterator end() const;
> - iterator begin();
> - iterator end();
> -};
> -
> -struct T {
> - struct iterator {
> - int& operator*();
> - const int& operator*()const;
> - iterator& operator ++();
> - bool operator!=(const iterator &other);
> - void insert(int);
> - int x;
> - };
> - iterator begin();
> - iterator end();
> -};
> -
> -struct U {
> - struct iterator {
> - Val& operator*();
> - const Val& operator*()const;
> - iterator& operator ++();
> - bool operator!=(const iterator &other);
> - Val *operator->();
> - };
> - iterator begin();
> - iterator end();
> - int x;
> -};
> -
> -struct X {
> - S s;
> - T t;
> - U u;
> - S getS();
> -};
> -
> -template<typename ElemType>
> -class dependent{
> - public:
> - struct iterator_base {
> - const ElemType& operator*()const;
> - iterator_base& operator ++();
> - bool operator!=(const iterator_base &other) const;
> - const ElemType *operator->() const;
> - };
> -
> - struct iterator : iterator_base {
> - ElemType& operator*();
> - iterator& operator ++();
> - ElemType *operator->();
> - };
> -
> - typedef iterator_base const_iterator;
> - const_iterator begin() const;
> - const_iterator end() const;
> - iterator begin();
> - iterator end();
> - unsigned size() const;
> - ElemType & operator[](unsigned);
> - const ElemType & operator[](unsigned) const;
> - ElemType & at(unsigned);
> - const ElemType & at(unsigned) const;
> -
> - // Intentionally evil.
> - dependent<ElemType> operator*();
> -
> - void foo();
> - void constFoo() const;
> -};
> -
> -template<typename First, typename Second>
> -class doublyDependent{
> - public:
> - struct Value {
> - First first;
> - Second second;
> - };
> -
> - struct iterator_base {
> - const Value& operator*()const;
> - iterator_base& operator ++();
> - bool operator!=(const iterator_base &other) const;
> - const Value *operator->() const;
> - };
> -
> - struct iterator : iterator_base {
> - Value& operator*();
> - Value& operator ++();
> - Value *operator->();
> - };
> -
> - typedef iterator_base const_iterator;
> - const_iterator begin() const;
> - const_iterator end() const;
> - iterator begin();
> - iterator end();
> -};
> -
> -template<typename Contained>
> -class transparent {
> - public:
> - Contained *at();
> - Contained *operator->();
> - Contained operator*();
> -};
> -
> -template<typename IteratorType>
> -struct Nested {
> - typedef IteratorType* iterator;
> - typedef const IteratorType* const_iterator;
> - IteratorType *operator->();
> - IteratorType operator*();
> - iterator begin();
> - iterator end();
> - const_iterator begin() const;
> - const_iterator end() const;
> -};
> -
> -// Like llvm::SmallPtrSet, the iterator has a dereference operator that returns
> -// by value instead of by reference.
> -template <typename T>
> -struct PtrSet {
> - struct iterator {
> - bool operator!=(const iterator &other) const;
> - const T operator*();
> - iterator &operator++();
> - };
> - iterator begin() const;
> - iterator end() const;
> -};
> -
> -template <typename T>
> -struct TypedefDerefContainer {
> - struct iterator {
> - typedef T &deref_type;
> - bool operator!=(const iterator &other) const;
> - deref_type operator*();
> - iterator &operator++();
> - };
> - iterator begin() const;
> - iterator end() const;
> -};
> -
> -template <typename T>
> -struct RValueDerefContainer {
> - struct iterator {
> - typedef T &&deref_type;
> - bool operator!=(const iterator &other) const;
> - deref_type operator*();
> - iterator &operator++();
> - };
> - iterator begin() const;
> - iterator end() const;
> -};
> -#endif // STRUCTURES_H
> Index: test/clang-modernize/LoopConvert/Inputs/negative-header.h
> ===================================================================
> --- test/clang-modernize/LoopConvert/Inputs/negative-header.h
> +++ /dev/null
> @@ -1,14 +0,0 @@
> -#ifndef NEGATIVE_HEADER_H
> -#define NEGATIVE_HEADER_H
> -
> -// Single FileCheck line to make sure that no loops are converted.
> -// CHECK-NOT: for ({{.*[^:]:[^:].*}})
> -static void loopInHeader() {
> - const int N = 10;
> - int arr[N];
> - int sum = 0;
> - for (int i = 0; i < N; ++i)
> - sum += arr[i];
> -}
> -
> -#endif // NEGATIVE_HEADER_H
> Index: test/clang-modernize/LoopConvert/Inputs/macro_problem.h
> ===================================================================
> --- test/clang-modernize/LoopConvert/Inputs/macro_problem.h
> +++ /dev/null
> @@ -1,7 +0,0 @@
> -#define myns nsblah
> -
> -namespace nsblah {
> -struct MyType {
> -};
> -
> -} // namespace nsblah
> Index: test/clang-modernize/HeaderReplacements/no_yaml.cpp
> ===================================================================
> --- test/clang-modernize/HeaderReplacements/no_yaml.cpp
> +++ /dev/null
> @@ -1,25 +0,0 @@
> -// Ensure that if -serialize-replacements is not provided, no serialized
> -// replacement files should be generated and the changes are made directly.
> -//
> -// RUN: rm -rf %T/Inputs
> -// RUN: mkdir -p %T/Inputs
> -// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
> -// RUN: grep -Ev "// *[A-Z-]+:" %S/Inputs/no_yaml.h > %T/Inputs/no_yaml.h
> -// RUN: clang-modernize -loop-convert %t.cpp -include=%T/Inputs -- -I %T/Inputs/no_yaml.h
> -// RUN: FileCheck --input-file=%t.cpp %s
> -// RUN: FileCheck --input-file=%T/Inputs/no_yaml.h %S/Inputs/no_yaml.h
> -// RUN: ls %T | FileCheck %s --check-prefix=NO_YAML
> -//
> -// NO_YAML-NOT: {{no_yaml.cpp_.*.yaml}}
> -#include "Inputs/no_yaml.h"
> -
> -void func() {
> - int arr[10];
> - for (unsigned i = 0; i < sizeof(arr)/sizeof(int); ++i) {
> - arr[i] = 0;
> - // CHECK: for (auto & elem : arr) {
> - // CHECK-NEXT: elem = 0;
> - }
> -
> - update(arr);
> -}
> Index: test/clang-modernize/HeaderReplacements/main_expected.yaml
> ===================================================================
> --- test/clang-modernize/HeaderReplacements/main_expected.yaml
> +++ /dev/null
> @@ -1,12 +0,0 @@
> ----
> -MainSourceFile: '$(path)/main.cpp'
> -Replacements:
> - - FilePath: '$(path)/common.h'
> - Offset: 506
> - Length: 2
> - ReplacementText: elem
> - - FilePath: '$(path)/common.h'
> - Offset: 432
> - Length: 61
> - ReplacementText: '(auto & elem : C)'
> -...
> Index: test/clang-modernize/HeaderReplacements/main.cpp
> ===================================================================
> --- test/clang-modernize/HeaderReplacements/main.cpp
> +++ /dev/null
> @@ -1,36 +0,0 @@
> -// The following block tests the following:
> -// - Only 1 file is generated per translation unit
> -// - Replacements are written in YAML that matches the expected YAML file
> -// The test is run in %T/SerializeTest so it's easy to create a clean test
> -// directory.
> -//
> -// RUN: rm -rf %T/SerializeTest
> -// RUN: mkdir -p %T/SerializeTest
> -// RUN: cp %S/main.cpp %S/common.cpp %S/common.h %T/SerializeTest
> -// RUN: clang-modernize -loop-convert -serialize-replacements -serialize-dir=%T/SerializeTest -include=%T/SerializeTest %T/SerializeTest/main.cpp %T/SerializeTest/common.cpp --
> -// Check that only 1 file is generated per translation unit
> -// RUN: ls -1 %T/SerializeTest | FileCheck %s --check-prefix=MAIN_CPP
> -// RUN: ls -1 %T/SerializeTest | FileCheck %s --check-prefix=COMMON_CPP
> -// We need to put the build path to the expected YAML file to diff against the generated one.
> -// RUN: sed -e 's#$(path)#%/T/SerializeTest#g' -e "s#[^[:space:]]'[^[:space:]]#''#g" -e "s#'\([-a-zA-Z0-9_/^., \t]*\)'#\1#g" %S/main_expected.yaml > %T/SerializeTest/main_expected.yaml
> -// RUN: sed -i -e 's#\\#/#g' %T/SerializeTest/main.cpp_*.yaml
> -// RUN: diff -b %T/SerializeTest/main_expected.yaml %T/SerializeTest/main.cpp_*.yaml
> -// RUN: sed -e 's#$(path)#%/T/SerializeTest#g' -e "s#[^[:space:]]'[^[:space:]]#''#g" -e "s#'\([-a-zA-Z0-9_/^., \t]*\)'#\1#g" %S/common_expected.yaml > %T/SerializeTest/common_expected.yaml
> -// RUN: sed -i -e 's#\\#/#g' %T/SerializeTest/common.cpp_*.yaml
> -// RUN: diff -b %T/SerializeTest/common_expected.yaml %T/SerializeTest/common.cpp_*.yaml
> -//
> -// The following are for FileCheck when used on output of 'ls'. See above.
> -// MAIN_CPP: {{^main.cpp_.*.yaml$}}
> -// MAIN_CPP-NOT: {{main.cpp_.*.yaml}}
> -//
> -// COMMON_CPP: {{^common.cpp_.*.yaml$}}
> -// COMMON_CPP-NOT: {{common.cpp_.*.yaml}}
> -
> -// REQUIRES: shell
> -
> -#include "common.h"
> -
> -void test_header_replacement() {
> - dostuff();
> - func2();
> -}
> Index: test/clang-modernize/HeaderReplacements/common_expected.yaml
> ===================================================================
> --- test/clang-modernize/HeaderReplacements/common_expected.yaml
> +++ /dev/null
> @@ -1,20 +0,0 @@
> ----
> -MainSourceFile: '$(path)/common.cpp'
> -Replacements:
> - - FilePath: '$(path)/common.h'
> - Offset: 506
> - Length: 2
> - ReplacementText: elem
> - - FilePath: '$(path)/common.h'
> - Offset: 432
> - Length: 61
> - ReplacementText: '(auto & elem : C)'
> - - FilePath: '$(path)/common.cpp'
> - Offset: 289
> - Length: 2
> - ReplacementText: elem
> - - FilePath: '$(path)/common.cpp'
> - Offset: 206
> - Length: 63
> - ReplacementText: '(auto & elem : C1)'
> -...
> Index: test/clang-modernize/HeaderReplacements/common.h
> ===================================================================
> --- test/clang-modernize/HeaderReplacements/common.h
> +++ /dev/null
> @@ -1,27 +0,0 @@
> -#ifndef CPP11_MIGRATE_TEST_HEADER_REPLACEMENTS_COMMON_H
> -#define CPP11_MIGRATE_TEST_HEADER_REPLACEMENTS_COMMON_H
> -
> -struct container {
> - struct iterator {
> - int &operator*();
> - const int &operator*() const;
> - iterator &operator++();
> - bool operator!=(const iterator &other);
> - };
> -
> - iterator begin();
> - iterator end();
> - void push_back(const int &);
> -};
> -
> -void func1(int &I);
> -void func2();
> -
> -void dostuff() {
> - container C;
> - for (container::iterator I = C.begin(), E = C.end(); I != E; ++I) {
> - func1(*I);
> - }
> -}
> -
> -#endif // CPP11_MIGRATE_TEST_HEADER_REPLACEMENTS_COMMON_H
> Index: test/clang-modernize/HeaderReplacements/common.cpp
> ===================================================================
> --- test/clang-modernize/HeaderReplacements/common.cpp
> +++ /dev/null
> @@ -1,16 +0,0 @@
> -// This is just a dummy run command to keep lit happy. Tests for this file are
> -// in main.cpp
> -// RUN: true
> -
> -#include "common.h"
> -
> -void func1(int &I) {
> -}
> -
> -void func2() {
> - container C1;
> - container C2;
> - for (container::iterator I = C1.begin(), E = C1.end(); I != E; ++I) {
> - C2.push_back(*I);
> - }
> -}
> Index: test/clang-modernize/HeaderReplacements/Inputs/no_yaml.h
> ===================================================================
> --- test/clang-modernize/HeaderReplacements/Inputs/no_yaml.h
> +++ /dev/null
> @@ -1,8 +0,0 @@
> -void update(int (&arr)[10]) {
> - int val = 1;
> - for (unsigned i = 0; i < sizeof(arr)/sizeof(int); ++i) {
> - arr[i] = val++;
> - // CHECK: for (auto & elem : arr) {
> - // CHECK-NEXT: elem = val++;
> - }
> -}
> Index: test/clang-modernize/Core/Reformatting.cpp
> ===================================================================
> --- test/clang-modernize/Core/Reformatting.cpp
> +++ /dev/null
> @@ -1,44 +0,0 @@
> -// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
> -// RUN: clang-modernize -format -use-auto %t.cpp
> -// RUN: FileCheck --strict-whitespace -input-file=%t.cpp %s
> -
> -// Ensure that -style is forwarded to clang-apply-replacements by using a style
> -// other than LLVM and ensuring the result is styled as requested.
> -// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
> -// RUN: clang-modernize -format -style=Google -use-nullptr %t.cpp
> -// RUN: FileCheck --check-prefix=Google --strict-whitespace -input-file=%t.cpp %s
> -
> -// Ensure -style-config is forwarded to clang-apply-replacements. The .clang-format
> -// in %S/Inputs is a dump of the Google style so the same test can be used.
> -// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
> -// RUN: clang-modernize -format -style=file -style-config=%S/Inputs -use-nullptr %t.cpp
> -// RUN: FileCheck --check-prefix=Google --strict-whitespace -input-file=%t.cpp %s
> -
> -class MyType012345678901234567890123456789 {
> -public:
> - MyType012345678901234567890123456789()
> - : iiiiiiiiiiii(0), jjjjjjjjjjjj(0), kkkkkkkkkkkk(0), mmmmmmmmmmmm(0),
> - nnnnnnnnnnnn(0) {}
> - // Google: iiiiiiiiiiii(nullptr),
> - // Google-NEXT: jjjjjjjjjjjj(nullptr),
> - // Google-NEXT: kkkkkkkkkkkk(nullptr),
> - // Google-NEXT: mmmmmmmmmmmm(nullptr),
> - // Google-NEXT: nnnnnnnnnnnn(nullptr) {}
> -
> -private:
> - int *iiiiiiiiiiii;
> - int *jjjjjjjjjjjj;
> - int *kkkkkkkkkkkk;
> - int *mmmmmmmmmmmm;
> - int *nnnnnnnnnnnn;
> -};
> -
> -int f() {
> - MyType012345678901234567890123456789 *a =
> - new MyType012345678901234567890123456789();
> - // CHECK: {{^\ \ auto\ a\ \=\ new\ MyType012345678901234567890123456789\(\);}}
> -
> - delete a;
> -
> - return 0;
> -}
> Index: test/clang-modernize/Core/Inputs/.clang-format
> ===================================================================
> --- test/clang-modernize/Core/Inputs/.clang-format
> +++ /dev/null
> @@ -1,42 +0,0 @@
> ----
> -# BasedOnStyle: Google
> -AccessModifierOffset: -1
> -ConstructorInitializerIndentWidth: 4
> -AlignEscapedNewlinesLeft: true
> -AlignTrailingComments: true
> -AllowAllParametersOfDeclarationOnNextLine: true
> -AllowShortIfStatementsOnASingleLine: true
> -AllowShortLoopsOnASingleLine: true
> -AlwaysBreakTemplateDeclarations: true
> -AlwaysBreakBeforeMultilineStrings: true
> -BreakBeforeBinaryOperators: false
> -BreakConstructorInitializersBeforeComma: false
> -BinPackParameters: true
> -ColumnLimit: 80
> -ConstructorInitializerAllOnOneLineOrOnePerLine: true
> -DerivePointerBinding: true
> -ExperimentalAutoDetectBinPacking: false
> -IndentCaseLabels: true
> -MaxEmptyLinesToKeep: 1
> -NamespaceIndentation: None
> -ObjCSpaceBeforeProtocolList: false
> -PenaltyBreakComment: 60
> -PenaltyBreakString: 1000
> -PenaltyBreakFirstLessLess: 120
> -PenaltyExcessCharacter: 1000000
> -PenaltyReturnTypeOnItsOwnLine: 200
> -PointerBindsToType: true
> -SpacesBeforeTrailingComments: 2
> -Cpp11BracedListStyle: true
> -Standard: Auto
> -IndentWidth: 2
> -TabWidth: 8
> -UseTab: Never
> -BreakBeforeBraces: Attach
> -SpacesInParentheses: false
> -SpaceInEmptyParentheses: false
> -SpacesInCStyleCastParentheses: false
> -SpaceAfterControlStatementKeyword: true
> -SpaceBeforeAssignmentOperators: true
> -...
> -
> Index: test/clang-modernize/Compilations/no_compilation.cpp
> ===================================================================
> --- test/clang-modernize/Compilations/no_compilation.cpp
> +++ /dev/null
> @@ -1,22 +0,0 @@
> -// The following block tests:
> -// - Neither -p nor -- was specified and a compilation database is detected
> -// from source0 but the file isn't found the compilation database then
> -// it's transformed using a fixed compilation database with c++11 support.
> -// (-- -std=c++11).
> -
> -// Create directory structure
> -// a1, a2 and a3 are specified paths for files in the compilation database but
> -// not a4.
> -// RUN: rm -rf %T/NoCompilation
> -// RUN: mkdir -p %T/NoCompilation
> -// RUN: mkdir -p %T/NoCompilation/a1
> -// RUN: mkdir -p %T/NoCompilation/a2
> -// RUN: mkdir -p %T/NoCompilation/a3
> -// RUN: mkdir -p %T/NoCompilation/a4
> -
> -// This test uses of a compilation database
> -// RUN: sed -e 's#$(path)#%/T/NoCompilation#g' %S/Inputs/compile_commands.json > %T/NoCompilation/compile_commands.json
> -
> -// RUN: cp %S/Inputs/cpp11.cpp %T/NoCompilation/a4
> -// RUN: clang-modernize -use-nullptr %T/NoCompilation/a4/cpp11.cpp
> -// RUN: diff -b %S/Inputs/cpp11_expected.cpp %T/NoCompilation/a4/cpp11.cpp
> Index: test/clang-modernize/Compilations/fixed_comp_inc.cpp
> ===================================================================
> --- test/clang-modernize/Compilations/fixed_comp_inc.cpp
> +++ /dev/null
> @@ -1,20 +0,0 @@
> -// The following block tests:
> -// - A fixed compilation database is provided and -exclude was also used.
> -
> -// Create directory structure
> -// a1, a2 and a3 are specified paths for files in the compilation database.
> -// RUN: rm -rf %T/FixedCompInc
> -// RUN: mkdir -p %T/FixedCompInc
> -// RUN: mkdir -p %T/FixedCompInc/a1
> -// RUN: mkdir -p %T/FixedCompInc/a2
> -// RUN: mkdir -p %T/FixedCompInc/a3
> -
> -// Check that only files not explicitly excluded are transformed.
> -// RUN: cp %S/Inputs/compilations.cpp %T/FixedCompInc/a1
> -// RUN: cp %S/Inputs/compilations.cpp %T/FixedCompInc/a2
> -// RUN: cp %S/Inputs/compilations.cpp %T/FixedCompInc/a3
> -
> -// RUN: clang-modernize -use-nullptr %T/FixedCompInc/a1/compilations.cpp %T/FixedCompInc/a2/compilations.cpp %T/FixedCompInc/a3/compilations.cpp -exclude=%T/FixedCompInc/a2 --
> -// RUN: diff -b %S/Inputs/compilations_expected.cpp %T/FixedCompInc/a1/compilations.cpp
> -// RUN: not diff -b %S/Inputs/compilations_expected.cpp %T/FixedCompInc/a2/compilations.cpp
> -// RUN: diff -b %S/Inputs/compilations_expected.cpp %T/FixedCompInc/a3/compilations.cpp
> Index: test/clang-modernize/Compilations/fixed_comp.cpp
> ===================================================================
> --- test/clang-modernize/Compilations/fixed_comp.cpp
> +++ /dev/null
> @@ -1,18 +0,0 @@
> -// The following block tests that files are transformed when -- is specified.
> -
> -// Create directory structure
> -// a1, a2 and a3 are specified paths for files in the compilation database.
> -// RUN: rm -rf %T/FixedComp
> -// RUN: mkdir -p %T/FixedComp
> -// RUN: mkdir -p %T/FixedComp/a1
> -// RUN: mkdir -p %T/FixedComp/a2
> -// RUN: mkdir -p %T/FixedComp/a3
> -
> -// RUN: cp %S/Inputs/compilations.cpp %T/FixedComp/a1
> -// RUN: cp %S/Inputs/compilations.cpp %T/FixedComp/a2
> -// RUN: cp %S/Inputs/compilations.cpp %T/FixedComp/a3
> -
> -// RUN: clang-modernize -use-nullptr %T/FixedComp/a1/compilations.cpp %T/FixedComp/a3/compilations.cpp --
> -// RUN: diff -b %S/Inputs/compilations_expected.cpp %T/FixedComp/a1/compilations.cpp
> -// RUN: not diff -b %S/Inputs/compilations_expected.cpp %T/FixedComp/a2/compilations.cpp
> -// RUN: diff -b %S/Inputs/compilations_expected.cpp %T/FixedComp/a3/compilations.cpp
> Index: test/clang-modernize/Compilations/detect_from_source.cpp
> ===================================================================
> --- test/clang-modernize/Compilations/detect_from_source.cpp
> +++ /dev/null
> @@ -1,23 +0,0 @@
> -// The following block tests:
> -// - A compilation database is detected from source0.
> -
> -// Create directory structure
> -// a1, a2 and a3 are specified paths for files in the compilation database.
> -// RUN: rm -rf %T/DetectFromSource
> -// RUN: mkdir -p %T/DetectFromSource
> -// RUN: mkdir -p %T/DetectFromSource/a1
> -// RUN: mkdir -p %T/DetectFromSource/a2
> -// RUN: mkdir -p %T/DetectFromSource/a3
> -
> -// This test uses a compilation database
> -// RUN: sed -e 's#$(path)#%/T/DetectFromSource#g' %S/Inputs/compile_commands.json > %T/DetectFromSource/compile_commands.json
> -
> -// Check that a compilation database can be auto-detected from source0
> -// RUN: cp %S/Inputs/compilations.cpp %T/DetectFromSource/a1
> -// RUN: cp %S/Inputs/compilations.cpp %T/DetectFromSource/a2
> -// RUN: cp %S/Inputs/compilations.cpp %T/DetectFromSource/a3
> -
> -// RUN: clang-modernize -use-nullptr %T/DetectFromSource/a1/compilations.cpp %T/DetectFromSource/a3/compilations.cpp
> -// RUN: diff -b %S/Inputs/compilations_expected.cpp %T/DetectFromSource/a1/compilations.cpp
> -// RUN: not diff -b %S/Inputs/compilations_expected.cpp %T/DetectFromSource/a2/compilations.cpp
> -// RUN: diff -b %S/Inputs/compilations_expected.cpp %T/DetectFromSource/a3/compilations.cpp
> Index: test/clang-modernize/Compilations/detect_from_path.cpp
> ===================================================================
> --- test/clang-modernize/Compilations/detect_from_path.cpp
> +++ /dev/null
> @@ -1,24 +0,0 @@
> -// The following block tests:
> -// - A compilation database is detected from build path specified by -p and
> -// files are provided.
> -
> -// Create directory structure
> -// a1, a2 and a3 are specified paths for files in the compilation database.
> -// RUN: rm -rf %T/DetectFromPath
> -// RUN: mkdir -p %T/DetectFromPath
> -// RUN: mkdir -p %T/DetectFromPath/a1
> -// RUN: mkdir -p %T/DetectFromPath/a2
> -// RUN: mkdir -p %T/DetectFromPath/a3
> -
> -// This test uses a compilation database
> -// RUN: sed -e 's#$(path)#%/T/DetectFromPath#g' %S/Inputs/compile_commands.json > %T/DetectFromPath/compile_commands.json
> -
> -// Check that files are transformed when -p is provided and files are specified.
> -// RUN: cp %S/Inputs/compilations.cpp %T/DetectFromPath/a1
> -// RUN: cp %S/Inputs/compilations.cpp %T/DetectFromPath/a2
> -// RUN: cp %S/Inputs/compilations.cpp %T/DetectFromPath/a3
> -
> -// RUN: clang-modernize -use-nullptr -p=%T/DetectFromPath %T/DetectFromPath/a1/compilations.cpp %T/DetectFromPath/a3/compilations.cpp
> -// RUN: diff -b %S/Inputs/compilations_expected.cpp %T/DetectFromPath/a1/compilations.cpp
> -// RUN: not diff -b %S/Inputs/compilations_expected.cpp %T/DetectFromPath/a2/compilations.cpp
> -// RUN: diff -b %S/Inputs/compilations_expected.cpp %T/DetectFromPath/a3/compilations.cpp
> Index: test/clang-modernize/Compilations/compilation_not_inc.cpp
> ===================================================================
> --- test/clang-modernize/Compilations/compilation_not_inc.cpp
> +++ /dev/null
> @@ -1,24 +0,0 @@
> -// The following block tests:
> -// - A compilation database is detected from build path specified by -p but
> -// neither sources nor -include was provided.
> -
> -// Create directory structure
> -// a1, a2 and a3 are specified paths for files in the compilation database.
> -// RUN: rm -rf %T/CompilationNotInc
> -// RUN: mkdir -p %T/CompilationNotInc
> -// RUN: mkdir -p %T/CompilationNotInc/a1
> -// RUN: mkdir -p %T/CompilationNotInc/a2
> -// RUN: mkdir -p %T/CompilationNotInc/a3
> -
> -// This test uses a compilation database
> -// RUN: sed -e 's#$(path)#%/T/CompilationNotInc#g' %S/Inputs/compile_commands.json > %T/CompilationNotInc/compile_commands.json
> -
> -// Check that no files are transformed when -p is specified but not -include.
> -// RUN: cp %S/Inputs/compilations.cpp %T/CompilationNotInc/a1
> -// RUN: cp %S/Inputs/compilations.cpp %T/CompilationNotInc/a2
> -// RUN: cp %S/Inputs/compilations.cpp %T/CompilationNotInc/a3
> -
> -// RUN: not clang-modernize -use-nullptr -p=%T/CompilationNotInc
> -// RUN: not diff -b %T/compilations_expected.cpp %T/CompilationNotInc/a1/compilations.cpp
> -// RUN: not diff -b %T/compilations_expected.cpp %T/CompilationNotInc/a2/compilations.cpp
> -// RUN: not diff -b %T/compilations_expected.cpp %T/CompilationNotInc/a3/compilations.cpp
> Index: test/clang-modernize/Compilations/compilation_inc_sources.cpp
> ===================================================================
> --- test/clang-modernize/Compilations/compilation_inc_sources.cpp
> +++ /dev/null
> @@ -1,22 +0,0 @@
> -// Test that only specified sources are transformed when -p and -include are
> -// specified along with sources.
> -
> -// Create directory structure
> -// a1, a2 and a3 are specified paths for files in the compilation database.
> -// RUN: rm -rf %T/CompilationIncSources
> -// RUN: mkdir -p %T/CompilationIncSources
> -// RUN: mkdir -p %T/CompilationIncSources/a1
> -// RUN: mkdir -p %T/CompilationIncSources/a2
> -// RUN: mkdir -p %T/CompilationIncSources/a3
> -
> -// This test uses a compilation database
> -// RUN: sed -e 's#$(path)#%/T/CompilationIncSources#g' %S/Inputs/compile_commands.json > %T/CompilationIncSources/compile_commands.json
> -
> -// RUN: cp %S/Inputs/compilations.cpp %T/CompilationIncSources/a1
> -// RUN: cp %S/Inputs/compilations.cpp %T/CompilationIncSources/a2
> -// RUN: cp %S/Inputs/compilations.cpp %T/CompilationIncSources/a3
> -
> -// RUN: clang-modernize -use-nullptr -p=%T/CompilationIncSources -include=%T/CompilationIncSources %T/CompilationIncSources/a2/compilations.cpp
> -// RUN: not diff -b %S/Inputs/compilations_expected.cpp %T/CompilationIncSources/a1/compilations.cpp
> -// RUN: diff -b %S/Inputs/compilations_expected.cpp %T/CompilationIncSources/a2/compilations.cpp
> -// RUN: not diff -b %S/Inputs/compilations_expected.cpp %T/CompilationIncSources/a3/compilations.cpp
> Index: test/clang-modernize/Compilations/compilation_inc.cpp
> ===================================================================
> --- test/clang-modernize/Compilations/compilation_inc.cpp
> +++ /dev/null
> @@ -1,24 +0,0 @@
> -// The following block tests:
> -// - A compilation database is detected from build path specified by -p and
> -// -include was provided.
> -
> -// Create directory structure
> -// a1, a2 and a3 are specified paths for files in the compilation database.
> -// RUN: rm -rf %T/CompilationInc
> -// RUN: mkdir -p %T/CompilationInc
> -// RUN: mkdir -p %T/CompilationInc/a1
> -// RUN: mkdir -p %T/CompilationInc/a2
> -// RUN: mkdir -p %T/CompilationInc/a3
> -
> -// This test uses a compilation database
> -// RUN: sed -e 's#$(path)#%/T/CompilationInc#g' %S/Inputs/compile_commands.json > %T/CompilationInc/compile_commands.json
> -
> -// Check that files are transformed when -p and -include are specified.
> -// RUN: cp %S/Inputs/compilations.cpp %T/CompilationInc/a1
> -// RUN: cp %S/Inputs/compilations.cpp %T/CompilationInc/a2
> -// RUN: cp %S/Inputs/compilations.cpp %T/CompilationInc/a3
> -
> -// RUN: clang-modernize -use-nullptr -p=%T/CompilationInc -include=%T/CompilationInc/a1,%T/CompilationInc/a3
> -// RUN: diff -b %S/Inputs/compilations_expected.cpp %T/CompilationInc/a1/compilations.cpp
> -// RUN: not diff -b %S/Inputs/compilations_expected.cpp %T/CompilationInc/a2/compilations.cpp
> -// RUN: diff -b %S/Inputs/compilations_expected.cpp %T/CompilationInc/a3/compilations.cpp
> Index: test/clang-modernize/Compilations/Inputs/cpp11_expected.cpp
> ===================================================================
> --- test/clang-modernize/Compilations/Inputs/cpp11_expected.cpp
> +++ /dev/null
> @@ -1,4 +0,0 @@
> -void foo() {
> - int *p = nullptr;
> - int *k = nullptr;
> -}
> Index: test/clang-modernize/Compilations/Inputs/cpp11.cpp
> ===================================================================
> --- test/clang-modernize/Compilations/Inputs/cpp11.cpp
> +++ /dev/null
> @@ -1,4 +0,0 @@
> -void foo() {
> - int *p = 0;
> - int *k = nullptr;
> -}
> Index: test/clang-modernize/Compilations/Inputs/compile_commands.json
> ===================================================================
> --- test/clang-modernize/Compilations/Inputs/compile_commands.json
> +++ /dev/null
> @@ -1,17 +0,0 @@
> -[
> -{
> - "directory": "$(path)/a1/",
> - "command": "clang++ -o compilations.o -c $(path)/a1/compilations.cpp -std=c++11",
> - "file": "$(path)/a1/compilations.cpp"
> -},
> -{
> - "directory": "$(path)/a2/",
> - "command": "clang++ -o compilations.o -c $(path)/a2/compilations.cpp -std=c++11",
> - "file": "$(path)/a2/compilations.cpp"
> -},
> -{
> - "directory": "$(path)/a3/",
> - "command": "clang++ -o compilations.o -c $(path)/a3/compilations.cpp -std=c++11",
> - "file": "$(path)/a3/compilations.cpp"
> -}
> -]
> Index: test/clang-modernize/Compilations/Inputs/compilations_expected.cpp
> ===================================================================
> --- test/clang-modernize/Compilations/Inputs/compilations_expected.cpp
> +++ /dev/null
> @@ -1,3 +0,0 @@
> -void foo() {
> - int *p = nullptr;
> -}
> Index: test/clang-modernize/Compilations/Inputs/compilations.cpp
> ===================================================================
> --- test/clang-modernize/Compilations/Inputs/compilations.cpp
> +++ /dev/null
> @@ -1,3 +0,0 @@
> -void foo() {
> - int *p = 0;
> -}
> Index: test/clang-modernize/Combined/compilers.cpp
> ===================================================================
> --- test/clang-modernize/Combined/compilers.cpp
> +++ /dev/null
> @@ -1,63 +0,0 @@
> -// RUN: grep -Ev "// *[A-Z0-9-]+:" %s > %t.cpp
> -// RUN: clang-modernize -for-compilers=clang-2.9 %t.cpp -- -std=c++11
> -// RUN: FileCheck -check-prefix=CLANG-29 -input-file=%t.cpp %s
> -//
> -// RUN: grep -Ev "// *[A-Z0-9-]+:" %s > %t.cpp
> -// RUN: clang-modernize -for-compilers=clang-2.9 -override-macros %t.cpp -- -std=c++11
> -// RUN: FileCheck -check-prefix=CLANG-29-OV-MACROS -input-file=%t.cpp %s
> -//
> -// RUN: grep -Ev "// *[A-Z0-9-]+:" %s > %t.cpp
> -// RUN: clang-modernize -for-compilers=clang-3.0 %t.cpp -- -std=c++11
> -// RUN: FileCheck -check-prefix=CLANG-30 -input-file=%t.cpp %s
> -//
> -// RUN: grep -Ev "// *[A-Z0-9-]+:" %s > %t.cpp
> -// RUN: clang-modernize -for-compilers=gcc-4.6 %t.cpp -- -std=c++11
> -// RUN: FileCheck -check-prefix=GCC-46 -input-file=%t.cpp %s
> -//
> -// RUN: grep -Ev "// *[A-Z0-9-]+:" %s > %t.cpp
> -// RUN: clang-modernize -for-compilers=gcc-4.7 %t.cpp -- -std=c++11
> -// RUN: FileCheck -check-prefix=GCC-47 -input-file=%t.cpp %s
> -//
> -// RUN: grep -Ev "// *[A-Z0-9-]+:" %s > %t.cpp
> -// RUN: clang-modernize -for-compilers=icc-13 %t.cpp -- -std=c++11
> -// RUN: FileCheck -check-prefix=ICC-13 -input-file=%t.cpp %s
> -//
> -// RUN: grep -Ev "// *[A-Z0-9-]+:" %s > %t.cpp
> -// RUN: clang-modernize -for-compilers=icc-14 %t.cpp -- -std=c++11
> -// RUN: FileCheck -check-prefix=ICC-14 -input-file=%t.cpp %s
> -//
> -// RUN: grep -Ev "// *[A-Z0-9-]+:" %s > %t.cpp
> -// RUN: clang-modernize -for-compilers=msvc-8 %t.cpp -- -std=c++11
> -// RUN: FileCheck -check-prefix=MSVC-8 -input-file=%t.cpp %s
> -//
> -// Test multiple compilers
> -// RUN: grep -Ev "// *[A-Z0-9-]+:" %s > %t.cpp
> -// RUN: clang-modernize -for-compilers=clang-3.0,gcc-4.6,gcc-4.7 %t.cpp -- -std=c++11
> -// RUN: FileCheck -check-prefix=MULTIPLE -input-file=%t.cpp %s
> -//
> -// Test unknown platform
> -// RUN: not clang-modernize -for-compilers=foo-10 %t.cpp -- -std=c++11
> -//
> -// Test when no transforms can be selected because the compiler lacks support of
> -// the needed C++11 features
> -// RUN: not clang-modernize -for-compilers=clang-2.0 %t.cpp -- -std=c++11
> -
> -// Test add overrides
> -struct A {
> - virtual A *clone() = 0;
> -};
> -
> -#define LLVM_OVERRIDE override
> -
> -struct B : A {
> - virtual B *clone();
> - // CLANG-29-OV-MACROS: virtual B *clone() LLVM_OVERRIDE;
> - // CLANG-29: virtual B *clone();
> - // CLANG-30: virtual B *clone() override;
> - // GCC-46: virtual B *clone();
> - // GCC-47: virtual B *clone() override;
> - // ICC-13: virtual B *clone();
> - // ICC-14: virtual B *clone() override;
> - // MSVC-8: virtual B *clone() override;
> - // MULTIPLE: virtual B *clone();
> -};
> Index: test/clang-modernize/Combined/combined.cpp
> ===================================================================
> --- test/clang-modernize/Combined/combined.cpp
> +++ /dev/null
> @@ -1,45 +0,0 @@
> -// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
> -// RUN: grep -Ev "// *[A-Z-]+:" %s > %t_risky.cpp
> -// RUN: clang-modernize -loop-convert -use-nullptr %t.cpp -- -std=c++11
> -// RUN: FileCheck -input-file=%t.cpp %s
> -// RUN: clang-modernize -loop-convert -use-nullptr -risk=risky %t_risky.cpp -- -std=c++11
> -// RUN: FileCheck -check-prefix=RISKY -input-file=%t_risky.cpp %s
> -
> -#define NULL 0
> -
> -struct T {
> - struct iterator {
> - int *& operator*();
> - const int *& operator*() const;
> - iterator & operator++();
> - bool operator!=(const iterator &other);
> - void insert(int *);
> - int *x;
> - };
> -
> - iterator begin();
> - iterator end();
> -};
> -
> -void test_loopconvert_and_nullptr_iterator() {
> - T t;
> -
> - for (T::iterator it = t.begin(); it != t.end(); ++it) {
> - *it = NULL;
> - }
> -
> - // CHECK: for (auto & elem : t)
> - // CHECK-NEXT: elem = nullptr;
> -}
> -
> -void test_loopconvert_and_nullptr_risky() {
> - const int N = 10;
> - int *(*pArr)[N];
> -
> - for (int i = 0; i < N; ++i) {
> - (*pArr)[i] = NULL;
> - }
> -
> - // RISKY: for (auto & elem : *pArr)
> - // RISKY-NEXT: elem = nullptr;
> -}
> Index: test/clang-modernize/AddOverride/pure_specifier_fail.cpp
> ===================================================================
> --- test/clang-modernize/AddOverride/pure_specifier_fail.cpp
> +++ /dev/null
> @@ -1,20 +0,0 @@
> -// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
> -// RUN: clang-modernize -add-override %t.cpp -- -I %S
> -// RUN: FileCheck -input-file=%t.cpp %s
> -// XFAIL: *
> -
> -// Test that override isn't placed correctly after "pure overrides"
> -struct A {
> - virtual A *clone() = 0;
> -};
> -struct B : A {
> - virtual B *clone() { return new B(); }
> -};
> -struct C : B {
> - virtual B *clone() = 0;
> - // CHECK: struct C : B {
> - // CHECK: virtual B *clone() override = 0;
> -};
> -struct D : C {
> - virtual D *clone() { return new D(); }
> -};
> Index: test/clang-modernize/AddOverride/basic.cpp
> ===================================================================
> --- test/clang-modernize/AddOverride/basic.cpp
> +++ /dev/null
> @@ -1,161 +0,0 @@
> -// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
> -// RUN: clang-modernize -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: clang-modernize -add-override -override-macros %t.cpp -- -I %S -std=c++11
> -// RUN: FileCheck --check-prefix=MACRO --input-file=%t.cpp %s
> -
> -struct A {
> - virtual ~A();
> - // CHECK: virtual ~A();
> - void f();
> - virtual void h() const;
> - // CHECK: virtual void h() const;
> - virtual void i() = 0;
> - // CHECK: virtual void i() = 0;
> -};
> -
> -// Test that override isn't added to non-virtual functions.
> -struct B : public A {
> - void f();
> - // CHECK: struct B
> - // CHECK-NEXT: void f();
> -};
> -
> -// Test that override is added to functions that override virtual functions.
> -struct C : public A {
> - void h() const;
> - // 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.
> -struct D : public A {
> - void h();
> - // CHECK: struct D
> - // CHECK-NEXT: void h();
> -};
> -
> -// Test that override isn't added again to functions that already have it.
> -struct E : public A {
> - 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.
> -struct F : public A {
> - virtual ~F();
> - // CHECK: struct F
> - // CHECK-NEXT: virtual ~F();
> -};
> -
> -// Test that override is placed before any end of line comments.
> -struct G : public A {
> - void h() const; // comment
> - void i() // 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.
> -struct H : public A {
> - void h() const { }
> - // CHECK: struct H
> - // CHECK-NEXT: void h() const override { }
> -};
> -
> -// Test that override is placed correctly if there is a body on the next line.
> -struct I : public A {
> - void h() const
> - { }
> - // 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.
> -struct J : public A {
> - void h() const;
> - // 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.
> -struct K : public A {
> - auto h() const -> void;
> - // CHECK: struct K
> - // CHECK-NEXT: auto h() const -> void override;
> -};
> -
> -#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: 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 {
> - virtual APure *clone() = 0;
> -};
> -struct BPure : APure {
> - virtual BPure *clone() { return new BPure(); }
> -};
> -struct CPure : BPure {
> - virtual BPure *clone() = 0;
> - // CHECK: struct CPure : BPure {
> - // CHECK-NOT: virtual BPure *clone() = 0 override;
> - // CHECK: };
> -};
> -struct DPure : CPure {
> - virtual DPure *clone() { return new DPure(); }
> -};
> -
> -// Test that override is not added on dangerous template constructs
> -struct Base1 {
> - virtual void f();
> -};
> -struct Base2 {};
> -template<typename T> struct Derived : T {
> - void f(); // adding 'override' here will break instantiation of Derived<Base2>
> - // CHECK: struct Derived
> - // CHECK-NEXT: void f();
> -};
> -Derived<Base1> d1;
> -Derived<Base2> d2;
> -
> -#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;
> -};
> Index: test/CMakeLists.txt
> ===================================================================
> --- test/CMakeLists.txt
> +++ test/CMakeLists.txt
> @@ -36,7 +36,6 @@
>
> # Individual tools we test.
> clang-apply-replacements
> - clang-modernize
> clang-rename
> clang-query
> clang-tidy
> Index: docs/index.rst
> ===================================================================
> --- docs/index.rst
> +++ docs/index.rst
> @@ -15,7 +15,6 @@
> .. toctree::
> :maxdepth: 1
>
> - clang-modernize
> clang-tidy/index
> modularize
> pp-trace
> Index: docs/cpp11-migrate.rst
> ===================================================================
> --- docs/cpp11-migrate.rst
> +++ docs/cpp11-migrate.rst
> @@ -1,5 +1,2 @@
> -============================
> -C++11 Migrator User's Manual
> -============================
> -
> -This tool has been renamed :doc:`clang-modernize <clang-modernize>`.
> +All :program:`clang-modernize` transforms have moved to :doc:`clang-tidy/index`
> +(see the ``modernize`` module).
> Index: docs/clang-modernize.rst
> ===================================================================
> --- docs/clang-modernize.rst
> +++ docs/clang-modernize.rst
> @@ -1,112 +1,2 @@
> -.. index:: clang-modernize
> -
> -.. note::
> -
> - **Deprecation**
> -
> - As of September 2015 all :program:`clang-modernize` transforms have been
> - ported to :doc:`clang-tidy/index`. :program:`clang-modernize` is deprecated
> - and is going to be removed soon.
> -
> -
> -==================================
> -Clang C++ Modernizer User's Manual
> -==================================
> -
> -.. toctree::
> - :hidden:
> -
> - UseAutoTransform
> - UseNullptrTransform
> - LoopConvertTransform
> - AddOverrideTransform
> - PassByValueTransform
> - ReplaceAutoPtrTransform
> - ModernizerUsage
> - cpp11-migrate
> - MigratorUsage
> -
> -:program:`clang-modernize` is a standalone tool used to automatically convert
> -C++ code written against old standards to use features of the newest C++
> -standard where appropriate.
> -
> -Getting Started
> -===============
> -
> -To build from source:
> -
> -1. Read `Getting Started with the LLVM System`_ and `Clang Tools
> - Documentation`_ for information on getting sources for LLVM, Clang, and
> - Clang Extra Tools.
> -
> -2. `Getting Started with the LLVM System`_ and `Building LLVM with CMake`_ give
> - directions for how to build. With sources all checked out into the
> - right place the LLVM build will build Clang Extra Tools and their
> - dependencies automatically.
> -
> - * If using CMake, you can also use the ``clang-modernize`` target to build
> - just the Modernizer and its dependencies.
> -
> -Before continuing, take a look at :doc:`ModernizerUsage` to see how to invoke
> -the Modernizer.
> -
> -Before running the Modernizer on code you'll need the arguments you'd normally
> -pass to the compiler. If you're migrating a single file with few compiler
> -arguments, it might be easier to pass the compiler args on the command line
> -after ``--``. If you don't have any compiler arguments then ``--`` is not needed.
> -If you're working with multiple files or even a single file with many compiler
> -args, it's probably best to use a *compilation database*.
> -
> -A `compilation database`_ contains the command-line arguments for multiple
> -files. If the code you want to transform can be built with CMake, you can
> -generate this database easily by running CMake with the
> -``-DCMAKE_EXPORT_COMPILE_COMMANDS=ON`` option. The Ninja_ build system, since
> -v1.2, can create this file too using the *compdb* tool: ``ninja -t compdb``. If
> -you're not already using either of these tools or cannot easily make use of
> -them you might consider looking into Bear_.
> -
> -In addition to the compiler arguments you usually build your code with, you must
> -provide the option for enabling C++11 features. For clang and versions of gcc
> -≥ v4.8 this is ``-std=c++11``.
> -
> -With compiler arguments in hand, the modernizer can be applied to sources. Each
> -transform is applied to all sources before the next transform. All the changes
> -generated by each transform pass are serialized to disk and applied using
> -``clang-apply-replacements``. This executable must be located on the ``PATH``
> -or be present in the same directory as the ``clang-modernizer`` executable. If
> -any changes fail to apply, the modernizer will **not** proceed to the next
> -transform and will halt.
> -
> -There's a small chance that changes made by a transform will produce code that
> -doesn't compile, also causing the modernizer to halt. This can happen with
> -bugs in the transforms or use of the pre-processor to make the same code behave
> -differently between translation units. Before logging a bug, be sure which
> -situation you are dealing with.
> -
> -.. _Ninja: http://martine.github.io/ninja/
> -.. _Bear: https://github.com/rizsotto/Bear
> -.. _compilation database: http://clang.llvm.org/docs/JSONCompilationDatabase.html
> -.. _Getting Started with the LLVM System: http://llvm.org/docs/GettingStarted.html
> -.. _Building LLVM with CMake: http://llvm.org/docs/CMake.html
> -.. _Clang Tools Documentation: http://clang.llvm.org/docs/ClangTools.html
> -
> -
> -.. _transforms:
> -
> -Transformations
> -===============
> -
> -The Modernizer is a collection of independent transforms which can be
> -independently enabled. The transforms currently implemented are:
> -
> -* :doc:`LoopConvertTransform`
> -
> -* :doc:`UseNullptrTransform`
> -
> -* :doc:`UseAutoTransform`
> -
> -* :doc:`AddOverrideTransform`
> -
> -* :doc:`PassByValueTransform`
> -
> -* :doc:`ReplaceAutoPtrTransform`
> +All :program:`clang-modernize` transforms have moved to :doc:`clang-tidy/index`
> +(see the ``modernize`` module).
> Index: docs/UseNullptrTransform.rst
> ===================================================================
> --- docs/UseNullptrTransform.rst
> +++ /dev/null
> @@ -1,82 +0,0 @@
> -.. index:: Use-Nullptr Transform
> -
> -=====================
> -Use-Nullptr Transform
> -=====================
> -
> -The Use-Nullptr Transform is a transformation to convert the usage of null
> -pointer constants (eg. ``NULL``, ``0``) to use the new C++11 ``nullptr``
> -keyword. The transform is enabled with the :option:`-use-nullptr` option of
> -:program:`clang-modernize`.
> -
> -Example
> -=======
> -
> -.. code-block:: c++
> -
> - void assignment() {
> - char *a = NULL;
> - char *b = 0;
> - char c = 0;
> - }
> -
> - int *ret_ptr() {
> - return 0;
> - }
> -
> -
> -transforms to:
> -
> -.. code-block:: c++
> -
> - void assignment() {
> - char *a = nullptr;
> - char *b = nullptr;
> - char c = 0;
> - }
> -
> - 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
> -
> - clang-modernize -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.
> Index: docs/UseAutoTransform.rst
> ===================================================================
> --- docs/UseAutoTransform.rst
> +++ /dev/null
> @@ -1,137 +0,0 @@
> -.. index:: Use-Auto Transform
> -
> -==================
> -Use-Auto Transform
> -==================
> -
> -The Use-Auto Transform is responsible for using the ``auto`` type specifier for
> -variable declarations to *improve code readability and maintainability*. The
> -transform is enabled with the :option:`-use-auto` option of
> -:program:`clang-modernize`. For example:
> -
> -.. code-block:: c++
> -
> - std::vector<int>::iterator I = my_container.begin();
> -
> - // transforms to:
> -
> - auto I = my_container.begin();
> -
> -The ``auto`` type specifier will only be introduced in situations where the
> -variable type matches the type of the initializer expression. In other words
> -``auto`` should deduce the same type that was originally spelled in the source.
> -However, not every situation should be transformed:
> -
> -.. code-block:: c++
> -
> - int val = 42;
> - InfoStruct &I = SomeObject.getInfo();
> -
> - // Should not become:
> -
> - auto val = 42;
> - auto &I = SomeObject.getInfo();
> -
> -In this example using ``auto`` for builtins doesn't improve readability. In
> -other situations it makes the code less self-documenting impairing readability
> -and maintainability. As a result, ``auto`` is used only introduced in specific
> -situations described below.
> -
> -Iterators
> -=========
> -
> -Iterator type specifiers tend to be long and used frequently, especially in
> -loop constructs. Since the functions generating iterators have a common format,
> -the type specifier can be replaced without obscuring the meaning of code while
> -improving readability and maintainability.
> -
> -.. code-block:: c++
> -
> - for (std::vector<int>::iterator I = my_container.begin(),
> - E = my_container.end();
> - I != E; ++I) {
> - }
> -
> - // becomes
> -
> - for (auto I = my_container.begin(), E = my_container.end(); I != E; ++I) {
> - }
> -
> -The transform will only replace iterator type-specifiers when all of the
> -following conditions are satisfied:
> -* The iterator is for one of the standard container in ``std`` namespace:
> -
> - * ``array``
> -
> - * ``deque``
> -
> - * ``forward_list``
> -
> - * ``list``
> -
> - * ``vector``
> -
> - * ``map``
> -
> - * ``multimap``
> -
> - * ``set``
> -
> - * ``multiset``
> -
> - * ``unordered_map``
> -
> - * ``unordered_multimap``
> -
> - * ``unordered_set``
> -
> - * ``unordered_multiset``
> -
> - * ``queue``
> -
> - * ``priority_queue``
> -
> - * ``stack``
> -
> -* The iterator is one of the possible iterator types for standard containers:
> -
> - * ``iterator``
> -
> - * ``reverse_iterator``
> -
> - * ``const_iterator``
> -
> - * ``const_reverse_iterator``
> -
> -* In addition to using iterator types directly, typedefs or other ways of
> - referring to those types are also allowed. However, implementation-specific
> - types for which a type like ``std::vector<int>::iterator`` is itself a
> - typedef will not be transformed. Consider the following examples:
> -
> -.. code-block:: c++
> -
> - // The following direct uses of iterator types will be transformed.
> - std::vector<int>::iterator I = MyVec.begin();
> - {
> - using namespace std;
> - list<int>::iterator I = MyList.begin();
> - }
> -
> - // The type specifier for J would transform to auto since it's a typedef
> - // to a standard iterator type.
> - typedef std::map<int, std::string>::const_iterator map_iterator;
> - map_iterator J = MyMap.begin();
> -
> - // The following implementation-specific iterator type for which
> - // std::vector<int>::iterator could be a typedef would not be transformed.
> - __gnu_cxx::__normal_iterator<int*, std::vector> K = MyVec.begin();
> -
> -* The initializer for the variable being declared is not a braced initializer
> - list. Otherwise, use of ``auto`` would cause the type of the variable to be
> - deduced as``std::initializer_list``.
> -
> -Known Limitations
> -=================
> -* If the initializer is an explicit conversion constructor, the transform will
> - not replace the type specifier even though it would be safe to do so.
> -* User-defined iterators are not handled at this time.
> Index: docs/ReplaceAutoPtrTransform.rst
> ===================================================================
> --- docs/ReplaceAutoPtrTransform.rst
> +++ /dev/null
> @@ -1,72 +0,0 @@
> -.. index:: Replace-AutoPtr Transform
> -
> -=========================
> -Replace-AutoPtr Transform
> -=========================
> -
> -The Replace-AutoPtr Transform replaces the uses of the deprecated class
> -``std::auto_ptr`` by ``std::unique_ptr`` (introduced in C++11). The transfer of
> -ownership, done by the copy-constructor and the assignment operator, is changed
> -to match ``std::unique_ptr`` usage by using explicit calls to ``std::move()``.
> -The transform is enabled with the :option:`-replace-auto_ptr` option of
> -:program:`clang-modernize`.
> -
> -Migration example:
> -
> -.. code-block:: c++
> -
> - -void take_ownership_fn(std::auto_ptr<int> int_ptr);
> - +void take_ownership_fn(std::unique_ptr<int> int_ptr);
> -
> - void f(int x) {
> - - std::auto_ptr<int> a(new int(x));
> - - std::auto_ptr<int> b;
> - + std::unique_ptr<int> a(new int(x));
> - + std::unique_ptr<int> b;
> -
> - - b = a;
> - - take_ownership_fn(b);
> - + b = std::move(a);
> - + take_ownership_fn(std::move(b));
> - }
> -
> -
> -Known Limitations
> -=================
> -* If headers modification is not activated or if a header is not allowed to be
> - changed this transform will produce broken code (compilation error), where the
> - the headers' code will stay unchanged while the code using them will be
> - changed.
> -
> -* Client code that declares a reference to an ``std::auto_ptr`` coming from code
> - that can't be migrated (such as a header coming from a 3\ :sup:`rd` party
> - library) will produce a compilation error after migration. This is because the
> - type of the reference will be changed to ``std::unique_ptr`` but the type
> - returned by the library won't change, binding a reference to
> - ``std::unique_ptr`` from an ``std::auto_ptr``. This pattern doesn't make much
> - sense and usually ``std::auto_ptr`` are stored by value (otherwise what is the
> - point in using them instead of a reference or a pointer?).
> -
> - .. code-block:: c++
> -
> - // <3rd-party header...>
> - std::auto_ptr<int> get_value();
> - const std::auto_ptr<int> & get_ref();
> -
> - // <calling code (with migration)...>
> - -std::auto_ptr<int> a(get_value());
> - +std::unique_ptr<int> a(get_value()); // ok, unique_ptr constructed from auto_ptr
> -
> - -const std::auto_ptr<int> & p = get_ptr();
> - +const std::unique_ptr<int> & p = get_ptr(); // won't compile
> -
> -* Non-instantiated templates aren't modified.
> -
> - .. code-block:: c++
> -
> - template <typename X>
> - void f() {
> - std::auto_ptr<X> p;
> - }
> -
> - // only 'f<int>()' (or similar) will trigger the replacement
> Index: docs/PassByValueTransform.rst
> ===================================================================
> --- docs/PassByValueTransform.rst
> +++ /dev/null
> @@ -1,165 +0,0 @@
> -.. index:: Pass-By-Value Transform
> -
> -=======================
> -Pass-By-Value Transform
> -=======================
> -
> -The Pass-By-Value Transform makes use of the pass-by-value idiom when possible.
> -
> -With move semantics added to the language and the standard library updated with
> -move constructors added for many types it is now interesting to take an argument
> -directly by value, instead of by const-reference, and then copy. This
> -transformation allows the compiler to take care of choosing the best way to
> -construct the copy.
> -
> -The transformation is usually beneficial when the calling code passes an
> -*rvalue* and assumes the move construction is a cheap operation. This short
> -example illustrates how the construction of the value happens:
> -
> - .. code-block:: c++
> -
> - void foo(std::string s);
> - std::string get_str();
> -
> - void f(const std::string &str) {
> - foo(str); // lvalue -> copy construction
> - foo(get_str()); // prvalue -> move construction
> - }
> -
> -.. note::
> -
> - Currently only constructors are transformed to make use of pass-by-value.
> - Contributions that handle other situations are welcome!
> -
> -
> -Pass-by-value in constructors
> ------------------------------
> -
> -Replaces the uses of const-references constructor parameters that are copied
> -into class fields. The parameter is then moved with `std::move()`.
> -
> -Since `std::move()` is a library function declared in `<utility>` it may be
> -necessary to add this include. The transform will add the include directive when
> -necessary.
> -
> -Example::
> -
> - $ clang-modernize -pass-by-value ctor.cpp
> -
> -**ctor.cpp**
> -
> - .. code-block:: c++
> -
> - #include <string>
> -
> - class Foo {
> - public:
> - - Foo(const std::string &Copied, const std::string &ReadOnly)
> - - : Copied(Copied), ReadOnly(ReadOnly)
> - + Foo(std::string Copied, const std::string &ReadOnly)
> - + : Copied(std::move(Copied)), ReadOnly(ReadOnly)
> - {}
> -
> - private:
> - std::string Copied;
> - const std::string &ReadOnly;
> - };
> -
> - std::string get_cwd();
> -
> - void f(const std::string &Path) {
> - // The parameter corresponding to 'get_cwd()' is move-constructed. By
> - // using pass-by-value in the Foo constructor we managed to avoid a
> - // copy-construction.
> - Foo foo(get_cwd(), Path);
> - }
> -
> -
> -If the parameter is used more than once no transformation is performed since
> -moved objects have an undefined state. It means the following code will be left
> -untouched:
> -
> -.. code-block:: c++
> -
> - #include <string>
> -
> - void pass(const std::string &S);
> -
> - struct Foo {
> - Foo(const std::string &S) : Str(S) {
> - pass(S);
> - }
> -
> - std::string Str;
> - };
> -
> -
> -Risk
> -^^^^
> -
> -This modification is considered **reasonably safe** (see :option:`-risk`
> -option).
> -
> -A situation where the generated code can be wrong is when the object referenced
> -is modified before the assignment in the init-list through a "hidden" reference.
> -
> -Example:
> -
> -.. code-block:: c++
> -
> - std::string s("foo");
> -
> - struct Base {
> - Base() {
> - s = "bar";
> - }
> - };
> -
> - struct Derived : Base {
> - - Derived(const std::string &S) : Field(S)
> - + Derived(std::string S) : Field(std::move(S))
> - { }
> -
> - std::string Field;
> - };
> -
> - void f() {
> - - Derived d(s); // d.Field holds "bar"
> - + Derived d(s); // d.Field holds "foo"
> - }
> -
> -
> -Note about delayed template parsing
> -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> -
> -When delayed template parsing is enabled, constructors part of templated
> -contexts; templated constructors, constructors in class templates, constructors
> -of inner classes of template classes, etc., are not transformed. Delayed
> -template parsing is enabled by default on Windows as a Microsoft extension:
> -`Clang Compiler User’s Manual - Microsoft extensions`_.
> -
> -Delayed template parsing can be enabled using the `-fdelayed-template-parsing`
> -flag and disabled using `-fno-delayed-template-parsing`.
> -
> -Example:
> -
> -.. code-block:: c++
> -
> - template <typename T> class C {
> - std::string S;
> -
> - public:
> - = // using -fdelayed-template-parsing (default on Windows)
> - = C(const std::string &S) : S(S) {}
> -
> - + // using -fno-delayed-template-parsing (default on non-Windows systems)
> - + C(std::string S) : S(std::move(S)) {}
> - };
> -
> -.. _Clang Compiler User’s Manual - Microsoft extensions: http://clang.llvm.org/docs/UsersManual.html#microsoft-extensions
> -
> -.. seealso::
> -
> - For more information about the pass-by-value idiom, read: `Want Speed? Pass by Value`_.
> -
> - .. _Want Speed? Pass by Value: http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/
> Index: docs/ModernizerUsage.rst
> ===================================================================
> --- docs/ModernizerUsage.rst
> +++ /dev/null
> @@ -1,313 +0,0 @@
> -=====================
> -clang-modernize Usage
> -=====================
> -
> -``clang-modernize [options] [<sources>...] [-- [args]]``
> -
> -``<source#>`` specifies the path to the source to migrate. This path may be
> -relative to the current directory. If no sources are provided, a compilation
> -database provided with `-p`_ can be used to provide sources together with the
> -`include/exclude options`_.
> -
> -By default all transformations are applied. There are two ways to enable a
> -subset of the transformations:
> -
> -1. Explicitly, by referring to the transform options directly, see
> - :ref:`transform-specific-command-line-options`.
> -2. Implicitly, based on the compilers to support, see
> - :ref:`-for-compilers=\<string\> <for-compilers-option>`.
> -
> -If both ways of specifying transforms are used only explicitly specified
> -transformations that are supported by the given compilers will be applied.
> -
> -General Command Line Options
> -============================
> -
> -.. option:: -help
> -
> - Displays tool usage instructions and command line options.
> -
> -.. option:: -version
> -
> - Displays the version information of this tool.
> -
> -.. _-p:
> -
> -.. option:: -p=<build-path>
> -
> - ``<build-path>`` is the directory containing a *compilation databasefile*, a
> - file named ``compile_commands.json``, which provides compiler arguments for
> - building each source file. CMake can generate this file by specifying
> - ``-DCMAKE_EXPORT_COMPILE_COMMANDS=ON`` when running CMake. Ninja_, since v1.2
> - can also generate this file with ``ninja -t compdb``. If the compilation
> - database cannot be used for any reason, an error is reported.
> -
> - This option is ignored if ``--`` is present.
> -
> - Files in the compilation database will be transformed if no sources are
> - provided and paths to files are explicitly included using ``-include`` or
> - ``-include-from``.
> - In order to transform all files in a compilation database the following
> - command line can be used:
> -
> - ``clang-modernize -p=<build-path> -include=<project_root>``
> -
> - Use ``-exclude`` or ``-exclude-from`` to limit the scope of ``-include``.
> -
> -.. _Ninja: http://martine.github.io/ninja/
> -
> -.. option:: -- [args]
> -
> - Another way to provide compiler arguments is to specify all arguments on the
> - command line following ``--``. Arguments provided this way are used for
> - *every* source file.
> -
> - If neither ``--`` nor ``-p`` are specified a compilation database is
> - searched for starting with the path of the first-provided source file and
> - proceeding through parent directories. If no compilation database is found or
> - one is found and cannot be used for any reason then ``-std=c++11`` is used as
> - the only compiler argument.
> -
> -.. option:: -risk=<risk-level>
> -
> - Some transformations may cause a change in semantics. In such cases the
> - maximum acceptable risk level specified through the ``-risk`` command
> - line option decides whether or not a transformation is applied.
> -
> - Three different risk level options are available:
> -
> - ``-risk=safe``
> - Perform only safe transformations.
> - ``-risk=reasonable`` (default)
> - Enable transformations that may change semantics.
> - ``-risk=risky``
> - Enable transformations that are likely to change semantics.
> -
> - The meaning of risk is handled differently for each transform. See
> - :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
> - file.
> -
> -.. option:: -summary
> -
> - Displays a summary of the number of changes each transform made or could have
> - made to each source file immediately after each transform is applied.
> - **Accepted** changes are those actually made. **Rejected** changes are those
> - that could have been made if the acceptable risk level were higher.
> - **Deferred** changes are those that might be possible but they might conflict
> - with other accepted changes. Re-applying the transform will resolve deferred
> - changes.
> -
> -.. _for-compilers-option:
> -
> -.. option:: -for-compilers=<string>
> -
> - Select transforms targeting the intersection of language features supported by
> - the given compilers.
> -
> - Four compilers are supported. The transforms are enabled according to this
> - table:
> -
> - =============== ===== === ==== ====
> - Transforms clang gcc icc mscv
> - =============== ===== === ==== ====
> - AddOverride (1) 3.0 4.7 14 8
> - LoopConvert 3.0 4.6 13 11
> - PassByValue 3.0 4.6 13 11
> - ReplaceAutoPtr 3.0 4.6 13 11
> - UseAuto 2.9 4.4 12 10
> - UseNullptr 3.0 4.6 12.1 10
> - =============== ===== === ==== ====
> -
> - (1): if *-override-macros* is provided it's assumed that the macros are C++11
> - aware and the transform is enabled without regard to the supported compilers.
> -
> - The structure of the argument to the `-for-compilers` option is
> - **<compiler>-<major ver>[.<minor ver>]** where **<compiler>** is one of the
> - compilers from the above table.
> -
> - Some examples:
> -
> - 1. To support `Clang >= 3.0`, `gcc >= 4.6` and `MSVC >= 11`:
> -
> - ``clang-modernize -for-compilers=clang-3.0,gcc-4.6,msvc-11 <args..>``
> -
> - Enables LoopConvert, ReplaceAutoPtr, UseAuto, UseNullptr.
> -
> - 2. To support `icc >= 12` while using a C++11-aware macro for the `override`
> - virtual specifier:
> -
> - ``clang-modernize -for-compilers=icc-12 -override-macros <args..>``
> -
> - Enables AddOverride and UseAuto.
> -
> - .. warning::
> -
> - If your version of Clang depends on the GCC headers (e.g: when `libc++` is
> - not used), then you probably want to add the GCC version to the targeted
> - platforms as well.
> -
> -.. option:: -perf[=<directory>]
> -
> - Turns on performance measurement and output functionality. The time it takes to
> - apply each transform is recorded by the migrator and written in JSON format
> - to a uniquely named file in the given ``<directory>``. All sources processed
> - by a single Modernizer process are written to the same output file. If
> - ``<directory>`` is not provided the default is ``./migrate_perf/``.
> -
> - The time recorded for a transform includes parsing and creating source code
> - replacements.
> -
> -.. option:: -serialize-replacements
> -
> - Causes the modernizer to generate replacements and serialize them to disk but
> - not apply them. This can be useful for debugging or for manually running
> - ``clang-apply-replacements``. Replacements are serialized in YAML_ format.
> - By default serialzied replacements are written to a temporary directory whose
> - name is written to stderr when serialization is complete.
> -
> -.. _YAML: http://www.yaml.org/
> -
> -.. option:: -serialize-dir=<string>
> -
> - Choose a directory to serialize replacements to. The directory must exist.
> -
> -.. _include/exclude options:
> -
> -Path Inclusion/Exclusion Options
> -================================
> -
> -.. option:: -include=<path1>,<path2>,...,<pathN>
> -
> - Use this option to indicate which directories contain files that can be
> - changed by the modernizer. Inidividual files may be specified if desired.
> - Multiple paths can be specified as a comma-separated list. Sources mentioned
> - explicitly on the command line are always included so this option controls
> - which other files (e.g. headers) may be changed while transforming
> - translation units.
> -
> -.. option:: -exclude=<path1>,<path2>,...,<pathN>
> -
> - Used with ``-include`` to provide finer control over which files and
> - directories can be transformed. Individual files and files within directories
> - specified by this option **will not** be transformed. Multiple paths can be
> - specified as a comma-separated list.
> -
> -.. option:: -include-from=<filename>
> -
> - Like ``-include`` but read paths from the given file. Paths should be one per
> - line.
> -
> -.. option:: -exclude-from=<filename>
> -
> - Like ``-exclude`` but read paths from the given file. Paths are listed one
> - per line.
> -
> -Formatting Command Line Options
> -===============================
> -
> -.. option:: -format
> -
> - Enable reformatting of code changed by transforms. Formatting is done after
> - every transform.
> -
> -.. option:: -style=<string>
> -
> - Specifies how formatting should be done. The behaviour of this option is
> - identical to the same option provided by clang-format_. Refer to
> - `clang-format's style options`_ for more details.
> -
> -.. option:: -style-config=<dir>
> -
> - When using ``-style=file``, the default behaviour is to look for
> - ``.clang-format`` starting in the current directory and then in ancestors. To
> - specify a directory to find the style configuration file, use this option.
> -
> -Example:
> -
> -.. code-block:: c++
> - :emphasize-lines: 10-12,18
> -
> - // file.cpp
> - for (std::vector<int>::const_iterator I = my_container.begin(),
> - E = my_container.end();
> - I != E; ++I) {
> - std::cout << *I << std::endl;
> - }
> -
> - // No reformatting:
> - // clang-modernize -use-auto file.cpp
> - for (auto I = my_container.begin(),
> - E = my_container.end();
> - I != E; ++I) {
> - std::cout << *I << std::endl;
> - }
> -
> - // With reformatting enabled:
> - // clang-modernize -format -use-auto file.cpp
> - for (auto I = my_container.begin(), E = my_container.end(); I != E; ++I) {
> - std::cout << *I << std::endl;
> - }
> -
> -.. _clang-format: http://clang.llvm.org/docs/ClangFormat.html
> -.. _clang-format's style options: http://clang.llvm.org/docs/ClangFormatStyleOptions.html
> -
> -
> -.. _transform-specific-command-line-options:
> -
> -Transform-Specific Command Line Options
> -=======================================
> -
> -.. option:: -loop-convert
> -
> - Makes use of C++11 range-based for loops where possible. See
> - :doc:`LoopConvertTransform`.
> -
> -.. option:: -use-nullptr
> -
> - 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
> - specifier. See :doc:`UseAutoTransform`.
> -
> -.. option:: -add-override
> -
> - Adds the override specifier to member functions where it is appropriate. That
> - is, the override specifier is added to member functions that override a
> - virtual function in a base class and that don't already have the specifier.
> - See :doc:`AddOverrideTransform`.
> -
> -.. option:: -override-macros
> -
> - Tells the Add Override Transform to locate a macro that expands to
> - ``override`` and use that macro instead of the ``override`` keyword directly.
> - If no such macro is found, ``override`` is still used. This option enables
> - projects that use such macros to maintain build compatibility with non-C++11
> - code.
> -
> -.. option:: -pass-by-value
> -
> - Replace const-reference parameters by values in situations where it can be
> - beneficial.
> - See :doc:`PassByValueTransform`.
> -
> -.. option:: -replace-auto_ptr
> -
> - Replace ``std::auto_ptr`` (deprecated in C++11) by ``std::unique_ptr`` and
> - wrap calls to the copy constructor and assignment operator with
> - ``std::move()``.
> - See :doc:`ReplaceAutoPtrTransform`.
> Index: docs/MigratorUsage.rst
> ===================================================================
> --- docs/MigratorUsage.rst
> +++ /dev/null
> @@ -1,6 +0,0 @@
> -===================
> -cpp11-migrate Usage
> -===================
> -
> -This program has been renamed :doc:`clang-modernize <clang-modernize>`, and its usage is now
> -found in :doc:`ModernizerUsage`.
> Index: docs/LoopConvertTransform.rst
> ===================================================================
> --- docs/LoopConvertTransform.rst
> +++ /dev/null
> @@ -1,257 +0,0 @@
> -.. index:: Loop Convert Transform
> -
> -======================
> -Loop Convert Transform
> -======================
> -
> -The Loop Convert Transform is a transformation to convert ``for(...; ...;
> -...)`` loops to use the new range-based loops in C++11. The transform is enabled
> -with the :option:`-loop-convert` option of :program:`clang-modernize`.
> -
> -Three kinds of loops can be converted:
> -
> -- Loops over statically allocated arrays
> -- Loops over containers, using iterators
> -- Loops over array-like containers, using ``operator[]`` and ``at()``
> -
> -Risk
> -====
> -
> -Risky
> ------
> -
> -In loops where the container expression is more complex than just a
> -reference to a declared expression (a variable, function, enum, etc.),
> -and some part of it appears elsewhere in the loop, we lower our confidence
> -in the transformation due to the increased risk of changing semantics.
> -Transformations for these loops are marked as `risky`, and thus will only
> -be converted if the acceptable risk level is set to ``-risk=risky``.
> -
> -.. code-block:: c++
> -
> - int arr[10][20];
> - int l = 5;
> -
> - for (int j = 0; j < 20; ++j)
> - int k = arr[l][j] + l; // using l outside arr[l] is considered risky
> -
> - for (int i = 0; i < obj.getVector().size(); ++i)
> - obj.foo(10); // using 'obj' is considered risky
> -
> -See
> -:ref:`Range-based loops evaluate end() only once<IncorrectRiskyTransformation>`
> -for an example of an incorrect transformation when the maximum acceptable risk
> -level is set to `risky`.
> -
> -Reasonable (Default)
> ---------------------
> -
> -If a loop calls ``.end()`` or ``.size()`` after each iteration, the
> -transformation for that loop is marked as `reasonable`, and thus will
> -be converted if the acceptable risk level is set to ``-risk=reasonable``
> -(default) or higher.
> -
> -.. code-block:: c++
> -
> - // using size() is considered reasonable
> - for (int i = 0; i < container.size(); ++i)
> - cout << container[i];
> -
> -Safe
> -----
> -
> -Any other loops that do not match the above criteria to be marked as
> -`risky` or `reasonable` are marked `safe`, and thus will be converted
> -if the acceptable risk level is set to ``-risk=safe`` or higher.
> -
> -.. code-block:: c++
> -
> - int arr[] = {1,2,3};
> -
> - for (int i = 0; i < 3; ++i)
> - cout << arr[i];
> -
> -Example
> -=======
> -
> -Original:
> -
> -.. code-block:: c++
> -
> - const int N = 5;
> - int arr[] = {1,2,3,4,5};
> - vector<int> v;
> - v.push_back(1);
> - v.push_back(2);
> - v.push_back(3);
> -
> - // safe transform
> - for (int i = 0; i < N; ++i)
> - cout << arr[i];
> -
> - // reasonable transform
> - for (vector<int>::iterator it = v.begin(); it != v.end(); ++it)
> - cout << *it;*
> -
> - // reasonable transform
> - for (int i = 0; i < v.size(); ++i)
> - cout << v[i];
> -
> -After transformation with risk level set to ``-risk=reasonable`` (default):
> -
> -.. code-block:: c++
> -
> - const int N = 5;
> - int arr[] = {1,2,3,4,5};
> - vector<int> v;
> - v.push_back(1);
> - v.push_back(2);
> - v.push_back(3);
> -
> - // safe transform
> - for (auto & elem : arr)
> - cout << elem;
> -
> - // reasonable transform
> - for (auto & elem : v)
> - cout << elem;
> -
> - // reasonable transform
> - for (auto & elem : v)
> - cout << elem;
> -
> -Limitations
> -===========
> -
> -There are certain situations where the tool may erroneously perform
> -transformations that remove information and change semantics. Users of the tool
> -should be aware of the behaviour and limitations of the transform outlined by
> -the cases below.
> -
> -Comments inside loop headers
> -----------------------------
> -
> -Comments inside the original loop header are ignored and deleted when
> -transformed.
> -
> -.. code-block:: c++
> -
> - for (int i = 0; i < N; /* This will be deleted */ ++i) { }
> -
> -Range-based loops evaluate end() only once
> -------------------------------------------
> -
> -The C++11 range-based for loop calls ``.end()`` only once during the
> -initialization of the loop. If in the original loop ``.end()`` is called after
> -each iteration the semantics of the transformed loop may differ.
> -
> -.. code-block:: c++
> -
> - // The following is semantically equivalent to the C++11 range-based for loop,
> - // therefore the semantics of the header will not change.
> - for (iterator it = container.begin(), e = container.end(); it != e; ++it) { }
> -
> - // Instead of calling .end() after each iteration, this loop will be
> - // transformed to call .end() only once during the initialization of the loop,
> - // which may affect semantics.
> - for (iterator it = container.begin(); it != container.end(); ++it) { }
> -
> -.. _IncorrectRiskyTransformation:
> -
> -As explained above, calling member functions of the container in the body
> -of the loop is considered `risky`. If the called member function modifies the
> -container the semantics of the converted loop will differ due to ``.end()``
> -being called only once.
> -
> -.. code-block:: c++
> -
> - bool flag = false;
> - for (vector<T>::iterator it = vec.begin(); it != vec.end(); ++it) {
> - // Add a copy of the first element to the end of the vector.
> - if (!flag) {
> - // This line makes this transformation 'risky'.
> - vec.push_back(*it);
> - flag = true;
> - }
> - cout << *it;
> - }
> -
> -The original code above prints out the contents of the container including the
> -newly added element while the converted loop, shown below, will only print the
> -original contents and not the newly added element.
> -
> -.. code-block:: c++
> -
> - bool flag = false;
> - for (auto & elem : vec) {
> - // Add a copy of the first element to the end of the vector.
> - if (!flag) {
> - // This line makes this transformation 'risky'
> - vec.push_back(elem);
> - flag = true;
> - }
> - cout << elem;
> - }
> -
> -Semantics will also be affected if ``.end()`` has side effects. For example, in
> -the case where calls to ``.end()`` are logged the semantics will change in the
> -transformed loop if ``.end()`` was originally called after each iteration.
> -
> -.. code-block:: c++
> -
> - iterator end() {
> - num_of_end_calls++;
> - return container.end();
> - }
> -
> -Overloaded operator->() with side effects
> ------------------------------------------
> -
> -Similarly, if ``operator->()`` was overloaded to have side effects, such as
> -logging, the semantics will change. If the iterator's ``operator->()`` was used
> -in the original loop it will be replaced with ``<container element>.<member>``
> -instead due to the implicit dereference as part of the range-based for loop.
> -Therefore any side effect of the overloaded ``operator->()`` will no longer be
> -performed.
> -
> -.. code-block:: c++
> -
> - for (iterator it = c.begin(); it != c.end(); ++it) {
> - it->func(); // Using operator->()
> - }
> - // Will be transformed to:
> - for (auto & elem : c) {
> - elem.func(); // No longer using operator->()
> - }
> -
> -Pointers and references to containers
> --------------------------------------
> -
> -While most of the transform's risk analysis is dedicated to determining whether
> -the iterator or container was modified within the loop, it is possible to
> -circumvent the analysis by accessing and modifying the container through a
> -pointer or reference.
> -
> -If the container were directly used instead of using the pointer or reference
> -the following transformation would have only been applied at the ``-risk=risky``
> -level since calling a member function of the container is considered `risky`.
> -The transform cannot identify expressions associated with the container that are
> -different than the one used in the loop header, therefore the transformation
> -below ends up being performed at the ``-risk=safe`` level.
> -
> -.. code-block:: c++
> -
> - vector<int> vec;
> -
> - vector<int> *ptr = &vec;
> - vector<int> &ref = vec;
> -
> - for (vector<int>::iterator it = vec.begin(), e = vec.end(); it != e; ++it) {
> - if (!flag) {
> - // Accessing and modifying the container is considered risky, but the risk
> - // level is not raised here.
> - ptr->push_back(*it);
> - ref.push_back(*it);
> - flag = true;
> - }
> - }
> Index: docs/AddOverrideTransform.rst
> ===================================================================
> --- docs/AddOverrideTransform.rst
> +++ /dev/null
> @@ -1,54 +0,0 @@
> -.. index:: Add-Override Transform
> -
> -======================
> -Add-Override Transform
> -======================
> -
> -The Add-Override Transform adds the ``override`` specifier to member
> -functions that override a virtual function in a base class and that
> -don't already have the specifier. The transform is enabled with the
> -:option:`-add-override` option of :program:`clang-modernize`.
> -For example:
> -
> -.. code-block:: c++
> -
> - class A {
> - public:
> - virtual void h() const;
> - };
> -
> - class B : public A {
> - public:
> - void h() const;
> -
> - // The declaration of h is transformed to
> - void h() const override;
> - };
> -
> -Using Expands-to-Override Macros
> -================================
> -
> -Like LLVM's ``LLVM_OVERRIDE``, several projects have macros that conditionally
> -expand to the ``override`` keyword when compiling with C++11 features enabled.
> -To maintain compatibility with non-C++11 builds, the Add-Override Transform
> -supports detection and use of these macros instead of using the ``override``
> -keyword directly. Specify ``-override-macros`` on the command line to the
> -Modernizer to enable this behavior.
> -
> -
> -Known Limitations
> -=================
> -* This transform will not insert the override keyword if a method is
> - pure. At the moment it's not possible to track down the pure
> - specifier location.
> -
> -.. code-block:: c++
> -
> - class B : public A {
> - public:
> - virtual void h() const = 0;
> -
> - // The declaration of h is NOT transformed to
> - virtual void h() const override = 0;
> - };
> -
> Index: clang-modernize/tool/Makefile
> ===================================================================
> --- clang-modernize/tool/Makefile
> +++ /dev/null
> @@ -1,58 +0,0 @@
> -##===- tools/extra/loop-convert/Makefile ----sssss----------*- Makefile -*-===##
> -#
> -# The LLVM Compiler Infrastructure
> -#
> -# This file is distributed under the University of Illinois Open Source
> -# License. See LICENSE.TXT for details.
> -#
> -##===----------------------------------------------------------------------===##
> -
> -CLANG_LEVEL := ../../../..
> -include $(CLANG_LEVEL)/../../Makefile.config
> -
> -TOOLNAME = clang-modernize
> -
> -# No plugins, optimize startup time.
> -TOOL_NO_EXPORTS = 1
> -
> -SOURCES = ClangModernize.cpp
> -
> -# FIXME: All these gross relative paths will go away once transforms are lib-ified.
> -
> -# For each Transform subdirectory add to SOURCES and BUILT_SOURCES.
> -# BUILT_SOURCES ensures a subdirectory is created to house object files from
> -# transform subdirectories. See below for more on .objdir.
> -SOURCES += $(addprefix ../LoopConvert/,$(notdir $(wildcard $(PROJ_SRC_DIR)/../LoopConvert/*.cpp)))
> -BUILT_SOURCES = $(ObjDir)/../LoopConvert/.objdir
> -SOURCES += $(addprefix ../UseNullptr/,$(notdir $(wildcard $(PROJ_SRC_DIR)/../UseNullptr/*.cpp)))
> -BUILT_SOURCES += $(ObjDir)/../UseNullptr/.objdir
> -SOURCES += $(addprefix ../UseAuto/,$(notdir $(wildcard $(PROJ_SRC_DIR)/../UseAuto/*.cpp)))
> -BUILT_SOURCES += $(ObjDir)/../UseAuto/.objdir
> -SOURCES += $(addprefix ../AddOverride/,$(notdir $(wildcard $(PROJ_SRC_DIR)/../AddOverride/*.cpp)))
> -BUILT_SOURCES += $(ObjDir)/../AddOverride/.objdir
> -SOURCES += $(addprefix ../PassByValue/,$(notdir $(wildcard $(PROJ_SRC_DIR)/../PassByValue/*.cpp)))
> -BUILT_SOURCES += $(ObjDir)/../PassByValue/.objdir
> -SOURCES += $(addprefix ../ReplaceAutoPtr/,$(notdir $(wildcard $(PROJ_SRC_DIR)/../ReplaceAutoPtr/*.cpp)))
> -BUILT_SOURCES += $(ObjDir)/../ReplaceAutoPtr/.objdir
> -
> -LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader support mc mcparser option
> -USEDLIBS = modernizeCore.a clangFormat.a \
> - clangTooling.a clangToolingCore.a clangFrontend.a \
> - clangSerialization.a clangDriver.a clangRewriteFrontend.a \
> - clangRewrite.a clangParse.a clangSema.a clangAnalysis.a \
> - clangAST.a clangASTMatchers.a clangEdit.a clangLex.a clangBasic.a
> -
> -include $(CLANG_LEVEL)/Makefile
> -
> -CPP.Flags += -I$(PROJ_SRC_DIR)/..
> -
> -# BUILT_SOURCES gets used as a prereq for many top-level targets. However, at
> -# the point those targets are defined, $(ObjDir) hasn't been defined and so the
> -# directory to create becomes /<name>/ which is not what we want. So instead,
> -# this .objdir recipe is defined at at point where $(ObjDir) is defined and
> -# it's specialized to $(ObjDir) to ensure it only works on targets we want it
> -# to.
> -$(ObjDir)/%.objdir:
> - $(Verb) $(MKDIR) $(ObjDir)/$* > /dev/null
> - $(Verb) $(DOTDIR_TIMESTAMP_COMMAND) > $@
> -
> Index: clang-modernize/tool/ClangModernize.cpp
> ===================================================================
> --- clang-modernize/tool/ClangModernize.cpp
> +++ /dev/null
> @@ -1,489 +0,0 @@
> -//===-- ClangModernize.cpp - Main file for Clang modernization tool -------===//
> -//
> -// 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 implements the C++11 feature migration tool main function
> -/// and transformation framework.
> -///
> -/// See user documentation for usage instructions.
> -///
> -//===----------------------------------------------------------------------===//
> -
> -#include "Core/PerfSupport.h"
> -#include "Core/ReplacementHandling.h"
> -#include "Core/Transform.h"
> -#include "Core/Transforms.h"
> -#include "clang/Basic/Diagnostic.h"
> -#include "clang/Basic/DiagnosticOptions.h"
> -#include "clang/Basic/SourceManager.h"
> -#include "clang/Basic/Version.h"
> -#include "clang/Format/Format.h"
> -#include "clang/Frontend/FrontendActions.h"
> -#include "clang/Tooling/CommonOptionsParser.h"
> -#include "clang/Tooling/Tooling.h"
> -#include "llvm/ADT/STLExtras.h"
> -#include "llvm/ADT/StringSwitch.h"
> -#include "llvm/Support/Path.h"
> -#include "llvm/Support/Signals.h"
> -
> -namespace cl = llvm::cl;
> -using namespace clang;
> -using namespace clang::tooling;
> -
> -static TransformOptions GlobalOptions;
> -
> -// All options must belong to locally defined categories for them to get shown
> -// by -help. We explicitly hide everything else (except -help and -version).
> -static cl::OptionCategory GeneralCategory("Modernizer Options");
> -static cl::OptionCategory FormattingCategory("Formatting Options");
> -static cl::OptionCategory IncludeExcludeCategory("Inclusion/Exclusion Options");
> -static cl::OptionCategory SerializeCategory("Serialization Options");
> -
> -static const cl::OptionCategory *const VisibleCategories[] = {
> - &GeneralCategory, &FormattingCategory, &IncludeExcludeCategory,
> - &SerializeCategory, &TransformCategory, &TransformsOptionsCategory,
> -};
> -
> -static cl::extrahelp CommonHelp(CommonOptionsParser::HelpMessage);
> -static cl::extrahelp MoreHelp(
> - "EXAMPLES:\n\n"
> - "Apply all transforms on a file that doesn't require compilation arguments:\n\n"
> - " clang-modernize file.cpp\n"
> - "\n"
> - "Convert for loops to ranged-based for loops for all files in the compilation\n"
> - "database that belong in a project subtree and then reformat the code\n"
> - "automatically using the LLVM style:\n\n"
> - " clang-modernize -p build/path -include project/path -format -loop-convert\n"
> - "\n"
> - "Make use of both nullptr and the override specifier, using git ls-files:\n"
> - "\n"
> - " git ls-files '*.cpp' | xargs -I{} clang-modernize -p build/path \\\n"
> - " -use-nullptr -add-override -override-macros {}\n"
> - "\n"
> - "Apply all transforms supported by both clang >= 3.0 and gcc >= 4.7 to\n"
> - "foo.cpp and any included headers in bar:\n\n"
> - " clang-modernize -for-compilers=clang-3.0,gcc-4.7 foo.cpp \\\n"
> - " -include bar -- -std=c++11 -Ibar\n\n");
> -
> -////////////////////////////////////////////////////////////////////////////////
> -/// General Options
> -
> -// This is set to hidden on purpose. The actual help text for this option is
> -// included in CommonOptionsParser::HelpMessage.
> -static cl::opt<std::string> BuildPath("p", cl::desc("Build Path"), cl::Optional,
> - cl::Hidden, cl::cat(GeneralCategory));
> -
> -static cl::list<std::string> SourcePaths(cl::Positional,
> - cl::desc("[<sources>...]"),
> - cl::ZeroOrMore,
> - cl::cat(GeneralCategory));
> -
> -static cl::opt<RiskLevel, /*ExternalStorage=*/true> MaxRiskLevel(
> - "risk", cl::desc("Select a maximum risk level:"),
> - cl::values(clEnumValN(RL_Safe, "safe", "Only safe transformations"),
> - clEnumValN(RL_Reasonable, "reasonable",
> - "Enable transformations that might change "
> - "semantics (default)"),
> - clEnumValN(RL_Risky, "risky",
> - "Enable transformations that are likely to "
> - "change semantics"),
> - clEnumValEnd),
> - cl::location(GlobalOptions.MaxRiskLevel), cl::init(RL_Reasonable),
> - cl::cat(GeneralCategory));
> -
> -static cl::opt<bool> FinalSyntaxCheck(
> - "final-syntax-check",
> - cl::desc("Check for correct syntax after applying transformations"),
> - cl::init(false), cl::cat(GeneralCategory));
> -
> -static cl::opt<bool> SummaryMode("summary", cl::desc("Print transform summary"),
> - cl::init(false), cl::cat(GeneralCategory));
> -
> -static cl::opt<std::string>
> -TimingDirectoryName("perf",
> - cl::desc("Capture performance data and output to specified "
> - "directory. Default: ./migrate_perf"),
> - cl::ValueOptional, cl::value_desc("directory name"),
> - cl::cat(GeneralCategory));
> -
> -static cl::opt<std::string> SupportedCompilers(
> - "for-compilers", cl::value_desc("string"),
> - cl::desc("Select transforms targeting the intersection of\n"
> - "language features supported by the given compilers.\n"
> - "Takes a comma-separated list of <compiler>-<version>.\n"
> - "\t<compiler> can be any of: clang, gcc, icc, msvc\n"
> - "\t<version> is <major>[.<minor>]\n"),
> - cl::cat(GeneralCategory));
> -
> -////////////////////////////////////////////////////////////////////////////////
> -/// Format Options
> -static cl::opt<bool> DoFormat(
> - "format",
> - cl::desc("Enable formatting of code changed by applying replacements.\n"
> - "Use -style to choose formatting style.\n"),
> - cl::cat(FormattingCategory));
> -
> -static cl::opt<std::string>
> -FormatStyleOpt("style", cl::desc(format::StyleOptionHelpDescription),
> - cl::init("LLVM"), cl::cat(FormattingCategory));
> -
> -// FIXME: Consider making the default behaviour for finding a style
> -// configuration file to start the search anew for every file being changed to
> -// handle situations where the style is different for different parts of a
> -// project.
> -
> -static cl::opt<std::string> FormatStyleConfig(
> - "style-config",
> - cl::desc("Path to a directory containing a .clang-format file\n"
> - "describing a formatting style to use for formatting\n"
> - "code when -style=file.\n"),
> - cl::init(""), cl::cat(FormattingCategory));
> -
> -////////////////////////////////////////////////////////////////////////////////
> -/// Include/Exclude Options
> -static cl::opt<std::string>
> -IncludePaths("include",
> - cl::desc("Comma-separated list of paths to consider to be "
> - "transformed"),
> - cl::cat(IncludeExcludeCategory));
> -
> -static cl::opt<std::string>
> -ExcludePaths("exclude", cl::desc("Comma-separated list of paths that can not "
> - "be transformed"),
> - cl::cat(IncludeExcludeCategory));
> -
> -static cl::opt<std::string>
> -IncludeFromFile("include-from", cl::value_desc("filename"),
> - cl::desc("File containing a list of paths to consider to "
> - "be transformed"),
> - cl::cat(IncludeExcludeCategory));
> -
> -static cl::opt<std::string>
> -ExcludeFromFile("exclude-from", cl::value_desc("filename"),
> - cl::desc("File containing a list of paths that can not be "
> - "transformed"),
> - cl::cat(IncludeExcludeCategory));
> -
> -////////////////////////////////////////////////////////////////////////////////
> -/// Serialization Options
> -
> -static cl::opt<bool>
> -SerializeOnly("serialize-replacements",
> - cl::desc("Serialize translation unit replacements to "
> - "disk instead of changing files."),
> - cl::init(false),
> - cl::cat(SerializeCategory));
> -
> -static cl::opt<std::string>
> -SerializeLocation("serialize-dir",
> - cl::desc("Path to an existing directory in which to write\n"
> - "serialized replacements. Default behaviour is to\n"
> - "write to a temporary directory.\n"),
> - cl::cat(SerializeCategory));
> -
> -////////////////////////////////////////////////////////////////////////////////
> -
> -static void printVersion() {
> - llvm::outs() << "clang-modernizer version " CLANG_VERSION_STRING
> - << "\n";
> -}
> -
> -/// \brief Extract the minimum compiler versions as requested on the command
> -/// line by the switch \c -for-compilers.
> -///
> -/// \param ProgName The name of the program, \c argv[0], used to print errors.
> -/// \param Error If an error occur while parsing the versions this parameter is
> -/// set to \c true, otherwise it will be left untouched.
> -static CompilerVersions handleSupportedCompilers(const char *ProgName,
> - bool &Error) {
> - if (SupportedCompilers.getNumOccurrences() == 0)
> - return CompilerVersions();
> - CompilerVersions RequiredVersions;
> - llvm::SmallVector<llvm::StringRef, 4> Compilers;
> -
> - llvm::StringRef(SupportedCompilers).split(Compilers, ",");
> -
> - for (llvm::SmallVectorImpl<llvm::StringRef>::iterator I = Compilers.begin(),
> - E = Compilers.end();
> - I != E; ++I) {
> - llvm::StringRef Compiler, VersionStr;
> - std::tie(Compiler, VersionStr) = I->split('-');
> - Version *V = llvm::StringSwitch<Version *>(Compiler)
> - .Case("clang", &RequiredVersions.Clang)
> - .Case("gcc", &RequiredVersions.Gcc).Case("icc", &RequiredVersions.Icc)
> - .Case("msvc", &RequiredVersions.Msvc).Default(nullptr);
> -
> - if (V == nullptr) {
> - llvm::errs() << ProgName << ": " << Compiler
> - << ": unsupported platform\n";
> - Error = true;
> - continue;
> - }
> - if (VersionStr.empty()) {
> - llvm::errs() << ProgName << ": " << *I
> - << ": missing version number in platform\n";
> - Error = true;
> - continue;
> - }
> -
> - Version Version = Version::getFromString(VersionStr);
> - if (Version.isNull()) {
> - llvm::errs()
> - << ProgName << ": " << *I
> - << ": invalid version, please use \"<major>[.<minor>]\" instead of \""
> - << VersionStr << "\"\n";
> - Error = true;
> - continue;
> - }
> - // support the lowest version given
> - if (V->isNull() || Version < *V)
> - *V = Version;
> - }
> - return RequiredVersions;
> -}
> -
> -static std::unique_ptr<CompilationDatabase>
> -autoDetectCompilations(std::string &ErrorMessage) {
> - // Auto-detect a compilation database from BuildPath.
> - if (BuildPath.getNumOccurrences() > 0)
> - return CompilationDatabase::autoDetectFromDirectory(BuildPath,
> - ErrorMessage);
> - // Try to auto-detect a compilation database from the first source.
> - if (!SourcePaths.empty()) {
> - if (std::unique_ptr<CompilationDatabase> Compilations =
> - CompilationDatabase::autoDetectFromSource(SourcePaths[0],
> - ErrorMessage)) {
> - // FIXME: just pass SourcePaths[0] once getCompileCommands supports
> - // non-absolute paths.
> - SmallString<64> Path(SourcePaths[0]);
> - llvm::sys::fs::make_absolute(Path);
> - std::vector<CompileCommand> Commands =
> - Compilations->getCompileCommands(Path);
> - // Ignore a detected compilation database that doesn't contain source0
> - // since it is probably an unrelated compilation database.
> - if (!Commands.empty())
> - return Compilations;
> - }
> - // Reset ErrorMessage since a fix compilation database will be created if
> - // it fails to detect one from source.
> - ErrorMessage = "";
> - // If no compilation database can be detected from source then we create a
> - // fixed compilation database with c++11 support.
> - std::string CommandLine[] = { "-std=c++11" };
> - return llvm::make_unique<FixedCompilationDatabase>(".", CommandLine);
> - }
> -
> - ErrorMessage = "Could not determine sources to transform";
> - return nullptr;
> -}
> -
> -// Predicate definition for determining whether a file is not included.
> -static bool isFileNotIncludedPredicate(llvm::StringRef FilePath) {
> - return !GlobalOptions.ModifiableFiles.isFileIncluded(FilePath);
> -}
> -
> -// Predicate definition for determining if a file was explicitly excluded.
> -static bool isFileExplicitlyExcludedPredicate(llvm::StringRef FilePath) {
> - if (GlobalOptions.ModifiableFiles.isFileExplicitlyExcluded(FilePath)) {
> - llvm::errs() << "Warning \"" << FilePath << "\" will not be transformed "
> - << "because it's in the excluded list.\n";
> - return true;
> - }
> - return false;
> -}
> -
> -int main(int argc, const char **argv) {
> - llvm::sys::PrintStackTraceOnErrorSignal();
> - Transforms TransformManager;
> - ReplacementHandling ReplacementHandler;
> -
> - TransformManager.registerTransforms();
> -
> - cl::HideUnrelatedOptions(llvm::makeArrayRef(VisibleCategories));
> - cl::SetVersionPrinter(&printVersion);
> -
> - // Parse options and generate compilations.
> - std::unique_ptr<CompilationDatabase> Compilations(
> - FixedCompilationDatabase::loadFromCommandLine(argc, argv));
> - cl::ParseCommandLineOptions(argc, argv);
> -
> - // Populate the ModifiableFiles structure.
> - GlobalOptions.ModifiableFiles.readListFromString(IncludePaths, ExcludePaths);
> - GlobalOptions.ModifiableFiles.readListFromFile(IncludeFromFile,
> - ExcludeFromFile);
> -
> - if (!Compilations) {
> - std::string ErrorMessage;
> - Compilations = autoDetectCompilations(ErrorMessage);
> - if (!Compilations) {
> - llvm::errs() << llvm::sys::path::filename(argv[0]) << ": " << ErrorMessage
> - << "\n";
> - return 1;
> - }
> - }
> -
> - // Populate source files.
> - std::vector<std::string> Sources;
> - if (!SourcePaths.empty()) {
> - // Use only files that are not explicitly excluded.
> - std::remove_copy_if(SourcePaths.begin(), SourcePaths.end(),
> - std::back_inserter(Sources),
> - isFileExplicitlyExcludedPredicate);
> - } else {
> - if (GlobalOptions.ModifiableFiles.isIncludeListEmpty()) {
> - llvm::errs() << llvm::sys::path::filename(argv[0])
> - << ": Use -include to indicate which files of "
> - << "the compilatiion database to transform.\n";
> - return 1;
> - }
> - // Use source paths from the compilation database.
> - // We only transform files that are explicitly included.
> - Sources = Compilations->getAllFiles();
> - std::vector<std::string>::iterator E = std::remove_if(
> - Sources.begin(), Sources.end(), isFileNotIncludedPredicate);
> - Sources.erase(E, Sources.end());
> - }
> -
> - if (Sources.empty()) {
> - llvm::errs() << llvm::sys::path::filename(argv[0])
> - << ": Could not determine sources to transform.\n";
> - return 1;
> - }
> -
> - // Enable timming.
> - GlobalOptions.EnableTiming = TimingDirectoryName.getNumOccurrences() > 0;
> -
> - bool CmdSwitchError = false;
> - CompilerVersions RequiredVersions =
> - handleSupportedCompilers(argv[0], CmdSwitchError);
> - if (CmdSwitchError)
> - return 1;
> -
> - TransformManager.createSelectedTransforms(GlobalOptions, RequiredVersions);
> -
> - if (TransformManager.begin() == TransformManager.end()) {
> - if (SupportedCompilers.empty())
> - llvm::errs() << llvm::sys::path::filename(argv[0])
> - << ": no selected transforms\n";
> - else
> - llvm::errs() << llvm::sys::path::filename(argv[0])
> - << ": no transforms available for specified compilers\n";
> - return 1;
> - }
> -
> - llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> DiagOpts(
> - new DiagnosticOptions());
> - DiagnosticsEngine Diagnostics(
> - llvm::IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()),
> - DiagOpts.get());
> -
> - // FIXME: Make this DiagnosticsEngine available to all Transforms probably via
> - // GlobalOptions.
> -
> - // If SerializeReplacements is requested, then code reformatting must be
> - // turned off and only one transform should be requested.
> - if (SerializeOnly &&
> - (std::distance(TransformManager.begin(), TransformManager.end()) > 1 ||
> - DoFormat)) {
> - llvm::errs() << "Serialization of replacements requested for multiple "
> - "transforms.\nChanges from only one transform can be "
> - "serialized.\n";
> - return 1;
> - }
> -
> - // If we're asked to apply changes to files on disk, need to locate
> - // clang-apply-replacements.
> - if (!SerializeOnly) {
> - if (!ReplacementHandler.findClangApplyReplacements(argv[0])) {
> - llvm::errs() << "Could not find clang-apply-replacements\n";
> - return 1;
> - }
> -
> - if (DoFormat)
> - ReplacementHandler.enableFormatting(FormatStyleOpt, FormatStyleConfig);
> - }
> -
> - StringRef TempDestinationDir;
> - if (SerializeLocation.getNumOccurrences() > 0)
> - ReplacementHandler.setDestinationDir(SerializeLocation);
> - else
> - TempDestinationDir = ReplacementHandler.useTempDestinationDir();
> -
> - SourcePerfData PerfData;
> -
> - for (Transforms::const_iterator I = TransformManager.begin(),
> - E = TransformManager.end();
> - I != E; ++I) {
> - Transform *T = *I;
> -
> - if (T->apply(*Compilations, Sources) != 0) {
> - // FIXME: Improve ClangTool to not abort if just one file fails.
> - return 1;
> - }
> -
> - if (GlobalOptions.EnableTiming)
> - collectSourcePerfData(*T, PerfData);
> -
> - if (SummaryMode) {
> - llvm::outs() << "Transform: " << T->getName()
> - << " - Accepted: " << T->getAcceptedChanges();
> - if (T->getChangesNotMade()) {
> - llvm::outs() << " - Rejected: " << T->getRejectedChanges()
> - << " - Deferred: " << T->getDeferredChanges();
> - }
> - llvm::outs() << "\n";
> - }
> -
> - if (!ReplacementHandler.serializeReplacements(T->getAllReplacements()))
> - return 1;
> -
> - if (!SerializeOnly)
> - if (!ReplacementHandler.applyReplacements())
> - return 1;
> - }
> -
> - // Let the user know which temporary directory the replacements got written
> - // to.
> - if (SerializeOnly && !TempDestinationDir.empty())
> - llvm::errs() << "Replacements serialized to: " << TempDestinationDir << "\n";
> -
> - if (FinalSyntaxCheck) {
> - ClangTool SyntaxTool(*Compilations, SourcePaths);
> - if (SyntaxTool.run(newFrontendActionFactory<SyntaxOnlyAction>().get()) != 0)
> - return 1;
> - }
> -
> - // Report execution times.
> - if (GlobalOptions.EnableTiming && !PerfData.empty()) {
> - std::string DirectoryName = TimingDirectoryName;
> - // Use default directory name.
> - if (DirectoryName.empty())
> - DirectoryName = "./migrate_perf";
> - writePerfDataJSON(DirectoryName, PerfData);
> - }
> -
> - return 0;
> -}
> -
> -// These anchors are used to force the linker to link the transforms
> -extern volatile int AddOverrideTransformAnchorSource;
> -extern volatile int LoopConvertTransformAnchorSource;
> -extern volatile int PassByValueTransformAnchorSource;
> -extern volatile int ReplaceAutoPtrTransformAnchorSource;
> -extern volatile int UseAutoTransformAnchorSource;
> -extern volatile int UseNullptrTransformAnchorSource;
> -
> -static int TransformsAnchorsDestination[] = {
> - AddOverrideTransformAnchorSource,
> - LoopConvertTransformAnchorSource,
> - PassByValueTransformAnchorSource,
> - ReplaceAutoPtrTransformAnchorSource,
> - UseAutoTransformAnchorSource,
> - UseNullptrTransformAnchorSource
> -};
> Index: clang-modernize/tool/CMakeLists.txt
> ===================================================================
> --- clang-modernize/tool/CMakeLists.txt
> +++ /dev/null
> @@ -1,49 +0,0 @@
> -set(LLVM_LINK_COMPONENTS support)
> -
> -set (ClangModernizeSources
> - ClangModernize.cpp
> - )
> -
> -# FIXME: Lib-ify the transforms to simplify the build rules.
> -
> -# For each transform subdirectory.
> -file(GLOB_RECURSE LoopConvertSources "../LoopConvert/*.cpp")
> -list(APPEND ClangModernizeSources ${LoopConvertSources})
> -
> -file(GLOB_RECURSE UseNullptrSources "../UseNullptr/*.cpp")
> -list(APPEND ClangModernizeSources ${UseNullptrSources})
> -
> -file(GLOB_RECURSE UseAutoSources "../UseAuto/*.cpp")
> -list(APPEND ClangModernizeSources ${UseAutoSources})
> -
> -file(GLOB_RECURSE AddOverrideSources "../AddOverride/*.cpp")
> -list(APPEND ClangModernizeSources ${AddOverrideSources})
> -
> -file(GLOB_RECURSE PassByValueSources "../PassByValue/*.cpp")
> -list(APPEND ClangModernizeSources ${PassByValueSources})
> -
> -file(GLOB_RECURSE ReplaceAutoPtrSources "../ReplaceAutoPtr/*.cpp")
> -list(APPEND ClangModernizeSources ${ReplaceAutoPtrSources})
> -
> -add_clang_executable(clang-modernize
> - ${ClangModernizeSources}
> - )
> -
> -add_dependencies(clang-modernize
> - clang-headers clang-apply-replacements
> - )
> -
> -target_link_libraries(clang-modernize
> - clangAST
> - clangASTMatchers
> - clangBasic
> - clangFormat
> - clangFrontend
> - clangLex
> - clangTooling
> - clangToolingCore
> - modernizeCore
> - )
> -
> -install(TARGETS clang-modernize
> - RUNTIME DESTINATION bin)
> Index: clang-modernize/UseNullptr/UseNullptr.h
> ===================================================================
> --- clang-modernize/UseNullptr/UseNullptr.h
> +++ /dev/null
> @@ -1,35 +0,0 @@
> -//===-- UseNullptr/UseNullptr.h - C++11 nullptr 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 CLANG_MODERNIZE_USE_NULLPTR_H
> -#define CLANG_MODERNIZE_USE_NULLPTR_H
> -
> -#include "Core/Transform.h"
> -#include "llvm/Support/Compiler.h" // For override
> -
> -/// \brief Subclass of Transform that transforms null pointer constants into
> -/// C++11's nullptr keyword where possible.
> -class UseNullptrTransform : public Transform {
> -public:
> - UseNullptrTransform(const TransformOptions &Options)
> - : Transform("UseNullptr", Options) {}
> -
> - /// \see Transform::run().
> - int apply(const clang::tooling::CompilationDatabase &Database,
> - const std::vector<std::string> &SourcePaths) override;
> -};
> -
> -#endif // CLANG_MODERNIZE_USE_NULLPTR_H
> Index: clang-modernize/UseNullptr/UseNullptr.cpp
> ===================================================================
> --- clang-modernize/UseNullptr/UseNullptr.cpp
> +++ /dev/null
> @@ -1,80 +0,0 @@
> -//===-- UseNullptr/UseNullptr.cpp - C++11 nullptr migration ---------------===//
> -//
> -// 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/Tooling/Refactoring.h"
> -#include "clang/Tooling/Tooling.h"
> -
> -using clang::ast_matchers::MatchFinder;
> -using namespace clang::tooling;
> -using namespace clang;
> -namespace cl = llvm::cl;
> -
> -static cl::opt<std::string>
> -UserNullMacroNames("user-null-macros",
> - cl::desc("Comma-separated list of user-defined "
> - "macro names that behave like NULL"),
> - cl::cat(TransformsOptionsCategory), cl::init(""));
> -
> -int UseNullptrTransform::apply(const CompilationDatabase &Database,
> - const std::vector<std::string> &SourcePaths) {
> - ClangTool UseNullptrTool(Database, SourcePaths);
> -
> - unsigned AcceptedChanges = 0;
> -
> - llvm::SmallVector<llvm::StringRef, 1> MacroNames;
> - if (!UserNullMacroNames.empty()) {
> - llvm::StringRef S = UserNullMacroNames;
> - S.split(MacroNames, ",");
> - }
> - MatchFinder Finder;
> - NullptrFixer Fixer(AcceptedChanges, MacroNames, /*Owner=*/ *this);
> -
> - Finder.addMatcher(makeCastSequenceMatcher(), &Fixer);
> - if (int result = UseNullptrTool.run(createActionFactory(Finder).get())) {
> - llvm::errs() << "Error encountered during translation.\n";
> - return result;
> - }
> -
> - setAcceptedChanges(AcceptedChanges);
> -
> - return 0;
> -}
> -
> -namespace {
> -struct UseNullptrFactory : TransformFactory {
> - UseNullptrFactory() {
> - Since.Clang = Version(3, 0);
> - Since.Gcc = Version(4, 6);
> - Since.Icc = Version(12, 1);
> - Since.Msvc = Version(10);
> - }
> -
> - Transform *createTransform(const TransformOptions &Opts) override {
> - return new UseNullptrTransform(Opts);
> - }
> -};
> -} // namespace
> -
> -// Register the factory using this statically initialized variable.
> -static TransformFactoryRegistry::Add<UseNullptrFactory>
> -X("use-nullptr", "Make use of nullptr keyword where possible");
> -
> -// This anchor is used to force the linker to link in the generated object file
> -// and thus register the factory.
> -volatile int UseNullptrTransformAnchorSource = 0;
> Index: clang-modernize/UseNullptr/NullptrMatchers.h
> ===================================================================
> --- clang-modernize/UseNullptr/NullptrMatchers.h
> +++ /dev/null
> @@ -1,31 +0,0 @@
> -//===-- UseNullptr/NullptrMatchers.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 CLANG_MODERNIZE_USE_NULLPTR_MATCHERS_H
> -#define CLANG_MODERNIZE_USE_NULLPTR_MATCHERS_H
> -
> -#include "clang/ASTMatchers/ASTMatchers.h"
> -
> -// Names to bind with matched expressions.
> -extern const char *CastSequence;
> -
> -/// \brief Create a matcher that finds implicit casts as well as the head of a
> -/// sequence of zero or more nested explicit casts that have an implicit cast
> -/// to null within.
> -/// Finding sequences of explict casts is necessary so that an entire sequence
> -/// can be replaced instead of just the inner-most implicit cast.
> -clang::ast_matchers::StatementMatcher makeCastSequenceMatcher();
> -
> -#endif // CLANG_MODERNIZE_USE_NULLPTR_MATCHERS_H
> Index: clang-modernize/UseNullptr/NullptrMatchers.cpp
> ===================================================================
> --- clang-modernize/UseNullptr/NullptrMatchers.cpp
> +++ /dev/null
> @@ -1,70 +0,0 @@
> -//===-- UseNullptr/NullptrMatchers.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 *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;
> -}
> -
> -AST_MATCHER(Type, sugaredNullptrType) {
> - const Type *DesugaredType = Node.getUnqualifiedDesugaredType();
> - if (const BuiltinType *BT = dyn_cast<BuiltinType>(DesugaredType))
> - return BT->getKind() == BuiltinType::NullPtr;
> - return false;
> -}
> -
> -} // end namespace ast_matchers
> -} // end namespace clang
> -
> -StatementMatcher makeCastSequenceMatcher() {
> - StatementMatcher ImplicitCastToNull =
> - implicitCastExpr(
> - isNullToPointer(),
> - unless(
> - hasSourceExpression(
> - hasType(sugaredNullptrType())
> - )
> - )
> - );
> -
> - return castExpr(
> - anyOf(
> - ImplicitCastToNull,
> - explicitCastExpr(
> - hasDescendant(ImplicitCastToNull)
> - )
> - ),
> - unless(hasAncestor(explicitCastExpr()))
> - ).bind(CastSequence);
> -}
> Index: clang-modernize/UseNullptr/NullptrActions.h
> ===================================================================
> --- clang-modernize/UseNullptr/NullptrActions.h
> +++ /dev/null
> @@ -1,43 +0,0 @@
> -//===-- UseNullptr/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 CLANG_MODERNIZE_NULLPTR_ACTIONS_H
> -#define CLANG_MODERNIZE_NULLPTR_ACTIONS_H
> -
> -#include "Core/Transform.h"
> -#include "clang/ASTMatchers/ASTMatchFinder.h"
> -#include "clang/Tooling/Refactoring.h"
> -
> -// The type for user-defined macro names that behave like NULL
> -typedef llvm::SmallVector<llvm::StringRef, 1> UserMacroNames;
> -
> -/// \brief The callback to be used for nullptr migration matchers.
> -///
> -class NullptrFixer : public clang::ast_matchers::MatchFinder::MatchCallback {
> -public:
> - NullptrFixer(unsigned &AcceptedChanges,
> - llvm::ArrayRef<llvm::StringRef> UserMacros, Transform &Owner);
> -
> - /// \brief Entry point to the callback called when matches are made.
> - void
> - run(const clang::ast_matchers::MatchFinder::MatchResult &Result) override;
> -
> -private:
> - unsigned &AcceptedChanges;
> - UserMacroNames UserNullMacros;
> - Transform &Owner;
> -};
> -
> -#endif // CLANG_MODERNIZE_NULLPTR_ACTIONS_H
> Index: clang-modernize/UseNullptr/NullptrActions.cpp
> ===================================================================
> --- clang-modernize/UseNullptr/NullptrActions.cpp
> +++ /dev/null
> @@ -1,441 +0,0 @@
> -//===-- UseNullptr/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"
> -#include "clang/Basic/CharInfo.h"
> -#include "clang/Lex/Lexer.h"
> -
> -using namespace clang::ast_matchers;
> -using namespace clang::tooling;
> -using namespace clang;
> -namespace cl = llvm::cl;
> -
> -namespace {
> -
> -const char *NullMacroName = "NULL";
> -
> -bool isReplaceableRange(SourceLocation StartLoc, SourceLocation EndLoc,
> - const SourceManager &SM, const Transform &Owner) {
> - return SM.isWrittenInSameFile(StartLoc, EndLoc) &&
> - Owner.isFileModifiable(SM, StartLoc);
> -}
> -
> -/// \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.
> -void ReplaceWithNullptr(Transform &Owner, SourceManager &SM,
> - SourceLocation StartLoc, SourceLocation EndLoc) {
> - CharSourceRange Range(SourceRange(StartLoc, EndLoc), true);
> - // Add a space if nullptr follows an alphanumeric character. This happens
> - // whenever there is an c-style explicit cast to nullptr not surrounded by
> - // parentheses and right beside a return statement.
> - SourceLocation PreviousLocation = StartLoc.getLocWithOffset(-1);
> - if (isAlphanumeric(*FullSourceLoc(PreviousLocation, SM).getCharacterData()))
> - Owner.addReplacementForCurrentTU(
> - tooling::Replacement(SM, Range, " nullptr"));
> - else
> - Owner.addReplacementForCurrentTU(
> - tooling::Replacement(SM, Range, "nullptr"));
> -}
> -
> -/// \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 RecursiveASTVisitor for ensuring all nodes rooted at a given AST
> -/// subtree that have file-level source locations corresponding to a macro
> -/// argument have implicit NullTo(Member)Pointer nodes as ancestors.
> -class MacroArgUsageVisitor : public RecursiveASTVisitor<MacroArgUsageVisitor> {
> -public:
> - MacroArgUsageVisitor(SourceLocation CastLoc, const SourceManager &SM)
> - : CastLoc(CastLoc), SM(SM), Visited(false), CastFound(false),
> - InvalidFound(false) {
> - assert(CastLoc.isFileID());
> - }
> -
> - bool TraverseStmt(Stmt *S) {
> - bool VisitedPreviously = Visited;
> -
> - if (!RecursiveASTVisitor<MacroArgUsageVisitor>::TraverseStmt(S))
> - return false;
> -
> - // The point at which VisitedPreviously is false and Visited is true is the
> - // root of a subtree containing nodes whose locations match CastLoc. It's
> - // at this point we test that the Implicit NullTo(Member)Pointer cast was
> - // found or not.
> - if (!VisitedPreviously) {
> - if (Visited && !CastFound) {
> - // Found nodes with matching SourceLocations but didn't come across a
> - // cast. This is an invalid macro arg use. Can stop traversal
> - // completely now.
> - InvalidFound = true;
> - return false;
> - }
> - // Reset state as we unwind back up the tree.
> - CastFound = false;
> - Visited = false;
> - }
> - return true;
> - }
> -
> - bool VisitStmt(Stmt *S) {
> - if (SM.getFileLoc(S->getLocStart()) != CastLoc)
> - return true;
> - Visited = true;
> -
> - const ImplicitCastExpr *Cast = dyn_cast<ImplicitCastExpr>(S);
> - if (Cast && (Cast->getCastKind() == CK_NullToPointer ||
> - Cast->getCastKind() == CK_NullToMemberPointer))
> - CastFound = true;
> -
> - return true;
> - }
> -
> - bool foundInvalid() const { return InvalidFound; }
> -
> -private:
> - SourceLocation CastLoc;
> - const SourceManager &SM;
> -
> - bool Visited;
> - bool CastFound;
> - bool InvalidFound;
> -};
> -
> -/// \brief Looks for implicit casts as well as 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 single implicit cast or 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
> -/// leaving the outermost explicit cast unchanged to avoid introducing
> -/// ambiguities.
> -class CastSequenceVisitor : public RecursiveASTVisitor<CastSequenceVisitor> {
> -public:
> - CastSequenceVisitor(ASTContext &Context, const UserMacroNames &UserNullMacros,
> - unsigned &AcceptedChanges, Transform &Owner)
> - : SM(Context.getSourceManager()), Context(Context),
> - UserNullMacros(UserNullMacros), AcceptedChanges(AcceptedChanges),
> - Owner(Owner), FirstSubExpr(nullptr), PruneSubtree(false) {}
> -
> - bool TraverseStmt(Stmt *S) {
> - // Stop traversing down the tree if requested.
> - if (PruneSubtree) {
> - PruneSubtree = false;
> - return true;
> - }
> - return RecursiveASTVisitor<CastSequenceVisitor>::TraverseStmt(S);
> - }
> -
> - // 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) {
> - FirstSubExpr = nullptr;
> - return true;
> - } else if (!FirstSubExpr) {
> - FirstSubExpr = C->getSubExpr()->IgnoreParens();
> - }
> -
> - if (C->getCastKind() == CK_NullToPointer ||
> - C->getCastKind() == CK_NullToMemberPointer) {
> -
> - SourceLocation StartLoc = FirstSubExpr->getLocStart();
> - SourceLocation EndLoc = FirstSubExpr->getLocEnd();
> -
> - // If the location comes from a macro arg expansion, *all* uses of that
> - // arg must be checked to result in NullTo(Member)Pointer casts.
> - //
> - // If the location comes from a macro body expansion, check to see if its
> - // coming from one of the allowed 'NULL' macros.
> - if (SM.isMacroArgExpansion(StartLoc) && SM.isMacroArgExpansion(EndLoc)) {
> - SourceLocation FileLocStart = SM.getFileLoc(StartLoc),
> - FileLocEnd = SM.getFileLoc(EndLoc);
> - if (isReplaceableRange(FileLocStart, FileLocEnd, SM, Owner) &&
> - allArgUsesValid(C)) {
> - ReplaceWithNullptr(Owner, SM, FileLocStart, FileLocEnd);
> - ++AcceptedChanges;
> - }
> - return skipSubTree();
> - }
> -
> - if (SM.isMacroBodyExpansion(StartLoc) &&
> - SM.isMacroBodyExpansion(EndLoc)) {
> - llvm::StringRef OutermostMacroName =
> - GetOutermostMacroName(StartLoc, SM, Context.getLangOpts());
> -
> - // Check to see if the user wants to replace the macro being expanded.
> - if (std::find(UserNullMacros.begin(), UserNullMacros.end(),
> - OutermostMacroName) == UserNullMacros.end()) {
> - return skipSubTree();
> - }
> -
> - StartLoc = SM.getFileLoc(StartLoc);
> - EndLoc = SM.getFileLoc(EndLoc);
> - }
> -
> - if (!isReplaceableRange(StartLoc, EndLoc, SM, Owner)) {
> - return skipSubTree();
> - }
> - ReplaceWithNullptr(Owner, SM, StartLoc, EndLoc);
> - ++AcceptedChanges;
> -
> - return skipSubTree();
> - } // If NullTo(Member)Pointer cast.
> -
> - return true;
> - }
> -
> -private:
> - bool skipSubTree() { PruneSubtree = true; return true; }
> -
> - /// \brief Tests that all expansions of a macro arg, one of which expands to
> - /// result in \p CE, yield NullTo(Member)Pointer casts.
> - bool allArgUsesValid(const CastExpr *CE) {
> - SourceLocation CastLoc = CE->getLocStart();
> -
> - // Step 1: Get location of macro arg and location of the macro the arg was
> - // provided to.
> - SourceLocation ArgLoc, MacroLoc;
> - if (!getMacroAndArgLocations(CastLoc, ArgLoc, MacroLoc))
> - return false;
> -
> - // Step 2: Find the first ancestor that doesn't expand from this macro.
> - ast_type_traits::DynTypedNode ContainingAncestor;
> - if (!findContainingAncestor(
> - ast_type_traits::DynTypedNode::create<Stmt>(*CE), MacroLoc,
> - ContainingAncestor))
> - return false;
> -
> - // Step 3:
> - // Visit children of this containing parent looking for the least-descended
> - // nodes of the containing parent which are macro arg expansions that expand
> - // from the given arg location.
> - // Visitor needs: arg loc
> - MacroArgUsageVisitor ArgUsageVisitor(SM.getFileLoc(CastLoc), SM);
> - if (const Decl *D = ContainingAncestor.get<Decl>())
> - ArgUsageVisitor.TraverseDecl(const_cast<Decl *>(D));
> - else if (const Stmt *S = ContainingAncestor.get<Stmt>())
> - ArgUsageVisitor.TraverseStmt(const_cast<Stmt *>(S));
> - else
> - llvm_unreachable("Unhandled ContainingAncestor node type");
> -
> - if (ArgUsageVisitor.foundInvalid())
> - return false;
> -
> - return true;
> - }
> -
> - /// \brief Given the SourceLocation for a macro arg expansion, finds the
> - /// non-macro SourceLocation of the macro the arg was passed to and the
> - /// non-macro SourceLocation of the argument in the arg list to that macro.
> - /// These results are returned via \c MacroLoc and \c ArgLoc respectively.
> - /// These values are undefined if the return value is false.
> - ///
> - /// \returns false if one of the returned SourceLocations would be a
> - /// SourceLocation pointing within the definition of another macro.
> - bool getMacroAndArgLocations(SourceLocation Loc, SourceLocation &ArgLoc,
> - SourceLocation &MacroLoc) {
> - assert(Loc.isMacroID() && "Only reasonble to call this on macros");
> -
> - ArgLoc = Loc;
> -
> - // Find the location of the immediate macro expansion.
> - while (1) {
> - std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(ArgLoc);
> - const SrcMgr::SLocEntry *E = &SM.getSLocEntry(LocInfo.first);
> - const SrcMgr::ExpansionInfo &Expansion = E->getExpansion();
> -
> - SourceLocation OldArgLoc = ArgLoc;
> - ArgLoc = Expansion.getExpansionLocStart();
> - if (!Expansion.isMacroArgExpansion()) {
> - if (!MacroLoc.isFileID())
> - return false;
> -
> - StringRef Name =
> - Lexer::getImmediateMacroName(OldArgLoc, SM, Context.getLangOpts());
> - return std::find(UserNullMacros.begin(), UserNullMacros.end(), Name) !=
> - UserNullMacros.end();
> - }
> -
> - MacroLoc = SM.getImmediateExpansionRange(ArgLoc).first;
> -
> - ArgLoc = Expansion.getSpellingLoc().getLocWithOffset(LocInfo.second);
> - if (ArgLoc.isFileID())
> - return true;
> -
> - // If spelling location resides in the same FileID as macro expansion
> - // location, it means there is no inner macro.
> - FileID MacroFID = SM.getFileID(MacroLoc);
> - if (SM.isInFileID(ArgLoc, MacroFID))
> - // Don't transform this case. If the characters that caused the
> - // null-conversion come from within a macro, they can't be changed.
> - return false;
> - }
> -
> - llvm_unreachable("getMacroAndArgLocations");
> - }
> -
> - /// \brief Tests if TestMacroLoc is found while recursively unravelling
> - /// expansions starting at TestLoc. TestMacroLoc.isFileID() must be true.
> - /// Implementation is very similar to getMacroAndArgLocations() except in this
> - /// case, it's not assumed that TestLoc is expanded from a macro argument.
> - /// While unravelling expansions macro arguments are handled as with
> - /// getMacroAndArgLocations() but in this function macro body expansions are
> - /// also handled.
> - ///
> - /// False means either:
> - /// - TestLoc is not from a macro expansion
> - /// - TestLoc is from a different macro expansion
> - bool expandsFrom(SourceLocation TestLoc, SourceLocation TestMacroLoc) {
> - if (TestLoc.isFileID()) {
> - return false;
> - }
> -
> - SourceLocation Loc = TestLoc, MacroLoc;
> -
> - while (1) {
> - std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc);
> - const SrcMgr::SLocEntry *E = &SM.getSLocEntry(LocInfo.first);
> - const SrcMgr::ExpansionInfo &Expansion = E->getExpansion();
> -
> - Loc = Expansion.getExpansionLocStart();
> -
> - if (!Expansion.isMacroArgExpansion()) {
> - if (Loc.isFileID()) {
> - if (Loc == TestMacroLoc)
> - // Match made.
> - return true;
> - return false;
> - }
> - // Since Loc is still a macro ID and it's not an argument expansion, we
> - // don't need to do the work of handling an argument expansion. Simply
> - // keep recursively expanding until we hit a FileID or a macro arg
> - // expansion or a macro arg expansion.
> - continue;
> - }
> -
> - MacroLoc = SM.getImmediateExpansionRange(Loc).first;
> - if (MacroLoc.isFileID() && MacroLoc == TestMacroLoc)
> - // Match made.
> - return true;
> -
> - Loc = Expansion.getSpellingLoc();
> - Loc = Expansion.getSpellingLoc().getLocWithOffset(LocInfo.second);
> - if (Loc.isFileID())
> - // If we made it this far without finding a match, there is no match to
> - // be made.
> - return false;
> - }
> -
> - llvm_unreachable("expandsFrom");
> - }
> -
> - /// \brief Given a starting point \c Start in the AST, find an ancestor that
> - /// doesn't expand from the macro called at file location \c MacroLoc.
> - ///
> - /// \pre MacroLoc.isFileID()
> - /// \returns true if such an ancestor was found, false otherwise.
> - bool findContainingAncestor(ast_type_traits::DynTypedNode Start,
> - SourceLocation MacroLoc,
> - ast_type_traits::DynTypedNode &Result) {
> - // Below we're only following the first parent back up the AST. This should
> - // be fine since for the statements we care about there should only be one
> - // parent as far up as we care. If this assumption doesn't hold, need to
> - // revisit what to do here.
> -
> - assert(MacroLoc.isFileID());
> -
> - do {
> - const auto &Parents = Context.getParents(Start);
> - if (Parents.empty())
> - return false;
> - assert(Parents.size() == 1 &&
> - "Found an ancestor with more than one parent!");
> -
> - const ast_type_traits::DynTypedNode &Parent = Parents[0];
> -
> - SourceLocation Loc;
> - if (const Decl *D = Parent.get<Decl>())
> - Loc = D->getLocStart();
> - else if (const Stmt *S = Parent.get<Stmt>())
> - Loc = S->getLocStart();
> - else
> - llvm_unreachable("Expected to find Decl or Stmt containing ancestor");
> -
> - if (!expandsFrom(Loc, MacroLoc)) {
> - Result = Parent;
> - return true;
> - }
> - Start = Parent;
> - } while (1);
> -
> - llvm_unreachable("findContainingAncestor");
> - }
> -
> -private:
> - SourceManager &SM;
> - ASTContext &Context;
> - const UserMacroNames &UserNullMacros;
> - unsigned &AcceptedChanges;
> - Transform &Owner;
> - Expr *FirstSubExpr;
> - bool PruneSubtree;
> -};
> -} // namespace
> -
> -NullptrFixer::NullptrFixer(unsigned &AcceptedChanges,
> - llvm::ArrayRef<llvm::StringRef> UserMacros,
> - Transform &Owner)
> - : AcceptedChanges(AcceptedChanges), Owner(Owner) {
> - UserNullMacros.insert(UserNullMacros.begin(), UserMacros.begin(),
> - UserMacros.end());
> - UserNullMacros.insert(UserNullMacros.begin(), llvm::StringRef(NullMacroName));
> -}
> -
> -void NullptrFixer::run(const ast_matchers::MatchFinder::MatchResult &Result) {
> - const CastExpr *NullCast = Result.Nodes.getNodeAs<CastExpr>(CastSequence);
> - assert(NullCast && "Bad Callback. No node provided");
> - // Given an implicit null-ptr cast or 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(*Result.Context, UserNullMacros, AcceptedChanges,
> - Owner);
> - Visitor.TraverseStmt(const_cast<CastExpr *>(NullCast));
> -}
> Index: clang-modernize/UseAuto/UseAutoMatchers.h
> ===================================================================
> --- clang-modernize/UseAuto/UseAutoMatchers.h
> +++ /dev/null
> @@ -1,34 +0,0 @@
> -//===-- UseAutoMatchers.h - Matchers for use-auto transform -----*- 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 CLANG_MODERNIZE_USE_AUTO_MATCHERS_H
> -#define CLANG_MODERNIZE_USE_AUTO_MATCHERS_H
> -
> -#include "clang/ASTMatchers/ASTMatchers.h"
> -
> -extern const char *IteratorDeclStmtId;
> -extern const char *DeclWithNewId;
> -extern const char *NewExprId;
> -
> -/// \brief Create a matcher that matches declaration staments that have
> -/// variable declarations where the type is an iterator for an std container
> -/// and has an explicit initializer of the same type.
> -clang::ast_matchers::StatementMatcher makeIteratorDeclMatcher();
> -
> -/// \brief Create a matcher that matches variable declarations that are
> -/// initialized by a C++ new expression.
> -clang::ast_matchers::StatementMatcher makeDeclWithNewMatcher();
> -
> -#endif // CLANG_MODERNIZE_USE_AUTO_MATCHERS_H
> Index: clang-modernize/UseAuto/UseAutoMatchers.cpp
> ===================================================================
> --- clang-modernize/UseAuto/UseAutoMatchers.cpp
> +++ /dev/null
> @@ -1,280 +0,0 @@
> -//===-- UseAutoMatchers.cpp - Matchers for use-auto transform -------------===//
> -//
> -// 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 implementation for matcher-generating
> -/// functions and custom AST_MATCHERs.
> -///
> -//===----------------------------------------------------------------------===//
> -
> -#include "UseAutoMatchers.h"
> -#include "Core/CustomMatchers.h"
> -#include "clang/AST/ASTContext.h"
> -
> -using namespace clang::ast_matchers;
> -using namespace clang;
> -
> -const char *IteratorDeclStmtId = "iterator_decl";
> -const char *DeclWithNewId = "decl_new";
> -const char *NewExprId = "new_expr";
> -
> -namespace clang {
> -namespace ast_matchers {
> -
> -/// \brief Matches variable declarations that have explicit initializers that
> -/// are not initializer lists.
> -///
> -/// Given
> -/// \code
> -/// iterator I = Container.begin();
> -/// MyType A(42);
> -/// MyType B{2};
> -/// MyType C;
> -/// \endcode
> -/// varDecl(hasWrittenNonListInitializer()) matches \c I and \c A but not \c B
> -/// or \c C.
> -AST_MATCHER(VarDecl, hasWrittenNonListInitializer) {
> - const Expr *Init = Node.getAnyInitializer();
> - if (!Init)
> - return false;
> -
> - // The following test is based on DeclPrinter::VisitVarDecl() to find if an
> - // initializer is implicit or not.
> - bool ImplicitInit = false;
> - if (const CXXConstructExpr *Construct = dyn_cast<CXXConstructExpr>(Init)) {
> - if (Construct->isListInitialization())
> - return false;
> - ImplicitInit = Construct->getNumArgs() == 0 ||
> - Construct->getArg(0)->isDefaultArgument();
> - } else
> - if (Node.getInitStyle() == VarDecl::ListInit)
> - return false;
> -
> - return !ImplicitInit;
> -}
> -
> -/// \brief Matches QualTypes that are type sugar for QualTypes that match \c
> -/// SugarMatcher.
> -///
> -/// Given
> -/// \code
> -/// class C {};
> -/// typedef C my_type
> -/// typedef my_type my_other_type;
> -/// \endcode
> -///
> -/// \c qualType(isSugarFor(recordType(hasDeclaration(namedDecl(hasName("C"))))))
> -/// matches \c my_type and \c my_other_type.
> -AST_MATCHER_P(QualType, isSugarFor, internal::Matcher<QualType>, SugarMatcher) {
> - QualType QT = Node;
> - for (;;) {
> - if (SugarMatcher.matches(QT, Finder, Builder))
> - return true;
> -
> - QualType NewQT = QT.getSingleStepDesugaredType(Finder->getASTContext());
> - if (NewQT == QT)
> - break;
> - QT = NewQT;
> - }
> - return false;
> -}
> -
> -/// \brief Matches named declarations that have one of the standard iterator
> -/// names: iterator, reverse_iterator, const_iterator, const_reverse_iterator.
> -///
> -/// Given
> -/// \code
> -/// iterator I;
> -/// const_iterator CI;
> -/// \endcode
> -///
> -/// \c namedDecl(hasStdIteratorName()) matches \c I and \c CI.
> -AST_MATCHER(NamedDecl, hasStdIteratorName) {
> - static const char *const IteratorNames[] = {
> - "iterator",
> - "reverse_iterator",
> - "const_iterator",
> - "const_reverse_iterator"
> - };
> -
> - for (unsigned int i = 0;
> - i < llvm::array_lengthof(IteratorNames);
> - ++i) {
> - if (hasName(IteratorNames[i]).matches(Node, Finder, Builder))
> - return true;
> - }
> - return false;
> -}
> -
> -/// \brief Matches named declarations that have one of the standard container
> -/// names.
> -///
> -/// Given
> -/// \code
> -/// class vector {};
> -/// class forward_list {};
> -/// class my_vec {};
> -/// \endcode
> -///
> -/// \c recordDecl(hasStdContainerName()) matches \c vector and \c forward_list
> -/// but not \c my_vec.
> -AST_MATCHER(NamedDecl, hasStdContainerName) {
> - static const char *const ContainerNames[] = {
> - "array",
> - "deque",
> - "forward_list",
> - "list",
> - "vector",
> -
> - "map",
> - "multimap",
> - "set",
> - "multiset",
> -
> - "unordered_map",
> - "unordered_multimap",
> - "unordered_set",
> - "unordered_multiset",
> -
> - "queue",
> - "priority_queue",
> - "stack"
> - };
> -
> - for (unsigned int i = 0; i < llvm::array_lengthof(ContainerNames); ++i) {
> - if (hasName(ContainerNames[i]).matches(Node, Finder, Builder))
> - return true;
> - }
> - return false;
> -}
> -
> -} // namespace ast_matchers
> -} // namespace clang
> -
> -namespace {
> -// \brief Returns a TypeMatcher that matches typedefs for standard iterators
> -// inside records with a standard container name.
> -TypeMatcher typedefIterator() {
> - return typedefType(
> - hasDeclaration(
> - allOf(
> - namedDecl(hasStdIteratorName()),
> - hasDeclContext(
> - recordDecl(hasStdContainerName(), isFromStdNamespace())
> - )
> - )
> - )
> - );
> -}
> -
> -// \brief Returns a TypeMatcher that matches records named for standard
> -// iterators nested inside records named for standard containers.
> -TypeMatcher nestedIterator() {
> - return recordType(
> - hasDeclaration(
> - allOf(
> - namedDecl(hasStdIteratorName()),
> - hasDeclContext(
> - recordDecl(hasStdContainerName(), isFromStdNamespace())
> - )
> - )
> - )
> - );
> -}
> -
> -// \brief Returns a TypeMatcher that matches types declared with using
> -// declarations and which name standard iterators for standard containers.
> -TypeMatcher iteratorFromUsingDeclaration() {
> - // Types resulting from using declarations are
> - // represented by ElaboratedType.
> - return elaboratedType(
> - allOf(
> - // Unwrap the nested name specifier to test for
> - // one of the standard containers.
> - hasQualifier(
> - specifiesType(
> - templateSpecializationType(
> - hasDeclaration(
> - namedDecl(hasStdContainerName(), isFromStdNamespace())
> - )
> - )
> - )
> - ),
> - // The named type is what comes after the final
> - // '::' in the type. It should name one of the
> - // standard iterator names.
> - namesType(anyOf(
> - typedefType(
> - hasDeclaration(
> - namedDecl(hasStdIteratorName())
> - )
> - ),
> - recordType(
> - hasDeclaration(
> - namedDecl(hasStdIteratorName())
> - )
> - )
> - ))
> - )
> - );
> -}
> -} // namespace
> -
> -// \brief This matcher returns delaration statements that contain variable
> -// declarations with written non-list initializer for standard iterators.
> -StatementMatcher makeIteratorDeclMatcher() {
> - return declStmt(
> - // At least one varDecl should be a child of the declStmt to ensure it's a
> - // declaration list and avoid matching other declarations
> - // e.g. using directives.
> - has(varDecl()),
> - unless(has(varDecl(
> - anyOf(
> - unless(hasWrittenNonListInitializer()),
> - hasType(autoType()),
> - unless(hasType(
> - isSugarFor(
> - anyOf(
> - typedefIterator(),
> - nestedIterator(),
> - iteratorFromUsingDeclaration()
> - )
> - )
> - ))
> - )
> - )))
> - ).bind(IteratorDeclStmtId);
> -}
> -
> -StatementMatcher makeDeclWithNewMatcher() {
> - return declStmt(
> - has(varDecl()),
> - unless(has(varDecl(
> - anyOf(
> - unless(hasInitializer(
> - ignoringParenImpCasts(cxxNewExpr())
> - )),
> - // FIXME: TypeLoc information is not reliable where CV qualifiers are
> - // concerned so these types can't be handled for now.
> - hasType(pointerType(pointee(hasCanonicalType(hasLocalQualifiers())))),
> -
> - // FIXME: Handle function pointers. For now we ignore them because
> - // the replacement replaces the entire type specifier source range
> - // which includes the identifier.
> - hasType(
> - pointsTo(
> - pointsTo(
> - parenType(innerType(functionType()))
> - )
> - )
> - )
> - )
> - )))
> - ).bind(DeclWithNewId);
> -}
> Index: clang-modernize/UseAuto/UseAutoActions.h
> ===================================================================
> --- clang-modernize/UseAuto/UseAutoActions.h
> +++ /dev/null
> @@ -1,56 +0,0 @@
> -//===-- UseAuto/Actions.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 declarations for callbacks used by the
> -/// UseAuto transform.
> -///
> -//===----------------------------------------------------------------------===//
> -
> -#ifndef CLANG_MODERNIZE_USE_AUTO_ACTIONS_H
> -#define CLANG_MODERNIZE_USE_AUTO_ACTIONS_H
> -
> -#include "Core/Transform.h"
> -#include "clang/ASTMatchers/ASTMatchFinder.h"
> -#include "clang/Tooling/Refactoring.h"
> -
> -/// \brief The callback to be used when replacing type specifiers of variable
> -/// declarations that are iterators.
> -class IteratorReplacer
> - : public clang::ast_matchers::MatchFinder::MatchCallback {
> -public:
> - IteratorReplacer(unsigned &AcceptedChanges, RiskLevel, Transform &Owner)
> - : AcceptedChanges(AcceptedChanges), Owner(Owner) {}
> -
> - /// \brief Entry point to the callback called when matches are made.
> - void
> - run(const clang::ast_matchers::MatchFinder::MatchResult &Result) override;
> -
> -private:
> - unsigned &AcceptedChanges;
> - Transform &Owner;
> -};
> -
> -/// \brief The callback used when replacing type specifiers of variable
> -/// declarations initialized by a C++ new expression.
> -class NewReplacer : public clang::ast_matchers::MatchFinder::MatchCallback {
> -public:
> - NewReplacer(unsigned &AcceptedChanges, RiskLevel, Transform &Owner)
> - : AcceptedChanges(AcceptedChanges), Owner(Owner) {}
> -
> - /// \brief Entry point to the callback called when matches are made.
> - void
> - run(const clang::ast_matchers::MatchFinder::MatchResult &Result) override;
> -
> -private:
> - unsigned &AcceptedChanges;
> - Transform &Owner;
> -};
> -
> -#endif // CLANG_MODERNIZE_USE_AUTO_ACTIONS_H
> Index: clang-modernize/UseAuto/UseAutoActions.cpp
> ===================================================================
> --- clang-modernize/UseAuto/UseAutoActions.cpp
> +++ /dev/null
> @@ -1,147 +0,0 @@
> -//===-- UseAuto/UseAutoActions.cpp - Matcher callback impl ----------------===//
> -//
> -// 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 implementation of callbacks for the UseAuto
> -/// transform.
> -///
> -//===----------------------------------------------------------------------===//
> -
> -#include "UseAutoActions.h"
> -#include "UseAutoMatchers.h"
> -#include "clang/AST/ASTContext.h"
> -
> -using namespace clang::ast_matchers;
> -using namespace clang::tooling;
> -using namespace clang;
> -
> -void IteratorReplacer::run(const MatchFinder::MatchResult &Result) {
> - const DeclStmt *D = Result.Nodes.getNodeAs<DeclStmt>(IteratorDeclStmtId);
> - assert(D && "Bad Callback. No node provided");
> -
> - SourceManager &SM = *Result.SourceManager;
> - if (!Owner.isFileModifiable(SM, D->getLocStart()))
> - return;
> -
> - for (clang::DeclStmt::const_decl_iterator DI = D->decl_begin(),
> - DE = D->decl_end();
> - DI != DE; ++DI) {
> - const VarDecl *V = cast<VarDecl>(*DI);
> -
> - const Expr *ExprInit = V->getInit();
> -
> - // Skip expressions with cleanups from the initializer expression.
> - if (const ExprWithCleanups *E = dyn_cast<ExprWithCleanups>(ExprInit))
> - ExprInit = E->getSubExpr();
> -
> - const CXXConstructExpr *Construct = cast<CXXConstructExpr>(ExprInit);
> -
> - assert(Construct->getNumArgs() == 1u &&
> - "Expected constructor with single argument");
> -
> - // Drill down to the as-written initializer.
> - const Expr *E = (*Construct->arg_begin())->IgnoreParenImpCasts();
> - if (E != E->IgnoreConversionOperator())
> - // We hit a conversion operator. Early-out now as they imply an implicit
> - // conversion from a different type. Could also mean an explicit
> - // conversion from the same type but that's pretty rare.
> - return;
> -
> - if (const CXXConstructExpr *NestedConstruct = dyn_cast<CXXConstructExpr>(E))
> - // If we ran into an implicit conversion constructor, can't convert.
> - //
> - // FIXME: The following only checks if the constructor can be used
> - // implicitly, not if it actually was. Cases where the converting
> - // constructor was used explicitly won't get converted.
> - if (NestedConstruct->getConstructor()->isConvertingConstructor(false))
> - return;
> - if (!Result.Context->hasSameType(V->getType(), E->getType()))
> - return;
> - }
> - // Get the type location using the first declartion.
> - const VarDecl *V = cast<VarDecl>(*D->decl_begin());
> - TypeLoc TL = V->getTypeSourceInfo()->getTypeLoc();
> -
> - // WARNING: TypeLoc::getSourceRange() will include the identifier for things
> - // like function pointers. Not a concern since this action only works with
> - // iterators but something to keep in mind in the future.
> -
> - CharSourceRange Range(TL.getSourceRange(), true);
> - Owner.addReplacementForCurrentTU(tooling::Replacement(SM, Range, "auto"));
> - ++AcceptedChanges;
> -}
> -
> -void NewReplacer::run(const MatchFinder::MatchResult &Result) {
> - const DeclStmt *D = Result.Nodes.getNodeAs<DeclStmt>(DeclWithNewId);
> - assert(D && "Bad Callback. No node provided");
> -
> - SourceManager &SM = *Result.SourceManager;
> - if (!Owner.isFileModifiable(SM, D->getLocStart()))
> - return;
> -
> - const VarDecl *FirstDecl = cast<VarDecl>(*D->decl_begin());
> - // Ensure that there is at least one VarDecl within de DeclStmt.
> - assert(FirstDecl && "No VarDecl provided");
> -
> - const QualType FirstDeclType = FirstDecl->getType().getCanonicalType();
> -
> - std::vector<SourceLocation> StarLocations;
> - for (clang::DeclStmt::const_decl_iterator DI = D->decl_begin(),
> - DE = D->decl_end();
> - DI != DE; ++DI) {
> -
> - const VarDecl *V = cast<VarDecl>(*DI);
> - // Ensure that every DeclStmt child is a VarDecl.
> - assert(V && "No VarDecl provided");
> -
> - const CXXNewExpr *NewExpr =
> - cast<CXXNewExpr>(V->getInit()->IgnoreParenImpCasts());
> - // Ensure that every VarDecl has a CXXNewExpr initializer.
> - assert(NewExpr && "No CXXNewExpr provided");
> -
> - // If VarDecl and Initializer have mismatching unqualified types.
> - if (!Result.Context->hasSameUnqualifiedType(V->getType(),
> - NewExpr->getType()))
> - return;
> -
> - // Remove explicitly written '*' from declarations where there's more than
> - // one declaration in the declaration list.
> - if (DI == D->decl_begin())
> - continue;
> -
> - // All subsequent delcarations should match the same non-decorated type.
> - if (FirstDeclType != V->getType().getCanonicalType())
> - return;
> -
> - PointerTypeLoc Q =
> - V->getTypeSourceInfo()->getTypeLoc().getAs<PointerTypeLoc>();
> - while (!Q.isNull()) {
> - StarLocations.push_back(Q.getStarLoc());
> - Q = Q.getNextTypeLoc().getAs<PointerTypeLoc>();
> - }
> - }
> -
> - // Remove '*' from declarations using the saved star locations.
> - for (std::vector<SourceLocation>::iterator I = StarLocations.begin(),
> - E = StarLocations.end();
> - I != E; ++I) {
> - Owner.addReplacementForCurrentTU(tooling::Replacement(SM, *I, 1, ""));
> - }
> -
> - // FIXME: There is, however, one case we can address: when the VarDecl
> - // pointee is the same as the initializer, just more CV-qualified. However,
> - // TypeLoc information is not reliable where CV qualifiers are concerned so
> - // we can't do anything about this case for now.
> - CharSourceRange Range(
> - FirstDecl->getTypeSourceInfo()->getTypeLoc().getSourceRange(), true);
> - // Space after 'auto' to handle cases where the '*' in the pointer type
> - // is next to the identifier. This avoids changing 'int *p' into 'autop'.
> - Owner.addReplacementForCurrentTU(tooling::Replacement(SM, Range, "auto "));
> - ++AcceptedChanges;
> -}
> Index: clang-modernize/UseAuto/UseAuto.h
> ===================================================================
> --- clang-modernize/UseAuto/UseAuto.h
> +++ /dev/null
> @@ -1,41 +0,0 @@
> -//===-- UseAuto/UseAuto.h - Use auto type specifier -------------*- 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 UseAutoTransform class
> -/// which is the main interface to the use-auto transform that replaces
> -/// type specifiers with the special C++11 'auto' type specifier in certain
> -/// situations.
> -///
> -//===----------------------------------------------------------------------===//
> -
> -#ifndef CLANG_MODERNIZE_USE_AUTO_H
> -#define CLANG_MODERNIZE_USE_AUTO_H
> -
> -#include "Core/Transform.h"
> -#include "llvm/Support/Compiler.h"
> -
> -/// \brief Subclass of Transform that transforms type specifiers for variable
> -/// declarations into the special C++11 'auto' type specifier for certain cases:
> -/// * Iterators of std containers.
> -/// * More to come...
> -///
> -/// Other uses of the auto type specifier as outlined in C++11 [dcl.spec.auto]
> -/// p2 are not handled by this transform.
> -class UseAutoTransform : public Transform {
> -public:
> - UseAutoTransform(const TransformOptions &Options)
> - : Transform("UseAuto", Options) {}
> -
> - /// \see Transform::run().
> - int apply(const clang::tooling::CompilationDatabase &Database,
> - const std::vector<std::string> &SourcePaths) override;
> -};
> -
> -#endif // CLANG_MODERNIZE_USE_AUTO_H
> Index: clang-modernize/UseAuto/UseAuto.cpp
> ===================================================================
> --- clang-modernize/UseAuto/UseAuto.cpp
> +++ /dev/null
> @@ -1,70 +0,0 @@
> -//===-- UseAuto/UseAuto.cpp - Use auto type specifier ---------------------===//
> -//
> -// 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 UseAutoTransform class.
> -///
> -//===----------------------------------------------------------------------===//
> -
> -#include "UseAuto.h"
> -#include "UseAutoActions.h"
> -#include "UseAutoMatchers.h"
> -
> -using clang::ast_matchers::MatchFinder;
> -using namespace clang;
> -using namespace clang::tooling;
> -
> -int UseAutoTransform::apply(const clang::tooling::CompilationDatabase &Database,
> - const std::vector<std::string> &SourcePaths) {
> - ClangTool UseAutoTool(Database, SourcePaths);
> -
> - unsigned AcceptedChanges = 0;
> -
> - MatchFinder Finder;
> - ReplacementsVec Replaces;
> - IteratorReplacer ReplaceIterators(AcceptedChanges, Options().MaxRiskLevel,
> - /*Owner=*/ *this);
> - NewReplacer ReplaceNew(AcceptedChanges, Options().MaxRiskLevel,
> - /*Owner=*/ *this);
> -
> - Finder.addMatcher(makeIteratorDeclMatcher(), &ReplaceIterators);
> - Finder.addMatcher(makeDeclWithNewMatcher(), &ReplaceNew);
> -
> - if (int Result = UseAutoTool.run(createActionFactory(Finder).get())) {
> - llvm::errs() << "Error encountered during translation.\n";
> - return Result;
> - }
> -
> - setAcceptedChanges(AcceptedChanges);
> -
> - return 0;
> -}
> -
> -namespace {
> -struct UseAutoFactory : TransformFactory {
> - UseAutoFactory() {
> - Since.Clang = Version(2, 9);
> - Since.Gcc = Version(4, 4);
> - Since.Icc = Version(12);
> - Since.Msvc = Version(10);
> - }
> -
> - Transform *createTransform(const TransformOptions &Opts) override {
> - return new UseAutoTransform(Opts);
> - }
> -};
> -} // namespace
> -
> -// Register the factory using this statically initialized variable.
> -static TransformFactoryRegistry::Add<UseAutoFactory>
> -X("use-auto", "Use of 'auto' type specifier");
> -
> -// This anchor is used to force the linker to link in the generated object file
> -// and thus register the factory.
> -volatile int UseAutoTransformAnchorSource = 0;
> Index: clang-modernize/ReplaceAutoPtr/ReplaceAutoPtrMatchers.h
> ===================================================================
> --- clang-modernize/ReplaceAutoPtr/ReplaceAutoPtrMatchers.h
> +++ /dev/null
> @@ -1,64 +0,0 @@
> -//===-- ReplaceAutoPtrMatchers.h ---- std::auto_ptr replacement -*- 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 CLANG_MODERNIZE_REPLACE_AUTO_PTR_MATCHERS_H
> -#define CLANG_MODERNIZE_REPLACE_AUTO_PTR_MATCHERS_H
> -
> -#include "clang/ASTMatchers/ASTMatchers.h"
> -
> -/// Names to bind with matched expressions.
> -extern const char *AutoPtrTokenId;
> -extern const char *AutoPtrOwnershipTransferId;
> -
> -/// \brief Creates a matcher that finds the locations of types referring to the
> -/// \c std::auto_ptr() type.
> -///
> -/// \code
> -/// std::auto_ptr<int> a;
> -/// ^~~~~~~~~~~~~
> -///
> -/// typedef std::auto_ptr<int> int_ptr_t;
> -/// ^~~~~~~~~~~~~
> -///
> -/// std::auto_ptr<int> fn(std::auto_ptr<int>);
> -/// ^~~~~~~~~~~~~ ^~~~~~~~~~~~~
> -///
> -/// <etc...>
> -/// \endcode
> -clang::ast_matchers::TypeLocMatcher makeAutoPtrTypeLocMatcher();
> -
> -/// \brief Creates a matcher that finds the using declarations referring to
> -/// \c std::auto_ptr.
> -///
> -/// \code
> -/// using std::auto_ptr;
> -/// ^~~~~~~~~~~~~~~~~~~
> -/// \endcode
> -clang::ast_matchers::DeclarationMatcher makeAutoPtrUsingDeclMatcher();
> -
> -/// \brief Creates a matcher that finds the \c std::auto_ptr copy-ctor and
> -/// assign-operator expressions.
> -///
> -/// \c AutoPtrOwnershipTransferId is assigned to the argument of the expression,
> -/// this is the part that has to be wrapped by \c std::move().
> -///
> -/// \code
> -/// std::auto_ptr<int> i, j;
> -/// i = j;
> -/// ~~~~^
> -/// \endcode
> -clang::ast_matchers::StatementMatcher makeTransferOwnershipExprMatcher();
> -
> -#endif // CLANG_MODERNIZE_REPLACE_AUTO_PTR_MATCHERS_H
> Index: clang-modernize/ReplaceAutoPtr/ReplaceAutoPtrMatchers.cpp
> ===================================================================
> --- clang-modernize/ReplaceAutoPtr/ReplaceAutoPtrMatchers.cpp
> +++ /dev/null
> @@ -1,81 +0,0 @@
> -//===-- ReplaceAutoPtrMatchers.cpp -- std::auto_ptr replacement -----------===//
> -//
> -// 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 names for bound nodes found by AST matchers.
> -///
> -//===----------------------------------------------------------------------===//
> -
> -#include "ReplaceAutoPtrMatchers.h"
> -#include "Core/CustomMatchers.h"
> -
> -const char *AutoPtrTokenId = "AutoPtrTokenId";
> -const char *AutoPtrOwnershipTransferId = "AutoPtrOwnershipTransferId";
> -
> -namespace clang {
> -namespace ast_matchers {
> -
> -/// \brief Matches expressions that are lvalues.
> -///
> -/// In the following example, a[0] matches expr(isLValue()):
> -/// \code
> -/// std::string a[2];
> -/// std::string b;
> -/// b = a[0];
> -/// b = "this string won't match";
> -/// \endcode
> -AST_MATCHER(Expr, isLValue) {
> - return Node.getValueKind() == VK_LValue;
> -}
> -
> -} // end namespace ast_matchers
> -} // end namespace clang
> -
> -using namespace clang;
> -using namespace clang::ast_matchers;
> -
> -// shared matchers
> -static DeclarationMatcher AutoPtrDecl =
> - recordDecl(hasName("auto_ptr"), isFromStdNamespace());
> -
> -static TypeMatcher AutoPtrType = qualType(hasDeclaration(AutoPtrDecl));
> -
> -// Matcher that finds expressions that are candidates to be wrapped with
> -// 'std::move()'.
> -//
> -// Binds the id \c AutoPtrOwnershipTransferId to the expression.
> -static StatementMatcher MovableArgumentMatcher = expr(
> - allOf(isLValue(), hasType(AutoPtrType))).bind(AutoPtrOwnershipTransferId);
> -
> -TypeLocMatcher makeAutoPtrTypeLocMatcher() {
> - // skip elaboratedType() as the named type will match soon thereafter.
> - return typeLoc(loc(qualType(AutoPtrType, unless(elaboratedType()))))
> - .bind(AutoPtrTokenId);
> -}
> -
> -DeclarationMatcher makeAutoPtrUsingDeclMatcher() {
> - return usingDecl(hasAnyUsingShadowDecl(hasTargetDecl(
> - allOf(hasName("auto_ptr"), isFromStdNamespace())))).bind(AutoPtrTokenId);
> -}
> -
> -StatementMatcher makeTransferOwnershipExprMatcher() {
> - StatementMatcher assignOperator =
> - cxxOperatorCallExpr(allOf(
> - hasOverloadedOperatorName("="),
> - callee(cxxMethodDecl(ofClass(AutoPtrDecl))),
> - hasArgument(1, MovableArgumentMatcher)));
> -
> - StatementMatcher copyCtor =
> - cxxConstructExpr(allOf(hasType(AutoPtrType),
> - argumentCountIs(1),
> - hasArgument(0, MovableArgumentMatcher)));
> -
> - return anyOf(assignOperator, copyCtor);
> -}
> Index: clang-modernize/ReplaceAutoPtr/ReplaceAutoPtrActions.h
> ===================================================================
> --- clang-modernize/ReplaceAutoPtr/ReplaceAutoPtrActions.h
> +++ /dev/null
> @@ -1,99 +0,0 @@
> -//===-- ReplaceAutoPtrActions.h ----- std::auto_ptr replacement -*- 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 ASTMatcher callback for the
> -/// ReplaceAutoPtr transform.
> -///
> -//===----------------------------------------------------------------------===//
> -
> -#ifndef CLANG_MODERNIZE_REPLACE_AUTO_PTR_ACTIONS_H
> -#define CLANG_MODERNIZE_REPLACE_AUTO_PTR_ACTIONS_H
> -
> -#include "clang/ASTMatchers/ASTMatchFinder.h"
> -#include "clang/Tooling/Refactoring.h"
> -
> -class Transform;
> -
> -/// \brief The callback to be used when replacing the \c std::auto_ptr types and
> -/// using declarations.
> -class AutoPtrReplacer : public clang::ast_matchers::MatchFinder::MatchCallback {
> -public:
> - AutoPtrReplacer(unsigned &AcceptedChanges, Transform &Owner)
> - : AcceptedChanges(AcceptedChanges), Owner(Owner) {}
> -
> - /// \brief Entry point to the callback called when matches are made.
> - void
> - run(const clang::ast_matchers::MatchFinder::MatchResult &Result) override;
> -
> -private:
> - /// \brief Locates the \c auto_ptr token when it is referred by a \c TypeLoc.
> - ///
> - /// \code
> - /// std::auto_ptr<int> i;
> - /// ^~~~~~~~~~~~~
> - /// \endcode
> - /// The caret represents the location returned and the tildes cover the
> - /// parameter \p AutoPtrTypeLoc.
> - ///
> - /// \return An invalid \c SourceLocation if not found, otherwise the location
> - /// of the beginning of the \c auto_ptr token.
> - clang::SourceLocation locateFromTypeLoc(clang::TypeLoc AutoPtrTypeLoc,
> - const clang::SourceManager &SM);
> -
> - /// \brief Locates the \c auto_ptr token in using declarations.
> - ///
> - /// \code
> - /// using std::auto_ptr;
> - /// ^
> - /// \endcode
> - /// The caret represents the location returned.
> - ///
> - /// \return An invalid \c SourceLocation if not found, otherwise the
> - /// location of the beginning of the \c auto_ptr token.
> - clang::SourceLocation
> - locateFromUsingDecl(const clang::UsingDecl *UsingAutoPtrDecl,
> - const clang::SourceManager &SM);
> -
> -private:
> - unsigned &AcceptedChanges;
> - Transform &Owner;
> -};
> -
> -/// \brief The callback to be used to fix the ownership transfers of
> -/// \c auto_ptr,
> -///
> -/// \c unique_ptr requires to use \c std::move() explicitly in order to transfer
> -/// the ownership.
> -///
> -/// Given:
> -/// \code
> -/// std::auto_ptr<int> a, b;
> -/// a = b;
> -/// \endcode
> -/// The last statement is transformed to:
> -/// \code
> -/// a = std::move(b);
> -/// \endcode
> -class OwnershipTransferFixer
> - : public clang::ast_matchers::MatchFinder::MatchCallback {
> -public:
> - OwnershipTransferFixer(unsigned &AcceptedChanges, Transform &Owner)
> - : AcceptedChanges(AcceptedChanges), Owner(Owner) {}
> -
> - /// \brief Entry point to the callback called when matches are made.
> - void
> - run(const clang::ast_matchers::MatchFinder::MatchResult &Result) override;
> -
> -private:
> - unsigned &AcceptedChanges;
> - Transform &Owner;
> -};
> -
> -#endif // CLANG_MODERNIZE_REPLACE_AUTO_PTR_ACTIONS_H
> Index: clang-modernize/ReplaceAutoPtr/ReplaceAutoPtrActions.cpp
> ===================================================================
> --- clang-modernize/ReplaceAutoPtr/ReplaceAutoPtrActions.cpp
> +++ /dev/null
> @@ -1,107 +0,0 @@
> -//===-- ReplaceAutoPtrActions.cpp --- std::auto_ptr replacement -----------===//
> -//
> -// 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 ASTMatcher callback for the
> -/// ReplaceAutoPtr transform.
> -///
> -//===----------------------------------------------------------------------===//
> -
> -#include "ReplaceAutoPtrActions.h"
> -#include "Core/Transform.h"
> -#include "ReplaceAutoPtrMatchers.h"
> -#include "clang/AST/ASTContext.h"
> -#include "clang/Lex/Lexer.h"
> -
> -using namespace clang;
> -using namespace clang::tooling;
> -using namespace clang::ast_matchers;
> -
> -namespace {
> -
> -/// \brief Verifies that the token at \p BeginningOfToken is 'auto_ptr'.
> -bool checkTokenIsAutoPtr(clang::SourceLocation BeginningOfToken,
> - const clang::SourceManager &SM,
> - const clang::LangOptions &LangOptions) {
> - llvm::SmallVector<char, 8> Buffer;
> - bool Invalid = false;
> - llvm::StringRef Res =
> - Lexer::getSpelling(BeginningOfToken, Buffer, SM, LangOptions, &Invalid);
> -
> - if (Invalid)
> - return false;
> -
> - return Res == "auto_ptr";
> -}
> -
> -} // end anonymous namespace
> -
> -void AutoPtrReplacer::run(const MatchFinder::MatchResult &Result) {
> - SourceManager &SM = *Result.SourceManager;
> - SourceLocation IdentifierLoc;
> -
> - if (const TypeLoc *TL = Result.Nodes.getNodeAs<TypeLoc>(AutoPtrTokenId)) {
> - IdentifierLoc = locateFromTypeLoc(*TL, SM);
> - } else {
> - const UsingDecl *D = Result.Nodes.getNodeAs<UsingDecl>(AutoPtrTokenId);
> - assert(D && "Bad Callback. No node provided.");
> - IdentifierLoc = locateFromUsingDecl(D, SM);
> - }
> -
> - if (IdentifierLoc.isMacroID())
> - IdentifierLoc = SM.getSpellingLoc(IdentifierLoc);
> -
> - if (!Owner.isFileModifiable(SM, IdentifierLoc))
> - return;
> -
> - // make sure that only the 'auto_ptr' token is replaced and not the template
> - // aliases [temp.alias]
> - if (!checkTokenIsAutoPtr(IdentifierLoc, SM, LangOptions()))
> - return;
> -
> - Owner.addReplacementForCurrentTU(
> - Replacement(SM, IdentifierLoc, strlen("auto_ptr"), "unique_ptr"));
> - ++AcceptedChanges;
> -}
> -
> -SourceLocation AutoPtrReplacer::locateFromTypeLoc(TypeLoc AutoPtrTypeLoc,
> - const SourceManager &SM) {
> - TemplateSpecializationTypeLoc TL =
> - AutoPtrTypeLoc.getAs<TemplateSpecializationTypeLoc>();
> - if (TL.isNull())
> - return SourceLocation();
> -
> - return TL.getTemplateNameLoc();
> -}
> -
> -SourceLocation
> -AutoPtrReplacer::locateFromUsingDecl(const UsingDecl *UsingAutoPtrDecl,
> - const SourceManager &SM) {
> - return UsingAutoPtrDecl->getNameInfo().getBeginLoc();
> -}
> -
> -void OwnershipTransferFixer::run(const MatchFinder::MatchResult &Result) {
> - SourceManager &SM = *Result.SourceManager;
> - const Expr *E = Result.Nodes.getNodeAs<Expr>(AutoPtrOwnershipTransferId);
> - assert(E && "Bad Callback. No node provided.");
> -
> - CharSourceRange Range = Lexer::makeFileCharRange(
> - CharSourceRange::getTokenRange(E->getSourceRange()), SM, LangOptions());
> -
> - if (Range.isInvalid())
> - return;
> -
> - if (!Owner.isFileModifiable(SM, Range.getBegin()))
> - return;
> -
> - Owner.addReplacementForCurrentTU(
> - Replacement(SM, Range.getBegin(), 0, "std::move("));
> - Owner.addReplacementForCurrentTU(Replacement(SM, Range.getEnd(), 0, ")"));
> - AcceptedChanges += 2;
> -}
> Index: clang-modernize/ReplaceAutoPtr/ReplaceAutoPtr.h
> ===================================================================
> --- clang-modernize/ReplaceAutoPtr/ReplaceAutoPtr.h
> +++ /dev/null
> @@ -1,54 +0,0 @@
> -//===-- ReplaceAutoPtr.h ------------ std::auto_ptr replacement -*- 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 declaration of the ReplaceAutoPtrTransform
> -/// class.
> -///
> -//===----------------------------------------------------------------------===//
> -
> -#ifndef CLANG_MODERNIZE_REPLACE_AUTO_PTR_H
> -#define CLANG_MODERNIZE_REPLACE_AUTO_PTR_H
> -
> -#include "Core/Transform.h"
> -#include "llvm/Support/Compiler.h"
> -
> -/// \brief Subclass of Transform that transforms the deprecated \c std::auto_ptr
> -/// into the C++11 \c std::unique_ptr.
> -///
> -/// Note that both the \c std::auto_ptr type and the transfer of ownership are
> -/// transformed. \c std::auto_ptr provides two ways to transfer the ownership,
> -/// the copy-constructor and the assignment operator. Unlike most classes theses
> -/// operations do not 'copy' the resource but they 'steal' it.
> -/// \c std::unique_ptr uses move semantics instead, which makes the intent of
> -/// transferring the resource explicit. This difference between the two smart
> -/// pointers requires to wrap the copy-ctor and assign-operator with
> -/// \c std::move().
> -///
> -/// For example, given:
> -/// \code
> -/// std::auto_ptr<int> i, j;
> -/// i = j;
> -/// \endcode
> -/// the code is transformed to:
> -/// \code
> -/// std::unique_ptr<int> i, j;
> -/// i = std::move(j);
> -/// \endcode
> -class ReplaceAutoPtrTransform : public Transform {
> -public:
> - ReplaceAutoPtrTransform(const TransformOptions &Options)
> - : Transform("ReplaceAutoPtr", Options) {}
> -
> - /// \see Transform::run().
> - int apply(const clang::tooling::CompilationDatabase &Database,
> - const std::vector<std::string> &SourcePaths) override;
> -};
> -
> -#endif // CLANG_MODERNIZE_REPLACE_AUTO_PTR_H
> Index: clang-modernize/ReplaceAutoPtr/ReplaceAutoPtr.cpp
> ===================================================================
> --- clang-modernize/ReplaceAutoPtr/ReplaceAutoPtr.cpp
> +++ /dev/null
> @@ -1,67 +0,0 @@
> -//===-- ReplaceAutoPtr.cpp ---------- std::auto_ptr replacement -----------===//
> -//
> -// 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 ReplaceAutoPtrTransform
> -/// class.
> -///
> -//===----------------------------------------------------------------------===//
> -
> -#include "ReplaceAutoPtr.h"
> -#include "ReplaceAutoPtrActions.h"
> -#include "ReplaceAutoPtrMatchers.h"
> -
> -using namespace clang;
> -using namespace clang::tooling;
> -using namespace clang::ast_matchers;
> -
> -int
> -ReplaceAutoPtrTransform::apply(const CompilationDatabase &Database,
> - const std::vector<std::string> &SourcePaths) {
> - ClangTool Tool(Database, SourcePaths);
> - unsigned AcceptedChanges = 0;
> - MatchFinder Finder;
> - AutoPtrReplacer Replacer(AcceptedChanges, /*Owner=*/ *this);
> - OwnershipTransferFixer Fixer(AcceptedChanges, /*Owner=*/ *this);
> -
> - Finder.addMatcher(makeAutoPtrTypeLocMatcher(), &Replacer);
> - Finder.addMatcher(makeAutoPtrUsingDeclMatcher(), &Replacer);
> - Finder.addMatcher(makeTransferOwnershipExprMatcher(), &Fixer);
> -
> - if (Tool.run(createActionFactory(Finder).get())) {
> - llvm::errs() << "Error encountered during translation.\n";
> - return 1;
> - }
> -
> - setAcceptedChanges(AcceptedChanges);
> -
> - return 0;
> -}
> -
> -struct ReplaceAutoPtrFactory : TransformFactory {
> - ReplaceAutoPtrFactory() {
> - Since.Clang = Version(3, 0);
> - Since.Gcc = Version(4, 6);
> - Since.Icc = Version(13);
> - Since.Msvc = Version(11);
> - }
> -
> - Transform *createTransform(const TransformOptions &Opts) override {
> - return new ReplaceAutoPtrTransform(Opts);
> - }
> -};
> -
> -// Register the factory using this statically initialized variable.
> -static TransformFactoryRegistry::Add<ReplaceAutoPtrFactory>
> -X("replace-auto_ptr", "Replace std::auto_ptr (deprecated) by std::unique_ptr"
> - " (EXPERIMENTAL)");
> -
> -// This anchor is used to force the linker to link in the generated object file
> -// and thus register the factory.
> -volatile int ReplaceAutoPtrTransformAnchorSource = 0;
> Index: clang-modernize/PassByValue/PassByValueMatchers.h
> ===================================================================
> --- clang-modernize/PassByValue/PassByValueMatchers.h
> +++ /dev/null
> @@ -1,44 +0,0 @@
> -//===-- PassByValueMatchers.h -----------------------------------*- 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 CLANG_MODERNIZE_REPLACE_AUTO_PTR_MATCHERS_H
> -#define CLANG_MODERNIZE_REPLACE_AUTO_PTR_MATCHERS_H
> -
> -#include "clang/ASTMatchers/ASTMatchers.h"
> -
> -/// \name Names to bind with matched expressions
> -/// @{
> -extern const char *PassByValueCtorId;
> -extern const char *PassByValueParamId;
> -extern const char *PassByValueInitializerId;
> -/// @}
> -
> -/// \brief Creates a matcher that finds class field initializations that can
> -/// benefit from using the move constructor.
> -///
> -/// \code
> -/// class A {
> -/// public:
> -/// A(const std::string &S) : S(S) {}
> -/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PassByValueCtorId
> -/// ~~~~~~~~~~~~~~~~~~~~ PassByValueParamId
> -/// ~ PassByValueInitializerId
> -/// private:
> -/// std::string S;
> -/// };
> -/// \endcode
> -clang::ast_matchers::DeclarationMatcher makePassByValueCtorParamMatcher();
> -
> -#endif // CLANG_MODERNIZE_REPLACE_AUTO_PTR_MATCHERS_H
> Index: clang-modernize/PassByValue/PassByValueMatchers.cpp
> ===================================================================
> --- clang-modernize/PassByValue/PassByValueMatchers.cpp
> +++ /dev/null
> @@ -1,81 +0,0 @@
> -//===-- PassByValueMatchers.cpp -------------------------------------------===//
> -//
> -// 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 names for bound nodes found by AST matchers.
> -///
> -//===----------------------------------------------------------------------===//
> -
> -#include "PassByValueMatchers.h"
> -
> -const char *PassByValueCtorId = "Ctor";
> -const char *PassByValueParamId = "Param";
> -const char *PassByValueInitializerId = "Initializer";
> -
> -namespace clang {
> -namespace ast_matchers {
> -
> -/// \brief Matches move constructible classes.
> -///
> -/// Given
> -/// \code
> -/// // POD types are trivially move constructible
> -/// struct Foo { int a; };
> -///
> -/// struct Bar {
> -/// Bar(Bar &&) = deleted;
> -/// int a;
> -/// };
> -/// \endcode
> -/// recordDecl(isMoveConstructible())
> -/// matches "Foo".
> -AST_MATCHER(CXXRecordDecl, isMoveConstructible) {
> - for (CXXRecordDecl::ctor_iterator I = Node.ctor_begin(), E = Node.ctor_end(); I != E; ++I) {
> - const CXXConstructorDecl *Ctor = *I;
> - if (Ctor->isMoveConstructor() && !Ctor->isDeleted())
> - return true;
> - }
> - return false;
> -}
> -} // namespace ast_matchers
> -} // namespace clang
> -
> -using namespace clang;
> -using namespace clang::ast_matchers;
> -
> -static TypeMatcher constRefType() {
> - return lValueReferenceType(pointee(isConstQualified()));
> -}
> -
> -static TypeMatcher nonConstValueType() {
> - return qualType(unless(anyOf(referenceType(), isConstQualified())));
> -}
> -
> -DeclarationMatcher makePassByValueCtorParamMatcher() {
> - return cxxConstructorDecl(
> - forEachConstructorInitializer(cxxCtorInitializer(
> - // Clang builds a CXXConstructExpr only when it knowns which
> - // constructor will be called. In dependent contexts a ParenListExpr
> - // is generated instead of a CXXConstructExpr, filtering out templates
> - // automatically for us.
> - withInitializer(cxxConstructExpr(
> - has(declRefExpr(to(
> - parmVarDecl(hasType(qualType(
> - // match only const-ref or a non-const value
> - // parameters, rvalues and const-values
> - // shouldn't be modified.
> - anyOf(constRefType(), nonConstValueType()))))
> - .bind(PassByValueParamId)))),
> - hasDeclaration(cxxConstructorDecl(
> - isCopyConstructor(), unless(isDeleted()),
> - hasDeclContext(cxxRecordDecl(isMoveConstructible())))))))
> - .bind(PassByValueInitializerId)))
> - .bind(PassByValueCtorId);
> -}
> Index: clang-modernize/PassByValue/PassByValueActions.h
> ===================================================================
> --- clang-modernize/PassByValue/PassByValueActions.h
> +++ /dev/null
> @@ -1,74 +0,0 @@
> -//===-- PassByValueActions.h ------------------------------------*- 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 ASTMatcher callback for the
> -/// PassByValue transform.
> -///
> -//===----------------------------------------------------------------------===//
> -
> -#ifndef CLANG_MODERNIZE_PASS_BY_VALUE_ACTIONS_H
> -#define CLANG_MODERNIZE_PASS_BY_VALUE_ACTIONS_H
> -
> -#include "clang/ASTMatchers/ASTMatchFinder.h"
> -#include "clang/Tooling/Refactoring.h"
> -
> -class Transform;
> -class IncludeDirectives;
> -
> -/// \brief Callback that replaces const-ref parameters in constructors to use
> -/// pass-by-value semantic where applicable.
> -///
> -/// Modifications done by the callback:
> -/// - \#include \<utility\> is added if necessary for the definition of
> -/// \c std::move() to be available.
> -/// - The parameter type is changed from const-ref to value-type.
> -/// - In the init-list the parameter is moved.
> -///
> -/// Example:
> -/// \code
> -/// + #include <utility>
> -///
> -/// class Foo(const std::string &S) {
> -/// public:
> -/// - Foo(const std::string &S) : S(S) {}
> -/// + Foo(std::string S) : S(std::move(S)) {}
> -///
> -/// private:
> -/// std::string S;
> -/// };
> -/// \endcode
> -///
> -/// \note Since an include may be added by this matcher it's necessary to call
> -/// \c setIncludeDirectives() with an up-to-date \c IncludeDirectives. This is
> -/// typically done by overloading \c Transform::handleBeginSource().
> -class ConstructorParamReplacer
> - : public clang::ast_matchers::MatchFinder::MatchCallback {
> -public:
> - ConstructorParamReplacer(unsigned &AcceptedChanges, unsigned &RejectedChanges,
> - Transform &Owner)
> - : AcceptedChanges(AcceptedChanges), RejectedChanges(RejectedChanges),
> - Owner(Owner), IncludeManager(nullptr) {}
> -
> - void setIncludeDirectives(IncludeDirectives *Includes) {
> - IncludeManager = Includes;
> - }
> -
> -private:
> - /// \brief Entry point to the callback called when matches are made.
> - void
> - run(const clang::ast_matchers::MatchFinder::MatchResult &Result) override;
> -
> - unsigned &AcceptedChanges;
> - unsigned &RejectedChanges;
> - Transform &Owner;
> - IncludeDirectives *IncludeManager;
> -};
> -
> -#endif // CLANG_MODERNIZE_PASS_BY_VALUE_ACTIONS_H
> Index: clang-modernize/PassByValue/PassByValueActions.cpp
> ===================================================================
> --- clang-modernize/PassByValue/PassByValueActions.cpp
> +++ /dev/null
> @@ -1,175 +0,0 @@
> -//===-- PassByValueActions.cpp --------------------------------------------===//
> -//
> -// 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 ASTMatcher callback for the
> -/// PassByValue transform.
> -///
> -//===----------------------------------------------------------------------===//
> -
> -#include "PassByValueActions.h"
> -#include "Core/IncludeDirectives.h"
> -#include "Core/Transform.h"
> -#include "PassByValueMatchers.h"
> -#include "clang/AST/RecursiveASTVisitor.h"
> -#include "clang/Basic/SourceManager.h"
> -#include "clang/Lex/Lexer.h"
> -
> -using namespace clang;
> -using namespace clang::tooling;
> -using namespace clang::ast_matchers;
> -
> -namespace {
> -/// \brief \c clang::RecursiveASTVisitor that checks that the given
> -/// \c ParmVarDecl is used exactly one time.
> -///
> -/// \see ExactlyOneUsageVisitor::hasExactlyOneUsageIn()
> -class ExactlyOneUsageVisitor
> - : public RecursiveASTVisitor<ExactlyOneUsageVisitor> {
> - friend class RecursiveASTVisitor<ExactlyOneUsageVisitor>;
> -
> -public:
> - ExactlyOneUsageVisitor(const ParmVarDecl *ParamDecl) : ParamDecl(ParamDecl) {}
> -
> - /// \brief Whether or not the parameter variable is referred only once in the
> - /// given constructor.
> - bool hasExactlyOneUsageIn(const CXXConstructorDecl *Ctor) {
> - Count = 0;
> - TraverseDecl(const_cast<CXXConstructorDecl *>(Ctor));
> - return Count == 1;
> - }
> -
> -private:
> - /// \brief Counts the number of references to a variable.
> - ///
> - /// Stops the AST traversal if more than one usage is found.
> - bool VisitDeclRefExpr(DeclRefExpr *D) {
> - if (const ParmVarDecl *To = llvm::dyn_cast<ParmVarDecl>(D->getDecl()))
> - if (To == ParamDecl) {
> - ++Count;
> - if (Count > 1)
> - // no need to look further, used more than once
> - return false;
> - }
> - return true;
> - }
> -
> - const ParmVarDecl *ParamDecl;
> - unsigned Count;
> -};
> -} // end anonymous namespace
> -
> -/// \brief Whether or not \p ParamDecl is used exactly one time in \p Ctor.
> -///
> -/// Checks both in the init-list and the body of the constructor.
> -static bool paramReferredExactlyOnce(const CXXConstructorDecl *Ctor,
> - const ParmVarDecl *ParamDecl) {
> - ExactlyOneUsageVisitor Visitor(ParamDecl);
> - return Visitor.hasExactlyOneUsageIn(Ctor);
> -}
> -
> -/// \brief Find all references to \p ParamDecl across all of the
> -/// redeclarations of \p Ctor.
> -static void
> -collectParamDecls(const CXXConstructorDecl *Ctor, const ParmVarDecl *ParamDecl,
> - llvm::SmallVectorImpl<const ParmVarDecl *> &Results) {
> - unsigned ParamIdx = ParamDecl->getFunctionScopeIndex();
> -
> - for (CXXConstructorDecl::redecl_iterator I = Ctor->redecls_begin(),
> - E = Ctor->redecls_end();
> - I != E; ++I)
> - Results.push_back((*I)->getParamDecl(ParamIdx));
> -}
> -
> -void ConstructorParamReplacer::run(const MatchFinder::MatchResult &Result) {
> - assert(IncludeManager && "Include directives manager not set.");
> - SourceManager &SM = *Result.SourceManager;
> - const CXXConstructorDecl *Ctor =
> - Result.Nodes.getNodeAs<CXXConstructorDecl>(PassByValueCtorId);
> - const ParmVarDecl *ParamDecl =
> - Result.Nodes.getNodeAs<ParmVarDecl>(PassByValueParamId);
> - const CXXCtorInitializer *Initializer =
> - Result.Nodes.getNodeAs<CXXCtorInitializer>(PassByValueInitializerId);
> - assert(Ctor && ParamDecl && Initializer && "Bad Callback, missing node.");
> -
> - // Check this now to avoid unnecessary work. The param locations are checked
> - // later.
> - if (!Owner.isFileModifiable(SM, Initializer->getSourceLocation()))
> - return;
> -
> - // The parameter will be in an unspecified state after the move, so check if
> - // the parameter is used for anything else other than the copy. If so do not
> - // apply any changes.
> - if (!paramReferredExactlyOnce(Ctor, ParamDecl))
> - return;
> -
> - llvm::SmallVector<const ParmVarDecl *, 2> AllParamDecls;
> - collectParamDecls(Ctor, ParamDecl, AllParamDecls);
> -
> - // Generate all replacements for the params.
> - llvm::SmallVector<Replacement, 2> ParamReplaces;
> - for (unsigned I = 0, E = AllParamDecls.size(); I != E; ++I) {
> - TypeLoc ParamTL = AllParamDecls[I]->getTypeSourceInfo()->getTypeLoc();
> - ReferenceTypeLoc RefTL = ParamTL.getAs<ReferenceTypeLoc>();
> - SourceRange Range(AllParamDecls[I]->getLocStart(), ParamTL.getLocEnd());
> - CharSourceRange CharRange = Lexer::makeFileCharRange(
> - CharSourceRange::getTokenRange(Range), SM, LangOptions());
> -
> - // do not generate a replacement when the parameter is already a value
> - if (RefTL.isNull())
> - continue;
> -
> - // transform non-value parameters (e.g: const-ref) to values
> - TypeLoc ValueTypeLoc = RefTL.getPointeeLoc();
> - llvm::SmallString<32> ValueStr = Lexer::getSourceText(
> - CharSourceRange::getTokenRange(ValueTypeLoc.getSourceRange()), SM,
> - LangOptions());
> -
> - // If it's impossible to change one of the parameter (e.g: comes from an
> - // unmodifiable header) quit the callback now, do not generate any changes.
> - if (CharRange.isInvalid() || ValueStr.empty() ||
> - !Owner.isFileModifiable(SM, CharRange.getBegin()))
> - return;
> -
> - // 'const Foo ¶m' -> 'Foo param'
> - // ~~~~~~~~~~~ ~~~^
> - ValueStr += ' ';
> - ParamReplaces.push_back(Replacement(SM, CharRange, ValueStr));
> - }
> -
> - // Reject the changes if the the risk level is not acceptable.
> - if (!Owner.isAcceptableRiskLevel(RL_Reasonable)) {
> - RejectedChanges++;
> - return;
> - }
> -
> - // if needed, include <utility> in the file that uses std::move()
> - const FileEntry *STDMoveFile =
> - SM.getFileEntryForID(SM.getFileID(Initializer->getLParenLoc()));
> - const tooling::Replacement &IncludeReplace =
> - IncludeManager->addAngledInclude(STDMoveFile, "utility");
> - if (IncludeReplace.isApplicable()) {
> - Owner.addReplacementForCurrentTU(IncludeReplace);
> - AcceptedChanges++;
> - }
> -
> - // const-ref params becomes values (const Foo & -> Foo)
> - for (const Replacement *I = ParamReplaces.begin(), *E = ParamReplaces.end();
> - I != E; ++I) {
> - Owner.addReplacementForCurrentTU(*I);
> - }
> - AcceptedChanges += ParamReplaces.size();
> -
> - // move the value in the init-list
> - Owner.addReplacementForCurrentTU(Replacement(
> - SM, Initializer->getLParenLoc().getLocWithOffset(1), 0, "std::move("));
> - Owner.addReplacementForCurrentTU(
> - Replacement(SM, Initializer->getRParenLoc(), 0, ")"));
> - AcceptedChanges += 2;
> -}
> Index: clang-modernize/PassByValue/PassByValue.h
> ===================================================================
> --- clang-modernize/PassByValue/PassByValue.h
> +++ /dev/null
> @@ -1,73 +0,0 @@
> -//===-- PassByValue.h -------------------------------------------*- 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 declaration of the PassByValueTransform
> -/// class.
> -///
> -//===----------------------------------------------------------------------===//
> -
> -#ifndef CLANG_MODERNIZE_PASS_BY_VALUE_H
> -#define CLANG_MODERNIZE_PASS_BY_VALUE_H
> -
> -#include "Core/IncludeDirectives.h"
> -#include "Core/Transform.h"
> -
> -class ConstructorParamReplacer;
> -
> -/// \brief Subclass of Transform that uses pass-by-value semantic when move
> -/// constructors are available to avoid copies.
> -///
> -/// When a class constructor accepts an object by const reference with the
> -/// intention of copying the object the copy can be avoided in certain
> -/// situations if the object has a move constructor. First, the constructor is
> -/// changed to accept the object by value instead. Then this argument is moved
> -/// instead of copied into class-local storage. If an l-value is provided to the
> -/// constructor, there is no difference in the number of copies made. However,
> -/// if an r-value is passed, the copy is avoided completely.
> -///
> -/// For example, given:
> -/// \code
> -/// #include <string>
> -///
> -/// class A {
> -/// std::string S;
> -/// public:
> -/// A(const std::string &S) : S(S) {}
> -/// };
> -/// \endcode
> -/// the code is transformed to:
> -/// \code
> -/// #include <string>
> -///
> -/// class A {
> -/// std::string S;
> -/// public:
> -/// A(std::string S) : S(std::move(S)) {}
> -/// };
> -/// \endcode
> -class PassByValueTransform : public Transform {
> -public:
> - PassByValueTransform(const TransformOptions &Options)
> - : Transform("PassByValue", Options), Replacer(nullptr) {}
> -
> - /// \see Transform::apply().
> - int apply(const clang::tooling::CompilationDatabase &Database,
> - const std::vector<std::string> &SourcePaths) override;
> -
> -private:
> - /// \brief Setups the \c IncludeDirectives for the replacer.
> - bool handleBeginSource(clang::CompilerInstance &CI,
> - llvm::StringRef Filename) override;
> -
> - std::unique_ptr<IncludeDirectives> IncludeManager;
> - ConstructorParamReplacer *Replacer;
> -};
> -
> -#endif // CLANG_MODERNIZE_PASS_BY_VALUE_H
> Index: clang-modernize/PassByValue/PassByValue.cpp
> ===================================================================
> --- clang-modernize/PassByValue/PassByValue.cpp
> +++ /dev/null
> @@ -1,78 +0,0 @@
> -//===-- PassByValue.cpp ---------------------------------------------------===//
> -//
> -// 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 ReplaceAutoPtrTransform
> -/// class.
> -///
> -//===----------------------------------------------------------------------===//
> -
> -#include "PassByValue.h"
> -#include "PassByValueActions.h"
> -#include "PassByValueMatchers.h"
> -
> -using namespace clang;
> -using namespace clang::tooling;
> -using namespace clang::ast_matchers;
> -
> -int PassByValueTransform::apply(const tooling::CompilationDatabase &Database,
> - const std::vector<std::string> &SourcePaths) {
> - ClangTool Tool(Database, SourcePaths);
> - unsigned AcceptedChanges = 0;
> - unsigned RejectedChanges = 0;
> - MatchFinder Finder;
> - ConstructorParamReplacer Replacer(AcceptedChanges, RejectedChanges,
> - /*Owner=*/ *this);
> -
> - Finder.addMatcher(makePassByValueCtorParamMatcher(), &Replacer);
> -
> - // make the replacer available to handleBeginSource()
> - this->Replacer = &Replacer;
> -
> - if (Tool.run(createActionFactory(Finder).get())) {
> - llvm::errs() << "Error encountered during translation.\n";
> - return 1;
> - }
> -
> - setAcceptedChanges(AcceptedChanges);
> - setRejectedChanges(RejectedChanges);
> - return 0;
> -}
> -
> -bool PassByValueTransform::handleBeginSource(CompilerInstance &CI,
> - llvm::StringRef Filename) {
> - assert(Replacer && "Replacer not set");
> - IncludeManager.reset(new IncludeDirectives(CI));
> - Replacer->setIncludeDirectives(IncludeManager.get());
> - return Transform::handleBeginSource(CI, Filename);
> -}
> -
> -namespace {
> -struct PassByValueFactory : TransformFactory {
> - PassByValueFactory() {
> - // Based on the Replace Auto-Ptr Transform that is also using std::move().
> - Since.Clang = Version(3, 0);
> - Since.Gcc = Version(4, 6);
> - Since.Icc = Version(13);
> - Since.Msvc = Version(11);
> - }
> -
> - Transform *createTransform(const TransformOptions &Opts) override {
> - return new PassByValueTransform(Opts);
> - }
> -};
> -} // namespace
> -
> -// Register the factory using this statically initialized variable.
> -static TransformFactoryRegistry::Add<PassByValueFactory>
> -X("pass-by-value", "Pass parameters by value where possible");
> -
> -// This anchor is used to force the linker to link in the generated object file
> -// and thus register the factory.
> -volatile int PassByValueTransformAnchorSource = 0;
> Index: clang-modernize/Makefile
> ===================================================================
> --- clang-modernize/Makefile
> +++ /dev/null
> @@ -1,15 +0,0 @@
> -##===- tools/extra/loop-convert/Makefile ----sssss----------*- Makefile -*-===##
> -#
> -# The LLVM Compiler Infrastructure
> -#
> -# This file is distributed under the University of Illinois Open Source
> -# License. See LICENSE.TXT for details.
> -#
> -##===----------------------------------------------------------------------===##
> -
> -CLANG_LEVEL := ../../..
> -include $(CLANG_LEVEL)/../../Makefile.config
> -
> -DIRS = Core tool
> -
> -include $(CLANG_LEVEL)/Makefile
> Index: clang-modernize/LoopConvert/VariableNaming.h
> ===================================================================
> --- clang-modernize/LoopConvert/VariableNaming.h
> +++ /dev/null
> @@ -1,59 +0,0 @@
> -//===-- LoopConvert/VariableNaming.h - Gererate variable names --*- 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 VariableNamer class, which
> -/// is responsible for generating new variable names and ensuring that they do
> -/// not conflict with existing ones.
> -//
> -//===----------------------------------------------------------------------===//
> -
> -#ifndef CLANG_MODERNIZE_VARIABLE_NAMING_H
> -#define CLANG_MODERNIZE_VARIABLE_NAMING_H
> -
> -#include "StmtAncestor.h"
> -#include "clang/AST/ASTContext.h"
> -
> -/// \brief Create names for generated variables within a particular statement.
> -///
> -/// VariableNamer uses a DeclContext as a reference point, checking for any
> -/// conflicting declarations higher up in the context or within SourceStmt.
> -/// It creates a variable name using hints from a source container and the old
> -/// index, if they exist.
> -class VariableNamer {
> - public:
> - VariableNamer(
> - StmtGeneratedVarNameMap *GeneratedDecls, const StmtParentMap *ReverseAST,
> - const clang::Stmt *SourceStmt, const clang::VarDecl *OldIndex,
> - const clang::VarDecl *TheContainer, const clang::ASTContext *Context)
> - : GeneratedDecls(GeneratedDecls), ReverseAST(ReverseAST),
> - SourceStmt(SourceStmt), OldIndex(OldIndex), TheContainer(TheContainer),
> - Context(Context) {}
> -
> - /// \brief Generate a new index name.
> - ///
> - /// Generates the name to be used for an inserted iterator. It relies on
> - /// declarationExists() to determine that there are no naming conflicts, and
> - /// tries to use some hints from the container name and the old index name.
> - std::string createIndexName();
> -
> - private:
> - StmtGeneratedVarNameMap *GeneratedDecls;
> - const StmtParentMap *ReverseAST;
> - const clang::Stmt *SourceStmt;
> - const clang::VarDecl *OldIndex;
> - const clang::VarDecl *TheContainer;
> - const clang::ASTContext *Context;
> -
> - // Determine whether or not a declaration that would conflict with Symbol
> - // exists in an outer context or in any statement contained in SourceStmt.
> - bool declarationExists(llvm::StringRef Symbol);
> -};
> -
> -#endif // CLANG_MODERNIZE_VARIABLE_NAMING_H
> Index: clang-modernize/LoopConvert/VariableNaming.cpp
> ===================================================================
> --- clang-modernize/LoopConvert/VariableNaming.cpp
> +++ /dev/null
> @@ -1,95 +0,0 @@
> -//===-- LoopConvert/VariableNaming.cpp - Gererate variable names ----------===//
> -//
> -// 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 definitino of the VariableNamer class, which
> -/// is responsible for generating new variable names and ensuring that they do
> -/// not conflict with existing ones.
> -///
> -//===----------------------------------------------------------------------===//
> -
> -#include "VariableNaming.h"
> -
> -using namespace llvm;
> -using namespace clang;
> -
> -std::string VariableNamer::createIndexName() {
> - // FIXME: Add in naming conventions to handle:
> - // - Uppercase/lowercase indices
> - // - How to handle conflicts
> - // - An interactive process for naming
> - std::string IteratorName;
> - std::string ContainerName;
> - if (TheContainer)
> - ContainerName = TheContainer->getName().str();
> -
> - size_t Len = ContainerName.length();
> - if (Len > 1 && ContainerName[Len - 1] == 's')
> - IteratorName = ContainerName.substr(0, Len - 1);
> - else
> - IteratorName = "elem";
> -
> - if (!declarationExists(IteratorName))
> - return IteratorName;
> -
> - IteratorName = ContainerName + "_" + OldIndex->getName().str();
> - if (!declarationExists(IteratorName))
> - return IteratorName;
> -
> - IteratorName = ContainerName + "_elem";
> - if (!declarationExists(IteratorName))
> - return IteratorName;
> -
> - IteratorName += "_elem";
> - if (!declarationExists(IteratorName))
> - return IteratorName;
> -
> - IteratorName = "_elem_";
> -
> - // Someone defeated my naming scheme...
> - while (declarationExists(IteratorName))
> - IteratorName += "i";
> - return IteratorName;
> -}
> -
> -/// \brief Determines whether or not the the name \a Symbol conflicts with
> -/// language keywords or defined macros. Also checks if the name exists in
> -/// LoopContext, any of its parent contexts, or any of its child statements.
> -///
> -/// We also check to see if the same identifier was generated by this loop
> -/// converter in a loop nested within SourceStmt.
> -bool VariableNamer::declarationExists(StringRef Symbol) {
> - assert(Context != nullptr && "Expected an ASTContext");
> - IdentifierInfo &Ident = Context->Idents.get(Symbol);
> -
> - // Check if the symbol is not an identifier (ie. is a keyword or alias).
> - if (!isAnyIdentifier(Ident.getTokenID()))
> - return true;
> -
> - // Check for conflicting macro definitions.
> - if (Ident.hasMacroDefinition())
> - return true;
> -
> - // Determine if the symbol was generated in a parent context.
> - for (const Stmt *S = SourceStmt; S != nullptr; S = ReverseAST->lookup(S)) {
> - StmtGeneratedVarNameMap::const_iterator I = GeneratedDecls->find(S);
> - if (I != GeneratedDecls->end() && I->second == Symbol)
> - return true;
> - }
> -
> - // FIXME: Rather than detecting conflicts at their usages, we should check the
> - // parent context.
> - // For some reason, lookup() always returns the pair (NULL, NULL) because its
> - // StoredDeclsMap is not initialized (i.e. LookupPtr.getInt() is false inside
> - // of DeclContext::lookup()). Why is this?
> -
> - // Finally, determine if the symbol was used in the loop or a child context.
> - DeclFinderASTVisitor DeclFinder(Symbol, GeneratedDecls);
> - return DeclFinder.findUsages(SourceStmt);
> -}
> Index: clang-modernize/LoopConvert/StmtAncestor.h
> ===================================================================
> --- clang-modernize/LoopConvert/StmtAncestor.h
> +++ /dev/null
> @@ -1,201 +0,0 @@
> -//===-- LoopConvert/StmtAncestor.h - AST property visitors ------*- 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 of several RecursiveASTVisitors
> -/// used to build and check data structures used in loop migration.
> -///
> -//===----------------------------------------------------------------------===//
> -
> -#ifndef CLANG_MODERNIZE_STMT_ANCESTOR_H
> -#define CLANG_MODERNIZE_STMT_ANCESTOR_H
> -
> -#include "clang/AST/RecursiveASTVisitor.h"
> -
> -/// A map used to walk the AST in reverse: maps child Stmt to parent Stmt.
> -typedef llvm::DenseMap<const clang::Stmt*, const clang::Stmt*> StmtParentMap;
> -
> -/// A map used to walk the AST in reverse:
> -/// maps VarDecl to the to parent DeclStmt.
> -typedef
> -llvm::DenseMap<const clang::VarDecl*, const clang::DeclStmt*> DeclParentMap;
> -
> -/// A map used to track which variables have been removed by a refactoring pass.
> -/// It maps the parent ForStmt to the removed index variable's VarDecl.
> -typedef
> -llvm::DenseMap<const clang::ForStmt*, const clang::VarDecl*> ReplacedVarsMap;
> -
> -/// A map used to remember the variable names generated in a Stmt
> -typedef llvm::DenseMap<const clang::Stmt*, std::string> StmtGeneratedVarNameMap;
> -
> -/// A vector used to store the AST subtrees of an Expr.
> -typedef llvm::SmallVector<const clang::Expr*, 16> ComponentVector;
> -
> -/// \brief Class used build the reverse AST properties needed to detect
> -/// name conflicts and free variables.
> -class StmtAncestorASTVisitor :
> - public clang::RecursiveASTVisitor<StmtAncestorASTVisitor> {
> -public:
> - StmtAncestorASTVisitor() {
> - StmtStack.push_back(nullptr);
> - }
> -
> - /// \brief Run the analysis on the TranslationUnitDecl.
> - ///
> - /// In case we're running this analysis multiple times, don't repeat the work.
> - void gatherAncestors(const clang::TranslationUnitDecl *T) {
> - if (StmtAncestors.empty())
> - TraverseDecl(const_cast<clang::TranslationUnitDecl*>(T));
> - }
> -
> - /// Accessor for StmtAncestors.
> - const StmtParentMap &getStmtToParentStmtMap() {
> - return StmtAncestors;
> - }
> -
> - /// Accessor for DeclParents.
> - const DeclParentMap &getDeclToParentStmtMap() {
> - return DeclParents;
> - }
> -
> - friend class clang::RecursiveASTVisitor<StmtAncestorASTVisitor>;
> -
> -private:
> - StmtParentMap StmtAncestors;
> - DeclParentMap DeclParents;
> - llvm::SmallVector<const clang::Stmt*, 16> StmtStack;
> -
> - bool TraverseStmt(clang::Stmt *Statement);
> - bool VisitDeclStmt(clang::DeclStmt *Statement);
> -};
> -
> -/// Class used to find the variables and member expressions on which an
> -/// arbitrary expression depends.
> -class ComponentFinderASTVisitor :
> - public clang::RecursiveASTVisitor<ComponentFinderASTVisitor> {
> -public:
> - ComponentFinderASTVisitor() { }
> -
> - /// Find the components of an expression and place them in a ComponentVector.
> - void findExprComponents(const clang::Expr *SourceExpr) {
> - clang::Expr *E = const_cast<clang::Expr *>(SourceExpr);
> - TraverseStmt(E);
> - }
> -
> - /// Accessor for Components.
> - const ComponentVector &getComponents() {
> - return Components;
> - }
> -
> - friend class clang::RecursiveASTVisitor<ComponentFinderASTVisitor>;
> -
> -private:
> - ComponentVector Components;
> -
> - bool VisitDeclRefExpr(clang::DeclRefExpr *E);
> - bool VisitMemberExpr(clang::MemberExpr *Member);
> -};
> -
> -/// Class used to determine if an expression is dependent on a variable declared
> -/// inside of the loop where it would be used.
> -class DependencyFinderASTVisitor :
> - public clang::RecursiveASTVisitor<DependencyFinderASTVisitor> {
> -public:
> - DependencyFinderASTVisitor(const StmtParentMap *StmtParents,
> - const DeclParentMap *DeclParents,
> - const ReplacedVarsMap *ReplacedVars,
> - const clang::Stmt *ContainingStmt) :
> - StmtParents(StmtParents), DeclParents(DeclParents),
> - ContainingStmt(ContainingStmt), ReplacedVars(ReplacedVars) { }
> -
> - /// \brief Run the analysis on Body, and return true iff the expression
> - /// depends on some variable declared within ContainingStmt.
> - ///
> - /// This is intended to protect against hoisting the container expression
> - /// outside of an inner context if part of that expression is declared in that
> - /// inner context.
> - ///
> - /// For example,
> - /// \code
> - /// const int N = 10, M = 20;
> - /// int arr[N][M];
> - /// int getRow();
> - ///
> - /// for (int i = 0; i < M; ++i) {
> - /// int k = getRow();
> - /// printf("%d:", arr[k][i]);
> - /// }
> - /// \endcode
> - /// At first glance, this loop looks like it could be changed to
> - /// \code
> - /// for (int elem : arr[k]) {
> - /// int k = getIndex();
> - /// printf("%d:", elem);
> - /// }
> - /// \endcode
> - /// But this is malformed, since `k` is used before it is defined!
> - ///
> - /// In order to avoid this, this class looks at the container expression
> - /// `arr[k]` and decides whether or not it contains a sub-expression declared
> - /// within the the loop body.
> - bool dependsOnInsideVariable(const clang::Stmt *Body) {
> - DependsOnInsideVariable = false;
> - TraverseStmt(const_cast<clang::Stmt *>(Body));
> - return DependsOnInsideVariable;
> - }
> -
> - friend class clang::RecursiveASTVisitor<DependencyFinderASTVisitor>;
> -
> -private:
> - const StmtParentMap *StmtParents;
> - const DeclParentMap *DeclParents;
> - const clang::Stmt *ContainingStmt;
> - const ReplacedVarsMap *ReplacedVars;
> - bool DependsOnInsideVariable;
> -
> - bool VisitVarDecl(clang::VarDecl *V);
> - bool VisitDeclRefExpr(clang::DeclRefExpr *D);
> -};
> -
> -/// Class used to determine if any declarations used in a Stmt would conflict
> -/// with a particular identifier. This search includes the names that don't
> -/// actually appear in the AST (i.e. created by a refactoring tool) by including
> -/// a map from Stmts to generated names associated with those stmts.
> -class DeclFinderASTVisitor :
> - public clang::RecursiveASTVisitor<DeclFinderASTVisitor> {
> -public:
> - DeclFinderASTVisitor(const std::string &Name,
> - const StmtGeneratedVarNameMap *GeneratedDecls) :
> - Name(Name), GeneratedDecls(GeneratedDecls), Found(false) { }
> -
> - /// Attempts to find any usages of variables name Name in Body, returning
> - /// true when it is used in Body. This includes the generated loop variables
> - /// of ForStmts which have already been transformed.
> - bool findUsages(const clang::Stmt *Body) {
> - Found = false;
> - TraverseStmt(const_cast<clang::Stmt *>(Body));
> - return Found;
> - }
> -
> - friend class clang::RecursiveASTVisitor<DeclFinderASTVisitor>;
> -
> -private:
> - std::string Name;
> - /// GeneratedDecls keeps track of ForStmts which have been transformed,
> - /// mapping each modified ForStmt to the variable generated in the loop.
> - const StmtGeneratedVarNameMap *GeneratedDecls;
> - bool Found;
> -
> - bool VisitForStmt(clang::ForStmt *F);
> - bool VisitNamedDecl(clang::NamedDecl *D);
> - bool VisitDeclRefExpr(clang::DeclRefExpr *D);
> - bool VisitTypeLoc(clang::TypeLoc TL);
> -};
> -
> -#endif // CLANG_MODERNIZE_STMT_ANCESTOR_H
> Index: clang-modernize/LoopConvert/StmtAncestor.cpp
> ===================================================================
> --- clang-modernize/LoopConvert/StmtAncestor.cpp
> +++ /dev/null
> @@ -1,140 +0,0 @@
> -//===-- LoopConvert/StmtAncestor.cpp - AST property visitors --------------===//
> -//
> -// 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 of several RecursiveASTVisitors
> -/// used to build and check data structures used in loop migration.
> -///
> -//===----------------------------------------------------------------------===//
> -
> -#include "StmtAncestor.h"
> -
> -using namespace clang;
> -
> -/// \brief Tracks a stack of parent statements during traversal.
> -///
> -/// All this really does is inject push_back() before running
> -/// RecursiveASTVisitor::TraverseStmt() and pop_back() afterwards. The Stmt atop
> -/// the stack is the parent of the current statement (NULL for the topmost
> -/// statement).
> -bool StmtAncestorASTVisitor::TraverseStmt(Stmt *Statement) {
> - StmtAncestors.insert(std::make_pair(Statement, StmtStack.back()));
> - StmtStack.push_back(Statement);
> - RecursiveASTVisitor<StmtAncestorASTVisitor>::TraverseStmt(Statement);
> - StmtStack.pop_back();
> - return true;
> -}
> -
> -/// \brief Keep track of the DeclStmt associated with each VarDecl.
> -///
> -/// Combined with StmtAncestors, this provides roughly the same information as
> -/// Scope, as we can map a VarDecl to its DeclStmt, then walk up the parent tree
> -/// using StmtAncestors.
> -bool StmtAncestorASTVisitor::VisitDeclStmt(DeclStmt *Decls) {
> - for (DeclStmt::const_decl_iterator I = Decls->decl_begin(),
> - E = Decls->decl_end(); I != E; ++I)
> - if (const VarDecl *V = dyn_cast<VarDecl>(*I))
> - DeclParents.insert(std::make_pair(V, Decls));
> - return true;
> -}
> -
> -/// \brief record the DeclRefExpr as part of the parent expression.
> -bool ComponentFinderASTVisitor::VisitDeclRefExpr(DeclRefExpr *E) {
> - Components.push_back(E);
> - return true;
> -}
> -
> -/// \brief record the MemberExpr as part of the parent expression.
> -bool ComponentFinderASTVisitor::VisitMemberExpr(MemberExpr *Member) {
> - Components.push_back(Member);
> - return true;
> -}
> -
> -/// \brief Forward any DeclRefExprs to a check on the referenced variable
> -/// declaration.
> -bool DependencyFinderASTVisitor::VisitDeclRefExpr(DeclRefExpr *DeclRef) {
> - if (VarDecl *V = dyn_cast_or_null<VarDecl>(DeclRef->getDecl()))
> - return VisitVarDecl(V);
> - return true;
> -}
> -
> -/// \brief Determine if any this variable is declared inside the ContainingStmt.
> -bool DependencyFinderASTVisitor::VisitVarDecl(VarDecl *V) {
> - const Stmt *Curr = DeclParents->lookup(V);
> - // First, see if the variable was declared within an inner scope of the loop.
> - while (Curr != nullptr) {
> - if (Curr == ContainingStmt) {
> - DependsOnInsideVariable = true;
> - return false;
> - }
> - Curr = StmtParents->lookup(Curr);
> - }
> -
> - // Next, check if the variable was removed from existence by an earlier
> - // iteration.
> - for (ReplacedVarsMap::const_iterator I = ReplacedVars->begin(),
> - E = ReplacedVars->end(); I != E; ++I)
> - if ((*I).second == V) {
> - DependsOnInsideVariable = true;
> - return false;
> - }
> - return true;
> -}
> -
> -/// \brief If we already created a variable for TheLoop, check to make sure
> -/// that the name was not already taken.
> -bool DeclFinderASTVisitor::VisitForStmt(ForStmt *TheLoop) {
> - StmtGeneratedVarNameMap::const_iterator I = GeneratedDecls->find(TheLoop);
> - if (I != GeneratedDecls->end() && I->second == Name) {
> - Found = true;
> - return false;
> - }
> - return true;
> -}
> -
> -/// \brief If any named declaration within the AST subtree has the same name,
> -/// then consider Name already taken.
> -bool DeclFinderASTVisitor::VisitNamedDecl(NamedDecl *D) {
> - const IdentifierInfo *Ident = D->getIdentifier();
> - if (Ident && Ident->getName() == Name) {
> - Found = true;
> - return false;
> - }
> - return true;
> -}
> -
> -/// \brief Forward any declaration references to the actual check on the
> -/// referenced declaration.
> -bool DeclFinderASTVisitor::VisitDeclRefExpr(DeclRefExpr *DeclRef) {
> - if (NamedDecl *D = dyn_cast<NamedDecl>(DeclRef->getDecl()))
> - return VisitNamedDecl(D);
> - return true;
> -}
> -
> -/// \brief If the new variable name conflicts with any type used in the loop,
> -/// then we mark that variable name as taken.
> -bool DeclFinderASTVisitor::VisitTypeLoc(TypeLoc TL) {
> - QualType QType = TL.getType();
> -
> - // Check if our name conflicts with a type, to handle for typedefs.
> - if (QType.getAsString() == Name) {
> - Found = true;
> - return false;
> - }
> - // Check for base type conflicts. For example, when a struct is being
> - // referenced in the body of the loop, the above getAsString() will return the
> - // whole type (ex. "struct s"), but will be caught here.
> - if (const IdentifierInfo *Ident = QType.getBaseTypeIdentifier()) {
> - if (Ident->getName() == Name) {
> - Found = true;
> - return false;
> - }
> - }
> - return true;
> -}
> Index: clang-modernize/LoopConvert/LoopMatchers.h
> ===================================================================
> --- clang-modernize/LoopConvert/LoopMatchers.h
> +++ /dev/null
> @@ -1,42 +0,0 @@
> -//===-- LoopConvert/LoopMatchers.h - Matchers for for loops -----*- 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 declarations of the matchers for use in migrating
> -/// C++ for loops. The matchers are responsible for checking the general shape
> -/// of the for loop, namely the init, condition, and increment portions.
> -/// Further analysis will be needed to confirm that the loop is in fact
> -/// convertible in the matcher callback.
> -///
> -//===----------------------------------------------------------------------===//
> -
> -#ifndef CLANG_MODERNIZE_LOOP_MATCHERS_H
> -#define CLANG_MODERNIZE_LOOP_MATCHERS_H
> -
> -#include "clang/ASTMatchers/ASTMatchers.h"
> -
> -// Constants used for matcher name bindings
> -extern const char LoopName[];
> -extern const char ConditionBoundName[];
> -extern const char ConditionVarName[];
> -extern const char ConditionEndVarName[];
> -extern const char IncrementVarName[];
> -extern const char InitVarName[];
> -extern const char BeginCallName[];
> -extern const char EndExprName[];
> -extern const char EndCallName[];
> -extern const char EndVarName[];
> -extern const char DerefByValueResultName[];
> -extern const char DerefByRefResultName[];
> -
> -clang::ast_matchers::StatementMatcher makeArrayLoopMatcher();
> -clang::ast_matchers::StatementMatcher makeIteratorLoopMatcher();
> -clang::ast_matchers::StatementMatcher makePseudoArrayLoopMatcher();
> -
> -#endif // CLANG_MODERNIZE_LOOP_MATCHERS_H
> Index: clang-modernize/LoopConvert/LoopMatchers.cpp
> ===================================================================
> --- clang-modernize/LoopConvert/LoopMatchers.cpp
> +++ /dev/null
> @@ -1,345 +0,0 @@
> -//===-- LoopConvert/LoopMatchers.cpp - Matchers for for loops -------------===//
> -//
> -// 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 definitions of the matchers for use in migrating
> -/// C++ for loops.
> -///
> -//===----------------------------------------------------------------------===//
> -
> -#include "LoopMatchers.h"
> -
> -using namespace clang::ast_matchers;
> -using namespace clang;
> -
> -const char LoopName[] = "forLoop";
> -const char ConditionBoundName[] = "conditionBound";
> -const char ConditionVarName[] = "conditionVar";
> -const char IncrementVarName[] = "incrementVar";
> -const char InitVarName[] = "initVar";
> -const char BeginCallName[] = "beginCall";
> -const char EndCallName[] = "endCall";
> -const char ConditionEndVarName[] = "conditionEndVar";
> -const char EndVarName[] = "endVar";
> -const char DerefByValueResultName[] = "derefByValueResult";
> -const char DerefByRefResultName[] = "derefByRefResult";
> -
> -// shared matchers
> -static const TypeMatcher AnyType = anything();
> -
> -static const StatementMatcher IntegerComparisonMatcher =
> - expr(ignoringParenImpCasts(declRefExpr(to(
> - varDecl(hasType(isInteger())).bind(ConditionVarName)))));
> -
> -static const DeclarationMatcher InitToZeroMatcher =
> - varDecl(hasInitializer(ignoringParenImpCasts(
> - integerLiteral(equals(0))))).bind(InitVarName);
> -
> -static const StatementMatcher IncrementVarMatcher =
> - declRefExpr(to(
> - varDecl(hasType(isInteger())).bind(IncrementVarName)));
> -
> -// FIXME: How best to document complicated matcher expressions? They're fairly
> -// self-documenting...but there may be some unintuitive parts.
> -
> -/// \brief The matcher for loops over arrays.
> -///
> -/// In this general example, assuming 'j' and 'k' are of integral type:
> -/// \code
> -/// for (int i = 0; j < 3 + 2; ++k) { ... }
> -/// \endcode
> -/// The following string identifiers are bound to these parts of the AST:
> -/// ConditionVarName: 'j' (as a VarDecl)
> -/// ConditionBoundName: '3 + 2' (as an Expr)
> -/// InitVarName: 'i' (as a VarDecl)
> -/// IncrementVarName: 'k' (as a VarDecl)
> -/// LoopName: The entire for loop (as a ForStmt)
> -///
> -/// Client code will need to make sure that:
> -/// - The three index variables identified by the matcher are the same
> -/// VarDecl.
> -/// - The index variable is only used as an array index.
> -/// - All arrays indexed by the loop are the same.
> -StatementMatcher makeArrayLoopMatcher() {
> - StatementMatcher ArrayBoundMatcher =
> - expr(hasType(isInteger())).bind(ConditionBoundName);
> -
> - return forStmt(
> - hasLoopInit(declStmt(hasSingleDecl(InitToZeroMatcher))),
> - hasCondition(anyOf(binaryOperator(hasOperatorName("<"),
> - hasLHS(IntegerComparisonMatcher),
> - hasRHS(ArrayBoundMatcher)),
> - binaryOperator(hasOperatorName(">"),
> - hasLHS(ArrayBoundMatcher),
> - hasRHS(IntegerComparisonMatcher)))),
> - hasIncrement(unaryOperator(hasOperatorName("++"),
> - hasUnaryOperand(IncrementVarMatcher))))
> - .bind(LoopName);
> -}
> -
> -/// \brief The matcher used for iterator-based for loops.
> -///
> -/// This matcher is more flexible than array-based loops. It will match
> -/// catch loops of the following textual forms (regardless of whether the
> -/// iterator type is actually a pointer type or a class type):
> -///
> -/// Assuming f, g, and h are of type containerType::iterator,
> -/// \code
> -/// for (containerType::iterator it = container.begin(),
> -/// e = createIterator(); f != g; ++h) { ... }
> -/// for (containerType::iterator it = container.begin();
> -/// f != anotherContainer.end(); ++h) { ... }
> -/// \endcode
> -/// The following string identifiers are bound to the parts of the AST:
> -/// InitVarName: 'it' (as a VarDecl)
> -/// ConditionVarName: 'f' (as a VarDecl)
> -/// LoopName: The entire for loop (as a ForStmt)
> -/// In the first example only:
> -/// EndVarName: 'e' (as a VarDecl)
> -/// ConditionEndVarName: 'g' (as a VarDecl)
> -/// In the second example only:
> -/// EndCallName: 'container.end()' (as a CXXMemberCallExpr)
> -///
> -/// Client code will need to make sure that:
> -/// - The iterator variables 'it', 'f', and 'h' are the same
> -/// - The two containers on which 'begin' and 'end' are called are the same
> -/// - If the end iterator variable 'g' is defined, it is the same as 'f'
> -StatementMatcher makeIteratorLoopMatcher() {
> - StatementMatcher BeginCallMatcher =
> - cxxMemberCallExpr(
> - argumentCountIs(0),
> - callee(
> - cxxMethodDecl(hasName("begin"))
> - )
> - ).bind(BeginCallName);
> -
> - DeclarationMatcher InitDeclMatcher =
> - varDecl(
> - hasInitializer(
> - anyOf(
> - ignoringParenImpCasts(BeginCallMatcher),
> - materializeTemporaryExpr(ignoringParenImpCasts(BeginCallMatcher)),
> - hasDescendant(BeginCallMatcher)
> - )
> - )
> - ).bind(InitVarName);
> -
> - DeclarationMatcher EndDeclMatcher =
> - varDecl(hasInitializer(anything())).bind(EndVarName);
> -
> - StatementMatcher EndCallMatcher = cxxMemberCallExpr(
> - argumentCountIs(0), callee(cxxMethodDecl(hasName("end"))));
> -
> - StatementMatcher IteratorBoundMatcher =
> - expr(anyOf(ignoringParenImpCasts(declRefExpr(to(
> - varDecl().bind(ConditionEndVarName)))),
> - ignoringParenImpCasts(
> - expr(EndCallMatcher).bind(EndCallName)),
> - materializeTemporaryExpr(ignoringParenImpCasts(
> - expr(EndCallMatcher).bind(EndCallName)))));
> -
> - StatementMatcher IteratorComparisonMatcher =
> - expr(ignoringParenImpCasts(declRefExpr(to(
> - varDecl().bind(ConditionVarName)))));
> -
> - StatementMatcher OverloadedNEQMatcher = cxxOperatorCallExpr(
> - hasOverloadedOperatorName("!="),
> - argumentCountIs(2),
> - hasArgument(0, IteratorComparisonMatcher),
> - hasArgument(1, IteratorBoundMatcher));
> -
> - // This matcher tests that a declaration is a CXXRecordDecl that has an
> - // overloaded operator*(). If the operator*() returns by value instead of by
> - // reference then the return type is tagged with DerefByValueResultName.
> - internal::Matcher<VarDecl> TestDerefReturnsByValue =
> - hasType(
> - cxxRecordDecl(
> - hasMethod(
> - allOf(
> - hasOverloadedOperatorName("*"),
> - anyOf(
> - // Tag the return type if it's by value.
> - returns(
> - qualType(
> - unless(hasCanonicalType(referenceType()))
> - ).bind(DerefByValueResultName)
> - ),
> - returns(
> - // Skip loops where the iterator's operator* returns an
> - // rvalue reference. This is just weird.
> - qualType(
> - unless(
> - hasCanonicalType(rValueReferenceType())
> - )
> - ).bind(DerefByRefResultName)
> - )
> - )
> - )
> - )
> - )
> - );
> -
> -
> - return
> - forStmt(
> - hasLoopInit(anyOf(
> - declStmt(
> - declCountIs(2),
> - containsDeclaration(0, InitDeclMatcher),
> - containsDeclaration(1, EndDeclMatcher)
> - ),
> - declStmt(hasSingleDecl(InitDeclMatcher))
> - )),
> - hasCondition(anyOf(
> - binaryOperator(
> - hasOperatorName("!="),
> - hasLHS(IteratorComparisonMatcher),
> - hasRHS(IteratorBoundMatcher)
> - ),
> - binaryOperator(
> - hasOperatorName("!="),
> - hasLHS(IteratorBoundMatcher),
> - hasRHS(IteratorComparisonMatcher)
> - ),
> - OverloadedNEQMatcher
> - )),
> - hasIncrement(anyOf(
> - unaryOperator(
> - hasOperatorName("++"),
> - hasUnaryOperand(
> - declRefExpr(to(
> - varDecl(hasType(pointsTo(AnyType))).bind(IncrementVarName)
> - ))
> - )
> - ),
> - cxxOperatorCallExpr(
> - hasOverloadedOperatorName("++"),
> - hasArgument(0,
> - declRefExpr(to(
> - varDecl(TestDerefReturnsByValue).bind(IncrementVarName)
> - ))
> - )
> - )
> - ))
> - ).bind(LoopName);
> -}
> -
> -/// \brief The matcher used for array-like containers (pseudoarrays).
> -///
> -/// This matcher is more flexible than array-based loops. It will match
> -/// loops of the following textual forms (regardless of whether the
> -/// iterator type is actually a pointer type or a class type):
> -///
> -/// Assuming f, g, and h are of type containerType::iterator,
> -/// \code
> -/// for (int i = 0, j = container.size(); f < g; ++h) { ... }
> -/// for (int i = 0; f < container.size(); ++h) { ... }
> -/// \endcode
> -/// The following string identifiers are bound to the parts of the AST:
> -/// InitVarName: 'i' (as a VarDecl)
> -/// ConditionVarName: 'f' (as a VarDecl)
> -/// LoopName: The entire for loop (as a ForStmt)
> -/// In the first example only:
> -/// EndVarName: 'j' (as a VarDecl)
> -/// ConditionEndVarName: 'g' (as a VarDecl)
> -/// In the second example only:
> -/// EndCallName: 'container.size()' (as a CXXMemberCallExpr)
> -///
> -/// Client code will need to make sure that:
> -/// - The index variables 'i', 'f', and 'h' are the same
> -/// - The containers on which 'size()' is called is the container indexed
> -/// - The index variable is only used in overloaded operator[] or
> -/// container.at()
> -/// - If the end iterator variable 'g' is defined, it is the same as 'j'
> -/// - The container's iterators would not be invalidated during the loop
> -StatementMatcher makePseudoArrayLoopMatcher() {
> - // Test that the incoming type has a record declaration that has methods
> - // called 'begin' and 'end'. If the incoming type is const, then make sure
> - // these methods are also marked const.
> - //
> - // FIXME: To be completely thorough this matcher should also ensure the
> - // return type of begin/end is an iterator that dereferences to the same as
> - // what operator[] or at() returns. Such a test isn't likely to fail except
> - // for pathological cases.
> - //
> - // FIXME: Also, a record doesn't necessarily need begin() and end(). Free
> - // functions called begin() and end() taking the container as an argument
> - // are also allowed.
> - TypeMatcher RecordWithBeginEnd =
> - qualType(anyOf(
> - qualType(
> - isConstQualified(),
> - hasDeclaration(
> - cxxRecordDecl(
> - hasMethod(
> - cxxMethodDecl(
> - hasName("begin"),
> - isConst()
> - )
> - ),
> - hasMethod(
> - cxxMethodDecl(
> - hasName("end"),
> - isConst()
> - )
> - )
> - )
> - ) // hasDeclaration
> - ), // qualType
> - qualType(
> - unless(isConstQualified()),
> - hasDeclaration(
> - cxxRecordDecl(
> - hasMethod(hasName("begin")),
> - hasMethod(hasName("end"))
> - )
> - )
> - ) // qualType
> - )
> - );
> -
> - StatementMatcher SizeCallMatcher = cxxMemberCallExpr(
> - argumentCountIs(0),
> - callee(cxxMethodDecl(anyOf(hasName("size"), hasName("length")))),
> - on(anyOf(hasType(pointsTo(RecordWithBeginEnd)),
> - hasType(RecordWithBeginEnd))));
> -
> - StatementMatcher EndInitMatcher =
> - expr(anyOf(
> - ignoringParenImpCasts(expr(SizeCallMatcher).bind(EndCallName)),
> - explicitCastExpr(hasSourceExpression(ignoringParenImpCasts(
> - expr(SizeCallMatcher).bind(EndCallName))))));
> -
> - DeclarationMatcher EndDeclMatcher =
> - varDecl(hasInitializer(EndInitMatcher)).bind(EndVarName);
> -
> - StatementMatcher IndexBoundMatcher =
> - expr(anyOf(
> - ignoringParenImpCasts(declRefExpr(to(
> - varDecl(hasType(isInteger())).bind(ConditionEndVarName)))),
> - EndInitMatcher));
> -
> - return forStmt(
> - hasLoopInit(anyOf(
> - declStmt(declCountIs(2),
> - containsDeclaration(0, InitToZeroMatcher),
> - containsDeclaration(1, EndDeclMatcher)),
> - declStmt(hasSingleDecl(InitToZeroMatcher)))),
> - hasCondition(anyOf(
> - binaryOperator(hasOperatorName("<"),
> - hasLHS(IntegerComparisonMatcher),
> - hasRHS(IndexBoundMatcher)),
> - binaryOperator(hasOperatorName(">"),
> - hasLHS(IndexBoundMatcher),
> - hasRHS(IntegerComparisonMatcher)))),
> - hasIncrement(unaryOperator(
> - hasOperatorName("++"),
> - hasUnaryOperand(IncrementVarMatcher))))
> - .bind(LoopName);
> -}
> Index: clang-modernize/LoopConvert/LoopConvert.h
> ===================================================================
> --- clang-modernize/LoopConvert/LoopConvert.h
> +++ /dev/null
> @@ -1,44 +0,0 @@
> -//===-- 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 LoopConvertTransform
> -/// class which is the main interface to the loop-convert transform that tries
> -/// to make use of range-based for loops where possible.
> -///
> -//===----------------------------------------------------------------------===//
> -
> -#ifndef CLANG_MODERNIZE_LOOP_CONVERT_H
> -#define CLANG_MODERNIZE_LOOP_CONVERT_H
> -
> -#include "Core/Transform.h"
> -#include "llvm/Support/Compiler.h" // For override
> -
> -// Forward decl for private implementation.
> -struct TUTrackingInfo;
> -
> -/// \brief Subclass of Transform that transforms for-loops into range-based
> -/// for-loops where possible.
> -class LoopConvertTransform : public Transform {
> -public:
> - LoopConvertTransform(const TransformOptions &Options)
> - : Transform("LoopConvert", Options) {}
> -
> - /// \see Transform::run().
> - int apply(const clang::tooling::CompilationDatabase &Database,
> - const std::vector<std::string> &SourcePaths) override;
> -
> - bool handleBeginSource(clang::CompilerInstance &CI,
> - llvm::StringRef Filename) override;
> -
> -private:
> - std::unique_ptr<TUTrackingInfo> TUInfo;
> -};
> -
> -#endif // CLANG_MODERNIZE_LOOP_CONVERT_H
> Index: clang-modernize/LoopConvert/LoopConvert.cpp
> ===================================================================
> --- clang-modernize/LoopConvert/LoopConvert.cpp
> +++ /dev/null
> @@ -1,93 +0,0 @@
> -//===-- LoopConvert/LoopConvert.cpp - C++11 for-loop migration ------------===//
> -//
> -// 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 LoopConvertTransform
> -/// class.
> -///
> -//===----------------------------------------------------------------------===//
> -
> -#include "LoopConvert.h"
> -#include "LoopActions.h"
> -#include "LoopMatchers.h"
> -#include "clang/Frontend/FrontendActions.h"
> -#include "clang/Tooling/Refactoring.h"
> -#include "clang/Tooling/Tooling.h"
> -
> -using clang::ast_matchers::MatchFinder;
> -using namespace clang::tooling;
> -using namespace clang;
> -
> -int LoopConvertTransform::apply(const CompilationDatabase &Database,
> - const std::vector<std::string> &SourcePaths) {
> - ClangTool LoopTool(Database, SourcePaths);
> -
> - unsigned AcceptedChanges = 0;
> - unsigned DeferredChanges = 0;
> - unsigned RejectedChanges = 0;
> -
> - TUInfo.reset(new TUTrackingInfo);
> -
> - MatchFinder Finder;
> - LoopFixer ArrayLoopFixer(*TUInfo, &AcceptedChanges, &DeferredChanges,
> - &RejectedChanges, Options().MaxRiskLevel, LFK_Array,
> - /*Owner=*/ *this);
> - Finder.addMatcher(makeArrayLoopMatcher(), &ArrayLoopFixer);
> - LoopFixer IteratorLoopFixer(*TUInfo, &AcceptedChanges, &DeferredChanges,
> - &RejectedChanges, Options().MaxRiskLevel,
> - LFK_Iterator, /*Owner=*/ *this);
> - Finder.addMatcher(makeIteratorLoopMatcher(), &IteratorLoopFixer);
> - LoopFixer PseudoarrrayLoopFixer(*TUInfo, &AcceptedChanges, &DeferredChanges,
> - &RejectedChanges, Options().MaxRiskLevel,
> - LFK_PseudoArray, /*Owner=*/ *this);
> - Finder.addMatcher(makePseudoArrayLoopMatcher(), &PseudoarrrayLoopFixer);
> -
> - if (int result = LoopTool.run(createActionFactory(Finder).get())) {
> - llvm::errs() << "Error encountered during translation.\n";
> - return result;
> - }
> -
> - setAcceptedChanges(AcceptedChanges);
> - setRejectedChanges(RejectedChanges);
> - setDeferredChanges(DeferredChanges);
> -
> - return 0;
> -}
> -
> -bool
> -LoopConvertTransform::handleBeginSource(clang::CompilerInstance &CI,
> - llvm::StringRef Filename) {
> - // Reset and initialize per-TU tracking structures.
> - TUInfo->reset();
> -
> - return Transform::handleBeginSource(CI, Filename);
> -}
> -
> -namespace {
> -struct LoopConvertFactory : TransformFactory {
> - LoopConvertFactory() {
> - Since.Clang = Version(3, 0);
> - Since.Gcc = Version(4, 6);
> - Since.Icc = Version(13);
> - Since.Msvc = Version(11);
> - }
> -
> - Transform *createTransform(const TransformOptions &Opts) override {
> - return new LoopConvertTransform(Opts);
> - }
> -};
> -} // namespace
> -
> -// Register the factory using this statically initialized variable.
> -static TransformFactoryRegistry::Add<LoopConvertFactory>
> -X("loop-convert", "Make use of range-based for loops where possible");
> -
> -// This anchor is used to force the linker to link in the generated object file
> -// and thus register the factory.
> -volatile int LoopConvertTransformAnchorSource = 0;
> Index: clang-modernize/LoopConvert/LoopActions.h
> ===================================================================
> --- clang-modernize/LoopConvert/LoopActions.h
> +++ /dev/null
> @@ -1,116 +0,0 @@
> -//===-- LoopConvert/LoopActions.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 declares matchers and callbacks for use in migrating C++
> -/// for loops.
> -///
> -//===----------------------------------------------------------------------===//
> -
> -#ifndef CLANG_MODERNIZE_LOOP_ACTIONS_H
> -#define CLANG_MODERNIZE_LOOP_ACTIONS_H
> -
> -#include "Core/Transform.h"
> -#include "StmtAncestor.h"
> -#include "clang/AST/ASTContext.h"
> -#include "clang/AST/RecursiveASTVisitor.h"
> -#include "clang/ASTMatchers/ASTMatchFinder.h"
> -#include "clang/Tooling/Refactoring.h"
> -
> -struct Usage;
> -class Confidence;
> -// The main computational result of ForLoopIndexUseVisitor.
> -typedef llvm::SmallVector<Usage, 8> UsageResult;
> -
> -enum LoopFixerKind {
> - LFK_Array,
> - LFK_Iterator,
> - LFK_PseudoArray
> -};
> -
> -struct TUTrackingInfo {
> -
> - /// \brief Reset and initialize per-TU tracking information.
> - ///
> - /// Must be called before using container accessors.
> - void reset() {
> - ParentFinder.reset(new StmtAncestorASTVisitor);
> - GeneratedDecls.clear();
> - ReplacedVars.clear();
> - }
> -
> - /// \name Accessors
> - /// \{
> - StmtAncestorASTVisitor &getParentFinder() { return *ParentFinder; }
> - StmtGeneratedVarNameMap &getGeneratedDecls() { return GeneratedDecls; }
> - ReplacedVarsMap &getReplacedVars() { return ReplacedVars; }
> - /// \}
> -
> -private:
> - std::unique_ptr<StmtAncestorASTVisitor> ParentFinder;
> - StmtGeneratedVarNameMap GeneratedDecls;
> - ReplacedVarsMap ReplacedVars;
> -};
> -
> -/// \brief The callback to be used for loop migration matchers.
> -///
> -/// The callback does extra checking not possible in matchers, and attempts to
> -/// convert the for loop, if possible.
> -class LoopFixer : public clang::ast_matchers::MatchFinder::MatchCallback {
> -public:
> - LoopFixer(TUTrackingInfo &TUInfo, unsigned *AcceptedChanges,
> - unsigned *DeferredChanges, unsigned *RejectedChanges,
> - RiskLevel MaxRisk, LoopFixerKind FixerKind, Transform &Owner)
> - : TUInfo(TUInfo), AcceptedChanges(AcceptedChanges),
> - DeferredChanges(DeferredChanges), RejectedChanges(RejectedChanges),
> - MaxRisk(MaxRisk), FixerKind(FixerKind), Owner(Owner) {}
> -
> - void
> - run(const clang::ast_matchers::MatchFinder::MatchResult &Result) override;
> -
> -private:
> - TUTrackingInfo &TUInfo;
> - unsigned *AcceptedChanges;
> - unsigned *DeferredChanges;
> - unsigned *RejectedChanges;
> - RiskLevel MaxRisk;
> - LoopFixerKind FixerKind;
> - Transform &Owner;
> -
> - /// \brief Computes the changes needed to convert a given for loop, and
> - /// applies it.
> - void doConversion(clang::ASTContext *Context, const clang::VarDecl *IndexVar,
> - const clang::VarDecl *MaybeContainer,
> - llvm::StringRef ContainerString, const UsageResult &Usages,
> - const clang::DeclStmt *AliasDecl, bool AliasUseRequired,
> - bool AliasFromForInit, const clang::ForStmt *TheLoop,
> - bool ContainerNeedsDereference, bool DerefByValue,
> - bool DerefByConstRef);
> -
> - /// \brief Given a loop header that would be convertible, discover all usages
> - /// of the index variable and convert the loop if possible.
> - void findAndVerifyUsages(clang::ASTContext *Context,
> - const clang::VarDecl *LoopVar,
> - const clang::VarDecl *EndVar,
> - const clang::Expr *ContainerExpr,
> - const clang::Expr *BoundExpr,
> - bool ContainerNeedsDereference, bool DerefByValue,
> - bool DerefByConstRef, const clang::ForStmt *TheLoop,
> - Confidence ConfidenceLevel);
> -
> - /// \brief Determine if the change should be deferred or rejected, returning
> - /// text which refers to the container iterated over if the change should
> - /// proceed.
> - llvm::StringRef checkDeferralsAndRejections(clang::ASTContext *Context,
> - const clang::Expr *ContainerExpr,
> - Confidence ConfidenceLevel,
> - const clang::ForStmt *TheLoop);
> -};
> -
> -#endif // CLANG_MODERNIZE_LOOP_ACTIONS_H
> Index: clang-modernize/LoopConvert/LoopActions.cpp
> ===================================================================
> --- clang-modernize/LoopConvert/LoopActions.cpp
> +++ /dev/null
> @@ -1,1143 +0,0 @@
> -//===-- LoopConvert/LoopActions.cpp - C++11 For loop migration ------------===//
> -//
> -// 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 defines matchers and callbacks for use in migrating C++
> -/// for loops.
> -///
> -//===----------------------------------------------------------------------===//
> -
> -#include "LoopActions.h"
> -#include "LoopMatchers.h"
> -#include "VariableNaming.h"
> -#include "clang/Lex/Lexer.h"
> -
> -using namespace clang::ast_matchers;
> -using namespace clang::tooling;
> -using namespace clang;
> -
> -/// \brief The information needed to describe a valid convertible usage
> -/// of an array index or iterator.
> -struct Usage {
> - const Expr *E;
> - bool IsArrow;
> - SourceRange Range;
> -
> - explicit Usage(const Expr *E)
> - : E(E), IsArrow(false), Range(E->getSourceRange()) { }
> - Usage(const Expr *E, bool IsArrow, SourceRange Range)
> - : E(E), IsArrow(IsArrow), Range(Range) { }
> -};
> -
> -/// \brief A class to encapsulate lowering of the tool's confidence level.
> -///
> -/// Confidence is a quantity opposite in meaning to Risk. Since clang-modernize
> -/// uses risk, this class reverses the meaning for the legacy loop convert
> -/// code.
> -class Confidence {
> -public:
> - /// \brief Initialize confidence level.
> - explicit Confidence(RiskLevel Level) :
> - CurrentLevel(Level) {}
> -
> - /// \brief Lower the internal confidence level to Level, but do not raise it.
> - void lowerTo(RiskLevel Level) {
> - CurrentLevel = std::max(Level, CurrentLevel);
> - }
> -
> - /// \brief Return the internal confidence level.
> - RiskLevel getRiskLevel() const { return CurrentLevel; }
> -
> -private:
> - RiskLevel CurrentLevel;
> -};
> -
> -/// \brief Discover usages of expressions consisting of index or iterator
> -/// access.
> -///
> -/// Given an index variable, recursively crawls a for loop to discover if the
> -/// index variable is used in a way consistent with range-based for loop access.
> -class ForLoopIndexUseVisitor
> - : public RecursiveASTVisitor<ForLoopIndexUseVisitor> {
> - public:
> - ForLoopIndexUseVisitor(ASTContext *Context, const VarDecl *IndexVar,
> - const VarDecl *EndVar, const Expr *ContainerExpr,
> - const Expr *ArrayBoundExpr,
> - bool ContainerNeedsDereference) :
> - Context(Context), IndexVar(IndexVar), EndVar(EndVar),
> - ContainerExpr(ContainerExpr), ArrayBoundExpr(ArrayBoundExpr),
> - ContainerNeedsDereference(ContainerNeedsDereference),
> - OnlyUsedAsIndex(true), AliasDecl(nullptr), ConfidenceLevel(RL_Safe),
> - NextStmtParent(nullptr), CurrStmtParent(nullptr),
> - ReplaceWithAliasUse(false), AliasFromForInit(false) {
> - if (ContainerExpr) {
> - addComponent(ContainerExpr);
> - llvm::FoldingSetNodeID ID;
> - const Expr *E = ContainerExpr->IgnoreParenImpCasts();
> - E->Profile(ID, *Context, true);
> - }
> - }
> -
> - /// \brief Finds all uses of IndexVar in Body, placing all usages in Usages,
> - /// and returns true if IndexVar was only used in a way consistent with a
> - /// range-based for loop.
> - ///
> - /// The general strategy is to reject any DeclRefExprs referencing IndexVar,
> - /// with the exception of certain acceptable patterns.
> - /// For arrays, the DeclRefExpr for IndexVar must appear as the index of an
> - /// ArraySubscriptExpression. Iterator-based loops may dereference
> - /// IndexVar or call methods through operator-> (builtin or overloaded).
> - /// Array-like containers may use IndexVar as a parameter to the at() member
> - /// function and in overloaded operator[].
> - bool findAndVerifyUsages(const Stmt *Body) {
> - TraverseStmt(const_cast<Stmt *>(Body));
> - return OnlyUsedAsIndex && ContainerExpr;
> - }
> -
> - /// \brief Add a set of components that we should consider relevant to the
> - /// container.
> - void addComponents(const ComponentVector &Components) {
> - // FIXME: add sort(on ID)+unique to avoid extra work.
> - for (ComponentVector::const_iterator I = Components.begin(),
> - E = Components.end(); I != E; ++I)
> - addComponent(*I);
> - }
> -
> - /// \brief Accessor for Usages.
> - const UsageResult &getUsages() const { return Usages; }
> -
> - /// \brief Get the container indexed by IndexVar, if any.
> - const Expr *getContainerIndexed() const {
> - return ContainerExpr;
> - }
> -
> - /// \brief Returns the statement declaring the variable created as an alias
> - /// for the loop element, if any.
> - const DeclStmt *getAliasDecl() const { return AliasDecl; }
> -
> - /// \brief Accessor for ConfidenceLevel.
> - RiskLevel getRiskLevel() const {
> - return ConfidenceLevel.getRiskLevel();
> - }
> -
> - /// \brief Indicates if the alias declaration was in a place where it cannot
> - /// simply be removed but rather replaced with a use of the alias variable.
> - /// For example, variables declared in the condition of an if, switch, or for
> - /// stmt.
> - bool aliasUseRequired() const { return ReplaceWithAliasUse; }
> -
> - /// \brief Indicates if the alias declaration came from the init clause of a
> - /// nested for loop. SourceRanges provided by Clang for DeclStmts in this
> - /// case need to be adjusted.
> - bool aliasFromForInit() const { return AliasFromForInit; }
> -
> - private:
> - /// Typedef used in CRTP functions.
> - typedef RecursiveASTVisitor<ForLoopIndexUseVisitor> VisitorBase;
> - friend class RecursiveASTVisitor<ForLoopIndexUseVisitor>;
> -
> - /// Overriden methods for RecursiveASTVisitor's traversal.
> - bool TraverseArraySubscriptExpr(ArraySubscriptExpr *E);
> - bool TraverseCXXMemberCallExpr(CXXMemberCallExpr *MemberCall);
> - bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *OpCall);
> - bool TraverseMemberExpr(MemberExpr *Member);
> - bool TraverseUnaryDeref(UnaryOperator *Uop);
> - bool VisitDeclRefExpr(DeclRefExpr *E);
> - bool VisitDeclStmt(DeclStmt *S);
> - bool TraverseStmt(Stmt *S);
> -
> - /// \brief Add an expression to the list of expressions on which the container
> - /// expression depends.
> - void addComponent(const Expr *E) {
> - llvm::FoldingSetNodeID ID;
> - const Expr *Node = E->IgnoreParenImpCasts();
> - Node->Profile(ID, *Context, true);
> - DependentExprs.push_back(std::make_pair(Node, ID));
> - }
> -
> - // Input member variables:
> - ASTContext *Context;
> - /// The index variable's VarDecl.
> - const VarDecl *IndexVar;
> - /// The loop's 'end' variable, which cannot be mentioned at all.
> - const VarDecl *EndVar;
> - /// The Expr which refers to the container.
> - const Expr *ContainerExpr;
> - /// The Expr which refers to the terminating condition for array-based loops.
> - const Expr *ArrayBoundExpr;
> - bool ContainerNeedsDereference;
> -
> - // Output member variables:
> - /// A container which holds all usages of IndexVar as the index of
> - /// ArraySubscriptExpressions.
> - UsageResult Usages;
> - bool OnlyUsedAsIndex;
> - /// The DeclStmt for an alias to the container element.
> - const DeclStmt *AliasDecl;
> - Confidence ConfidenceLevel;
> - /// \brief A list of expressions on which ContainerExpr depends.
> - ///
> - /// If any of these expressions are encountered outside of an acceptable usage
> - /// of the loop element, lower our confidence level.
> - llvm::SmallVector<
> - std::pair<const Expr *, llvm::FoldingSetNodeID>, 16> DependentExprs;
> -
> - /// The parent-in-waiting. Will become the real parent once we traverse down
> - /// one level in the AST.
> - const Stmt *NextStmtParent;
> - /// The actual parent of a node when Visit*() calls are made. Only the
> - /// parentage of DeclStmt's to possible iteration/selection statements is of
> - /// importance.
> - const Stmt *CurrStmtParent;
> -
> - /// \see aliasUseRequired().
> - bool ReplaceWithAliasUse;
> - /// \see aliasFromForInit().
> - bool AliasFromForInit;
> -};
> -
> -/// \brief Obtain the original source code text from a SourceRange.
> -static StringRef getStringFromRange(SourceManager &SourceMgr,
> - const LangOptions &LangOpts,
> - SourceRange Range) {
> - if (SourceMgr.getFileID(Range.getBegin()) !=
> - SourceMgr.getFileID(Range.getEnd()))
> - return nullptr;
> -
> - CharSourceRange SourceChars(Range, true);
> - return Lexer::getSourceText(SourceChars, SourceMgr, LangOpts);
> -}
> -
> -/// \brief Returns the DeclRefExpr represented by E, or NULL if there isn't one.
> -static const DeclRefExpr *getDeclRef(const Expr *E) {
> - return dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts());
> -}
> -
> -/// \brief If the given expression is actually a DeclRefExpr, find and return
> -/// the underlying VarDecl; otherwise, return NULL.
> -static const VarDecl *getReferencedVariable(const Expr *E) {
> - if (const DeclRefExpr *DRE = getDeclRef(E))
> - return dyn_cast<VarDecl>(DRE->getDecl());
> - return nullptr;
> -}
> -
> -/// \brief Returns true when the given expression is a member expression
> -/// whose base is `this` (implicitly or not).
> -static bool isDirectMemberExpr(const Expr *E) {
> - if (const MemberExpr *Member = dyn_cast<MemberExpr>(E->IgnoreParenImpCasts()))
> - return isa<CXXThisExpr>(Member->getBase()->IgnoreParenImpCasts());
> - return false;
> -}
> -
> -/// \brief Returns true when two ValueDecls are the same variable.
> -static bool areSameVariable(const ValueDecl *First, const ValueDecl *Second) {
> - return First && Second &&
> - First->getCanonicalDecl() == Second->getCanonicalDecl();
> -}
> -
> -/// \brief Determines if an expression is a declaration reference to a
> -/// particular variable.
> -static bool exprReferencesVariable(const ValueDecl *Target, const Expr *E) {
> - if (!Target || !E)
> - return false;
> - const DeclRefExpr *Decl = getDeclRef(E);
> - return Decl && areSameVariable(Target, Decl->getDecl());
> -}
> -
> -/// \brief Returns true when two Exprs are equivalent.
> -static bool areSameExpr(ASTContext *Context, const Expr *First,
> - const Expr *Second) {
> - if (!First || !Second)
> - return false;
> -
> - llvm::FoldingSetNodeID FirstID, SecondID;
> - First->Profile(FirstID, *Context, true);
> - Second->Profile(SecondID, *Context, true);
> - return FirstID == SecondID;
> -}
> -
> -/// \brief Look through conversion/copy constructors to find the explicit
> -/// initialization expression, returning it is found.
> -///
> -/// The main idea is that given
> -/// vector<int> v;
> -/// we consider either of these initializations
> -/// vector<int>::iterator it = v.begin();
> -/// vector<int>::iterator it(v.begin());
> -/// and retrieve `v.begin()` as the expression used to initialize `it` but do
> -/// not include
> -/// vector<int>::iterator it;
> -/// vector<int>::iterator it(v.begin(), 0); // if this constructor existed
> -/// as being initialized from `v.begin()`
> -static const Expr *digThroughConstructors(const Expr *E) {
> - if (!E)
> - return nullptr;
> - E = E->IgnoreParenImpCasts();
> - if (const CXXConstructExpr *ConstructExpr = dyn_cast<CXXConstructExpr>(E)) {
> - // The initial constructor must take exactly one parameter, but base class
> - // and deferred constructors can take more.
> - if (ConstructExpr->getNumArgs() != 1 ||
> - ConstructExpr->getConstructionKind() != CXXConstructExpr::CK_Complete)
> - return nullptr;
> - E = ConstructExpr->getArg(0);
> - if (const MaterializeTemporaryExpr *Temp =
> - dyn_cast<MaterializeTemporaryExpr>(E))
> - E = Temp->GetTemporaryExpr();
> - return digThroughConstructors(E);
> - }
> - return E;
> -}
> -
> -/// \brief If the expression is a dereference or call to operator*(), return the
> -/// operand. Otherwise, return NULL.
> -static const Expr *getDereferenceOperand(const Expr *E) {
> - if (const UnaryOperator *Uop = dyn_cast<UnaryOperator>(E))
> - return Uop->getOpcode() == UO_Deref ? Uop->getSubExpr() : nullptr;
> -
> - if (const CXXOperatorCallExpr *OpCall = dyn_cast<CXXOperatorCallExpr>(E))
> - return OpCall->getOperator() == OO_Star && OpCall->getNumArgs() == 1 ?
> - OpCall->getArg(0) : nullptr;
> -
> - return nullptr;
> -}
> -
> -/// \brief Returns true when the Container contains an Expr equivalent to E.
> -template<typename ContainerT>
> -static bool containsExpr(ASTContext *Context, const ContainerT *Container,
> - const Expr *E) {
> - llvm::FoldingSetNodeID ID;
> - E->Profile(ID, *Context, true);
> - for (typename ContainerT::const_iterator I = Container->begin(),
> - End = Container->end(); I != End; ++I)
> - if (ID == I->second)
> - return true;
> - return false;
> -}
> -
> -/// \brief Returns true when the index expression is a declaration reference to
> -/// IndexVar.
> -///
> -/// If the index variable is `index`, this function returns true on
> -/// arrayExpression[index];
> -/// containerExpression[index];
> -/// but not
> -/// containerExpression[notIndex];
> -static bool isIndexInSubscriptExpr(const Expr *IndexExpr,
> - const VarDecl *IndexVar) {
> - const DeclRefExpr *Idx = getDeclRef(IndexExpr);
> - return Idx && Idx->getType()->isIntegerType()
> - && areSameVariable(IndexVar, Idx->getDecl());
> -}
> -
> -/// \brief Returns true when the index expression is a declaration reference to
> -/// IndexVar, Obj is the same expression as SourceExpr after all parens and
> -/// implicit casts are stripped off.
> -///
> -/// If PermitDeref is true, IndexExpression may
> -/// be a dereference (overloaded or builtin operator*).
> -///
> -/// This function is intended for array-like containers, as it makes sure that
> -/// both the container and the index match.
> -/// If the loop has index variable `index` and iterates over `container`, then
> -/// isIndexInSubscriptExpr returns true for
> -/// \code
> -/// container[index]
> -/// container.at(index)
> -/// container->at(index)
> -/// \endcode
> -/// but not for
> -/// \code
> -/// container[notIndex]
> -/// notContainer[index]
> -/// \endcode
> -/// If PermitDeref is true, then isIndexInSubscriptExpr additionally returns
> -/// true on these expressions:
> -/// \code
> -/// (*container)[index]
> -/// (*container).at(index)
> -/// \endcode
> -static bool isIndexInSubscriptExpr(ASTContext *Context, const Expr *IndexExpr,
> - const VarDecl *IndexVar, const Expr *Obj,
> - const Expr *SourceExpr, bool PermitDeref) {
> - if (!SourceExpr || !Obj || !isIndexInSubscriptExpr(IndexExpr, IndexVar))
> - return false;
> -
> - if (areSameExpr(Context, SourceExpr->IgnoreParenImpCasts(),
> - Obj->IgnoreParenImpCasts()))
> - return true;
> -
> - if (const Expr *InnerObj = getDereferenceOperand(Obj->IgnoreParenImpCasts()))
> - if (PermitDeref && areSameExpr(Context, SourceExpr->IgnoreParenImpCasts(),
> - InnerObj->IgnoreParenImpCasts()))
> - return true;
> -
> - return false;
> -}
> -
> -/// \brief Returns true when Opcall is a call a one-parameter dereference of
> -/// IndexVar.
> -///
> -/// For example, if the index variable is `index`, returns true for
> -/// *index
> -/// but not
> -/// index
> -/// *notIndex
> -static bool isDereferenceOfOpCall(const CXXOperatorCallExpr *OpCall,
> - const VarDecl *IndexVar) {
> - return OpCall->getOperator() == OO_Star && OpCall->getNumArgs() == 1 &&
> - exprReferencesVariable(IndexVar, OpCall->getArg(0));
> -}
> -
> -/// \brief Returns true when Uop is a dereference of IndexVar.
> -///
> -/// For example, if the index variable is `index`, returns true for
> -/// *index
> -/// but not
> -/// index
> -/// *notIndex
> -static bool isDereferenceOfUop(const UnaryOperator *Uop,
> - const VarDecl *IndexVar) {
> - return Uop->getOpcode() == UO_Deref &&
> - exprReferencesVariable(IndexVar, Uop->getSubExpr());
> -}
> -
> -/// \brief Determines whether the given Decl defines a variable initialized to
> -/// the loop object.
> -///
> -/// This is intended to find cases such as
> -/// \code
> -/// for (int i = 0; i < arraySize(arr); ++i) {
> -/// T t = arr[i];
> -/// // use t, do not use i
> -/// }
> -/// \endcode
> -/// and
> -/// \code
> -/// for (iterator i = container.begin(), e = container.end(); i != e; ++i) {
> -/// T t = *i;
> -/// // use t, do not use i
> -/// }
> -/// \endcode
> -static bool isAliasDecl(const Decl *TheDecl, const VarDecl *IndexVar) {
> - const VarDecl *VDecl = dyn_cast<VarDecl>(TheDecl);
> - if (!VDecl)
> - return false;
> - if (!VDecl->hasInit())
> - return false;
> - const Expr *Init =
> - digThroughConstructors(VDecl->getInit()->IgnoreParenImpCasts());
> - if (!Init)
> - return false;
> -
> - switch (Init->getStmtClass()) {
> - case Stmt::ArraySubscriptExprClass: {
> - const ArraySubscriptExpr *E = cast<ArraySubscriptExpr>(Init);
> - // We don't really care which array is used here. We check to make sure
> - // it was the correct one later, since the AST will traverse it next.
> - return isIndexInSubscriptExpr(E->getIdx(), IndexVar);
> - }
> -
> - case Stmt::UnaryOperatorClass:
> - return isDereferenceOfUop(cast<UnaryOperator>(Init), IndexVar);
> -
> - case Stmt::CXXOperatorCallExprClass: {
> - const CXXOperatorCallExpr *OpCall = cast<CXXOperatorCallExpr>(Init);
> - if (OpCall->getOperator() == OO_Star)
> - return isDereferenceOfOpCall(OpCall, IndexVar);
> - if (OpCall->getOperator() == OO_Subscript) {
> - assert(OpCall->getNumArgs() == 2);
> - return true;
> - }
> - break;
> - }
> -
> - case Stmt::CXXMemberCallExprClass:
> - return true;
> -
> - default:
> - break;
> - }
> - return false;
> -}
> -
> -/// \brief Determines whether the bound of a for loop condition expression is
> -/// the same as the statically computable size of ArrayType.
> -///
> -/// Given
> -/// \code
> -/// const int N = 5;
> -/// int arr[N];
> -/// \endcode
> -/// This is intended to permit
> -/// \code
> -/// for (int i = 0; i < N; ++i) { /* use arr[i] */ }
> -/// for (int i = 0; i < arraysize(arr); ++i) { /* use arr[i] */ }
> -/// \endcode
> -static bool arrayMatchesBoundExpr(ASTContext *Context,
> - const QualType &ArrayType,
> - const Expr *ConditionExpr) {
> - if (!ConditionExpr || ConditionExpr->isValueDependent())
> - return false;
> - const ConstantArrayType *ConstType =
> - Context->getAsConstantArrayType(ArrayType);
> - if (!ConstType)
> - return false;
> - llvm::APSInt ConditionSize;
> - if (!ConditionExpr->isIntegerConstantExpr(ConditionSize, *Context))
> - return false;
> - llvm::APSInt ArraySize(ConstType->getSize());
> - return llvm::APSInt::isSameValue(ConditionSize, ArraySize);
> -}
> -
> -/// \brief If the unary operator is a dereference of IndexVar, include it
> -/// as a valid usage and prune the traversal.
> -///
> -/// For example, if container.begin() and container.end() both return pointers
> -/// to int, this makes sure that the initialization for `k` is not counted as an
> -/// unconvertible use of the iterator `i`.
> -/// \code
> -/// for (int *i = container.begin(), *e = container.end(); i != e; ++i) {
> -/// int k = *i + 2;
> -/// }
> -/// \endcode
> -bool ForLoopIndexUseVisitor::TraverseUnaryDeref(UnaryOperator *Uop) {
> - // If we dereference an iterator that's actually a pointer, count the
> - // occurrence.
> - if (isDereferenceOfUop(Uop, IndexVar)) {
> - Usages.push_back(Usage(Uop));
> - return true;
> - }
> -
> - return VisitorBase::TraverseUnaryOperator(Uop);
> -}
> -
> -/// \brief If the member expression is operator-> (overloaded or not) on
> -/// IndexVar, include it as a valid usage and prune the traversal.
> -///
> -/// For example, given
> -/// \code
> -/// struct Foo { int bar(); int x; };
> -/// vector<Foo> v;
> -/// \endcode
> -/// the following uses will be considered convertible:
> -/// \code
> -/// for (vector<Foo>::iterator i = v.begin(), e = v.end(); i != e; ++i) {
> -/// int b = i->bar();
> -/// int k = i->x + 1;
> -/// }
> -/// \endcode
> -/// though
> -/// \code
> -/// for (vector<Foo>::iterator i = v.begin(), e = v.end(); i != e; ++i) {
> -/// int k = i.insert(1);
> -/// }
> -/// for (vector<Foo>::iterator i = v.begin(), e = v.end(); i != e; ++i) {
> -/// int b = e->bar();
> -/// }
> -/// \endcode
> -/// will not.
> -bool ForLoopIndexUseVisitor::TraverseMemberExpr(MemberExpr *Member) {
> - const Expr *Base = Member->getBase();
> - const DeclRefExpr *Obj = getDeclRef(Base);
> - const Expr *ResultExpr = Member;
> - QualType ExprType;
> - if (const CXXOperatorCallExpr *Call =
> - dyn_cast<CXXOperatorCallExpr>(Base->IgnoreParenImpCasts())) {
> - // If operator->() is a MemberExpr containing a CXXOperatorCallExpr, then
> - // the MemberExpr does not have the expression we want. We therefore catch
> - // that instance here.
> - // For example, if vector<Foo>::iterator defines operator->(), then the
> - // example `i->bar()` at the top of this function is a CXXMemberCallExpr
> - // referring to `i->` as the member function called. We want just `i`, so
> - // we take the argument to operator->() as the base object.
> - if(Call->getOperator() == OO_Arrow) {
> - assert(Call->getNumArgs() == 1 &&
> - "Operator-> takes more than one argument");
> - Obj = getDeclRef(Call->getArg(0));
> - ResultExpr = Obj;
> - ExprType = Call->getCallReturnType(*Context);
> - }
> - }
> -
> - if (Member->isArrow() && Obj && exprReferencesVariable(IndexVar, Obj)) {
> - if (ExprType.isNull())
> - ExprType = Obj->getType();
> -
> - assert(ExprType->isPointerType() && "Operator-> returned non-pointer type");
> - // FIXME: This works around not having the location of the arrow operator.
> - // Consider adding OperatorLoc to MemberExpr?
> - SourceLocation ArrowLoc =
> - Lexer::getLocForEndOfToken(Base->getExprLoc(), 0,
> - Context->getSourceManager(),
> - Context->getLangOpts());
> - // If something complicated is happening (i.e. the next token isn't an
> - // arrow), give up on making this work.
> - if (ArrowLoc.isValid()) {
> - Usages.push_back(Usage(ResultExpr, /*IsArrow=*/true,
> - SourceRange(Base->getExprLoc(), ArrowLoc)));
> - return true;
> - }
> - }
> - return TraverseStmt(Member->getBase());
> -}
> -
> -/// \brief If a member function call is the at() accessor on the container with
> -/// IndexVar as the single argument, include it as a valid usage and prune
> -/// the traversal.
> -///
> -/// Member calls on other objects will not be permitted.
> -/// Calls on the iterator object are not permitted, unless done through
> -/// operator->(). The one exception is allowing vector::at() for pseudoarrays.
> -bool ForLoopIndexUseVisitor::TraverseCXXMemberCallExpr(
> - CXXMemberCallExpr *MemberCall) {
> - MemberExpr *Member =
> - dyn_cast<MemberExpr>(MemberCall->getCallee()->IgnoreParenImpCasts());
> - if (!Member)
> - return VisitorBase::TraverseCXXMemberCallExpr(MemberCall);
> - // We specifically allow an accessor named "at" to let STL in, though
> - // this is restricted to pseudo-arrays by requiring a single, integer
> - // argument.
> - const IdentifierInfo *Ident = Member->getMemberDecl()->getIdentifier();
> - if (Ident && Ident->isStr("at") && MemberCall->getNumArgs() == 1) {
> - if (isIndexInSubscriptExpr(Context, MemberCall->getArg(0), IndexVar,
> - Member->getBase(), ContainerExpr,
> - ContainerNeedsDereference)) {
> - Usages.push_back(Usage(MemberCall));
> - return true;
> - }
> - }
> -
> - if (containsExpr(Context, &DependentExprs, Member->getBase()))
> - ConfidenceLevel.lowerTo(RL_Risky);
> -
> - return VisitorBase::TraverseCXXMemberCallExpr(MemberCall);
> -}
> -
> -/// \brief If an overloaded operator call is a dereference of IndexVar or
> -/// a subscript of a the container with IndexVar as the single argument,
> -/// include it as a valid usage and prune the traversal.
> -///
> -/// For example, given
> -/// \code
> -/// struct Foo { int bar(); int x; };
> -/// vector<Foo> v;
> -/// void f(Foo);
> -/// \endcode
> -/// the following uses will be considered convertible:
> -/// \code
> -/// for (vector<Foo>::iterator i = v.begin(), e = v.end(); i != e; ++i) {
> -/// f(*i);
> -/// }
> -/// for (int i = 0; i < v.size(); ++i) {
> -/// int i = v[i] + 1;
> -/// }
> -/// \endcode
> -bool ForLoopIndexUseVisitor::TraverseCXXOperatorCallExpr(
> - CXXOperatorCallExpr *OpCall) {
> - switch (OpCall->getOperator()) {
> - case OO_Star:
> - if (isDereferenceOfOpCall(OpCall, IndexVar)) {
> - Usages.push_back(Usage(OpCall));
> - return true;
> - }
> - break;
> -
> - case OO_Subscript:
> - if (OpCall->getNumArgs() != 2)
> - break;
> - if (isIndexInSubscriptExpr(Context, OpCall->getArg(1), IndexVar,
> - OpCall->getArg(0), ContainerExpr,
> - ContainerNeedsDereference)) {
> - Usages.push_back(Usage(OpCall));
> - return true;
> - }
> - break;
> -
> - default:
> - break;
> - }
> - return VisitorBase::TraverseCXXOperatorCallExpr(OpCall);
> -}
> -
> -/// \brief If we encounter an array with IndexVar as the index of an
> -/// ArraySubsriptExpression, note it as a consistent usage and prune the
> -/// AST traversal.
> -///
> -/// For example, given
> -/// \code
> -/// const int N = 5;
> -/// int arr[N];
> -/// \endcode
> -/// This is intended to permit
> -/// \code
> -/// for (int i = 0; i < N; ++i) { /* use arr[i] */ }
> -/// \endcode
> -/// but not
> -/// \code
> -/// for (int i = 0; i < N; ++i) { /* use notArr[i] */ }
> -/// \endcode
> -/// and further checking needs to be done later to ensure that exactly one array
> -/// is referenced.
> -bool ForLoopIndexUseVisitor::TraverseArraySubscriptExpr(
> - ArraySubscriptExpr *E) {
> - Expr *Arr = E->getBase();
> - if (!isIndexInSubscriptExpr(E->getIdx(), IndexVar))
> - return VisitorBase::TraverseArraySubscriptExpr(E);
> -
> - if ((ContainerExpr && !areSameExpr(Context, Arr->IgnoreParenImpCasts(),
> - ContainerExpr->IgnoreParenImpCasts()))
> - || !arrayMatchesBoundExpr(Context, Arr->IgnoreImpCasts()->getType(),
> - ArrayBoundExpr)) {
> - // If we have already discovered the array being indexed and this isn't it
> - // or this array doesn't match, mark this loop as unconvertible.
> - OnlyUsedAsIndex = false;
> - return VisitorBase::TraverseArraySubscriptExpr(E);
> - }
> -
> - if (!ContainerExpr)
> - ContainerExpr = Arr;
> -
> - Usages.push_back(Usage(E));
> - return true;
> -}
> -
> -/// \brief If we encounter a reference to IndexVar in an unpruned branch of the
> -/// traversal, mark this loop as unconvertible.
> -///
> -/// This implements the whitelist for convertible loops: any usages of IndexVar
> -/// not explicitly considered convertible by this traversal will be caught by
> -/// this function.
> -///
> -/// Additionally, if the container expression is more complex than just a
> -/// DeclRefExpr, and some part of it is appears elsewhere in the loop, lower
> -/// our confidence in the transformation.
> -///
> -/// For example, these are not permitted:
> -/// \code
> -/// for (int i = 0; i < N; ++i) { printf("arr[%d] = %d", i, arr[i]); }
> -/// for (vector<int>::iterator i = container.begin(), e = container.end();
> -/// i != e; ++i)
> -/// i.insert(0);
> -/// for (vector<int>::iterator i = container.begin(), e = container.end();
> -/// i != e; ++i)
> -/// i.insert(0);
> -/// for (vector<int>::iterator i = container.begin(), e = container.end();
> -/// i != e; ++i)
> -/// if (i + 1 != e)
> -/// printf("%d", *i);
> -/// \endcode
> -///
> -/// And these will raise the risk level:
> -/// \code
> -/// int arr[10][20];
> -/// int l = 5;
> -/// for (int j = 0; j < 20; ++j)
> -/// int k = arr[l][j] + l; // using l outside arr[l] is considered risky
> -/// for (int i = 0; i < obj.getVector().size(); ++i)
> -/// obj.foo(10); // using `obj` is considered risky
> -/// \endcode
> -bool ForLoopIndexUseVisitor::VisitDeclRefExpr(DeclRefExpr *E) {
> - const ValueDecl *TheDecl = E->getDecl();
> - if (areSameVariable(IndexVar, TheDecl) || areSameVariable(EndVar, TheDecl))
> - OnlyUsedAsIndex = false;
> - if (containsExpr(Context, &DependentExprs, E))
> - ConfidenceLevel.lowerTo(RL_Risky);
> - return true;
> -}
> -
> -/// \brief If we find that another variable is created just to refer to the loop
> -/// element, note it for reuse as the loop variable.
> -///
> -/// See the comments for isAliasDecl.
> -bool ForLoopIndexUseVisitor::VisitDeclStmt(DeclStmt *S) {
> - if (!AliasDecl && S->isSingleDecl() &&
> - isAliasDecl(S->getSingleDecl(), IndexVar)) {
> - AliasDecl = S;
> - if (CurrStmtParent) {
> - if (isa<IfStmt>(CurrStmtParent) ||
> - isa<WhileStmt>(CurrStmtParent) ||
> - isa<SwitchStmt>(CurrStmtParent))
> - ReplaceWithAliasUse = true;
> - else if (isa<ForStmt>(CurrStmtParent)) {
> - if (cast<ForStmt>(CurrStmtParent)->getConditionVariableDeclStmt() == S)
> - ReplaceWithAliasUse = true;
> - else
> - // It's assumed S came the for loop's init clause.
> - AliasFromForInit = true;
> - }
> - }
> - }
> -
> - return true;
> -}
> -
> -bool ForLoopIndexUseVisitor::TraverseStmt(Stmt *S) {
> - // All this pointer swapping is a mechanism for tracking immediate parentage
> - // of Stmts.
> - const Stmt *OldNextParent = NextStmtParent;
> - CurrStmtParent = NextStmtParent;
> - NextStmtParent = S;
> - bool Result = VisitorBase::TraverseStmt(S);
> - NextStmtParent = OldNextParent;
> - return Result;
> -}
> -
> -//// \brief Apply the source transformations necessary to migrate the loop!
> -void LoopFixer::doConversion(ASTContext *Context,
> - const VarDecl *IndexVar,
> - const VarDecl *MaybeContainer,
> - StringRef ContainerString,
> - const UsageResult &Usages,
> - const DeclStmt *AliasDecl,
> - bool AliasUseRequired,
> - bool AliasFromForInit,
> - const ForStmt *TheLoop,
> - bool ContainerNeedsDereference,
> - bool DerefByValue,
> - bool DerefByConstRef) {
> - std::string VarName;
> - bool VarNameFromAlias = Usages.size() == 1 && AliasDecl;
> - bool AliasVarIsRef = false;
> -
> - if (VarNameFromAlias) {
> - const VarDecl *AliasVar = cast<VarDecl>(AliasDecl->getSingleDecl());
> - VarName = AliasVar->getName().str();
> - AliasVarIsRef = AliasVar->getType()->isReferenceType();
> -
> - // We keep along the entire DeclStmt to keep the correct range here.
> - SourceRange ReplaceRange = AliasDecl->getSourceRange();
> -
> - std::string ReplacementText;
> - if (AliasUseRequired)
> - ReplacementText = VarName;
> - else if (AliasFromForInit)
> - // FIXME: Clang includes the location of the ';' but only for DeclStmt's
> - // in a for loop's init clause. Need to put this ';' back while removing
> - // the declaration of the alias variable. This is probably a bug.
> - ReplacementText = ";";
> -
> - Owner.addReplacementForCurrentTU(Replacement(
> - Context->getSourceManager(),
> - CharSourceRange::getTokenRange(ReplaceRange), ReplacementText));
> - // No further replacements are made to the loop, since the iterator or index
> - // was used exactly once - in the initialization of AliasVar.
> - } else {
> - VariableNamer Namer(&TUInfo.getGeneratedDecls(),
> - &TUInfo.getParentFinder().getStmtToParentStmtMap(),
> - TheLoop, IndexVar, MaybeContainer, Context);
> - VarName = Namer.createIndexName();
> - // First, replace all usages of the array subscript expression with our new
> - // variable.
> - for (UsageResult::const_iterator I = Usages.begin(), E = Usages.end();
> - I != E; ++I) {
> - std::string ReplaceText = I->IsArrow ? VarName + "." : VarName;
> - TUInfo.getReplacedVars().insert(std::make_pair(TheLoop, IndexVar));
> - Owner.addReplacementForCurrentTU(
> - Replacement(Context->getSourceManager(),
> - CharSourceRange::getTokenRange(I->Range), ReplaceText));
> - }
> - }
> -
> - // Now, we need to construct the new range expresion.
> - SourceRange ParenRange(TheLoop->getLParenLoc(), TheLoop->getRParenLoc());
> -
> - QualType AutoRefType = Context->getAutoDeductType();
> -
> - // If the new variable name is from the aliased variable, then the reference
> - // type for the new variable should only be used if the aliased variable was
> - // declared as a reference.
> - if (!VarNameFromAlias || AliasVarIsRef) {
> - // If an iterator's operator*() returns a 'T&' we can bind that to 'auto&'.
> - // If operator*() returns 'T' we can bind that to 'auto&&' which will deduce
> - // to 'T&&'.
> - if (DerefByValue)
> - AutoRefType = Context->getRValueReferenceType(AutoRefType);
> - else {
> - if (DerefByConstRef)
> - AutoRefType = Context->getConstType(AutoRefType);
> - AutoRefType = Context->getLValueReferenceType(AutoRefType);
> - }
> - }
> -
> - std::string MaybeDereference = ContainerNeedsDereference ? "*" : "";
> - std::string TypeString = AutoRefType.getAsString();
> - std::string Range = ("(" + TypeString + " " + VarName + " : "
> - + MaybeDereference + ContainerString + ")").str();
> - Owner.addReplacementForCurrentTU(
> - Replacement(Context->getSourceManager(),
> - CharSourceRange::getTokenRange(ParenRange), Range));
> - TUInfo.getGeneratedDecls().insert(make_pair(TheLoop, VarName));
> -}
> -
> -/// \brief Determine whether Init appears to be an initializing an iterator.
> -///
> -/// If it is, returns the object whose begin() or end() method is called, and
> -/// the output parameter isArrow is set to indicate whether the initialization
> -/// is called via . or ->.
> -static const Expr *getContainerFromBeginEndCall(const Expr *Init, bool IsBegin,
> - bool *IsArrow) {
> - // FIXME: Maybe allow declaration/initialization outside of the for loop?
> - const CXXMemberCallExpr *TheCall =
> - dyn_cast_or_null<CXXMemberCallExpr>(digThroughConstructors(Init));
> - if (!TheCall || TheCall->getNumArgs() != 0)
> - return nullptr;
> -
> - const MemberExpr *Member = dyn_cast<MemberExpr>(TheCall->getCallee());
> - if (!Member)
> - return nullptr;
> - const std::string Name = Member->getMemberDecl()->getName();
> - const std::string TargetName = IsBegin ? "begin" : "end";
> - if (Name != TargetName)
> - return nullptr;
> -
> - const Expr *SourceExpr = Member->getBase();
> - if (!SourceExpr)
> - return nullptr;
> -
> - *IsArrow = Member->isArrow();
> - return SourceExpr;
> -}
> -
> -/// \brief Determines the container whose begin() and end() functions are called
> -/// for an iterator-based loop.
> -///
> -/// BeginExpr must be a member call to a function named "begin()", and EndExpr
> -/// must be a member .
> -static const Expr *findContainer(ASTContext *Context, const Expr *BeginExpr,
> - const Expr *EndExpr,
> - bool *ContainerNeedsDereference) {
> - // Now that we know the loop variable and test expression, make sure they are
> - // valid.
> - bool BeginIsArrow = false;
> - bool EndIsArrow = false;
> - const Expr *BeginContainerExpr =
> - getContainerFromBeginEndCall(BeginExpr, /*IsBegin=*/true, &BeginIsArrow);
> - if (!BeginContainerExpr)
> - return nullptr;
> -
> - const Expr *EndContainerExpr =
> - getContainerFromBeginEndCall(EndExpr, /*IsBegin=*/false, &EndIsArrow);
> - // Disallow loops that try evil things like this (note the dot and arrow):
> - // for (IteratorType It = Obj.begin(), E = Obj->end(); It != E; ++It) { }
> - if (!EndContainerExpr || BeginIsArrow != EndIsArrow ||
> - !areSameExpr(Context, EndContainerExpr, BeginContainerExpr))
> - return nullptr;
> -
> - *ContainerNeedsDereference = BeginIsArrow;
> - return BeginContainerExpr;
> -}
> -
> -StringRef LoopFixer::checkDeferralsAndRejections(ASTContext *Context,
> - const Expr *ContainerExpr,
> - Confidence ConfidenceLevel,
> - const ForStmt *TheLoop) {
> - // If we already modified the range of this for loop, don't do any further
> - // updates on this iteration.
> - // FIXME: Once Replacements can detect conflicting edits, replace this
> - // implementation and rely on conflicting edit detection instead.
> - if (TUInfo.getReplacedVars().count(TheLoop)) {
> - ++*DeferredChanges;
> - return "";
> - }
> -
> - TUInfo.getParentFinder().gatherAncestors(Context->getTranslationUnitDecl());
> - // Ensure that we do not try to move an expression dependent on a local
> - // variable declared inside the loop outside of it!
> - DependencyFinderASTVisitor DependencyFinder(
> - &TUInfo.getParentFinder().getStmtToParentStmtMap(),
> - &TUInfo.getParentFinder().getDeclToParentStmtMap(),
> - &TUInfo.getReplacedVars(), TheLoop);
> -
> - // Not all of these are actually deferred changes.
> - // FIXME: Determine when the external dependency isn't an expression converted
> - // by another loop.
> - if (DependencyFinder.dependsOnInsideVariable(ContainerExpr)) {
> - ++*DeferredChanges;
> - return "";
> - }
> - if (ConfidenceLevel.getRiskLevel() > MaxRisk) {
> - ++*RejectedChanges;
> - return "";
> - }
> -
> - StringRef ContainerString;
> - if (isa<CXXThisExpr>(ContainerExpr->IgnoreParenImpCasts())) {
> - ContainerString = "this";
> - } else {
> - ContainerString = getStringFromRange(Context->getSourceManager(),
> - Context->getLangOpts(),
> - ContainerExpr->getSourceRange());
> - }
> -
> - // In case someone is using an evil macro, reject this change.
> - if (ContainerString.empty())
> - ++*RejectedChanges;
> - return ContainerString;
> -}
> -
> -/// \brief Given that we have verified that the loop's header appears to be
> -/// convertible, run the complete analysis on the loop to determine if the
> -/// loop's body is convertible.
> -void LoopFixer::findAndVerifyUsages(ASTContext *Context,
> - const VarDecl *LoopVar,
> - const VarDecl *EndVar,
> - const Expr *ContainerExpr,
> - const Expr *BoundExpr,
> - bool ContainerNeedsDereference,
> - bool DerefByValue,
> - bool DerefByConstRef,
> - const ForStmt *TheLoop,
> - Confidence ConfidenceLevel) {
> - ForLoopIndexUseVisitor Finder(Context, LoopVar, EndVar, ContainerExpr,
> - BoundExpr, ContainerNeedsDereference);
> - if (ContainerExpr) {
> - ComponentFinderASTVisitor ComponentFinder;
> - ComponentFinder.findExprComponents(ContainerExpr->IgnoreParenImpCasts());
> - Finder.addComponents(ComponentFinder.getComponents());
> - }
> -
> - if (!Finder.findAndVerifyUsages(TheLoop->getBody()))
> - return;
> -
> - ConfidenceLevel.lowerTo(Finder.getRiskLevel());
> - if (FixerKind == LFK_Array) {
> - // The array being indexed by IndexVar was discovered during traversal.
> - ContainerExpr = Finder.getContainerIndexed()->IgnoreParenImpCasts();
> - // Very few loops are over expressions that generate arrays rather than
> - // array variables. Consider loops over arrays that aren't just represented
> - // by a variable to be risky conversions.
> - if (!getReferencedVariable(ContainerExpr) &&
> - !isDirectMemberExpr(ContainerExpr))
> - ConfidenceLevel.lowerTo(RL_Risky);
> - }
> -
> - std::string ContainerString =
> - checkDeferralsAndRejections(Context, ContainerExpr,
> - ConfidenceLevel, TheLoop);
> - if (ContainerString.empty())
> - return;
> -
> - doConversion(Context, LoopVar, getReferencedVariable(ContainerExpr),
> - ContainerString, Finder.getUsages(), Finder.getAliasDecl(),
> - Finder.aliasUseRequired(), Finder.aliasFromForInit(), TheLoop,
> - ContainerNeedsDereference, DerefByValue, DerefByConstRef);
> - ++*AcceptedChanges;
> -}
> -
> -/// \brief The LoopFixer callback, which determines if loops discovered by the
> -/// matchers are convertible, printing information about the loops if so.
> -void LoopFixer::run(const MatchFinder::MatchResult &Result) {
> - const BoundNodes &Nodes = Result.Nodes;
> - Confidence ConfidenceLevel(RL_Safe);
> - ASTContext *Context = Result.Context;
> - const ForStmt *TheLoop = Nodes.getStmtAs<ForStmt>(LoopName);
> -
> - if (!Owner.isFileModifiable(Context->getSourceManager(),TheLoop->getForLoc()))
> - return;
> -
> - // Check that we have exactly one index variable and at most one end variable.
> - const VarDecl *LoopVar = Nodes.getDeclAs<VarDecl>(IncrementVarName);
> - const VarDecl *CondVar = Nodes.getDeclAs<VarDecl>(ConditionVarName);
> - const VarDecl *InitVar = Nodes.getDeclAs<VarDecl>(InitVarName);
> - if (!areSameVariable(LoopVar, CondVar) || !areSameVariable(LoopVar, InitVar))
> - return;
> - const VarDecl *EndVar = Nodes.getDeclAs<VarDecl>(EndVarName);
> - const VarDecl *ConditionEndVar =
> - Nodes.getDeclAs<VarDecl>(ConditionEndVarName);
> - if (EndVar && !areSameVariable(EndVar, ConditionEndVar))
> - return;
> -
> - // If the end comparison isn't a variable, we can try to work with the
> - // expression the loop variable is being tested against instead.
> - const CXXMemberCallExpr *EndCall =
> - Nodes.getStmtAs<CXXMemberCallExpr>(EndCallName);
> - const Expr *BoundExpr = Nodes.getStmtAs<Expr>(ConditionBoundName);
> - // If the loop calls end()/size() after each iteration, lower our confidence
> - // level.
> - if (FixerKind != LFK_Array && !EndVar)
> - ConfidenceLevel.lowerTo(RL_Reasonable);
> -
> - const Expr *ContainerExpr = nullptr;
> - bool DerefByValue = false;
> - bool DerefByConstRef = false;
> - bool ContainerNeedsDereference = false;
> - // FIXME: Try to put most of this logic inside a matcher. Currently, matchers
> - // don't allow the right-recursive checks in digThroughConstructors.
> - if (FixerKind == LFK_Iterator) {
> - ContainerExpr = findContainer(Context, LoopVar->getInit(),
> - EndVar ? EndVar->getInit() : EndCall,
> - &ContainerNeedsDereference);
> -
> - QualType InitVarType = InitVar->getType();
> - QualType CanonicalInitVarType = InitVarType.getCanonicalType();
> -
> - const CXXMemberCallExpr *BeginCall =
> - Nodes.getNodeAs<CXXMemberCallExpr>(BeginCallName);
> - assert(BeginCall && "Bad Callback. No begin call expression.");
> - QualType CanonicalBeginType =
> - BeginCall->getMethodDecl()->getReturnType().getCanonicalType();
> -
> - if (CanonicalBeginType->isPointerType() &&
> - CanonicalInitVarType->isPointerType()) {
> - QualType BeginPointeeType = CanonicalBeginType->getPointeeType();
> - QualType InitPointeeType = CanonicalInitVarType->getPointeeType();
> - // If the initializer and the variable are both pointers check if the
> - // un-qualified pointee types match otherwise we don't use auto.
> - if (!Context->hasSameUnqualifiedType(InitPointeeType, BeginPointeeType))
> - return;
> - } else {
> - // Check for qualified types to avoid conversions from non-const to const
> - // iterator types.
> - if (!Context->hasSameType(CanonicalInitVarType, CanonicalBeginType))
> - return;
> - }
> -
> - DerefByValue = Nodes.getNodeAs<QualType>(DerefByValueResultName) != nullptr;
> - if (!DerefByValue) {
> - if (const QualType *DerefType =
> - Nodes.getNodeAs<QualType>(DerefByRefResultName)) {
> - // A node will only be bound with DerefByRefResultName if we're dealing
> - // with a user-defined iterator type. Test the const qualification of
> - // the reference type.
> - DerefByConstRef = (*DerefType)->getAs<ReferenceType>()->getPointeeType()
> - .isConstQualified();
> - } else {
> - // By nature of the matcher this case is triggered only for built-in
> - // iterator types (i.e. pointers).
> - assert(isa<PointerType>(CanonicalInitVarType) &&
> - "Non-class iterator type is not a pointer type");
> - QualType InitPointeeType = CanonicalInitVarType->getPointeeType();
> - QualType BeginPointeeType = CanonicalBeginType->getPointeeType();
> - // If the initializer and variable have both the same type just use auto
> - // otherwise we test for const qualification of the pointed-at type.
> - if (!Context->hasSameType(InitPointeeType, BeginPointeeType))
> - DerefByConstRef = InitPointeeType.isConstQualified();
> - }
> - } else {
> - // If the dereference operator returns by value then test for the
> - // canonical const qualification of the init variable type.
> - DerefByConstRef = CanonicalInitVarType.isConstQualified();
> - }
> - } else if (FixerKind == LFK_PseudoArray) {
> - if (!EndCall)
> - return;
> - ContainerExpr = EndCall->getImplicitObjectArgument();
> - const MemberExpr *Member = dyn_cast<MemberExpr>(EndCall->getCallee());
> - if (!Member)
> - return;
> - ContainerNeedsDereference = Member->isArrow();
> - }
> - // We must know the container or an array length bound.
> - if (!ContainerExpr && !BoundExpr)
> - return;
> -
> - findAndVerifyUsages(Context, LoopVar, EndVar, ContainerExpr, BoundExpr,
> - ContainerNeedsDereference, DerefByValue, DerefByConstRef,
> - TheLoop, ConfidenceLevel);
> -}
> Index: clang-modernize/Core/Transforms.h
> ===================================================================
> --- clang-modernize/Core/Transforms.h
> +++ /dev/null
> @@ -1,84 +0,0 @@
> -//===-- Core/Transforms.h - class Transforms Def'n --------------*- 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 for class Transforms which is
> -/// responsible for defining the command-line arguments exposing
> -/// transformations to the user and applying requested transforms.
> -///
> -//===----------------------------------------------------------------------===//
> -
> -#ifndef CLANG_MODERNIZE_TRANSFORMS_H
> -#define CLANG_MODERNIZE_TRANSFORMS_H
> -
> -#include "llvm/ADT/StringRef.h"
> -#include "llvm/Support/CommandLine.h"
> -#include <vector>
> -
> -// Forward declarations
> -namespace llvm {
> -namespace cl {
> -class Option;
> -} // namespace cl
> -} // namespace llvm
> -class Transform;
> -struct TransformOptions;
> -struct CompilerVersions;
> -
> -typedef Transform *(*TransformCreator)(const TransformOptions &);
> -template <typename T>
> -Transform *ConstructTransform(const TransformOptions &Options) {
> - return new T(Options);
> -}
> -
> -/// \brief To group transforms together when printing the help.
> -extern llvm::cl::OptionCategory TransformCategory;
> -
> -/// \brief Class encapsulating the creation of command line bool options
> -/// for each transform and instantiating transforms chosen by the user.
> -class Transforms {
> -public:
> - typedef std::vector<Transform*> TransformVec;
> - typedef TransformVec::const_iterator const_iterator;
> -
> -public:
> -
> - ~Transforms();
> -
> - /// \brief Registers all available transforms causing them to be made
> - /// available on the command line.
> - ///
> - /// Be sure to register all transforms *before* parsing command line options.
> - void registerTransforms();
> -
> - /// \brief Instantiate all transforms that were selected on the command line.
> - ///
> - /// Call *after* parsing options.
> - void createSelectedTransforms(const TransformOptions &Options,
> - const CompilerVersions &RequiredVersions);
> -
> - /// \brief Return an iterator to the start of a container of instantiated
> - /// transforms.
> - const_iterator begin() const { return ChosenTransforms.begin(); }
> -
> - /// \brief Return an iterator to the end of a container of instantiated
> - /// transforms.
> - const_iterator end() const { return ChosenTransforms.end(); }
> -
> -private:
> - bool hasAnyExplicitOption() const;
> -
> - typedef llvm::StringMap<llvm::cl::opt<bool> *> OptionMap;
> -
> -private:
> - TransformVec ChosenTransforms;
> - OptionMap Options;
> -};
> -
> -#endif // CLANG_MODERNIZE_TRANSFORMS_H
> Index: clang-modernize/Core/Transforms.cpp
> ===================================================================
> --- clang-modernize/Core/Transforms.cpp
> +++ /dev/null
> @@ -1,71 +0,0 @@
> -//===-- Core/Transforms.cpp - class Transforms Impl -----------------------===//
> -//
> -// 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 for class Transforms.
> -///
> -//===----------------------------------------------------------------------===//
> -
> -#include "Core/Transforms.h"
> -#include "Core/Transform.h"
> -
> -namespace cl = llvm::cl;
> -
> -cl::OptionCategory TransformCategory("Transforms");
> -
> -Transforms::~Transforms() {
> - for (std::vector<Transform *>::iterator I = ChosenTransforms.begin(),
> - E = ChosenTransforms.end();
> - I != E; ++I)
> - delete *I;
> -
> - for (OptionMap::iterator I = Options.begin(), E = Options.end(); I != E; ++I)
> - delete I->getValue();
> -}
> -
> -void Transforms::registerTransforms() {
> - for (TransformFactoryRegistry::iterator I = TransformFactoryRegistry::begin(),
> - E = TransformFactoryRegistry::end();
> - I != E; ++I)
> - Options[I->getName()] = new cl::opt<bool>(
> - I->getName(), cl::desc(I->getDesc()), cl::cat(TransformCategory));
> -}
> -
> -bool Transforms::hasAnyExplicitOption() const {
> - for (OptionMap::const_iterator I = Options.begin(), E = Options.end(); I != E;
> - ++I)
> - if (*I->second)
> - return true;
> - return false;
> -}
> -
> -void
> -Transforms::createSelectedTransforms(const TransformOptions &GlobalOptions,
> - const CompilerVersions &RequiredVersions) {
> - // if at least one transform is set explicitly on the command line, do not
> - // enable non-explicit ones
> - bool EnableAllTransformsByDefault = !hasAnyExplicitOption();
> -
> - for (TransformFactoryRegistry::iterator I = TransformFactoryRegistry::begin(),
> - E = TransformFactoryRegistry::end();
> - I != E; ++I) {
> - bool ExplicitlyEnabled = *Options[I->getName()];
> - bool OptionEnabled = EnableAllTransformsByDefault || ExplicitlyEnabled;
> -
> - if (!OptionEnabled)
> - continue;
> -
> - std::unique_ptr<TransformFactory> Factory(I->instantiate());
> - if (Factory->supportsCompilers(RequiredVersions))
> - ChosenTransforms.push_back(Factory->createTransform(GlobalOptions));
> - else if (ExplicitlyEnabled)
> - llvm::errs() << "note: " << '-' << I->getName()
> - << ": transform not available for specified compilers\n";
> - }
> -}
> Index: clang-modernize/Core/Transform.h
> ===================================================================
> --- clang-modernize/Core/Transform.h
> +++ /dev/null
> @@ -1,329 +0,0 @@
> -//===-- Core/Transform.h - Transform Base Class Def'n -----------*- 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 declaration for the base Transform class from
> -/// which all transforms must subclass.
> -///
> -//===----------------------------------------------------------------------===//
> -
> -#ifndef CLANG_MODERNIZE_TRANSFORM_H
> -#define CLANG_MODERNIZE_TRANSFORM_H
> -
> -#include "Core/IncludeExcludeInfo.h"
> -#include "Core/Refactoring.h"
> -#include "llvm/Support/CommandLine.h"
> -#include "llvm/Support/Registry.h"
> -#include "llvm/Support/Timer.h"
> -#include <string>
> -#include <vector>
> -
> -/// \brief Description of the riskiness of actions that can be taken by
> -/// transforms.
> -enum RiskLevel {
> - /// Transformations that will not change semantics.
> - RL_Safe,
> -
> - /// Transformations that might change semantics.
> - RL_Reasonable,
> -
> - /// Transformations that are likely to change semantics.
> - RL_Risky
> -};
> -
> -// Forward declarations
> -namespace clang {
> -class CompilerInstance;
> -namespace tooling {
> -class CompilationDatabase;
> -class FrontendActionFactory;
> -} // namespace tooling
> -namespace ast_matchers {
> -class MatchFinder;
> -} // namespace ast_matchers
> -} // namespace clang
> -
> -// \brief Maps main source file names to a TranslationUnitReplacements
> -// structure storing replacements for that translation unit.
> -typedef llvm::StringMap<clang::tooling::TranslationUnitReplacements>
> -TUReplacementsMap;
> -
> -/// \brief To group transforms' options together when printing the help.
> -extern llvm::cl::OptionCategory TransformsOptionsCategory;
> -
> -/// \brief Container for global options affecting all transforms.
> -struct TransformOptions {
> - /// \brief Enable the use of performance timers.
> - bool EnableTiming;
> -
> - /// \brief Contains information on which files are safe to transform and
> - /// which aren't.
> - IncludeExcludeInfo ModifiableFiles;
> -
> - /// \brief Maximum allowed level of risk.
> - RiskLevel MaxRiskLevel;
> -};
> -
> -/// \brief Abstract base class for all C++11 migration transforms.
> -///
> -/// Subclasses must call createActionFactory() to create a
> -/// FrontendActionFactory to pass to ClangTool::run(). Subclasses are also
> -/// responsible for calling setOverrides() before calling ClangTool::run().
> -///
> -/// If timing is enabled (see TransformOptions), per-source performance timing
> -/// is recorded and stored in a TimingVec for later access with timing_begin()
> -/// and timing_end().
> -class Transform {
> -public:
> - /// \brief Constructor
> - /// \param Name Name of the transform for human-readable purposes (e.g. -help
> - /// text)
> - /// \param Options Global options that affect all Transforms.
> - Transform(llvm::StringRef Name, const TransformOptions &Options);
> -
> - virtual ~Transform();
> -
> - /// \brief Apply a transform to all files listed in \p SourcePaths.
> - ///
> - /// \param[in] Database Contains information for how to compile all files in
> - /// \p SourcePaths.
> - /// \param[in] SourcePaths list of sources to transform.
> - ///
> - /// \returns \parblock
> - /// \li 0 if successful
> - /// \li 1 otherwise
> - virtual int apply(const clang::tooling::CompilationDatabase &Database,
> - const std::vector<std::string> &SourcePaths) = 0;
> -
> - /// \brief Query if changes were made during the last call to apply().
> - bool getChangesMade() const { return AcceptedChanges > 0; }
> -
> - /// \brief Query if changes were not made due to conflicts with other changes
> - /// made during the last call to apply() or if changes were too risky for the
> - /// requested risk level.
> - bool getChangesNotMade() const {
> - return RejectedChanges > 0 || DeferredChanges > 0;
> - }
> -
> - /// \brief Query the number of accepted changes.
> - unsigned getAcceptedChanges() const { return AcceptedChanges; }
> - /// \brief Query the number of changes considered too risky.
> - unsigned getRejectedChanges() const { return RejectedChanges; }
> - /// \brief Query the number of changes not made because they conflicted with
> - /// early changes.
> - unsigned getDeferredChanges() const { return DeferredChanges; }
> -
> - /// \brief Query transform name.
> - llvm::StringRef getName() const { return Name; }
> -
> - /// \brief Reset internal state of the transform.
> - ///
> - /// Useful if calling apply() several times with one instantiation of a
> - /// transform.
> - void Reset() {
> - AcceptedChanges = 0;
> - RejectedChanges = 0;
> - DeferredChanges = 0;
> - }
> -
> - /// \brief Tests if the file containing \a Loc is allowed to be modified by
> - /// the Modernizer.
> - bool isFileModifiable(const clang::SourceManager &SM,
> - clang::SourceLocation Loc) const;
> -
> - /// \brief Whether a transformation with a risk level of \p RiskLevel is
> - /// acceptable or not.
> - bool isAcceptableRiskLevel(RiskLevel RiskLevel) const {
> - return RiskLevel <= GlobalOptions.MaxRiskLevel;
> - }
> -
> - /// \brief Called before parsing a translation unit for a FrontendAction.
> - ///
> - /// Transform uses this function to apply file overrides and start
> - /// performance timers. Subclasses overriding this function must call it
> - /// before returning.
> - virtual bool handleBeginSource(clang::CompilerInstance &CI,
> - llvm::StringRef Filename);
> -
> - /// \brief Called after FrontendAction has been run over a translation unit.
> - ///
> - /// Transform uses this function to stop performance timers. Subclasses
> - /// overriding this function must call it before returning. A call to
> - /// handleEndSource() for a given translation unit is expected to be called
> - /// immediately after the corresponding handleBeginSource() call.
> - virtual void handleEndSource();
> -
> - /// \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(); }
> -
> - /// \brief Add a Replacement to the list for the current translation unit.
> - ///
> - /// \returns \parblock
> - /// \li true on success
> - /// \li false if there is no current translation unit
> - bool addReplacementForCurrentTU(const clang::tooling::Replacement &R);
> -
> - /// \brief Accessor to Replacements across all transformed translation units.
> - const TUReplacementsMap &getAllReplacements() const {
> - return Replacements;
> - }
> -
> -protected:
> -
> - void setAcceptedChanges(unsigned Changes) {
> - AcceptedChanges = Changes;
> - }
> - void setRejectedChanges(unsigned Changes) {
> - RejectedChanges = Changes;
> - }
> - void setDeferredChanges(unsigned Changes) {
> - DeferredChanges = Changes;
> - }
> -
> - /// \brief Allows subclasses to manually add performance timer data.
> - ///
> - /// \p Label should probably include the source file name somehow as the
> - /// duration info is simply added to the vector of timing data which holds
> - /// data for all sources processed by this transform.
> - void addTiming(llvm::StringRef Label, llvm::TimeRecord Duration);
> -
> - /// \brief Provide access for subclasses to the TransformOptions they were
> - /// created with.
> - const TransformOptions &Options() { return GlobalOptions; }
> -
> - /// \brief Subclasses must call this function to create a
> - /// FrontendActionFactory to pass to ClangTool.
> - ///
> - /// The factory returned by this function is responsible for calling back to
> - /// Transform to call handleBeginSource() and handleEndSource().
> - std::unique_ptr<clang::tooling::FrontendActionFactory>
> - createActionFactory(clang::ast_matchers::MatchFinder &Finder);
> -
> -private:
> - const std::string Name;
> - const TransformOptions &GlobalOptions;
> - TUReplacementsMap Replacements;
> - std::string CurrentSource;
> - TimingVec Timings;
> - unsigned AcceptedChanges;
> - unsigned RejectedChanges;
> - unsigned DeferredChanges;
> -};
> -
> -/// \brief Describes a version number of the form major[.minor] (minor being
> -/// optional).
> -struct Version {
> - explicit Version(unsigned Major = 0, unsigned Minor = 0)
> - : Major(Major), Minor(Minor) {}
> -
> - bool operator<(Version RHS) const {
> - if (Major < RHS.Major)
> - return true;
> - if (Major == RHS.Major)
> - return Minor < RHS.Minor;
> - return false;
> - }
> -
> - bool operator==(Version RHS) const {
> - return Major == RHS.Major && Minor == RHS.Minor;
> - }
> -
> - bool operator!=(Version RHS) const { return !(*this == RHS); }
> - bool operator>(Version RHS) const { return RHS < *this; }
> - bool operator<=(Version RHS) const { return !(*this > RHS); }
> - bool operator>=(Version RHS) const { return !(*this < RHS); }
> -
> - bool isNull() const { return Minor == 0 && Major == 0; }
> - unsigned getMajor() const { return Major; }
> - unsigned getMinor() const { return Minor; }
> -
> - /// \brief Creates a version from a string of the form \c major[.minor].
> - ///
> - /// Note that any version component after \c minor is ignored.
> - ///
> - /// \return A null version is returned on error.
> - static Version getFromString(llvm::StringRef VersionStr);
> -
> -private:
> - unsigned Major;
> - unsigned Minor;
> -};
> -
> -/// \brief Convenience structure to store the version of some compilers.
> -struct CompilerVersions {
> - Version Clang, Gcc, Icc, Msvc;
> -};
> -
> -/// \brief A factory that can instantiate a specific transform.
> -///
> -/// Each transform should subclass this class and implement
> -/// \c createTransform().
> -///
> -/// In the sub-classed factory constructor, specify the earliest versions since
> -/// the compilers in \c CompilerVersions support the feature introduced by the
> -/// transform. See the example below.
> -///
> -/// Note that you should use \c TransformFactoryRegistry to register the
> -/// transform globally.
> -///
> -/// Example:
> -/// \code
> -/// class MyTransform : public Transform { ... };
> -///
> -/// struct MyFactory : TransformFactory {
> -/// MyFactory() {
> -/// Since.Clang = Version(3, 0);
> -/// Since.Gcc = Version(4, 7);
> -/// Since.Icc = Version(12);
> -/// Since.Msvc = Version(10);
> -/// }
> -///
> -/// Transform *createTransform(const TransformOptions &Opts) override {
> -/// return new MyTransform(Opts);
> -/// }
> -/// };
> -///
> -/// // Register the factory using this statically initialized variable.
> -/// static TransformFactoryRegistry::Add<MyFactory>
> -/// X("my-transform", "<Short description of my transform>");
> -///
> -/// // This anchor is used to force the linker to link in the generated object
> -/// // file and thus register the factory.
> -/// volatile int MyTransformAnchorSource = 0;
> -/// \endcode
> -class TransformFactory {
> -public:
> - virtual ~TransformFactory();
> - virtual Transform *createTransform(const TransformOptions &) = 0;
> -
> - /// \brief Whether the transform is supported by the required compilers or
> - /// not.
> - bool supportsCompilers(CompilerVersions Required) const;
> -
> -protected:
> - /// \brief Since when the C++11 feature introduced by this transform has been
> - /// available.
> - ///
> - /// Can be set by the sub-class in the constructor body.
> - CompilerVersions Since;
> -};
> -
> -typedef llvm::Registry<TransformFactory> TransformFactoryRegistry;
> -
> -extern template class llvm::Registry<TransformFactory>;
> -
> -#endif // CLANG_MODERNIZE_TRANSFORM_H
> Index: clang-modernize/Core/Transform.cpp
> ===================================================================
> --- clang-modernize/Core/Transform.cpp
> +++ /dev/null
> @@ -1,169 +0,0 @@
> -//===-- Core/Transform.cpp - Transform Base Class Def'n -------------------===//
> -//
> -// 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 for the base Transform class from
> -/// which all transforms must subclass.
> -///
> -//===----------------------------------------------------------------------===//
> -
> -#include "Core/Transform.h"
> -#include "clang/ASTMatchers/ASTMatchFinder.h"
> -#include "clang/Basic/LangOptions.h"
> -#include "clang/Basic/SourceManager.h"
> -#include "clang/Frontend/CompilerInstance.h"
> -#include "clang/Tooling/Tooling.h"
> -#include "llvm/ADT/STLExtras.h"
> -
> -template class llvm::Registry<TransformFactory>;
> -
> -using namespace clang;
> -
> -llvm::cl::OptionCategory TransformsOptionsCategory("Transforms' options");
> -
> -namespace {
> -
> -using namespace tooling;
> -using namespace ast_matchers;
> -
> -/// \brief Custom FrontendActionFactory to produce FrontendActions that simply
> -/// forward (Begin|End)SourceFileAction calls to a given Transform.
> -class ActionFactory : public clang::tooling::FrontendActionFactory {
> -public:
> - ActionFactory(MatchFinder &Finder, Transform &Owner)
> - : Finder(Finder), Owner(Owner) {}
> -
> - FrontendAction *create() override {
> - return new FactoryAdaptor(Finder, Owner);
> - }
> -
> -private:
> - class FactoryAdaptor : public ASTFrontendAction {
> - public:
> - FactoryAdaptor(MatchFinder &Finder, Transform &Owner)
> - : Finder(Finder), Owner(Owner) {}
> -
> - std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &,
> - StringRef) override {
> - return Finder.newASTConsumer();
> - }
> -
> - bool BeginSourceFileAction(CompilerInstance &CI,
> - StringRef Filename) override {
> - if (!ASTFrontendAction::BeginSourceFileAction(CI, Filename))
> - return false;
> -
> - return Owner.handleBeginSource(CI, Filename);
> - }
> -
> - void EndSourceFileAction() override {
> - Owner.handleEndSource();
> - return ASTFrontendAction::EndSourceFileAction();
> - }
> -
> - private:
> - MatchFinder &Finder;
> - Transform &Owner;
> - };
> -
> - MatchFinder &Finder;
> - Transform &Owner;
> -};
> -} // namespace
> -
> -Transform::Transform(llvm::StringRef Name, const TransformOptions &Options)
> - : Name(Name), GlobalOptions(Options) {
> - Reset();
> -}
> -
> -Transform::~Transform() {}
> -
> -bool Transform::isFileModifiable(const SourceManager &SM,
> - SourceLocation Loc) const {
> - if (SM.isWrittenInMainFile(Loc))
> - return true;
> -
> - const FileEntry *FE = SM.getFileEntryForID(SM.getFileID(Loc));
> - if (!FE)
> - return false;
> -
> - return GlobalOptions.ModifiableFiles.isFileIncluded(FE->getName());
> -}
> -
> -bool Transform::handleBeginSource(CompilerInstance &CI, StringRef Filename) {
> - CurrentSource = Filename;
> -
> - if (Options().EnableTiming) {
> - Timings.push_back(std::make_pair(Filename.str(), llvm::TimeRecord()));
> - Timings.back().second -= llvm::TimeRecord::getCurrentTime(true);
> - }
> - return true;
> -}
> -
> -void Transform::handleEndSource() {
> - CurrentSource.clear();
> - if (Options().EnableTiming)
> - Timings.back().second += llvm::TimeRecord::getCurrentTime(false);
> -}
> -
> -void Transform::addTiming(llvm::StringRef Label, llvm::TimeRecord Duration) {
> - Timings.push_back(std::make_pair(Label.str(), Duration));
> -}
> -
> -bool
> -Transform::addReplacementForCurrentTU(const clang::tooling::Replacement &R) {
> - if (CurrentSource.empty())
> - return false;
> -
> - TranslationUnitReplacements &TU = Replacements[CurrentSource];
> - if (TU.MainSourceFile.empty())
> - TU.MainSourceFile = CurrentSource;
> - TU.Replacements.push_back(R);
> -
> - return true;
> -}
> -
> -std::unique_ptr<FrontendActionFactory>
> -Transform::createActionFactory(MatchFinder &Finder) {
> - return llvm::make_unique<ActionFactory>(Finder, /*Owner=*/*this);
> -}
> -
> -Version Version::getFromString(llvm::StringRef VersionStr) {
> - llvm::StringRef MajorStr, MinorStr;
> - Version V;
> -
> - std::tie(MajorStr, MinorStr) = VersionStr.split('.');
> - if (!MinorStr.empty()) {
> - llvm::StringRef Ignore;
> - std::tie(MinorStr, Ignore) = MinorStr.split('.');
> - if (MinorStr.getAsInteger(10, V.Minor))
> - return Version();
> - }
> - if (MajorStr.getAsInteger(10, V.Major))
> - return Version();
> - return V;
> -}
> -
> -TransformFactory::~TransformFactory() {}
> -
> -namespace {
> -bool versionSupported(Version Required, Version AvailableSince) {
> - // null version, means no requirements, means supported
> - if (Required.isNull())
> - return true;
> - return Required >= AvailableSince;
> -}
> -} // end anonymous namespace
> -
> -bool TransformFactory::supportsCompilers(CompilerVersions Required) const {
> - return versionSupported(Required.Clang, Since.Clang) &&
> - versionSupported(Required.Gcc, Since.Gcc) &&
> - versionSupported(Required.Icc, Since.Icc) &&
> - versionSupported(Required.Msvc, Since.Msvc);
> -}
> Index: clang-modernize/Core/ReplacementHandling.h
> ===================================================================
> --- clang-modernize/Core/ReplacementHandling.h
> +++ /dev/null
> @@ -1,127 +0,0 @@
> -//===-- Core/ReplacementHandling.h ------------------------------*- 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 defines the ReplacementHandling class which abstracts
> -/// serialization and application of serialized replacements.
> -///
> -//===----------------------------------------------------------------------===//
> -
> -#ifndef CLANG_MODERNIZE_REPLACEMENTHANDLING_H
> -#define CLANG_MODERNIZE_REPLACEMENTHANDLING_H
> -
> -#include "Core/Transform.h"
> -#include "llvm/ADT/StringRef.h"
> -
> -class ReplacementHandling {
> -public:
> -
> - ReplacementHandling() : DoFormat(false) {}
> -
> - /// \brief Finds the path to the executable 'clang-apply-replacements'.
> - ///
> - /// The executable is searched for on the PATH. If not found, looks in the
> - /// same directory as the image used to start the current executable.
> - ///
> - /// \param[in] Argv0 argv[0] as passed to main().
> - ///
> - /// \returns \parblock
> - /// \li true if clang-apply-replacements was found.
> - /// \li false otherwise.
> - bool findClangApplyReplacements(const char *Argv0);
> -
> - /// \brief Set the name of the directory in which replacements will be
> - /// serialized.
> - ///
> - /// \param[in] Dir Destination directory name
> - void setDestinationDir(llvm::StringRef Dir) { DestinationDir = Dir; }
> -
> - /// \brief Create a new temporary directory to serialize replacements into.
> - ///
> - /// \returns The name of the directory createdy.
> - llvm::StringRef useTempDestinationDir();
> -
> - /// \brief Enable clang-apply-replacements do code reformatting when applying
> - /// serialized replacements.
> - ///
> - /// \param[in] Style Value to pass to clang-apply-replacement's --style
> - /// option.
> - /// \param[in] StyleConfigDir If non-empty, value to pass to
> - /// clang-apply-replacement's --style-config option.
> - void enableFormatting(llvm::StringRef Style,
> - llvm::StringRef StyleConfigDir = "");
> -
> - /// \brief Write all TranslationUnitReplacements stored in \c Replacements
> - /// to disk.
> - ///
> - /// \pre Destination directory must have been previously set by calling
> - /// setDestiantionDir() or useTempDestinationDir().
> - /// \pre Destination dir must exist.
> - ///
> - /// \param[in] Replacements Container of replacements to serialize.
> - ///
> - /// \returns \parblock
> - /// \li true if all replacements were serialized successfully to
> - /// disk.
> - /// \li false otherwise.
> - bool serializeReplacements(const TUReplacementsMap &Replacements);
> -
> - /// \brief Invoke clang-apply-replacements to apply all serialized
> - /// replacements stored in the destination directory.
> - ///
> - /// \pre Destination directory must have been previously set by calling
> - /// setDestiantionDir() or useTempDestinationDir().
> - ///
> - /// \returns \parblock
> - /// \li true if clang-apply-replacements was successfully launched
> - /// and successfully completed.
> - /// \li false otherwise.
> - bool applyReplacements();
> -
> - /// \brief Generate a unique filename to store the replacements.
> - ///
> - /// Generates a unique filename in \c DestinationDir. The filename is generated
> - /// following this pattern:
> - ///
> - /// DestinationDir/Prefix_%%_%%_%%_%%_%%_%%.yaml
> - ///
> - /// where Prefix := llvm::sys::path::filename(MainSourceFile) and all '%' will
> - /// be replaced by a randomly chosen hex digit.
> - ///
> - /// \param[in] DestinationDir Directory the unique file should be placed in.
> - /// \param[in] MainSourceFile Full path to the source file.
> - /// \param[out] Result The resulting unique filename.
> - /// \param[out] Error If an error occurs a description of that error is
> - /// placed in this string.
> - ///
> - /// \returns \parblock
> - /// \li true on success
> - /// \li false if a unique file name could not be created.
> - static bool generateReplacementsFileName(llvm::StringRef DestinationDir,
> - llvm::StringRef MainSourceFile,
> - llvm::SmallVectorImpl<char> &Result,
> - llvm::SmallVectorImpl<char> &Error);
> -
> - /// \brief Helper to create a temporary directory name.
> - ///
> - /// \post The directory named by the returned string exists.
> - ///
> - /// \returns A temp directory name.
> - static std::string generateTempDir();
> -
> -private:
> -
> - std::string CARPath;
> - std::string DestinationDir;
> - bool DoFormat;
> - std::string FormatStyle;
> - std::string StyleConfigDir;
> -};
> -
> -#endif // CLANG_MODERNIZE_REPLACEMENTHANDLING_H
> Index: clang-modernize/Core/ReplacementHandling.cpp
> ===================================================================
> --- clang-modernize/Core/ReplacementHandling.cpp
> +++ /dev/null
> @@ -1,155 +0,0 @@
> -//===-- Core/ReplacementHandling.cpp --------------------------------------===//
> -//
> -// 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 implementations for the ReplacementHandling class.
> -///
> -//===----------------------------------------------------------------------===//
> -
> -#include "Core/ReplacementHandling.h"
> -#include "clang/Tooling/ReplacementsYaml.h"
> -#include "llvm/ADT/SmallString.h"
> -#include "llvm/Support/FileSystem.h"
> -#include "llvm/Support/Path.h"
> -#include "llvm/Support/Program.h"
> -#include <system_error>
> -
> -using namespace llvm;
> -using namespace llvm::sys;
> -using namespace clang::tooling;
> -
> -bool ReplacementHandling::findClangApplyReplacements(const char *Argv0) {
> - ErrorOr<std::string> CARPathOrErr =
> - findProgramByName("clang-apply-replacements");
> - if (!CARPathOrErr)
> - return true;
> -
> - CARPath = *CARPathOrErr;
> - static int StaticSymbol;
> - std::string ClangModernizePath = fs::getMainExecutable(Argv0, &StaticSymbol);
> - SmallString<128> TestPath = path::parent_path(ClangModernizePath);
> - path::append(TestPath, "clang-apply-replacements");
> - if (fs::can_execute(Twine(TestPath)))
> - CARPath = TestPath.str();
> -
> - return !CARPath.empty();
> -}
> -
> -StringRef ReplacementHandling::useTempDestinationDir() {
> - DestinationDir = generateTempDir();
> - return DestinationDir;
> -}
> -
> -void ReplacementHandling::enableFormatting(StringRef Style,
> - StringRef StyleConfigDir) {
> - DoFormat = true;
> - FormatStyle = Style;
> - this->StyleConfigDir = StyleConfigDir;
> -}
> -
> -bool ReplacementHandling::serializeReplacements(
> - const TUReplacementsMap &Replacements) {
> - assert(!DestinationDir.empty() && "Destination directory not set");
> -
> - bool Errors = false;
> -
> - for (TUReplacementsMap::const_iterator I = Replacements.begin(),
> - E = Replacements.end();
> - I != E; ++I) {
> - SmallString<128> ReplacementsFileName;
> - SmallString<64> Error;
> - bool Result = generateReplacementsFileName(DestinationDir,
> - I->getValue().MainSourceFile,
> - ReplacementsFileName, Error);
> - if (!Result) {
> - errs() << "Failed to generate replacements filename:" << Error << "\n";
> - Errors = true;
> - continue;
> - }
> -
> - std::error_code EC;
> - raw_fd_ostream ReplacementsFile(ReplacementsFileName, EC, fs::F_None);
> - if (EC) {
> - errs() << "Error opening file: " << EC.message() << "\n";
> - Errors = true;
> - continue;
> - }
> - yaml::Output YAML(ReplacementsFile);
> - YAML << const_cast<TranslationUnitReplacements &>(I->getValue());
> - }
> - return !Errors;
> -}
> -
> -bool ReplacementHandling::applyReplacements() {
> - SmallVector<const char *, 8> Argv;
> - Argv.push_back(CARPath.c_str());
> - std::string Style = "--style=" + FormatStyle;
> - std::string StyleConfig = "--style-config=" + StyleConfigDir;
> - if (DoFormat) {
> - Argv.push_back("--format");
> - Argv.push_back(Style.c_str());
> - if (!StyleConfigDir.empty())
> - Argv.push_back(StyleConfig.c_str());
> - }
> - Argv.push_back("--remove-change-desc-files");
> - Argv.push_back(DestinationDir.c_str());
> -
> - // Argv array needs to be null terminated.
> - Argv.push_back(nullptr);
> -
> - std::string ErrorMsg;
> - bool ExecutionFailed = false;
> - int ReturnCode = ExecuteAndWait(CARPath.c_str(), Argv.data(),
> - /* env */ nullptr, /* redirects */ nullptr,
> - /* secondsToWait */ 0, /* memoryLimit */ 0,
> - &ErrorMsg, &ExecutionFailed);
> - if (ExecutionFailed || !ErrorMsg.empty()) {
> - errs() << "Failed to launch clang-apply-replacements: " << ErrorMsg << "\n";
> - errs() << "Command Line:\n";
> - for (const char **I = Argv.begin(), **E = Argv.end(); I != E; ++I) {
> - if (*I)
> - errs() << *I << "\n";
> - }
> - return false;
> - }
> -
> - if (ReturnCode != 0) {
> - errs() << "clang-apply-replacements failed with return code " << ReturnCode
> - << "\n";
> - return false;
> - }
> -
> - return true;
> -}
> -
> -std::string ReplacementHandling::generateTempDir() {
> - SmallString<128> Prefix;
> - path::system_temp_directory(true, Prefix);
> - path::append(Prefix, "clang-modernize");
> - SmallString<128> Result;
> - fs::createUniqueDirectory(Twine(Prefix), Result);
> - return Result.str();
> -}
> -
> -bool ReplacementHandling::generateReplacementsFileName(
> - StringRef DestinationDir, StringRef MainSourceFile,
> - SmallVectorImpl<char> &Result, SmallVectorImpl<char> &Error) {
> -
> - Error.clear();
> - SmallString<128> Prefix = DestinationDir;
> - path::append(Prefix, path::filename(MainSourceFile));
> - if (std::error_code EC =
> - fs::createUniqueFile(Prefix + "_%%_%%_%%_%%_%%_%%.yaml", Result)) {
> - const std::string &Msg = EC.message();
> - Error.append(Msg.begin(), Msg.end());
> - return false;
> - }
> -
> - return true;
> -}
> Index: clang-modernize/Core/Refactoring.h
> ===================================================================
> --- clang-modernize/Core/Refactoring.h
> +++ /dev/null
> @@ -1,31 +0,0 @@
> -//===-- Core/Refactoring.h - Stand-in for Tooling/Refactoring.h -*- 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 is meant to be used instead of clang/Tooling/Refactoring.h
> -/// until such time as clang::tooling::Replacements is re-implemented as a
> -/// vector instead of a set.
> -///
> -//===----------------------------------------------------------------------===//
> -
> -#ifndef CLANG_MODERNIZE_REPLACEMENTS_VEC_H
> -#define CLANG_MODERNIZE_REPLACEMENTS_VEC_H
> -
> -#include "clang/Tooling/Refactoring.h"
> -
> -// FIXME: Remove this file when clang::tooling::Replacements becomes a vector
> -// instead of a set.
> -
> -namespace clang {
> -namespace tooling {
> -typedef std::vector<clang::tooling::Replacement> ReplacementsVec;
> -}
> -}
> -
> -#endif // CLANG_MODERNIZE_REPLACEMENTS_VEC_H
> Index: clang-modernize/Core/PerfSupport.h
> ===================================================================
> --- clang-modernize/Core/PerfSupport.h
> +++ /dev/null
> @@ -1,56 +0,0 @@
> -//===-- Core/PerfSupport.h - Perf measurement helpers -----------*- 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 helper functionality for measuring performance and
> -/// recording data to file.
> -///
> -//===----------------------------------------------------------------------===//
> -
> -#ifndef CLANG_MODERNIZE_PERFSUPPORT_H
> -#define CLANG_MODERNIZE_PERFSUPPORT_H
> -
> -#include "Transform.h"
> -#include "llvm/ADT/StringRef.h"
> -#include <map>
> -#include <vector>
> -
> -/// \brief A single piece of performance data: a duration in milliseconds and a
> -/// label for that duration.
> -struct PerfItem {
> - PerfItem(const llvm::StringRef Label, float Duration)
> - : Label(Label), Duration(Duration) {}
> -
> - /// Label for this performance measurement.
> - std::string Label;
> -
> - /// Duration in milliseconds.
> - float Duration;
> -};
> -
> -/// Maps source file names to a vector of durations/labels.
> -typedef std::map<std::string, std::vector<PerfItem> > SourcePerfData;
> -
> -/// Extracts durations collected by a Transform for all sources and adds them
> -/// to a SourcePerfData map where data is organized by source file.
> -extern void collectSourcePerfData(const Transform &T, SourcePerfData &Data);
> -
> -/// Write timing results to a JSON formatted file.
> -///
> -/// File is placed in the directory given by \p DirectoryName. File is named in
> -/// a unique way with time and process ID to avoid naming collisions with
> -/// existing files or files being generated by other migrator processes.
> -void writePerfDataJSON(
> - const llvm::StringRef DirectoryName,
> - const SourcePerfData &TimingResults);
> -
> -/// Dump a SourcePerfData map to llvm::errs().
> -extern void dumpPerfData(const SourcePerfData &Data);
> -
> -#endif // CLANG_MODERNIZE_PERFSUPPORT_H
> Index: clang-modernize/Core/PerfSupport.cpp
> ===================================================================
> --- clang-modernize/Core/PerfSupport.cpp
> +++ /dev/null
> @@ -1,101 +0,0 @@
> -//===-- Core/PerfSupport.cpp - Perf measurement helpers -------------------===//
> -//
> -// 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 implementations for performance measuring helpers.
> -///
> -//===----------------------------------------------------------------------===//
> -
> -#include "PerfSupport.h"
> -#include "llvm/Support/FileSystem.h"
> -#include "llvm/Support/Format.h"
> -#include "llvm/Support/Path.h"
> -#include "llvm/Support/Process.h"
> -#include "llvm/Support/raw_ostream.h"
> -
> -void collectSourcePerfData(const Transform &T, SourcePerfData &Data) {
> - for (Transform::TimingVec::const_iterator I = T.timing_begin(),
> - E = T.timing_end();
> - I != E; ++I) {
> - SourcePerfData::iterator DataI = Data.insert(
> - SourcePerfData::value_type(I->first, std::vector<PerfItem>())).first;
> - DataI->second
> - .push_back(PerfItem(T.getName(), I->second.getProcessTime() * 1000.0));
> - }
> -}
> -
> -void writePerfDataJSON(
> - const llvm::StringRef DirectoryName,
> - const SourcePerfData &TimingResults) {
> - // Create directory path if it doesn't exist
> - llvm::sys::fs::create_directories(DirectoryName);
> -
> - // Get PID and current time.
> - // FIXME: id_type on Windows is NOT a process id despite the function name.
> - // Need to call GetProcessId() providing it what get_id() returns. For now
> - // disabling PID-based file names until this is fixed properly.
> - //llvm::sys::self_process *SP = llvm::sys::process::get_self();
> - //id_type Pid = SP->get_id();
> - unsigned Pid = 0;
> - llvm::TimeRecord T = llvm::TimeRecord::getCurrentTime();
> -
> - std::string FileName;
> - llvm::raw_string_ostream SS(FileName);
> - SS << DirectoryName << "/" << static_cast<int>(T.getWallTime()) << "_" << Pid
> - << ".json";
> -
> - std::error_code EC;
> - llvm::raw_fd_ostream FileStream(SS.str(), EC, llvm::sys::fs::F_Text);
> - FileStream << "{\n";
> - FileStream << " \"Sources\" : [\n";
> - for (SourcePerfData::const_iterator I = TimingResults.begin(),
> - E = TimingResults.end();
> - I != E; ++I) {
> - // Terminate the last source with a comma before continuing to the next one.
> - if (I != TimingResults.begin())
> - FileStream << ",\n";
> -
> - FileStream << " {\n";
> - FileStream << " \"Source \" : \"" << I->first << "\",\n";
> - FileStream << " \"Data\" : [\n";
> - for (std::vector<PerfItem>::const_iterator IE = I->second.begin(),
> - EE = I->second.end();
> - IE != EE; ++IE) {
> - // Terminate the last perf item with a comma before continuing to the next
> - // one.
> - if (IE != I->second.begin())
> - FileStream << ",\n";
> -
> - FileStream << " {\n";
> - FileStream << " \"TimerId\" : \"" << IE->Label << "\",\n";
> - FileStream << " \"Time\" : " << llvm::format("%.2f", IE->Duration)
> - << "\n";
> -
> - FileStream << " }";
> -
> - }
> - FileStream << "\n ]\n";
> - FileStream << " }";
> - }
> - FileStream << "\n ]\n";
> - FileStream << "}";
> -}
> -
> -void dumpPerfData(const SourcePerfData &Data) {
> - for (SourcePerfData::const_iterator I = Data.begin(), E = Data.end(); I != E;
> - ++I) {
> - llvm::errs() << I->first << ":\n";
> - for (std::vector<PerfItem>::const_iterator VecI = I->second.begin(),
> - VecE = I->second.end();
> - VecI != VecE; ++VecI) {
> - llvm::errs() << " " << VecI->Label << ": "
> - << llvm::format("%.1f", VecI->Duration) << "ms\n";
> - }
> - }
> -}
> Index: clang-modernize/Core/Makefile
> ===================================================================
> --- clang-modernize/Core/Makefile
> +++ /dev/null
> @@ -1,14 +0,0 @@
> -##===- clang-modernize/Core/Makefile -----------------------*- Makefile -*-===##
> -#
> -# The LLVM Compiler Infrastructure
> -#
> -# This file is distributed under the University of Illinois Open Source
> -# License. See LICENSE.TXT for details.
> -#
> -##===----------------------------------------------------------------------===##
> -CLANG_LEVEL := ../../../..
> -LIBRARYNAME := modernizeCore
> -
> -include $(CLANG_LEVEL)/Makefile
> -
> -CPP.Flags += -I$(PROJ_SRC_DIR)/.. -I$(PROJ_SRC_DIR)/../../clang-apply-replacements/include
> Index: clang-modernize/Core/IncludeExcludeInfo.h
> ===================================================================
> --- clang-modernize/Core/IncludeExcludeInfo.h
> +++ /dev/null
> @@ -1,62 +0,0 @@
> -//===-- Core/IncludeExcludeInfo.h - IncludeExclude class def'n --*- 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 for the IncludeExcludeInfo class
> -/// to handle the include and exclude command line options.
> -///
> -//===----------------------------------------------------------------------===//
> -
> -#ifndef CLANG_MODERNIZE_INCLUDEEXCLUDEINFO_H
> -#define CLANG_MODERNIZE_INCLUDEEXCLUDEINFO_H
> -
> -#include "llvm/ADT/StringRef.h"
> -#include <system_error>
> -#include <vector>
> -
> -/// \brief Class encapsulating the handling of include and exclude paths
> -/// provided by the user through command line options.
> -class IncludeExcludeInfo {
> -public:
> - /// \brief Read and parse a comma-separated lists of paths from
> - /// \a IncludeString and \a ExcludeString.
> - ///
> - /// Returns error_code::success() on successful parse of the strings or
> - /// an error_code indicating the encountered error.
> - std::error_code readListFromString(llvm::StringRef IncludeString,
> - llvm::StringRef ExcludeString);
> -
> - /// \brief Read and parse the lists of paths from \a IncludeListFile
> - /// and \a ExcludeListFile. Each file should contain one path per line.
> - ///
> - /// Returns error_code::success() on successful read and parse of both files
> - /// or an error_code indicating the encountered error.
> - std::error_code readListFromFile(llvm::StringRef IncludeListFile,
> - llvm::StringRef ExcludeListFile);
> -
> - /// \brief Determine if the given path is in the list of include paths but
> - /// not in the list of exclude paths.
> - ///
> - /// \a FilePath shouldn't contain relative operators i.e. ".." or "." since
> - /// Path comes from the include/exclude list of paths in which relative
> - /// operators were removed.
> - bool isFileIncluded(llvm::StringRef FilePath) const;
> -
> - /// \brief Determine if a file path was explicitly excluded.
> - bool isFileExplicitlyExcluded(llvm::StringRef FilePath) const;
> -
> - /// \brief Determine if a list of include paths was provided.
> - bool isIncludeListEmpty() const { return IncludeList.empty(); }
> -
> -private:
> - std::vector<std::string> IncludeList;
> - std::vector<std::string> ExcludeList;
> -};
> -
> -#endif // CLANG_MODERNIZE_INCLUDEEXCLUDEINFO_H
> Index: clang-modernize/Core/IncludeExcludeInfo.cpp
> ===================================================================
> --- clang-modernize/Core/IncludeExcludeInfo.cpp
> +++ /dev/null
> @@ -1,179 +0,0 @@
> -//===-- Core/IncludeExcludeInfo.cpp - IncludeExclude class impl -----------===//
> -//
> -// 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 IncludeExcludeInfo class
> -/// to handle the include and exclude command line options.
> -///
> -//===----------------------------------------------------------------------===//
> -
> -#include "IncludeExcludeInfo.h"
> -#include "llvm/Support/CommandLine.h"
> -#include "llvm/Support/FileSystem.h"
> -#include "llvm/Support/MemoryBuffer.h"
> -#include "llvm/Support/Path.h"
> -#include "llvm/Support/raw_ostream.h"
> -
> -using namespace llvm;
> -
> -/// A string type to represent paths.
> -typedef SmallString<64> PathString;
> -
> -namespace {
> -/// \brief Helper function to determine whether a file has the same path
> -/// prefix as \a Path.
> -///
> -/// \a Path must be an absolute path.
> -bool fileHasPathPrefix(StringRef File, StringRef Path) {
> - // Converts File to its absolute path.
> - PathString AbsoluteFile = File;
> - sys::fs::make_absolute(AbsoluteFile);
> -
> - // Convert path strings to sys::path to iterate over each of its directories.
> - sys::path::const_iterator FileI = sys::path::begin(AbsoluteFile),
> - FileE = sys::path::end(AbsoluteFile),
> - PathI = sys::path::begin(Path),
> - PathE = sys::path::end(Path);
> - while (FileI != FileE && PathI != PathE) {
> - // If the strings aren't equal then the two paths aren't contained within
> - // each other.
> - bool IsSeparator = ((FileI->size() == 1) && (PathI->size() == 1) &&
> - sys::path::is_separator((*FileI)[0]) &&
> - sys::path::is_separator((*PathI)[0]));
> - if (!FileI->equals(*PathI) && !IsSeparator)
> - return false;
> - ++FileI;
> - ++PathI;
> - }
> - return true;
> -}
> -
> -/// \brief Helper function for removing relative operators from a given
> -/// path i.e. "..", ".".
> -/// \a Path must be a absolute path.
> -std::string removeRelativeOperators(StringRef Path) {
> - sys::path::const_iterator PathI = sys::path::begin(Path);
> - sys::path::const_iterator PathE = sys::path::end(Path);
> - SmallVector<StringRef, 16> PathT;
> - while (PathI != PathE) {
> - if (PathI->equals("..")) {
> - // Test if we have reached the root then Path is invalid.
> - if (PathT.empty())
> - return "";
> - PathT.pop_back();
> - } else if (!PathI->equals("."))
> - PathT.push_back(*PathI);
> - ++PathI;
> - }
> - // Rebuild the new path.
> - PathString NewPath;
> - for (SmallVectorImpl<StringRef>::iterator I = PathT.begin(), E = PathT.end();
> - I != E; ++I) {
> - llvm::sys::path::append(NewPath, *I);
> - }
> - return NewPath.str();
> -}
> -
> -/// \brief Helper function to tokenize a string of paths and populate
> -/// the vector.
> -std::error_code parseCLInput(StringRef Line, std::vector<std::string> &List,
> - StringRef Separator) {
> - SmallVector<StringRef, 32> Tokens;
> - Line.split(Tokens, Separator, /*MaxSplit=*/ -1, /*KeepEmpty=*/ false);
> - for (SmallVectorImpl<StringRef>::iterator I = Tokens.begin(),
> - E = Tokens.end();
> - I != E; ++I) {
> - // Convert each path to its absolute path.
> - PathString Path = I->rtrim();
> - if (std::error_code Err = sys::fs::make_absolute(Path))
> - return Err;
> - // Remove relative operators from the path.
> - std::string AbsPath = removeRelativeOperators(Path);
> - // Add only non-empty paths to the list.
> - if (!AbsPath.empty())
> - List.push_back(AbsPath);
> - else
> - llvm::errs() << "Unable to parse input path: " << *I << "\n";
> -
> - llvm::errs() << "Parse: " <<List.back() << "\n";
> - }
> - return std::error_code();
> -}
> -} // end anonymous namespace
> -
> -std::error_code
> -IncludeExcludeInfo::readListFromString(StringRef IncludeString,
> - StringRef ExcludeString) {
> - if (std::error_code Err = parseCLInput(IncludeString, IncludeList,
> - /*Separator=*/","))
> - return Err;
> - if (std::error_code Err = parseCLInput(ExcludeString, ExcludeList,
> - /*Separator=*/","))
> - return Err;
> - return std::error_code();
> -}
> -
> -std::error_code
> -IncludeExcludeInfo::readListFromFile(StringRef IncludeListFile,
> - StringRef ExcludeListFile) {
> - if (!IncludeListFile.empty()) {
> - ErrorOr<std::unique_ptr<MemoryBuffer>> FileBuf =
> - MemoryBuffer::getFile(IncludeListFile);
> - if (std::error_code Err = FileBuf.getError()) {
> - errs() << "Unable to read from include file.\n";
> - return Err;
> - }
> - if (std::error_code Err =
> - parseCLInput(FileBuf.get()->getBuffer(), IncludeList,
> - /*Separator=*/"\n"))
> - return Err;
> - }
> - if (!ExcludeListFile.empty()) {
> - ErrorOr<std::unique_ptr<MemoryBuffer>> FileBuf =
> - MemoryBuffer::getFile(ExcludeListFile);
> - if (std::error_code Err = FileBuf.getError()) {
> - errs() << "Unable to read from exclude file.\n";
> - return Err;
> - }
> - if (std::error_code Err =
> - parseCLInput(FileBuf.get()->getBuffer(), ExcludeList,
> - /*Separator=*/"\n"))
> - return Err;
> - }
> - return std::error_code();
> -}
> -
> -bool IncludeExcludeInfo::isFileIncluded(StringRef FilePath) const {
> - bool InIncludeList = false;
> -
> - for (std::vector<std::string>::const_iterator I = IncludeList.begin(),
> - E = IncludeList.end();
> - I != E; ++I)
> - if ((InIncludeList = fileHasPathPrefix(FilePath, *I)))
> - break;
> -
> - // If file is not in the list of included paths then it is not necessary
> - // to check the excluded path list.
> - if (!InIncludeList)
> - return false;
> -
> - // If the file is in the included list but not is not explicitly excluded,
> - // then it is safe to transform.
> - return !isFileExplicitlyExcluded(FilePath);
> -}
> -
> -bool IncludeExcludeInfo::isFileExplicitlyExcluded(StringRef FilePath) const {
> - for (std::vector<std::string>::const_iterator I = ExcludeList.begin(),
> - E = ExcludeList.end();
> - I != E; ++I)
> - if (fileHasPathPrefix(FilePath, *I))
> - return true;
> -
> - return false;
> -}
> Index: clang-modernize/Core/IncludeDirectives.h
> ===================================================================
> --- clang-modernize/Core/IncludeDirectives.h
> +++ /dev/null
> @@ -1,141 +0,0 @@
> -//===-- Core/IncludeDirectives.h - Include directives handling --*- 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 declares the IncludeDirectives class that helps with
> -/// detecting and modifying \#include directives.
> -///
> -//===----------------------------------------------------------------------===//
> -
> -#ifndef CLANG_MODERNIZE_INCLUDE_DIRECTIVES_H
> -#define CLANG_MODERNIZE_INCLUDE_DIRECTIVES_H
> -
> -#include "clang/Basic/SourceLocation.h"
> -#include "clang/Tooling/Refactoring.h"
> -#include "llvm/ADT/DenseMap.h"
> -#include "llvm/ADT/SmallPtrSet.h"
> -#include "llvm/ADT/StringRef.h"
> -#include <vector>
> -
> -namespace clang {
> -class Preprocessor;
> -} // namespace clang
> -
> -/// \brief Support for include directives handling.
> -///
> -/// This class should be created with a \c clang::CompilerInstance before the
> -/// file is preprocessed in order to collect the inclusion information. It can
> -/// be queried as long as the compiler instance is valid.
> -class IncludeDirectives {
> -public:
> - IncludeDirectives(clang::CompilerInstance &CI);
> -
> - /// \brief Add an angled include to a the given file.
> - ///
> - /// \param File A file accessible by a SourceManager
> - /// \param Include The include file as it should be written in the code.
> - ///
> - /// \returns \parblock
> - /// \li A null Replacement (check using \c Replacement::isApplicable()), if
> - /// the \c Include is already visible from \c File.
> - /// \li Otherwise, a non-null Replacement that, when applied, inserts an
> - /// \c \#include into \c File.
> - clang::tooling::Replacement addAngledInclude(llvm::StringRef File,
> - llvm::StringRef Include);
> - clang::tooling::Replacement addAngledInclude(const clang::FileEntry *File,
> - llvm::StringRef Include);
> -
> - /// \brief Check if \p Include is included by \p File or any of the files
> - /// \p File includes.
> - bool hasInclude(const clang::FileEntry *File, llvm::StringRef Include) const;
> -
> -private:
> - friend class IncludeDirectivesPPCallback;
> -
> - /// \brief Contains information about an inclusion.
> - class Entry {
> - public:
> - Entry(clang::SourceLocation HashLoc, const clang::FileEntry *IncludedFile,
> - bool Angled)
> - : HashLoc(HashLoc), IncludedFile(IncludedFile), Angled(Angled) {}
> -
> - /// \brief The location of the '#'.
> - clang::SourceLocation getHashLocation() const { return HashLoc; }
> -
> - /// \brief The file included by this include directive.
> - const clang::FileEntry *getIncludedFile() const { return IncludedFile; }
> -
> - /// \brief \c true if the include use angle brackets, \c false otherwise
> - /// when using of quotes.
> - bool isAngled() const { return Angled; }
> -
> - private:
> - clang::SourceLocation HashLoc;
> - const clang::FileEntry *IncludedFile;
> - bool Angled;
> - };
> -
> - // A list of entries.
> - typedef std::vector<Entry> EntryVec;
> -
> - // A list of source locations.
> - typedef std::vector<clang::SourceLocation> LocationVec;
> -
> - // Associates files to their includes.
> - typedef llvm::DenseMap<const clang::FileEntry *, EntryVec> FileToEntriesMap;
> -
> - // Associates headers to their include guards if any. The location is the
> - // location of the hash from the #define.
> - typedef llvm::DenseMap<const clang::FileEntry *, clang::SourceLocation>
> - HeaderToGuardMap;
> -
> - /// \brief Type used by \c lookForInclude() to keep track of the files that
> - /// have already been processed.
> - typedef llvm::SmallPtrSet<const clang::FileEntry *, 32> SeenFilesSet;
> -
> - /// \brief Recursively look if an include is included by \p File or any of the
> - /// headers \p File includes.
> - ///
> - /// \param File The file where to start the search.
> - /// \param IncludeLocs These are the hash locations of the \#include
> - /// directives we are looking for.
> - /// \param Seen Used to avoid visiting a same file more than once during the
> - /// recursion.
> - bool lookForInclude(const clang::FileEntry *File,
> - const LocationVec &IncludeLocs, SeenFilesSet &Seen) const;
> -
> - /// \brief Find the end of a file header and returns a pair (FileOffset,
> - /// NewLineFlags).
> - ///
> - /// Source files often contain a file header (copyright, license, explanation
> - /// of the file content). An \#include should preferably be put after this.
> - std::pair<unsigned, unsigned>
> - findFileHeaderEndOffset(clang::FileID FID) const;
> -
> - /// \brief Finds the offset where an angled include should be added and
> - /// returns a pair (FileOffset, NewLineFlags).
> - std::pair<unsigned, unsigned>
> - angledIncludeInsertionOffset(clang::FileID FID) const;
> -
> - /// \brief Find the location of an include directive that can be used to
> - /// insert an inclusion after.
> - ///
> - /// If no such include exists returns a null SourceLocation.
> - clang::SourceLocation angledIncludeHintLoc(clang::FileID FID) const;
> -
> - clang::CompilerInstance &CI;
> - clang::SourceManager &Sources;
> - FileToEntriesMap FileToEntries;
> - // maps include filename as written in the source code to the source locations
> - // where it appears
> - llvm::StringMap<LocationVec> IncludeAsWrittenToLocationsMap;
> - HeaderToGuardMap HeaderToGuard;
> -};
> -
> -#endif // CLANG_MODERNIZE_INCLUDE_DIRECTIVES_H
> Index: clang-modernize/Core/IncludeDirectives.cpp
> ===================================================================
> --- clang-modernize/Core/IncludeDirectives.cpp
> +++ /dev/null
> @@ -1,480 +0,0 @@
> -//===-- Core/IncludeDirectives.cpp - Include directives handling ----------===//
> -//
> -// 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 defines the IncludeDirectives class that helps with
> -/// detecting and modifying \#include directives.
> -///
> -//===----------------------------------------------------------------------===//
> -
> -#include "IncludeDirectives.h"
> -#include "clang/Basic/CharInfo.h"
> -#include "clang/Frontend/CompilerInstance.h"
> -#include "clang/Lex/HeaderSearch.h"
> -#include "clang/Lex/Preprocessor.h"
> -#include "llvm/ADT/STLExtras.h"
> -#include "llvm/ADT/StringSwitch.h"
> -#include <stack>
> -
> -using namespace clang;
> -using namespace clang::tooling;
> -using llvm::StringRef;
> -
> -/// \brief PPCallbacks that fills-in the include information in the given
> -/// \c IncludeDirectives.
> -class IncludeDirectivesPPCallback : public clang::PPCallbacks {
> - // Struct helping the detection of header guards in the various callbacks
> - struct GuardDetection {
> - GuardDetection(FileID FID)
> - : FID(FID), Count(0), TheMacro(nullptr), CountAtEndif(0) {}
> -
> - FileID FID;
> - // count for relevant preprocessor directives
> - unsigned Count;
> - // the macro that is tested in the top most ifndef for the header guard
> - // (e.g: GUARD_H)
> - const IdentifierInfo *TheMacro;
> - // the hash locations of #ifndef, #define, #endif
> - SourceLocation IfndefLoc, DefineLoc, EndifLoc;
> - // the value of Count once the #endif is reached
> - unsigned CountAtEndif;
> -
> - /// \brief Check that with all the information gathered if this is a
> - /// potential header guard.
> - ///
> - /// Meaning a top-most \#ifndef has been found, followed by a define and the
> - /// last preprocessor directive was the terminating \#endif.
> - ///
> - /// FIXME: accept the \#if !defined identifier form too.
> - bool isPotentialHeaderGuard() const {
> - return Count == CountAtEndif && DefineLoc.isValid();
> - }
> - };
> -
> -public:
> - IncludeDirectivesPPCallback(IncludeDirectives *Self)
> - : Self(Self), Guard(nullptr) {}
> - ~IncludeDirectivesPPCallback() override {}
> -
> -private:
> - void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
> - StringRef FileName, bool IsAngled,
> - CharSourceRange FilenameRange, const FileEntry *File,
> - StringRef SearchPath, StringRef RelativePath,
> - const Module *Imported) override {
> - SourceManager &SM = Self->Sources;
> - const FileEntry *FE = SM.getFileEntryForID(SM.getFileID(HashLoc));
> - assert(FE && "Valid file expected.");
> -
> - IncludeDirectives::Entry E(HashLoc, File, IsAngled);
> - Self->FileToEntries[FE].push_back(E);
> - Self->IncludeAsWrittenToLocationsMap[FileName].push_back(HashLoc);
> - }
> -
> - // Keep track of the current file in the stack
> - void FileChanged(SourceLocation Loc, FileChangeReason Reason,
> - SrcMgr::CharacteristicKind FileType,
> - FileID PrevFID) override {
> - SourceManager &SM = Self->Sources;
> - switch (Reason) {
> - case EnterFile:
> - Files.push(GuardDetection(SM.getFileID(Loc)));
> - Guard = &Files.top();
> - break;
> -
> - case ExitFile:
> - if (Guard->isPotentialHeaderGuard())
> - handlePotentialHeaderGuard(*Guard);
> - Files.pop();
> - Guard = &Files.top();
> - break;
> -
> - default:
> - break;
> - }
> - }
> -
> - /// \brief Mark this header as guarded in the IncludeDirectives if it's a
> - /// proper header guard.
> - void handlePotentialHeaderGuard(const GuardDetection &Guard) {
> - SourceManager &SM = Self->Sources;
> - const FileEntry *File = SM.getFileEntryForID(Guard.FID);
> - const LangOptions &LangOpts = Self->CI.getLangOpts();
> -
> - // Null file can happen for the <built-in> buffer for example. They
> - // shouldn't have header guards though...
> - if (!File)
> - return;
> -
> - // The #ifndef should be the next thing after the preamble. We aren't
> - // checking for equality because it can also be part of the preamble if the
> - // preamble is the whole file.
> - unsigned Preamble =
> - Lexer::ComputePreamble(SM.getBuffer(Guard.FID)->getBuffer(), LangOpts)
> - .first;
> - unsigned IfndefOffset = SM.getFileOffset(Guard.IfndefLoc);
> - if (IfndefOffset > (Preamble + 1))
> - return;
> -
> - // No code is allowed in the code remaining after the #endif.
> - const llvm::MemoryBuffer *Buffer = SM.getBuffer(Guard.FID);
> - Lexer Lex(SM.getLocForStartOfFile(Guard.FID), LangOpts,
> - Buffer->getBufferStart(),
> - Buffer->getBufferStart() + SM.getFileOffset(Guard.EndifLoc),
> - Buffer->getBufferEnd());
> -
> - // Find the first newline not part of a multi-line comment.
> - Token Tok;
> - Lex.LexFromRawLexer(Tok); // skip endif
> - Lex.LexFromRawLexer(Tok);
> -
> - // Not a proper header guard, the remainder of the file contains something
> - // else than comments or whitespaces.
> - if (Tok.isNot(tok::eof))
> - return;
> -
> - // Add to the location of the define to the IncludeDirectives for this file.
> - Self->HeaderToGuard[File] = Guard.DefineLoc;
> - }
> -
> - void Ifndef(SourceLocation Loc, const Token &MacroNameTok,
> - const MacroDefinition &MD) override {
> - Guard->Count++;
> -
> - // If this #ifndef is the top-most directive and the symbol isn't defined
> - // store those information in the guard detection, the next step will be to
> - // check for the define.
> - if (Guard->Count == 1 && !MD) {
> - IdentifierInfo *MII = MacroNameTok.getIdentifierInfo();
> -
> - Guard->IfndefLoc = Loc;
> - Guard->TheMacro = MII;
> - }
> - }
> -
> - void MacroDefined(const Token &MacroNameTok,
> - const MacroDirective *MD) override {
> - Guard->Count++;
> -
> - // If this #define is the second directive of the file and the symbol
> - // defined is the same as the one checked in the #ifndef then store the
> - // information about this define.
> - if (Guard->Count == 2 && Guard->TheMacro != nullptr) {
> - IdentifierInfo *MII = MacroNameTok.getIdentifierInfo();
> -
> - // macro unrelated to the ifndef, doesn't look like a proper header guard
> - if (MII->getName() != Guard->TheMacro->getName())
> - return;
> -
> - Guard->DefineLoc = MacroNameTok.getLocation();
> - }
> - }
> -
> - void Endif(SourceLocation Loc, SourceLocation IfLoc) override {
> - Guard->Count++;
> -
> - // If it's the #endif corresponding to the top-most #ifndef
> - if (Self->Sources.getDecomposedLoc(Guard->IfndefLoc) !=
> - Self->Sources.getDecomposedLoc(IfLoc))
> - return;
> -
> - // And that the top-most #ifndef was followed by the right #define
> - if (Guard->DefineLoc.isInvalid())
> - return;
> -
> - // Then save the information about this #endif. Once the file is exited we
> - // will check if it was the final preprocessor directive.
> - Guard->CountAtEndif = Guard->Count;
> - Guard->EndifLoc = Loc;
> - }
> -
> - void MacroExpands(const Token &, const MacroDefinition &, SourceRange,
> - const MacroArgs *) override {
> - Guard->Count++;
> - }
> - void MacroUndefined(const Token &, const MacroDefinition &) override {
> - Guard->Count++;
> - }
> - void Defined(const Token &, const MacroDefinition &, SourceRange) override {
> - Guard->Count++;
> - }
> - void If(SourceLocation, SourceRange, ConditionValueKind) override {
> - Guard->Count++;
> - }
> - void Elif(SourceLocation, SourceRange, ConditionValueKind,
> - SourceLocation) override {
> - Guard->Count++;
> - }
> - void Ifdef(SourceLocation, const Token &, const MacroDefinition &) override {
> - Guard->Count++;
> - }
> - void Else(SourceLocation, SourceLocation) override {
> - Guard->Count++;
> - }
> -
> - IncludeDirectives *Self;
> - // keep track of the guard info through the include stack
> - std::stack<GuardDetection> Files;
> - // convenience field pointing to Files.top().second
> - GuardDetection *Guard;
> -};
> -
> -// Flags that describes where to insert newlines.
> -enum NewLineFlags {
> - // Prepend a newline at the beginning of the insertion.
> - NL_Prepend = 0x1,
> -
> - // Prepend another newline at the end of the insertion.
> - NL_PrependAnother = 0x2,
> -
> - // Add two newlines at the end of the insertion.
> - NL_AppendTwice = 0x4,
> -
> - // Convenience value to enable both \c NL_Prepend and \c NL_PrependAnother.
> - NL_PrependTwice = NL_Prepend | NL_PrependAnother
> -};
> -
> -/// \brief Guess the end-of-line sequence used in the given FileID. If the
> -/// sequence can't be guessed return an Unix-style newline.
> -static StringRef guessEOL(SourceManager &SM, FileID ID) {
> - StringRef Content = SM.getBufferData(ID);
> - StringRef Buffer = Content.substr(Content.find_first_of("\r\n"));
> -
> - return llvm::StringSwitch<StringRef>(Buffer)
> - .StartsWith("\r\n", "\r\n")
> - .StartsWith("\n\r", "\n\r")
> - .StartsWith("\r", "\r")
> - .Default("\n");
> -}
> -
> -/// \brief Find the end of the end of the directive, either the beginning of a
> -/// newline or the end of file.
> -//
> -// \return The offset into the file where the directive ends along with a
> -// boolean value indicating whether the directive ends because the end of file
> -// was reached or not.
> -static std::pair<unsigned, bool> findDirectiveEnd(SourceLocation HashLoc,
> - SourceManager &SM,
> - const LangOptions &LangOpts) {
> - FileID FID = SM.getFileID(HashLoc);
> - unsigned Offset = SM.getFileOffset(HashLoc);
> - StringRef Content = SM.getBufferData(FID);
> - Lexer Lex(SM.getLocForStartOfFile(FID), LangOpts, Content.begin(),
> - Content.begin() + Offset, Content.end());
> - Lex.SetCommentRetentionState(true);
> - Token Tok;
> -
> - // This loop look for the newline after our directive but avoids the ones part
> - // of a multi-line comments:
> - //
> - // #include <foo> /* long \n comment */\n
> - // ~~ no ~~ yes
> - for (;;) {
> - // find the beginning of the end-of-line sequence
> - StringRef::size_type EOLOffset = Content.find_first_of("\r\n", Offset);
> - // ends because EOF was reached
> - if (EOLOffset == StringRef::npos)
> - return std::make_pair(Content.size(), true);
> -
> - // find the token that contains our end-of-line
> - unsigned TokEnd = 0;
> - do {
> - Lex.LexFromRawLexer(Tok);
> - TokEnd = SM.getFileOffset(Tok.getLocation()) + Tok.getLength();
> -
> - // happens when the whitespaces are eaten after a multiline comment
> - if (Tok.is(tok::eof))
> - return std::make_pair(EOLOffset, false);
> - } while (TokEnd < EOLOffset);
> -
> - // the end-of-line is not part of a multi-line comment, return its location
> - if (Tok.isNot(tok::comment))
> - return std::make_pair(EOLOffset, false);
> -
> - // for the next search to start after the end of this token
> - Offset = TokEnd;
> - }
> -}
> -
> -IncludeDirectives::IncludeDirectives(clang::CompilerInstance &CI)
> - : CI(CI), Sources(CI.getSourceManager()) {
> - // addPPCallbacks takes ownership of the callback
> - CI.getPreprocessor().addPPCallbacks(
> - llvm::make_unique<IncludeDirectivesPPCallback>(this));
> -}
> -
> -bool IncludeDirectives::lookForInclude(const FileEntry *File,
> - const LocationVec &IncludeLocs,
> - SeenFilesSet &Seen) const {
> - // mark this file as visited
> - Seen.insert(File);
> -
> - // First check if included directly in this file
> - for (LocationVec::const_iterator I = IncludeLocs.begin(),
> - E = IncludeLocs.end();
> - I != E; ++I)
> - if (Sources.getFileEntryForID(Sources.getFileID(*I)) == File)
> - return true;
> -
> - // Otherwise look recursively all the included files
> - FileToEntriesMap::const_iterator EntriesIt = FileToEntries.find(File);
> - if (EntriesIt == FileToEntries.end())
> - return false;
> - for (EntryVec::const_iterator I = EntriesIt->second.begin(),
> - E = EntriesIt->second.end();
> - I != E; ++I) {
> - // skip if this header has already been checked before
> - if (Seen.count(I->getIncludedFile()))
> - continue;
> - if (lookForInclude(I->getIncludedFile(), IncludeLocs, Seen))
> - return true;
> - }
> - return false;
> -}
> -
> -bool IncludeDirectives::hasInclude(const FileEntry *File,
> - StringRef Include) const {
> - llvm::StringMap<LocationVec>::const_iterator It =
> - IncludeAsWrittenToLocationsMap.find(Include);
> -
> - // Include isn't included in any file
> - if (It == IncludeAsWrittenToLocationsMap.end())
> - return false;
> -
> - SeenFilesSet Seen;
> - return lookForInclude(File, It->getValue(), Seen);
> -}
> -
> -Replacement IncludeDirectives::addAngledInclude(const clang::FileEntry *File,
> - llvm::StringRef Include) {
> - FileID FID = Sources.translateFile(File);
> - assert(FID.isValid() && "Invalid file entry given!");
> -
> - if (hasInclude(File, Include))
> - return Replacement();
> -
> - unsigned Offset, NLFlags;
> - std::tie(Offset, NLFlags) = angledIncludeInsertionOffset(FID);
> -
> - StringRef EOL = guessEOL(Sources, FID);
> - llvm::SmallString<32> InsertionText;
> - if (NLFlags & NL_Prepend)
> - InsertionText += EOL;
> - if (NLFlags & NL_PrependAnother)
> - InsertionText += EOL;
> - InsertionText += "#include <";
> - InsertionText += Include;
> - InsertionText += ">";
> - if (NLFlags & NL_AppendTwice) {
> - InsertionText += EOL;
> - InsertionText += EOL;
> - }
> - return Replacement(File->getName(), Offset, 0, InsertionText);
> -}
> -
> -Replacement IncludeDirectives::addAngledInclude(llvm::StringRef File,
> - llvm::StringRef Include) {
> - const FileEntry *Entry = Sources.getFileManager().getFile(File);
> - assert(Entry && "Invalid file given!");
> - return addAngledInclude(Entry, Include);
> -}
> -
> -std::pair<unsigned, unsigned>
> -IncludeDirectives::findFileHeaderEndOffset(FileID FID) const {
> - unsigned NLFlags = NL_Prepend;
> - StringRef Content = Sources.getBufferData(FID);
> - Lexer Lex(Sources.getLocForStartOfFile(FID), CI.getLangOpts(),
> - Content.begin(), Content.begin(), Content.end());
> - Lex.SetCommentRetentionState(true);
> - Lex.SetKeepWhitespaceMode(true);
> -
> - // find the first newline not part of a multi-line comment
> - Token Tok;
> - do {
> - Lex.LexFromRawLexer(Tok);
> - unsigned Offset = Sources.getFileOffset(Tok.getLocation());
> - // allow one newline between the comments
> - if (Tok.is(tok::unknown) && isWhitespace(Content[Offset])) {
> - StringRef Whitespaces(Content.substr(Offset, Tok.getLength()));
> - if (Whitespaces.count('\n') == 1 || Whitespaces.count('\r') == 1)
> - Lex.LexFromRawLexer(Tok);
> - else {
> - // add an empty line to separate the file header and the inclusion
> - NLFlags = NL_PrependTwice;
> - }
> - }
> - } while (Tok.is(tok::comment));
> -
> - // apparently there is no header, insertion point is the beginning of the file
> - if (Tok.isNot(tok::unknown))
> - return std::make_pair(0, NL_AppendTwice);
> - return std::make_pair(Sources.getFileOffset(Tok.getLocation()), NLFlags);
> -}
> -
> -SourceLocation
> -IncludeDirectives::angledIncludeHintLoc(FileID FID) const {
> - FileToEntriesMap::const_iterator EntriesIt =
> - FileToEntries.find(Sources.getFileEntryForID(FID));
> -
> - if (EntriesIt == FileToEntries.end())
> - return SourceLocation();
> -
> - HeaderSearch &HeaderInfo = CI.getPreprocessor().getHeaderSearchInfo();
> - const EntryVec &Entries = EntriesIt->second;
> - EntryVec::const_reverse_iterator QuotedCandidate = Entries.rend();
> - for (EntryVec::const_reverse_iterator I = Entries.rbegin(),
> - E = Entries.rend();
> - I != E; ++I) {
> - // Headers meant for multiple inclusion can potentially appears in the
> - // middle of the code thus making them a poor choice for an insertion point.
> - if (!HeaderInfo.isFileMultipleIncludeGuarded(I->getIncludedFile()))
> - continue;
> -
> - // return preferably the last angled include
> - if (I->isAngled())
> - return I->getHashLocation();
> -
> - // keep track of the last quoted include that is guarded
> - if (QuotedCandidate == Entries.rend())
> - QuotedCandidate = I;
> - }
> -
> - if (QuotedCandidate == Entries.rend())
> - return SourceLocation();
> -
> - // return the last quoted-include if we couldn't find an angled one
> - return QuotedCandidate->getHashLocation();
> -}
> -
> -std::pair<unsigned, unsigned>
> -IncludeDirectives::angledIncludeInsertionOffset(FileID FID) const {
> - SourceLocation Hint = angledIncludeHintLoc(FID);
> - unsigned NL_Flags = NL_Prepend;
> -
> - // If we can't find a similar include and we are in a header check if it's a
> - // guarded header. If so the hint will be the location of the #define from the
> - // guard.
> - if (Hint.isInvalid()) {
> - const FileEntry *File = Sources.getFileEntryForID(FID);
> - HeaderToGuardMap::const_iterator GuardIt = HeaderToGuard.find(File);
> - if (GuardIt != HeaderToGuard.end()) {
> - // get the hash location from the #define
> - Hint = GuardIt->second;
> - // we want a blank line between the #define and the #include
> - NL_Flags = NL_PrependTwice;
> - }
> - }
> -
> - // no hints, insertion is done after the file header
> - if (Hint.isInvalid())
> - return findFileHeaderEndOffset(FID);
> -
> - unsigned Offset = findDirectiveEnd(Hint, Sources, CI.getLangOpts()).first;
> - return std::make_pair(Offset, NL_Flags);
> -}
> Index: clang-modernize/Core/CustomMatchers.h
> ===================================================================
> --- clang-modernize/Core/CustomMatchers.h
> +++ /dev/null
> @@ -1,59 +0,0 @@
> -//===-- Core/CustomMatchers.h - Perf measurement helpers -----------*- 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 custom matchers to be used by different
> -/// transforms that requier the same matchers.
> -///
> -//===----------------------------------------------------------------------===//
> -
> -#ifndef CLANG_MODERNIZE_CUSTOMMATCHERS_H
> -#define CLANG_MODERNIZE_CUSTOMMATCHERS_H
> -
> -#include "clang/ASTMatchers/ASTMatchers.h"
> -
> -namespace clang {
> -namespace ast_matchers {
> -
> -/// \brief Matches declarations whose declaration context is the C++ standard
> -/// library namespace \c std.
> -///
> -/// Note that inline namespaces are silently ignored during the lookup since
> -/// both libstdc++ and libc++ are known to use them for versioning purposes.
> -///
> -/// Given
> -/// \code
> -/// namespace ns {
> -/// struct my_type {};
> -/// using namespace std;
> -/// }
> -///
> -/// using std::vector;
> -/// using ns::my_type;
> -/// using ns::list;
> -/// \endcode
> -/// usingDecl(hasAnyUsingShadowDecl(hasTargetDecl(isFromStdNamespace())))
> -/// matches "using std::vector" and "using ns::list".
> -AST_MATCHER(Decl, isFromStdNamespace) {
> - const DeclContext *D = Node.getDeclContext();
> -
> - while (D->isInlineNamespace())
> - D = D->getParent();
> -
> - if (!D->isNamespace() || !D->getParent()->isTranslationUnit())
> - return false;
> -
> - const IdentifierInfo *Info = cast<NamespaceDecl>(D)->getIdentifier();
> -
> - return Info && Info->isStr("std");
> -}
> -} // namespace ast_matchers
> -} // namespace clang
> -
> -#endif // CLANG_MODERNIZE_CUSTOMMATCHERS_H
> Index: clang-modernize/Core/CMakeLists.txt
> ===================================================================
> --- clang-modernize/Core/CMakeLists.txt
> +++ /dev/null
> @@ -1,19 +0,0 @@
> -set(LLVM_LINK_COMPONENTS support)
> -
> -add_clang_library(modernizeCore
> - ReplacementHandling.cpp
> - Transforms.cpp
> - Transform.cpp
> - IncludeExcludeInfo.cpp
> - PerfSupport.cpp
> - IncludeDirectives.cpp
> -
> - LINK_LIBS
> - clangAST
> - clangASTMatchers
> - clangBasic
> - clangFrontend
> - clangLex
> - clangTooling
> - clangToolingCore
> - )
> Index: clang-modernize/CMakeLists.txt
> ===================================================================
> --- clang-modernize/CMakeLists.txt
> +++ /dev/null
> @@ -1,7 +0,0 @@
> -include_directories(
> - ${CMAKE_CURRENT_SOURCE_DIR}
> - ${ClangReplaceLocation}
> - )
> -
> -add_subdirectory(tool)
> -add_subdirectory(Core)
> Index: clang-modernize/AddOverride/AddOverrideMatchers.h
> ===================================================================
> --- clang-modernize/AddOverride/AddOverrideMatchers.h
> +++ /dev/null
> @@ -1,28 +0,0 @@
> -//===-- AddOverride/AddOverrideMatchers.h - add C++11 override --*- 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 CLANG_MODERNIZE_ADD_OVERRIDE_MATCHERS_H
> -#define CLANG_MODERNIZE_ADD_OVERRIDE_MATCHERS_H
> -
> -#include "clang/ASTMatchers/ASTMatchers.h"
> -
> -/// Name to bind with matched expressions.
> -extern const char *MethodId;
> -
> -/// \brief Create a matcher that finds member function declarations that are
> -/// candidates for adding the override attribute.
> -clang::ast_matchers::DeclarationMatcher makeCandidateForOverrideAttrMatcher();
> -
> -#endif // CLANG_MODERNIZE_ADD_OVERRIDE_MATCHERS_H
> Index: clang-modernize/AddOverride/AddOverrideMatchers.cpp
> ===================================================================
> --- clang-modernize/AddOverride/AddOverrideMatchers.cpp
> +++ /dev/null
> @@ -1,29 +0,0 @@
> -//===-- AddOverride/AddOverrideMatchers.cpp - C++11 override --------------===//
> -//
> -// 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 "AddOverrideMatchers.h"
> -#include "clang/AST/ASTContext.h"
> -
> -using namespace clang::ast_matchers;
> -using namespace clang;
> -
> -const char *MethodId = "method";
> -
> -DeclarationMatcher makeCandidateForOverrideAttrMatcher() {
> - return cxxMethodDecl(hasParent(recordDecl()),
> - isOverride(),
> - unless(cxxDestructorDecl())).bind(MethodId);
> -}
> -
> Index: clang-modernize/AddOverride/AddOverrideActions.h
> ===================================================================
> --- clang-modernize/AddOverride/AddOverrideActions.h
> +++ /dev/null
> @@ -1,46 +0,0 @@
> -//===-- AddOverride/AddOverrideActions.h - add C++11 override ---*- 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 AddOverrideFixer class
> -/// which is used as a ASTMatcher callback.
> -///
> -//===----------------------------------------------------------------------===//
> -
> -#ifndef CLANG_MODERNIZE_ADD_OVERRIDE_ACTIONS_H
> -#define CLANG_MODERNIZE_ADD_OVERRIDE_ACTIONS_H
> -
> -#include "clang/ASTMatchers/ASTMatchFinder.h"
> -#include "clang/Tooling/Refactoring.h"
> -
> -class Transform;
> -
> -/// \brief The callback to be used for add-override migration matchers.
> -///
> -class AddOverrideFixer : public clang::ast_matchers::MatchFinder::MatchCallback {
> -public:
> - AddOverrideFixer(unsigned &AcceptedChanges, bool DetectMacros,
> - Transform &Owner)
> - : AcceptedChanges(AcceptedChanges), DetectMacros(DetectMacros),
> - Owner(Owner) {}
> -
> - /// \brief Entry point to the callback called when matches are made.
> - void
> - run(const clang::ast_matchers::MatchFinder::MatchResult &Result) override;
> -
> - void setPreprocessor(clang::Preprocessor &PP) { this->PP = &PP; }
> -
> -private:
> - clang::Preprocessor *PP;
> - unsigned &AcceptedChanges;
> - bool DetectMacros;
> - Transform &Owner;
> -};
> -
> -#endif // CLANG_MODERNIZE_ADD_OVERRIDE_ACTIONS_H
> Index: clang-modernize/AddOverride/AddOverrideActions.cpp
> ===================================================================
> --- clang-modernize/AddOverride/AddOverrideActions.cpp
> +++ /dev/null
> @@ -1,100 +0,0 @@
> -//===-- AddOverride/AddOverrideActions.cpp - add C++11 override -----------===//
> -//
> -// 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 AddOverrideFixer class
> -/// which is used as an ASTMatcher callback.
> -///
> -//===----------------------------------------------------------------------===//
> -
> -#include "AddOverrideActions.h"
> -#include "AddOverrideMatchers.h"
> -#include "Core/Transform.h"
> -#include "clang/AST/ASTContext.h"
> -#include "clang/AST/Attr.h"
> -#include "clang/AST/RecursiveASTVisitor.h"
> -#include "clang/Basic/CharInfo.h"
> -#include "clang/Lex/Lexer.h"
> -#include "clang/Lex/Preprocessor.h"
> -
> -using namespace clang::ast_matchers;
> -using namespace clang::tooling;
> -using namespace clang;
> -
> -namespace {
> -
> -SourceLocation
> -backwardSkipWhitespacesAndComments(const SourceManager &SM,
> - const clang::ASTContext &Context,
> - SourceLocation Loc) {
> - for (;;) {
> - do {
> - Loc = Loc.getLocWithOffset(-1);
> - } while (isWhitespace(*FullSourceLoc(Loc, SM).getCharacterData()));
> -
> - Token Tok;
> - SourceLocation Beginning =
> - Lexer::GetBeginningOfToken(Loc, SM, Context.getLangOpts());
> - const bool Invalid =
> - Lexer::getRawToken(Beginning, Tok, SM, Context.getLangOpts());
> -
> - assert(!Invalid && "Expected a valid token.");
> - if (Invalid || Tok.getKind() != tok::comment)
> - return Loc.getLocWithOffset(1);
> - }
> -}
> -
> -} // end anonymous namespace
> -
> -void AddOverrideFixer::run(const MatchFinder::MatchResult &Result) {
> - SourceManager &SM = *Result.SourceManager;
> -
> - const CXXMethodDecl *M = Result.Nodes.getDeclAs<CXXMethodDecl>(MethodId);
> - assert(M && "Bad Callback. No node provided");
> -
> - if (const FunctionDecl *TemplateMethod = M->getTemplateInstantiationPattern())
> - M = cast<CXXMethodDecl>(TemplateMethod);
> -
> - if (!Owner.isFileModifiable(SM, M->getLocStart()))
> - return;
> -
> - // First check that there isn't already an override attribute.
> - if (M->hasAttr<OverrideAttr>())
> - return;
> -
> - // FIXME: Pure methods are not supported yet as it is difficult to track down
> - // the location of '= 0'.
> - if (M->isPure())
> - return;
> -
> - if (M->getParent()->hasAnyDependentBases())
> - return;
> -
> - SourceLocation StartLoc;
> - if (M->hasInlineBody()) {
> - // Insert the override specifier before the function body.
> - StartLoc = backwardSkipWhitespacesAndComments(SM, *Result.Context,
> - M->getBody()->getLocStart());
> - } else {
> - StartLoc = SM.getSpellingLoc(M->getLocEnd());
> - StartLoc = Lexer::getLocForEndOfToken(StartLoc, 0, SM, LangOptions());
> - }
> -
> - std::string ReplacementText = " override";
> - if (DetectMacros) {
> - assert(PP && "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();
> - }
> - Owner.addReplacementForCurrentTU(
> - tooling::Replacement(SM, StartLoc, 0, ReplacementText));
> - ++AcceptedChanges;
> -}
> Index: clang-modernize/AddOverride/AddOverride.h
> ===================================================================
> --- clang-modernize/AddOverride/AddOverride.h
> +++ /dev/null
> @@ -1,44 +0,0 @@
> -//===-- AddOverride/AddOverride.h - add C++11 override ----------*- 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 AddOverrideTransform
> -/// class which is the main interface to the transform that tries to add the
> -/// override keyword to declarations of member function that override virtual
> -/// functions in a base class.
> -///
> -//===----------------------------------------------------------------------===//
> -
> -#ifndef CLANG_MODERNIZE_ADD_OVERRIDE_H
> -#define CLANG_MODERNIZE_ADD_OVERRIDE_H
> -
> -#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(const TransformOptions &Options)
> - : Transform("AddOverride", Options) {}
> -
> - /// \see Transform::run().
> - int apply(const clang::tooling::CompilationDatabase &Database,
> - const std::vector<std::string> &SourcePaths) override;
> -
> - bool handleBeginSource(clang::CompilerInstance &CI,
> - llvm::StringRef Filename) override;
> -
> -private:
> - AddOverrideFixer *Fixer;
> -};
> -
> -#endif // CLANG_MODERNIZE_ADD_OVERRIDE_H
> Index: clang-modernize/AddOverride/AddOverride.cpp
> ===================================================================
> --- clang-modernize/AddOverride/AddOverride.cpp
> +++ /dev/null
> @@ -1,85 +0,0 @@
> -//===-- AddOverride/AddOverride.cpp - add C++11 override ------------------===//
> -//
> -// 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 AddOverrideTransform
> -/// class.
> -///
> -//===----------------------------------------------------------------------===//
> -
> -#include "AddOverride.h"
> -#include "AddOverrideActions.h"
> -#include "AddOverrideMatchers.h"
> -#include "clang/Frontend/CompilerInstance.h"
> -
> -using clang::ast_matchers::MatchFinder;
> -using namespace clang::tooling;
> -using namespace clang;
> -namespace cl = llvm::cl;
> -
> -static cl::opt<bool> DetectMacros(
> - "override-macros",
> - cl::desc("Detect and use macros that expand to the 'override' keyword."),
> - cl::cat(TransformsOptionsCategory));
> -
> -int AddOverrideTransform::apply(const CompilationDatabase &Database,
> - const std::vector<std::string> &SourcePaths) {
> - ClangTool AddOverrideTool(Database, SourcePaths);
> - unsigned AcceptedChanges = 0;
> - MatchFinder Finder;
> - AddOverrideFixer Fixer(AcceptedChanges, DetectMacros,
> - /*Owner=*/ *this);
> - Finder.addMatcher(makeCandidateForOverrideAttrMatcher(), &Fixer);
> -
> - // Make Fixer available to handleBeginSource().
> - this->Fixer = &Fixer;
> -
> - if (int result = AddOverrideTool.run(createActionFactory(Finder).get())) {
> - llvm::errs() << "Error encountered during translation.\n";
> - return result;
> - }
> -
> - setAcceptedChanges(AcceptedChanges);
> - return 0;
> -}
> -
> -bool AddOverrideTransform::handleBeginSource(clang::CompilerInstance &CI,
> - llvm::StringRef Filename) {
> - assert(Fixer != nullptr && "Fixer must be set");
> - Fixer->setPreprocessor(CI.getPreprocessor());
> - return Transform::handleBeginSource(CI, Filename);
> -}
> -
> -namespace {
> -struct AddOverrideFactory : TransformFactory {
> - AddOverrideFactory() {
> - // if detecting macros is enabled, do not impose requirements on the
> - // compiler. It is assumed that the macros use is "C++11-aware", meaning it
> - // won't expand to override if the compiler doesn't support the specifier.
> - if (!DetectMacros) {
> - Since.Clang = Version(3, 0);
> - Since.Gcc = Version(4, 7);
> - Since.Icc = Version(14);
> - Since.Msvc = Version(8);
> - }
> - }
> -
> - Transform *createTransform(const TransformOptions &Opts) override {
> - return new AddOverrideTransform(Opts);
> - }
> -};
> -} // namespace
> -
> -// Register the factory using this statically initialized variable.
> -static TransformFactoryRegistry::Add<AddOverrideFactory>
> -X("add-override", "Make use of override specifier where possible");
> -
> -// This anchor is used to force the linker to link in the generated object file
> -// and thus register the factory.
> -volatile int AddOverrideTransformAnchorSource = 0;
> Index: Makefile
> ===================================================================
> --- Makefile
> +++ Makefile
> @@ -12,8 +12,7 @@
> include $(CLANG_LEVEL)/../../Makefile.config
>
> PARALLEL_DIRS := tool-template modularize pp-trace
> -DIRS := clang-apply-replacements clang-modernize clang-rename clang-tidy \
> - clang-query unittests
> +DIRS := clang-apply-replacements clang-rename clang-tidy clang-query unittests
>
> include $(CLANG_LEVEL)/Makefile
>
> Index: CMakeLists.txt
> ===================================================================
> --- CMakeLists.txt
> +++ CMakeLists.txt
> @@ -1,5 +1,4 @@
> add_subdirectory(clang-apply-replacements)
> -add_subdirectory(clang-modernize)
> add_subdirectory(clang-rename)
> add_subdirectory(modularize)
> if(CLANG_ENABLE_STATIC_ANALYZER)
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
More information about the cfe-commits
mailing list