@@ -129,13 +129,37 @@ void rewriteSourceRange(Rewriter &R, const SourceRange &Range,
129
129
ErrFail);
130
130
}
131
131
132
+ // Wrapper for Rewriter::ReplaceText(CharSourceRange, StringRef) that works
133
+ // around a bug that occurs when text has previously been inserted at the start
134
+ // location of the specified range.
135
+ //
136
+ // When Rewriter::ReplaceText(CharSourceRange, StringRef) computes the range of
137
+ // the rewrite buffer to replace, it sets the start location to be after the
138
+ // previous insertion (RewriteBuffer::ReplaceText calls getMappedOffset with
139
+ // AfterInserts = true) but sets the length to include the length of the
140
+ // previous insertion (it calls getRangeSize with the default RewriteOptions
141
+ // with IncludeInsertsAtBeginOfRange = true). This causes the range to extend
142
+ // beyond the intended end location by an amount equal to the length of the
143
+ // previous insertion. We avoid the problem by calling getRangeSize ourselves
144
+ // with IncludeInsertsAtBeginOfRange = false.
145
+ //
146
+ // TODO: File an upstream Clang bug report if appropriate. As of this writing
147
+ // (2021-11-24), we found some discussion of the problem
148
+ // (https://reviews.llvm.org/D107503) but not a real entry in the bug tracker.
149
+ static bool replaceTextWorkaround (Rewriter &R, const CharSourceRange &Range,
150
+ const std::string &NewText) {
151
+ Rewriter::RewriteOptions Opts;
152
+ Opts.IncludeInsertsAtBeginOfRange = false ;
153
+ return R.ReplaceText (Range.getBegin (), R.getRangeSize (Range, Opts), NewText);
154
+ }
155
+
132
156
void rewriteSourceRange (Rewriter &R, const CharSourceRange &Range,
133
157
const std::string &NewText, bool ErrFail) {
134
158
// Attempt to rewrite the source range. First use the source range directly
135
159
// from the parameter.
136
160
bool RewriteSuccess = false ;
137
161
if (canRewrite (R, Range))
138
- RewriteSuccess = !R. ReplaceText ( Range, NewText);
162
+ RewriteSuccess = !replaceTextWorkaround (R, Range, NewText);
139
163
140
164
// If initial rewriting attempt failed (either because canRewrite returned
141
165
// false or because ReplaceText failed (returning true), try rewriting again
@@ -144,7 +168,7 @@ void rewriteSourceRange(Rewriter &R, const CharSourceRange &Range,
144
168
CharSourceRange Expand = clang::Lexer::makeFileCharRange (
145
169
Range, R.getSourceMgr (), R.getLangOpts ());
146
170
if (canRewrite (R, Expand))
147
- RewriteSuccess = !R. ReplaceText ( Expand, NewText);
171
+ RewriteSuccess = !replaceTextWorkaround (R, Expand, NewText);
148
172
}
149
173
150
174
// Emit an error if we were unable to rewrite the source range. This is more
0 commit comments