diff options
author | Edwin Vane <edwin.vane@intel.com> | 2013-06-18 15:44:58 +0000 |
---|---|---|
committer | Edwin Vane <edwin.vane@intel.com> | 2013-06-18 15:44:58 +0000 |
commit | ba6b32d1ce34dacaca5df11dfb5e460b1445914a (patch) | |
tree | 25b663f04bcef53af13f02efa948e48f296ae65a /clang-tools-extra | |
parent | 75d8fa51c9894df24e224b61c8b1f2cfbf6fc89d (diff) | |
download | bcm5719-llvm-ba6b32d1ce34dacaca5df11dfb5e460b1445914a.tar.gz bcm5719-llvm-ba6b32d1ce34dacaca5df11dfb5e460b1445914a.zip |
cpp11-migrate: Transforms honour header modification flag
Transforms will now make changes to headers if header modifications have been
enabled.
FIXME: Only UseNullptr contains a cursory header modification test. Other
transforms should have them too.
llvm-svn: 184197
Diffstat (limited to 'clang-tools-extra')
18 files changed, 206 insertions, 58 deletions
diff --git a/clang-tools-extra/cpp11-migrate/AddOverride/AddOverride.cpp b/clang-tools-extra/cpp11-migrate/AddOverride/AddOverride.cpp index f9a3a512675..1b77e128406 100644 --- a/clang-tools-extra/cpp11-migrate/AddOverride/AddOverride.cpp +++ b/clang-tools-extra/cpp11-migrate/AddOverride/AddOverride.cpp @@ -40,7 +40,9 @@ int AddOverrideTransform::apply(FileOverrides &InputStates, unsigned AcceptedChanges = 0; MatchFinder Finder; - AddOverrideFixer Fixer(getReplacements(), AcceptedChanges, DetectMacros); + + AddOverrideFixer Fixer(getReplacements(), AcceptedChanges, DetectMacros, + /*Owner=*/ *this); Finder.addMatcher(makeCandidateForOverrideAttrMatcher(), &Fixer); // Make Fixer available to handleBeginSource(). diff --git a/clang-tools-extra/cpp11-migrate/AddOverride/AddOverrideActions.cpp b/clang-tools-extra/cpp11-migrate/AddOverride/AddOverrideActions.cpp index 008e947410e..6407b86b9db 100644 --- a/clang-tools-extra/cpp11-migrate/AddOverride/AddOverrideActions.cpp +++ b/clang-tools-extra/cpp11-migrate/AddOverride/AddOverrideActions.cpp @@ -15,6 +15,7 @@ #include "AddOverrideActions.h" #include "AddOverrideMatchers.h" +#include "Core/Transform.h" #include "clang/Basic/CharInfo.h" #include "clang/AST/ASTContext.h" @@ -61,8 +62,7 @@ void AddOverrideFixer::run(const MatchFinder::MatchResult &Result) { if (const FunctionDecl *TemplateMethod = M->getTemplateInstantiationPattern()) M = cast<CXXMethodDecl>(TemplateMethod); - // Check that the method declaration is in the main file - if (!SM.isFromMainFile(M->getLocStart())) + if (!Owner.isFileModifiable(SM, M->getLocStart())) return; // First check that there isn't already an override attribute. diff --git a/clang-tools-extra/cpp11-migrate/AddOverride/AddOverrideActions.h b/clang-tools-extra/cpp11-migrate/AddOverride/AddOverrideActions.h index 831344344a1..1d125ebb7e1 100644 --- a/clang-tools-extra/cpp11-migrate/AddOverride/AddOverrideActions.h +++ b/clang-tools-extra/cpp11-migrate/AddOverride/AddOverrideActions.h @@ -15,18 +15,20 @@ #ifndef LLVM_TOOLS_CLANG_TOOLS_EXTRA_CPP11_MIGRATE_ADD_OVERRIDE_ACTIONS_H #define LLVM_TOOLS_CLANG_TOOLS_EXTRA_CPP11_MIGRATE_ADD_OVERRIDE_ACTIONS_H -#include "Core/Transform.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(clang::tooling::Replacements &Replace, - unsigned &AcceptedChanges, bool DetectMacros) + unsigned &AcceptedChanges, bool DetectMacros, + const Transform &Owner) : Replace(Replace), AcceptedChanges(AcceptedChanges), - DetectMacros(DetectMacros) {} + DetectMacros(DetectMacros), Owner(Owner) {} /// \brief Entry point to the callback called when matches are made. virtual void run(const clang::ast_matchers::MatchFinder::MatchResult &Result); @@ -38,6 +40,7 @@ private: clang::tooling::Replacements &Replace; unsigned &AcceptedChanges; bool DetectMacros; + const Transform &Owner; }; #endif // LLVM_TOOLS_CLANG_TOOLS_EXTRA_CPP11_MIGRATE_ADD_OVERRIDE_ACTIONS_H diff --git a/clang-tools-extra/cpp11-migrate/Core/Transform.cpp b/clang-tools-extra/cpp11-migrate/Core/Transform.cpp index 5fd73ad0380..7be91993bb8 100644 --- a/clang-tools-extra/cpp11-migrate/Core/Transform.cpp +++ b/clang-tools-extra/cpp11-migrate/Core/Transform.cpp @@ -156,6 +156,21 @@ Transform::Transform(llvm::StringRef Name, const TransformOptions &Options) Transform::~Transform() {} +bool Transform::isFileModifiable(const SourceManager &SM, + const SourceLocation &Loc) const { + if (SM.isFromMainFile(Loc)) + return true; + + if (!GlobalOptions.EnableHeaderModifications) + return false; + + const FileEntry *FE = SM.getFileEntryForID(SM.getFileID(Loc)); + if (!FE) + return false; + + return GlobalOptions.ModifiableHeaders.isFileIncluded(FE->getName()); +} + bool Transform::handleBeginSource(CompilerInstance &CI, StringRef Filename) { assert(Overrides != 0 && "Subclass transform didn't provide InputState"); diff --git a/clang-tools-extra/cpp11-migrate/Core/Transform.h b/clang-tools-extra/cpp11-migrate/Core/Transform.h index 651ee32e65f..1894d4464ce 100644 --- a/clang-tools-extra/cpp11-migrate/Core/Transform.h +++ b/clang-tools-extra/cpp11-migrate/Core/Transform.h @@ -131,6 +131,11 @@ public: DeferredChanges = 0; } + /// \brief Tests if the file containing \a Loc is allowed to be modified by + /// the Migrator. + bool isFileModifiable(const clang::SourceManager &SM, + const clang::SourceLocation &Loc) const; + /// \brief Called before parsing a translation unit for a FrontendAction. /// /// Transform uses this function to apply file overrides and start diff --git a/clang-tools-extra/cpp11-migrate/LoopConvert/LoopActions.cpp b/clang-tools-extra/cpp11-migrate/LoopConvert/LoopActions.cpp index 88c219aefec..f25e7d89476 100644 --- a/clang-tools-extra/cpp11-migrate/LoopConvert/LoopActions.cpp +++ b/clang-tools-extra/cpp11-migrate/LoopConvert/LoopActions.cpp @@ -1030,7 +1030,7 @@ void LoopFixer::run(const MatchFinder::MatchResult &Result) { ASTContext *Context = Result.Context; const ForStmt *TheLoop = Nodes.getStmtAs<ForStmt>(LoopName); - if (!Context->getSourceManager().isFromMainFile(TheLoop->getForLoc())) + if (!Owner.isFileModifiable(Context->getSourceManager(),TheLoop->getForLoc())) return; // Check that we have exactly one index variable and at most one end variable. diff --git a/clang-tools-extra/cpp11-migrate/LoopConvert/LoopActions.h b/clang-tools-extra/cpp11-migrate/LoopConvert/LoopActions.h index eebee338208..542f1a8c4f0 100644 --- a/clang-tools-extra/cpp11-migrate/LoopConvert/LoopActions.h +++ b/clang-tools-extra/cpp11-migrate/LoopConvert/LoopActions.h @@ -39,20 +39,20 @@ enum LoopFixerKind { /// convert the for loop, if possible. class LoopFixer : public clang::ast_matchers::MatchFinder::MatchCallback { public: - LoopFixer(StmtAncestorASTVisitor *ParentFinder, - clang::tooling::Replacements *Replace, - StmtGeneratedVarNameMap *GeneratedDecls, - ReplacedVarsMap *ReplacedVarRanges, - unsigned *AcceptedChanges, unsigned *DeferredChanges, - unsigned *RejectedChanges, - RiskLevel MaxRisk, - LoopFixerKind FixerKind) : - ParentFinder(ParentFinder), Replace(Replace), - GeneratedDecls(GeneratedDecls), ReplacedVarRanges(ReplacedVarRanges), - AcceptedChanges(AcceptedChanges), DeferredChanges(DeferredChanges), - RejectedChanges(RejectedChanges), - MaxRisk(MaxRisk), FixerKind(FixerKind) { } - virtual void run(const clang::ast_matchers::MatchFinder::MatchResult &Result); + LoopFixer(StmtAncestorASTVisitor *ParentFinder, + clang::tooling::Replacements *Replace, + StmtGeneratedVarNameMap *GeneratedDecls, + ReplacedVarsMap *ReplacedVarRanges, unsigned *AcceptedChanges, + unsigned *DeferredChanges, unsigned *RejectedChanges, + RiskLevel MaxRisk, LoopFixerKind FixerKind, const Transform &Owner) + : ParentFinder(ParentFinder), Replace(Replace), + GeneratedDecls(GeneratedDecls), ReplacedVarRanges(ReplacedVarRanges), + AcceptedChanges(AcceptedChanges), DeferredChanges(DeferredChanges), + RejectedChanges(RejectedChanges), MaxRisk(MaxRisk), + FixerKind(FixerKind), Owner(Owner) {} + + virtual void + run(const clang::ast_matchers::MatchFinder::MatchResult &Result); private: StmtAncestorASTVisitor *ParentFinder; @@ -64,6 +64,7 @@ class LoopFixer : public clang::ast_matchers::MatchFinder::MatchCallback { unsigned *RejectedChanges; RiskLevel MaxRisk; LoopFixerKind FixerKind; + const Transform &Owner; /// \brief Computes the changes needed to convert a given for loop, and /// applies it. diff --git a/clang-tools-extra/cpp11-migrate/LoopConvert/LoopConvert.cpp b/clang-tools-extra/cpp11-migrate/LoopConvert/LoopConvert.cpp index 1ab526a90f7..858ee0623d2 100644 --- a/clang-tools-extra/cpp11-migrate/LoopConvert/LoopConvert.cpp +++ b/clang-tools-extra/cpp11-migrate/LoopConvert/LoopConvert.cpp @@ -40,17 +40,18 @@ int LoopConvertTransform::apply(FileOverrides &InputStates, MatchFinder Finder; LoopFixer ArrayLoopFixer(&ParentFinder, &getReplacements(), &GeneratedDecls, &ReplacedVars, &AcceptedChanges, &DeferredChanges, - &RejectedChanges, Options().MaxRiskLevel, LFK_Array); + &RejectedChanges, Options().MaxRiskLevel, LFK_Array, + /*Owner=*/ *this); Finder.addMatcher(makeArrayLoopMatcher(), &ArrayLoopFixer); - LoopFixer IteratorLoopFixer(&ParentFinder, &getReplacements(), - &GeneratedDecls, &ReplacedVars, &AcceptedChanges, - &DeferredChanges, &RejectedChanges, - Options().MaxRiskLevel, LFK_Iterator); + LoopFixer IteratorLoopFixer( + &ParentFinder, &getReplacements(), &GeneratedDecls, &ReplacedVars, + &AcceptedChanges, &DeferredChanges, &RejectedChanges, + Options().MaxRiskLevel, LFK_Iterator, /*Owner=*/ *this); Finder.addMatcher(makeIteratorLoopMatcher(), &IteratorLoopFixer); LoopFixer PseudoarrrayLoopFixer( &ParentFinder, &getReplacements(), &GeneratedDecls, &ReplacedVars, &AcceptedChanges, &DeferredChanges, &RejectedChanges, - Options().MaxRiskLevel, LFK_PseudoArray); + Options().MaxRiskLevel, LFK_PseudoArray, /*Owner=*/ *this); Finder.addMatcher(makePseudoArrayLoopMatcher(), &PseudoarrrayLoopFixer); setOverrides(InputStates); diff --git a/clang-tools-extra/cpp11-migrate/UseAuto/UseAuto.cpp b/clang-tools-extra/cpp11-migrate/UseAuto/UseAuto.cpp index 0a8d0d2e3a8..b85f54712a7 100644 --- a/clang-tools-extra/cpp11-migrate/UseAuto/UseAuto.cpp +++ b/clang-tools-extra/cpp11-migrate/UseAuto/UseAuto.cpp @@ -29,9 +29,9 @@ int UseAutoTransform::apply(FileOverrides &InputStates, MatchFinder Finder; IteratorReplacer ReplaceIterators(getReplacements(), AcceptedChanges, - Options().MaxRiskLevel); + Options().MaxRiskLevel, /*Owner=*/ *this); NewReplacer ReplaceNew(getReplacements(), AcceptedChanges, - Options().MaxRiskLevel); + Options().MaxRiskLevel, /*Owner=*/ *this); Finder.addMatcher(makeIteratorDeclMatcher(), &ReplaceIterators); Finder.addMatcher(makeDeclWithNewMatcher(), &ReplaceNew); diff --git a/clang-tools-extra/cpp11-migrate/UseAuto/UseAutoActions.cpp b/clang-tools-extra/cpp11-migrate/UseAuto/UseAutoActions.cpp index 47050a7b84d..e20affa5e2b 100644 --- a/clang-tools-extra/cpp11-migrate/UseAuto/UseAutoActions.cpp +++ b/clang-tools-extra/cpp11-migrate/UseAuto/UseAutoActions.cpp @@ -25,7 +25,7 @@ void IteratorReplacer::run(const MatchFinder::MatchResult &Result) { assert(D && "Bad Callback. No node provided"); SourceManager &SM = *Result.SourceManager; - if (!SM.isFromMainFile(D->getLocStart())) + if (!Owner.isFileModifiable(SM, D->getLocStart())) return; for (clang::DeclStmt::const_decl_iterator DI = D->decl_begin(), @@ -81,7 +81,7 @@ void NewReplacer::run(const MatchFinder::MatchResult &Result) { assert(D && "Bad Callback. No node provided"); SourceManager &SM = *Result.SourceManager; - if (!SM.isFromMainFile(D->getLocStart())) + if (!Owner.isFileModifiable(SM, D->getLocStart())) return; const VarDecl *FirstDecl = cast<VarDecl>(*D->decl_begin()); diff --git a/clang-tools-extra/cpp11-migrate/UseAuto/UseAutoActions.h b/clang-tools-extra/cpp11-migrate/UseAuto/UseAutoActions.h index 31c41fb53ec..01170a68d23 100644 --- a/clang-tools-extra/cpp11-migrate/UseAuto/UseAutoActions.h +++ b/clang-tools-extra/cpp11-migrate/UseAuto/UseAutoActions.h @@ -25,9 +25,8 @@ class IteratorReplacer : public clang::ast_matchers::MatchFinder::MatchCallback { public: IteratorReplacer(clang::tooling::Replacements &Replace, - unsigned &AcceptedChanges, RiskLevel) - : Replace(Replace), AcceptedChanges(AcceptedChanges) { - } + unsigned &AcceptedChanges, RiskLevel, const Transform &Owner) + : Replace(Replace), AcceptedChanges(AcceptedChanges), Owner(Owner) {} /// \brief Entry point to the callback called when matches are made. virtual void run(const clang::ast_matchers::MatchFinder::MatchResult &Result) @@ -36,6 +35,7 @@ public: private: clang::tooling::Replacements &Replace; unsigned &AcceptedChanges; + const Transform &Owner; }; /// \brief The callback used when replacing type specifiers of variable @@ -43,9 +43,8 @@ private: class NewReplacer : public clang::ast_matchers::MatchFinder::MatchCallback { public: NewReplacer(clang::tooling::Replacements &Replace, unsigned &AcceptedChanges, - RiskLevel) - : Replace(Replace), AcceptedChanges(AcceptedChanges) { - } + RiskLevel, const Transform &Owner) + : Replace(Replace), AcceptedChanges(AcceptedChanges), Owner(Owner) {} /// \brief Entry point to the callback called when matches are made. virtual void run(const clang::ast_matchers::MatchFinder::MatchResult &Result) @@ -54,6 +53,7 @@ public: private: clang::tooling::Replacements &Replace; unsigned &AcceptedChanges; + const Transform &Owner; }; #endif // LLVM_TOOLS_CLANG_TOOLS_EXTRA_CPP11_MIGRATE_USE_AUTO_ACTIONS_H diff --git a/clang-tools-extra/cpp11-migrate/UseNullptr/NullptrActions.cpp b/clang-tools-extra/cpp11-migrate/UseNullptr/NullptrActions.cpp index 38e44d21e23..6f476113367 100644 --- a/clang-tools-extra/cpp11-migrate/UseNullptr/NullptrActions.cpp +++ b/clang-tools-extra/cpp11-migrate/UseNullptr/NullptrActions.cpp @@ -37,8 +37,9 @@ static llvm::cl::opt<std::string> UserNullMacroNames( llvm::cl::init("")); bool isReplaceableRange(SourceLocation StartLoc, SourceLocation EndLoc, - const SourceManager &SM) { - return SM.isFromSameFile(StartLoc, EndLoc) && SM.isFromMainFile(StartLoc); + const SourceManager &SM, const Transform &Owner) { + return SM.isFromSameFile(StartLoc, EndLoc) && + Owner.isFileModifiable(SM, StartLoc); } /// \brief Replaces the provided range with the text "nullptr", but only if @@ -152,10 +153,10 @@ class CastSequenceVisitor : public RecursiveASTVisitor<CastSequenceVisitor> { public: CastSequenceVisitor(tooling::Replacements &R, ASTContext &Context, const UserMacroNames &UserNullMacros, - unsigned &AcceptedChanges) + unsigned &AcceptedChanges, const Transform &Owner) : Replace(R), SM(Context.getSourceManager()), Context(Context), UserNullMacros(UserNullMacros), AcceptedChanges(AcceptedChanges), - FirstSubExpr(0), PruneSubtree(false) {} + Owner(Owner), FirstSubExpr(0), PruneSubtree(false) {} bool TraverseStmt(Stmt *S) { // Stop traversing down the tree if requested. @@ -191,7 +192,7 @@ public: if (SM.isMacroArgExpansion(StartLoc) && SM.isMacroArgExpansion(EndLoc)) { SourceLocation FileLocStart = SM.getFileLoc(StartLoc), FileLocEnd = SM.getFileLoc(EndLoc); - if (isReplaceableRange(FileLocStart, FileLocEnd, SM) && + if (isReplaceableRange(FileLocStart, FileLocEnd, SM, Owner) && allArgUsesValid(C)) { ReplaceWithNullptr(Replace, SM, FileLocStart, FileLocEnd); ++AcceptedChanges; @@ -214,7 +215,7 @@ public: EndLoc = SM.getFileLoc(EndLoc); } - if (!isReplaceableRange(StartLoc, EndLoc, SM)) { + if (!isReplaceableRange(StartLoc, EndLoc, SM, Owner)) { return skipSubTree(); } ReplaceWithNullptr(Replace, SM, StartLoc, EndLoc); @@ -419,14 +420,16 @@ private: ASTContext &Context; const UserMacroNames &UserNullMacros; unsigned &AcceptedChanges; + const Transform &Owner; Expr *FirstSubExpr; bool PruneSubtree; }; } // namespace NullptrFixer::NullptrFixer(clang::tooling::Replacements &Replace, - unsigned &AcceptedChanges, RiskLevel) - : Replace(Replace), AcceptedChanges(AcceptedChanges) { + unsigned &AcceptedChanges, RiskLevel, + const Transform &Owner) + : Replace(Replace), AcceptedChanges(AcceptedChanges), Owner(Owner) { if (!UserNullMacroNames.empty()) { llvm::StringRef S = UserNullMacroNames; S.split(UserNullMacros, ","); @@ -441,6 +444,6 @@ void NullptrFixer::run(const ast_matchers::MatchFinder::MatchResult &Result) { // null-to-pointer cast within use CastSequenceVisitor to identify sequences // of explicit casts that can be converted into 'nullptr'. CastSequenceVisitor Visitor(Replace, *Result.Context, UserNullMacros, - AcceptedChanges); + AcceptedChanges, Owner); Visitor.TraverseStmt(const_cast<CastExpr *>(NullCast)); } diff --git a/clang-tools-extra/cpp11-migrate/UseNullptr/NullptrActions.h b/clang-tools-extra/cpp11-migrate/UseNullptr/NullptrActions.h index c0779f9fa7b..6e70ddadfb5 100644 --- a/clang-tools-extra/cpp11-migrate/UseNullptr/NullptrActions.h +++ b/clang-tools-extra/cpp11-migrate/UseNullptr/NullptrActions.h @@ -26,9 +26,8 @@ typedef llvm::SmallVector<llvm::StringRef, 1> UserMacroNames; /// class NullptrFixer : public clang::ast_matchers::MatchFinder::MatchCallback { public: - NullptrFixer(clang::tooling::Replacements &Replace, - unsigned &AcceptedChanges, - RiskLevel); + NullptrFixer(clang::tooling::Replacements &Replace, unsigned &AcceptedChanges, + RiskLevel, const Transform &Owner); /// \brief Entry point to the callback called when matches are made. virtual void run(const clang::ast_matchers::MatchFinder::MatchResult &Result); @@ -37,6 +36,7 @@ private: clang::tooling::Replacements &Replace; unsigned &AcceptedChanges; UserMacroNames UserNullMacros; + const Transform &Owner; }; #endif // LLVM_TOOLS_CLANG_TOOLS_EXTRA_CPP11_MIGRATE_NULLPTR_ACTIONS_H diff --git a/clang-tools-extra/cpp11-migrate/UseNullptr/UseNullptr.cpp b/clang-tools-extra/cpp11-migrate/UseNullptr/UseNullptr.cpp index 75d3b00b639..759d3366188 100644 --- a/clang-tools-extra/cpp11-migrate/UseNullptr/UseNullptr.cpp +++ b/clang-tools-extra/cpp11-migrate/UseNullptr/UseNullptr.cpp @@ -33,8 +33,9 @@ int UseNullptrTransform::apply(FileOverrides &InputStates, unsigned AcceptedChanges = 0; MatchFinder Finder; - NullptrFixer Fixer(getReplacements(), AcceptedChanges, - Options().MaxRiskLevel); + NullptrFixer Fixer(getReplacements(), AcceptedChanges, Options().MaxRiskLevel, + /*Owner=*/ *this); + Finder.addMatcher(makeCastSequenceMatcher(), &Fixer); setOverrides(InputStates); diff --git a/clang-tools-extra/cpp11-migrate/tool/Cpp11Migrate.cpp b/clang-tools-extra/cpp11-migrate/tool/Cpp11Migrate.cpp index 773ba009a5d..f5b3818f7f0 100644 --- a/clang-tools-extra/cpp11-migrate/tool/Cpp11Migrate.cpp +++ b/clang-tools-extra/cpp11-migrate/tool/Cpp11Migrate.cpp @@ -171,8 +171,6 @@ int main(int argc, const char **argv) { E = FileStates.end(); I != E; ++I) { if (I->second.isSourceOverriden()) { - llvm::errs() << "Writing source: " << I->first << "\n"; - std::string ErrorInfo; llvm::raw_fd_ostream FileStream(I->first.c_str(), ErrorInfo, llvm::raw_fd_ostream::F_Binary); @@ -187,7 +185,6 @@ int main(int argc, const char **argv) { for (HeaderOverrides::const_iterator HeaderI = I->second.Headers.begin(), HeaderE = I->second.Headers.end(); HeaderI != HeaderE; ++HeaderI) { - llvm::errs() << "Writing header: " << HeaderI->first << "\n"; assert(!HeaderI->second.FileOverride.empty() && "A header override should not be empty"); std::string ErrorInfo; diff --git a/clang-tools-extra/test/cpp11-migrate/UseNullptr/Inputs/basic.h b/clang-tools-extra/test/cpp11-migrate/UseNullptr/Inputs/basic.h index 68c5a032ccd..144db769c29 100644 --- a/clang-tools-extra/test/cpp11-migrate/UseNullptr/Inputs/basic.h +++ b/clang-tools-extra/test/cpp11-migrate/UseNullptr/Inputs/basic.h @@ -1,2 +1,3 @@ int *global_p = 0; // CHECK: int *global_p = 0; +// HEADERS: int *global_p = nullptr; diff --git a/clang-tools-extra/test/cpp11-migrate/UseNullptr/basic.cpp b/clang-tools-extra/test/cpp11-migrate/UseNullptr/basic.cpp index 03606f6acd3..9057c1a17d7 100644 --- a/clang-tools-extra/test/cpp11-migrate/UseNullptr/basic.cpp +++ b/clang-tools-extra/test/cpp11-migrate/UseNullptr/basic.cpp @@ -1,8 +1,13 @@ +// RUN: mkdir -p %T/Inputs // RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp -// RUN: grep -Ev "// *[A-Z-]+:" %S/Inputs/basic.h > %T/basic.h -// RUN: cpp11-migrate -use-nullptr %t.cpp -- -std=c++98 -I %S +// RUN: grep -Ev "// *[A-Z-]+:" %S/Inputs/basic.h > %T/Inputs/basic.h +// RUN: cpp11-migrate -use-nullptr %t.cpp -- -std=c++98 -I %T -Wno-non-literal-null-conversion // RUN: FileCheck -input-file=%t.cpp %s -// RUN: FileCheck -input-file=%T/basic.h %S/Inputs/basic.h +// RUN: FileCheck -input-file=%T/Inputs/basic.h %S/Inputs/basic.h +// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp +// RUN: grep -Ev "// *[A-Z-]+:" %S/Inputs/basic.h > %T/Inputs/basic.h +// RUN: cpp11-migrate -headers -include=%T -use-nullptr %t.cpp -- -std=c++98 -I %T -Wno-non-literal-null-conversion +// RUN: FileCheck -check-prefix=HEADERS -input-file=%T/Inputs/basic.h %S/Inputs/basic.h #include "Inputs/basic.h" diff --git a/clang-tools-extra/unittests/cpp11-migrate/TransformTest.cpp b/clang-tools-extra/unittests/cpp11-migrate/TransformTest.cpp index af8a7a703ac..ab0c7e3783a 100644 --- a/clang-tools-extra/unittests/cpp11-migrate/TransformTest.cpp +++ b/clang-tools-extra/unittests/cpp11-migrate/TransformTest.cpp @@ -2,12 +2,14 @@ #include "Core/Transform.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/DeclGroup.h" -#include "clang/Tooling/Tooling.h" +#include "clang/ASTMatchers/ASTMatchers.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" #include "llvm/Support/Process.h" #include "llvm/Support/Path.h" #include "llvm/Support/PathV1.h" using namespace clang; +using namespace ast_matchers; class DummyTransform : public Transform { public: @@ -171,3 +173,115 @@ TEST(Transform, Timings) { ++I; EXPECT_EQ(T.timing_end(), I); } + +class ModifiableCallback + : public clang::ast_matchers::MatchFinder::MatchCallback { +public: + ModifiableCallback(const Transform &Owner, bool HeadersModifiable) + : Owner(Owner), HeadersModifiable(HeadersModifiable) {} + + virtual void + run(const clang::ast_matchers::MatchFinder::MatchResult &Result) { + const VarDecl *Decl = Result.Nodes.getNodeAs<VarDecl>("decl"); + ASSERT_TRUE(Decl != 0); + + 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. It should be modifiable only if + // header modifications are allowed. + else if (Decl->getName().equals("b")) + EXPECT_EQ(HeadersModifiable, + 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; + bool HeadersModifiable; +}; + +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(). + llvm::sys::Path SourceFile = llvm::sys::Path::GetCurrentDirectory(); + std::string CurrentDir = SourceFile.str(); + SourceFile.appendComponent("a.cc"); + std::string SourceFileName = SourceFile.str(); + + llvm::sys::Path HeaderFile = llvm::sys::Path::GetCurrentDirectory(); + HeaderFile.appendComponent("a.h"); + std::string HeaderFileName = HeaderFile.str(); + + llvm::sys::Path HeaderBFile = llvm::sys::Path::GetCurrentDirectory(); + HeaderBFile.appendComponent("temp"); + std::string ExcludeDir = HeaderBFile.str(); + HeaderBFile.appendComponent("b.h"); + std::string HeaderBFileName = HeaderBFile.str(); + + IncludeExcludeInfo IncInfo; + Options.ModifiableHeaders.readListFromString(CurrentDir, ExcludeDir); + + tooling::FixedCompilationDatabase Compilations(CurrentDir, std::vector<std::string>()); + std::vector<std::string> Sources; + Sources.push_back(SourceFileName); + tooling::ClangTool Tool(Compilations, Sources); + + Tool.mapVirtualFile(SourceFileName, + "#include \"a.h\"\n" + "#include \"temp/b.h\"\n" + "int a;"); + Tool.mapVirtualFile(HeaderFileName, "int b;"); + Tool.mapVirtualFile(HeaderBFileName, "int c;"); + + // Run tests with header modifications turned off. + { + SCOPED_TRACE("Header Modifications are OFF"); + Options.EnableHeaderModifications = false; + DummyTransform T("dummy", Options); + MatchFinder Finder; + Finder.addMatcher(varDecl().bind("decl"), new ModifiableCallback(T, false)); + Tool.run(tooling::newFrontendActionFactory(&Finder)); + } + + // Run again with header modifications turned on. + { + SCOPED_TRACE("Header Modifications are ON"); + Options.EnableHeaderModifications = true; + DummyTransform T("dummy", Options); + MatchFinder Finder; + Finder.addMatcher(varDecl().bind("decl"), new ModifiableCallback(T, true)); + Tool.run(tooling::newFrontendActionFactory(&Finder)); + } +} |