diff options
Diffstat (limited to 'clang-tools-extra/cpp11-migrate/UseNullptr/NullptrActions.cpp')
| -rw-r--r-- | clang-tools-extra/cpp11-migrate/UseNullptr/NullptrActions.cpp | 57 |
1 files changed, 46 insertions, 11 deletions
diff --git a/clang-tools-extra/cpp11-migrate/UseNullptr/NullptrActions.cpp b/clang-tools-extra/cpp11-migrate/UseNullptr/NullptrActions.cpp index f0ad46880aa..79b8b5fc1b4 100644 --- a/clang-tools-extra/cpp11-migrate/UseNullptr/NullptrActions.cpp +++ b/clang-tools-extra/cpp11-migrate/UseNullptr/NullptrActions.cpp @@ -28,6 +28,13 @@ using namespace clang; namespace { +const char *NullMacroName = "NULL"; + +static llvm::cl::opt<std::string> UserNullMacroNames( + "user-null-macros", llvm::cl::desc("Comma-separated list of user-defined " + "macro names that behave like NULL"), + llvm::cl::init("")); + /// \brief Replaces the provided range with the text "nullptr", but only if /// the start and end location are both in main file. /// Returns true if and only if a replacement was made. @@ -41,6 +48,25 @@ bool ReplaceWithNullptr(tooling::Replacements &Replace, SourceManager &SM, return false; } +/// \brief Returns the name of the outermost macro. +/// +/// Given +/// \code +/// #define MY_NULL NULL +/// \endcode +/// If \p Loc points to NULL, this function will return the name MY_NULL. +llvm::StringRef GetOutermostMacroName( + SourceLocation Loc, const SourceManager &SM, const LangOptions &LO) { + assert(Loc.isMacroID()); + SourceLocation OutermostMacroLoc; + + while (Loc.isMacroID()) { + OutermostMacroLoc = Loc; + Loc = SM.getImmediateMacroCallerLoc(Loc); + } + + return clang::Lexer::getImmediateMacroName(OutermostMacroLoc, SM, LO); +} } /// \brief Looks for a sequences of 0 or more explicit casts with an implicit @@ -101,6 +127,16 @@ private: Expr *FirstSubExpr; }; +NullptrFixer::NullptrFixer(clang::tooling::Replacements &Replace, + unsigned &AcceptedChanges, RiskLevel) + : Replace(Replace), AcceptedChanges(AcceptedChanges) { + if (!UserNullMacroNames.empty()) { + llvm::StringRef S = UserNullMacroNames; + S.split(UserNullMacros, ","); + } + UserNullMacros.insert(UserNullMacros.begin(), llvm::StringRef(NullMacroName)); +} + void NullptrFixer::run(const ast_matchers::MatchFinder::MatchResult &Result) { SourceManager &SM = *Result.SourceManager; @@ -127,20 +163,19 @@ void NullptrFixer::run(const ast_matchers::MatchFinder::MatchResult &Result) { EndLoc = SM.getFileLoc(EndLoc); } else if (SM.isMacroBodyExpansion(StartLoc) && SM.isMacroBodyExpansion(EndLoc)) { - llvm::StringRef ImmediateMacroName = clang::Lexer::getImmediateMacroName( - StartLoc, SM, Result.Context->getLangOpts()); - if (ImmediateMacroName != "NULL") - return; + llvm::StringRef OutermostMacroName = + GetOutermostMacroName(StartLoc, SM, Result.Context->getLangOpts()); - SourceLocation MacroCallerStartLoc = - SM.getImmediateMacroCallerLoc(StartLoc); - SourceLocation MacroCallerEndLoc = SM.getImmediateMacroCallerLoc(EndLoc); + // Check to see if the user wants to replace the macro being expanded. + bool ReplaceNullMacro = + std::find(UserNullMacros.begin(), UserNullMacros.end(), + OutermostMacroName) != UserNullMacros.end(); - if (MacroCallerStartLoc.isFileID() && MacroCallerEndLoc.isFileID()) { - StartLoc = SM.getFileLoc(StartLoc); - EndLoc = SM.getFileLoc(EndLoc); - } else + if (!ReplaceNullMacro) return; + + StartLoc = SM.getFileLoc(StartLoc); + EndLoc = SM.getFileLoc(EndLoc); } AcceptedChanges += |

