Index: clang-tools-extra/clang-apply-replacements/lib/Tooling/ApplyReplacements.cpp =================================================================== --- clang-tools-extra/clang-apply-replacements/lib/Tooling/ApplyReplacements.cpp +++ clang-tools-extra/clang-apply-replacements/lib/Tooling/ApplyReplacements.cpp @@ -231,7 +231,19 @@ // For now, printing directly the error reported by `AtomicChange` is // the easiest solution. errs() << llvm::toString(std::move(Err)) << "\n"; - ConflictDetected = true; + tooling::Replacements &Replacements = FileChange.getRefReplacements(); + unsigned NewOffset = Replacements.getShiftedCodePosition(R.getOffset()); + unsigned NewLength = + Replacements.getShiftedCodePosition(R.getOffset() + R.getLength()) - + NewOffset; + if (NewLength == R.getLength()) { + tooling::Replacement RR = tooling::Replacement( + R.getFilePath(), NewOffset, NewLength, R.getReplacementText()); + Replacements = Replacements.merge(tooling::Replacements(RR)); + } else { + llvm::errs() << "Can't resolve conflict, skipping the replacement.\n"; + ConflictDetected = true; + } } } FileChanges.try_emplace(Entry, Index: clang-tools-extra/test/clang-apply-replacements/Inputs/conflict-offset/conflict-offset.cpp =================================================================== --- /dev/null +++ clang-tools-extra/test/clang-apply-replacements/Inputs/conflict-offset/conflict-offset.cpp @@ -0,0 +1,4 @@ +class MyType {}; +// CHECK: #include +// CHECK-NEXT: #include +// CEHCK-NEXT: class MyType {}; Index: clang-tools-extra/test/clang-apply-replacements/Inputs/conflict-offset/file1.yaml =================================================================== --- /dev/null +++ clang-tools-extra/test/clang-apply-replacements/Inputs/conflict-offset/file1.yaml @@ -0,0 +1,24 @@ +--- +MainSourceFile: conflict-offset.cpp +Diagnostics: + - DiagnosticName: test-conflict-offset-insertion + DiagnosticMessage: + Message: Fix + FilePath: $(path)/conflict-offset.cpp + FileOffset: 0 + Replacements: + - FilePath: $(path)/conflict-offset.cpp + Offset: 0 + Length: 0 + ReplacementText: "#include \n" + - DiagnosticName: test-conflict-offset-insertion + DiagnosticMessage: + Message: Fix + FilePath: $(path)/conflict-offset.cpp + FileOffset: 0 + Replacements: + - FilePath: $(path)/conflict-offset.cpp + Offset: 0 + Length: 0 + ReplacementText: "#include \n" +... Index: clang-tools-extra/test/clang-apply-replacements/conflict-offset.cpp =================================================================== --- /dev/null +++ clang-tools-extra/test/clang-apply-replacements/conflict-offset.cpp @@ -0,0 +1,5 @@ +// RUN: mkdir -p %T/Inputs/conflict-offset +// RUN: grep -Ev "// *[A-Z-]+:" %S/Inputs/conflict-offset/conflict-offset.cpp > %T/Inputs/conflict-offset/conflict-offset.cpp +// RUN: sed "s#\$(path)#%/T/Inputs/conflict-offset#" %S/Inputs/conflict-offset/file1.yaml > %T/Inputs/conflict-offset/file1.yaml +// RUN: clang-apply-replacements %T/Inputs/conflict-offset +// RUN: FileCheck -input-file=%T/Inputs/conflict-offset/conflict-offset.cpp %S/Inputs/conflict-offset/conflict-offset.cpp Index: clang/include/clang/Tooling/Refactoring/AtomicChange.h =================================================================== --- clang/include/clang/Tooling/Refactoring/AtomicChange.h +++ clang/include/clang/Tooling/Refactoring/AtomicChange.h @@ -116,6 +116,8 @@ /// Returns a const reference to existing replacements. const Replacements &getReplacements() const { return Replaces; } + Replacements &getRefReplacements() { return Replaces; } + llvm::ArrayRef getInsertedHeaders() const { return InsertedHeaders; }