r247462 - [Edit] Fix issue with tracking what macro argument inputs have been edited.

Argyrios Kyrtzidis via cfe-commits cfe-commits at lists.llvm.org
Fri Sep 11 13:09:11 PDT 2015


Author: akirtzidis
Date: Fri Sep 11 15:09:11 2015
New Revision: 247462

URL: http://llvm.org/viewvc/llvm-project?rev=247462&view=rev
Log:
[Edit] Fix issue with tracking what macro argument inputs have been edited.

This was not working correctly, leading to erroneously rejecting valid edits.

Modified:
    cfe/trunk/include/clang/Edit/EditedSource.h
    cfe/trunk/lib/Edit/EditedSource.cpp
    cfe/trunk/test/ARCMT/objcmt-subscripting-literals.m
    cfe/trunk/test/ARCMT/objcmt-subscripting-literals.m.result

Modified: cfe/trunk/include/clang/Edit/EditedSource.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Edit/EditedSource.h?rev=247462&r1=247461&r2=247462&view=diff
==============================================================================
--- cfe/trunk/include/clang/Edit/EditedSource.h (original)
+++ cfe/trunk/include/clang/Edit/EditedSource.h Fri Sep 11 15:09:11 2015
@@ -10,9 +10,11 @@
 #ifndef LLVM_CLANG_EDIT_EDITEDSOURCE_H
 #define LLVM_CLANG_EDIT_EDITEDSOURCE_H
 
+#include "clang/Basic/IdentifierTable.h"
 #include "clang/Edit/FileOffset.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/TinyPtrVector.h"
 #include "llvm/Support/Allocator.h"
 #include <map>
 
@@ -39,14 +41,18 @@ class EditedSource {
   typedef std::map<FileOffset, FileEdit> FileEditsTy;
   FileEditsTy FileEdits;
 
-  llvm::DenseMap<unsigned, SourceLocation> ExpansionToArgMap;
+  llvm::DenseMap<unsigned, llvm::TinyPtrVector<IdentifierInfo*>>
+    ExpansionToArgMap;
+  SmallVector<std::pair<SourceLocation, IdentifierInfo*>, 2>
+    CurrCommitMacroArgExps;
 
+  IdentifierTable IdentTable;
   llvm::BumpPtrAllocator StrAlloc;
 
 public:
   EditedSource(const SourceManager &SM, const LangOptions &LangOpts,
                const PPConditionalDirectiveRecord *PPRec = nullptr)
-    : SourceMgr(SM), LangOpts(LangOpts), PPRec(PPRec),
+    : SourceMgr(SM), LangOpts(LangOpts), PPRec(PPRec), IdentTable(LangOpts),
       StrAlloc() { }
 
   const SourceManager &getSourceManager() const { return SourceMgr; }
@@ -76,6 +82,12 @@ private:
   StringRef getSourceText(FileOffset BeginOffs, FileOffset EndOffs,
                           bool &Invalid);
   FileEditsTy::iterator getActionForOffset(FileOffset Offs);
+  void deconstructMacroArgLoc(SourceLocation Loc,
+                              SourceLocation &ExpansionLoc,
+                              IdentifierInfo *&II);
+
+  void startingCommit();
+  void finishedCommit();
 };
 
 }

Modified: cfe/trunk/lib/Edit/EditedSource.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Edit/EditedSource.cpp?rev=247462&r1=247461&r2=247462&view=diff
==============================================================================
--- cfe/trunk/lib/Edit/EditedSource.cpp (original)
+++ cfe/trunk/lib/Edit/EditedSource.cpp Fri Sep 11 15:09:11 2015
@@ -23,6 +23,36 @@ void EditsReceiver::remove(CharSourceRan
   replace(range, StringRef());
 }
 
