r305845 - [clang] Fix format specifiers fixits for nested macros

Alexander Shaposhnikov via cfe-commits cfe-commits at lists.llvm.org
Tue Jun 20 13:46:58 PDT 2017


Author: alexshap
Date: Tue Jun 20 15:46:58 2017
New Revision: 305845

URL: http://llvm.org/viewvc/llvm-project?rev=305845&view=rev
Log:
[clang] Fix format specifiers fixits for nested macros

ExpansionLoc was previously calculated incorrectly in the case of 
nested macros expansions. In this diff we build the stack of expansions 
where the last one is the actual expansion which should be used 
for grouping together the edits. 
The definition of MacroArgUse is adjusted accordingly.

Test plan: make check-all

Differential revision: https://reviews.llvm.org/D34268

Modified:
    cfe/trunk/include/clang/Edit/EditedSource.h
    cfe/trunk/lib/Edit/EditedSource.cpp
    cfe/trunk/test/FixIt/fixit-format-darwin.m

Modified: cfe/trunk/include/clang/Edit/EditedSource.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Edit/EditedSource.h?rev=305845&r1=305844&r2=305845&view=diff
==============================================================================
--- cfe/trunk/include/clang/Edit/EditedSource.h (original)
+++ cfe/trunk/include/clang/Edit/EditedSource.h Tue Jun 20 15:46:58 2017
@@ -17,6 +17,7 @@
 #include "llvm/ADT/TinyPtrVector.h"
 #include "llvm/Support/Allocator.h"
 #include <map>
