[clang-tools-extra] r182013 - cpp11-migrate: Refactor NullptrActions
Edwin Vane
edwin.vane at intel.com
Thu May 16 07:54:24 PDT 2013
Author: revane
Date: Thu May 16 09:54:24 2013
New Revision: 182013
URL: http://llvm.org/viewvc/llvm-project?rev=182013&view=rev
Log:
cpp11-migrate: Refactor NullptrActions
Several free functions related to macro arg testing are being moved into
CastSequenceVisitor to facilitate upcoming fix.
Modified:
clang-tools-extra/trunk/cpp11-migrate/UseNullptr/NullptrActions.cpp
Modified: clang-tools-extra/trunk/cpp11-migrate/UseNullptr/NullptrActions.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/cpp11-migrate/UseNullptr/NullptrActions.cpp?rev=182013&r1=182012&r2=182013&view=diff
==============================================================================
--- clang-tools-extra/trunk/cpp11-migrate/UseNullptr/NullptrActions.cpp (original)
+++ clang-tools-extra/trunk/cpp11-migrate/UseNullptr/NullptrActions.cpp Thu May 16 09:54:24 2013
@@ -77,149 +77,6 @@ llvm::StringRef GetOutermostMacroName(
return clang::Lexer::getImmediateMacroName(OutermostMacroLoc, SM, LO);
}
-/// \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, const SourceManager &SM,
- 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();
-
- ArgLoc = Expansion.getExpansionLocStart();
- if (!Expansion.isMacroArgExpansion()) {
- // TODO: Insert test for user-defined null macro here.
- return MacroLoc.isFileID();
- }
-
- 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,
- const SourceManager &SM) {
- 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,
- ASTContext &Context) {
- // 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 {
- ASTContext::ParentVector Parents = Context.getParents(Start);
- if (Parents.empty())
- return false;
- assert(Parents.size() == 1 &&
- "Found an ancestor with more than one parent!");
-
- ASTContext::ParentVector::const_iterator I = Parents.begin();
-
- SourceLocation Loc;
- if (const Decl *D = I->get<Decl>())
- Loc = D->getLocStart();
- else if (const Stmt *S = I->get<Stmt>())
- Loc = S->getLocStart();
- else
- llvm_unreachable("Expected to find Decl or Stmt containing ancestor");
-
- if (!expandsFrom(Loc, MacroLoc, Context.getSourceManager())) {
- Result = *I;
- return true;
- }
- Start = *I;
- } while(1);
-
- llvm_unreachable("findContainingAncestor");
-}
-
/// \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.
@@ -280,43 +137,6 @@ private:
bool InvalidFound;
};
-/// \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, ASTContext &Context) {
- SourceLocation CastLoc = CE->getLocStart();
- const SourceManager &SM = Context.getSourceManager();
-
- // Step 1: Get location of macro arg and location of the macro the arg was
- // provided to.
- SourceLocation ArgLoc, MacroLoc;
- if (!getMacroAndArgLocations(CastLoc, SM, 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, Context))
- 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 Looks for implicit casts as well as sequences of 0 or more explicit
/// casts with an implicit null-to-pointer cast within.
///
@@ -372,7 +192,7 @@ public:
SourceLocation FileLocStart = SM.getFileLoc(StartLoc),
FileLocEnd = SM.getFileLoc(EndLoc);
if (isReplaceableRange(FileLocStart, FileLocEnd, SM) &&
- allArgUsesValid(C, Context)) {
+ allArgUsesValid(C)) {
ReplaceWithNullptr(Replace, SM, FileLocStart, FileLocEnd);
++AcceptedChanges;
}
@@ -409,6 +229,184 @@ public:
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();
+
+ ArgLoc = Expansion.getExpansionLocStart();
+ if (!Expansion.isMacroArgExpansion()) {
+ // TODO: Insert test for user-defined null macro here.
+ return MacroLoc.isFileID();
+ }
+
+ 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 {
+ ASTContext::ParentVector Parents = Context.getParents(Start);
+ if (Parents.empty())
+ return false;
+ assert(Parents.size() == 1 &&
+ "Found an ancestor with more than one parent!");
+
+ ASTContext::ParentVector::const_iterator I = Parents.begin();
+
+ SourceLocation Loc;
+ if (const Decl *D = I->get<Decl>())
+ Loc = D->getLocStart();
+ else if (const Stmt *S = I->get<Stmt>())
+ Loc = S->getLocStart();
+ else
+ llvm_unreachable("Expected to find Decl or Stmt containing ancestor");
+
+ if (!expandsFrom(Loc, MacroLoc)) {
+ Result = *I;
+ return true;
+ }
+ Start = *I;
+ } while (1);
+
+ llvm_unreachable("findContainingAncestor");
+ }
+
private:
tooling::Replacements &Replace;
SourceManager &SM;
More information about the cfe-commits
mailing list