[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