+#include <tuple>
 
 namespace clang {
   class LangOptions;
@@ -41,10 +42,20 @@ class EditedSource {
   typedef std::map<FileOffset, FileEdit> FileEditsTy;
   FileEditsTy FileEdits;
 
-  // Location of argument use inside the macro body 
-  typedef std::pair<IdentifierInfo*, SourceLocation> MacroArgUse;
-  llvm::DenseMap<unsigned, SmallVector<MacroArgUse, 2>>
-    ExpansionToArgMap;
+  struct MacroArgUse {
+    IdentifierInfo *Identifier;
+    SourceLocation ImmediateExpansionLoc;
+    // Location of argument use inside the top-level macro
+    SourceLocation UseLoc;
+
+    bool operator==(const MacroArgUse &Other) const {
+      return std::tie(Identifier, ImmediateExpansionLoc, UseLoc) ==
+             std::tie(Other.Identifier, Other.ImmediateExpansionLoc,
+                      Other.UseLoc);
+    }
+  };
+
+  llvm::DenseMap<unsigned, SmallVector<MacroArgUse, 2>> ExpansionToArgMap;
   SmallVector<std::pair<SourceLocation, MacroArgUse>, 2>
     CurrCommitMacroArgExps;
 

Modified: cfe/trunk/lib/Edit/EditedSource.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Edit/EditedSource.cpp?rev=305845&r1=305844&r2=305845&view=diff
==============================================================================
--- cfe/trunk/lib/Edit/EditedSource.cpp (original)
+++ cfe/trunk/lib/Edit/EditedSource.cpp Tue Jun 20 15:46:58 2017
@@ -28,13 +28,18 @@ void EditedSource::deconstructMacroArgLo
                                           MacroArgUse &ArgUse) {
   assert(SourceMgr.isMacroArgExpansion(Loc));
   SourceLocation DefArgLoc = SourceMgr.getImmediateExpansionRange(Loc).first;
-  ExpansionLoc = SourceMgr.getImmediateExpansionRange(DefArgLoc).first;
+  SourceLocation ImmediateExpansionLoc =
+      SourceMgr.getImmediateExpansionRange(DefArgLoc).first;
+  ExpansionLoc = ImmediateExpansionLoc;
+  while (SourceMgr.isMacroBodyExpansion(ExpansionLoc))
+    ExpansionLoc = SourceMgr.getImmediateExpansionRange(ExpansionLoc).first;
   SmallString<20> Buf;
   StringRef ArgName = Lexer::getSpelling(SourceMgr.getSpellingLoc(DefArgLoc),
                                          Buf, SourceMgr, LangOpts);
-  ArgUse = {nullptr, SourceLocation()};
+  ArgUse = MacroArgUse{nullptr, SourceLocation(), SourceLocation()};
   if (!ArgName.empty())
-    ArgUse = {&IdentTable.get(ArgName), SourceMgr.getSpellingLoc(DefArgLoc)};
+    ArgUse = {&IdentTable.get(ArgName), ImmediateExpansionLoc,
+              SourceMgr.getSpellingLoc(DefArgLoc)};
 }
 
 void EditedSource::startingCommit() {}
@@ -69,10 +74,11 @@ bool EditedSource::canInsertInOffset(Sou
     deconstructMacroArgLoc(OrigLoc, ExpLoc, ArgUse);
     auto I = ExpansionToArgMap.find(ExpLoc.getRawEncoding());
     if (I != ExpansionToArgMap.end() &&
-        std::find_if(
-            I->second.begin(), I->second.end(), [&](const MacroArgUse &U) {
-              return ArgUse.first == U.first && ArgUse.second != U.second;
-            }) != I->second.end()) {
+        find_if(I->second, [&](const MacroArgUse &U) {
+          return ArgUse.Identifier == U.Identifier &&
+                 std::tie(ArgUse.ImmediateExpansionLoc, ArgUse.UseLoc) !=
+                     std::tie(U.ImmediateExpansionLoc, U.UseLoc);
+        }) != I->second.end()) {
       // Trying to write in a macro argument input that has already been
       // written by a previous commit for another expansion of the same macro
       // argument name. For example:
@@ -89,7 +95,6 @@ bool EditedSource::canInsertInOffset(Sou
       return false;
     }
   }
-
   return true;
 }
 
@@ -102,13 +107,13 @@ bool EditedSource::commitInsert(SourceLo
     return true;
 
   if (SourceMgr.isMacroArgExpansion(OrigLoc)) {
-    SourceLocation ExpLoc;
     MacroArgUse ArgUse;
+    SourceLocation ExpLoc;
     deconstructMacroArgLoc(OrigLoc, ExpLoc, ArgUse);
-    if (ArgUse.first)
+    if (ArgUse.Identifier)
       CurrCommitMacroArgExps.emplace_back(ExpLoc, ArgUse);
   }
-  
+
   FileEdit &FA = FileEdits[Offs];
   if (FA.Text.empty()) {
     FA.Text = copyString(text);

Modified: cfe/trunk/test/FixIt/fixit-format-darwin.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/FixIt/fixit-format-darwin.m?rev=305845&r1=305844&r2=305845&view=diff
==============================================================================
--- cfe/trunk/test/FixIt/fixit-format-darwin.m (original)
+++ cfe/trunk/test/FixIt/fixit-format-darwin.m Tue Jun 20 15:46:58 2017
@@ -57,3 +57,20 @@ void test() {
   Log3("test 7: %s", getNSInteger(), getNSUInteger());
   // CHECK: Log3("test 7: %ld", (long)getNSInteger(), (unsigned long)getNSUInteger());
 }
+
+#define Outer1(...) \
+do { \
+  printf(__VA_ARGS__); \
+} while (0)
+
+#define Outer2(...) \
+do { \
+  Outer1(__VA_ARGS__); Outer1(__VA_ARGS__); \
+} while (0)
+
+void bug33447() {
+  Outer2("test 8: %s", getNSInteger());  
+  // CHECK: Outer2("test 8: %ld", (long)getNSInteger());
+  Outer2("test 9: %s %s", getNSInteger(), getNSInteger());
+  // CHECK: Outer2("test 9: %ld %ld", (long)getNSInteger(), (long)getNSInteger());
+}




More information about the cfe-commits mailing list