+void EditedSource::deconstructMacroArgLoc(SourceLocation Loc,
+                                          SourceLocation &ExpansionLoc,
+                                          IdentifierInfo *&II) {
+  assert(SourceMgr.isMacroArgExpansion(Loc));
+  SourceLocation DefArgLoc = SourceMgr.getImmediateExpansionRange(Loc).first;
+  ExpansionLoc = SourceMgr.getImmediateExpansionRange(DefArgLoc).first;
+  SmallString<20> Buf;
+  StringRef ArgName = Lexer::getSpelling(SourceMgr.getSpellingLoc(DefArgLoc),
+                                         Buf, SourceMgr, LangOpts);
+  II = nullptr;
+  if (!ArgName.empty()) {
+    II = &IdentTable.get(ArgName);
+  }
+}
+
+void EditedSource::startingCommit() {}
+
+void EditedSource::finishedCommit() {
+  for (auto &ExpArg : CurrCommitMacroArgExps) {
+    SourceLocation ExpLoc;
+    IdentifierInfo *II;
+    std::tie(ExpLoc, II) = ExpArg;
+    auto &ArgNames = ExpansionToArgMap[ExpLoc.getRawEncoding()];
+    if (std::find(ArgNames.begin(), ArgNames.end(), II) == ArgNames.end()) {
+      ArgNames.push_back(II);
+    }
+  }
+  CurrCommitMacroArgExps.clear();
+}
+
 StringRef EditedSource::copyString(const Twine &twine) {
   SmallString<128> Data;
   return copyString(twine.toStringRef(Data));
@@ -36,15 +66,27 @@ bool EditedSource::canInsertInOffset(Sou
   }
 
   if (SourceMgr.isMacroArgExpansion(OrigLoc)) {
-    SourceLocation
-      DefArgLoc = SourceMgr.getImmediateExpansionRange(OrigLoc).first;
-    SourceLocation
-      ExpLoc = SourceMgr.getImmediateExpansionRange(DefArgLoc).first;
-    llvm::DenseMap<unsigned, SourceLocation>::iterator
-      I = ExpansionToArgMap.find(ExpLoc.getRawEncoding());
-    if (I != ExpansionToArgMap.end() && I->second != DefArgLoc)
-      return false; // Trying to write in a macro argument input that has
-                 // already been written for another argument of the same macro. 
+    IdentifierInfo *II;
+    SourceLocation ExpLoc;
+    deconstructMacroArgLoc(OrigLoc, ExpLoc, II);
+    auto I = ExpansionToArgMap.find(ExpLoc.getRawEncoding());
+    if (I != ExpansionToArgMap.end() &&
+        std::find(I->second.begin(), I->second.end(), II) != 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:
+      //
+      // \code
+      //   #define MAC(x) ((x)+(x))
+      //   MAC(a)
+      // \endcode
+      //
+      // A commit modified the macro argument 'a' due to the first '(x)'
+      // expansion inside the macro definition, and a subsequent commit tried
+      // to modify 'a' again for the second '(x)' expansion. The edits of the
+      // second commit will be rejected.
+      return false;
+    }
   }
 
   return true;
@@ -59,11 +101,11 @@ bool EditedSource::commitInsert(SourceLo
     return true;
 
   if (SourceMgr.isMacroArgExpansion(OrigLoc)) {
-    SourceLocation
-      DefArgLoc = SourceMgr.getImmediateExpansionRange(OrigLoc).first;
-    SourceLocation
-      ExpLoc = SourceMgr.getImmediateExpansionRange(DefArgLoc).first;
-    ExpansionToArgMap[ExpLoc.getRawEncoding()] = DefArgLoc;
+    IdentifierInfo *II;
+    SourceLocation ExpLoc;
+    deconstructMacroArgLoc(OrigLoc, ExpLoc, II);
+    if (II)
+      CurrCommitMacroArgExps.emplace_back(ExpLoc, II);
   }
   
   FileEdit &FA = FileEdits[Offs];
@@ -219,6 +261,16 @@ bool EditedSource::commit(const Commit &
   if (!commit.isCommitable())
     return false;
 
+  struct CommitRAII {
+    EditedSource &Editor;
+    CommitRAII(EditedSource &Editor) : Editor(Editor) {
+      Editor.startingCommit();
+    }
+    ~CommitRAII() {
+      Editor.finishedCommit();
+    }
+  } CommitRAII(*this);
+
   for (edit::Commit::edit_iterator
          I = commit.edit_begin(), E = commit.edit_end(); I != E; ++I) {
     const edit::Commit::Edit &edit = *I;

Modified: cfe/trunk/test/ARCMT/objcmt-subscripting-literals.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ARCMT/objcmt-subscripting-literals.m?rev=247462&r1=247461&r2=247462&view=diff
==============================================================================
--- cfe/trunk/test/ARCMT/objcmt-subscripting-literals.m (original)
+++ cfe/trunk/test/ARCMT/objcmt-subscripting-literals.m Fri Sep 11 15:09:11 2015
@@ -88,6 +88,7 @@ typedef const struct __CFString * CFStri
 #define M(x) (x)
 #define PAIR(x) @#x, [NSNumber numberWithInt:(x)]
 #define TWO(x) ((x), (x))
+#define TWO_SEP(x,y) ((x), (y))
 
 @interface I {
   NSArray *ivarArr;
@@ -118,6 +119,7 @@ typedef const struct __CFString * CFStri
   id o = [arr objectAtIndex:2];
   o = [dict objectForKey:@"key"];
   o = TWO([dict objectForKey:@"key"]);
+  o = TWO_SEP([dict objectForKey:@"key"], [arr objectAtIndex:2]);
   o = [NSDictionary dictionaryWithObject:[NSDictionary dictionary] forKey:@"key"];
   NSMutableArray *marr = 0;
   NSMutableDictionary *mdict = 0;

Modified: cfe/trunk/test/ARCMT/objcmt-subscripting-literals.m.result
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ARCMT/objcmt-subscripting-literals.m.result?rev=247462&r1=247461&r2=247462&view=diff
==============================================================================
--- cfe/trunk/test/ARCMT/objcmt-subscripting-literals.m.result (original)
+++ cfe/trunk/test/ARCMT/objcmt-subscripting-literals.m.result Fri Sep 11 15:09:11 2015
@@ -88,6 +88,7 @@ typedef const struct __CFString * CFStri
 #define M(x) (x)
 #define PAIR(x) @#x, [NSNumber numberWithInt:(x)]
 #define TWO(x) ((x), (x))
+#define TWO_SEP(x,y) ((x), (y))
 
 @interface I {
   NSArray *ivarArr;
@@ -118,6 +119,7 @@ typedef const struct __CFString * CFStri
   id o = arr[2];
   o = dict[@"key"];
   o = TWO(dict[@"key"]);
+  o = TWO_SEP(dict[@"key"], arr[2]);
   o = @{@"key": @{}};
   NSMutableArray *marr = 0;
   NSMutableDictionary *mdict = 0;




More information about the cfe-commits mailing list