@@ -221,6 +221,8 @@ void DeclRewriter::rewriteDecls(ASTContext &Context, ProgramInfo &Info,
221
221
222
222
for (const auto *R : RewriteThese)
223
223
delete R;
224
+
225
+ DeclR.denestRecordDecls ();
224
226
}
225
227
226
228
void DeclRewriter::rewrite (RSet &ToRewrite) {
@@ -251,6 +253,46 @@ void DeclRewriter::rewrite(RSet &ToRewrite) {
251
253
}
252
254
}
253
255
256
+ void DeclRewriter::denestRecordDecls () {
257
+ // When there are multiple levels of nested RecordDecls, we need to process
258
+ // all the children of a RecordDecl RD before RD itself so that (1) the
259
+ // definitions of the children end up before the definition of RD (since the
260
+ // rewriter preserves order of insertions) and (2) the definitions of the
261
+ // children have been removed from the body of RD before we read the body of
262
+ // RD to move it. In effect, we want to process the RecordDecls in postorder.
263
+ // The easiest way to achieve this is to process them in order of their _end_
264
+ // locations.
265
+ std::sort (RecordDeclsToDenest.begin (), RecordDeclsToDenest.end (),
266
+ [&](RecordDecl *RD1, RecordDecl *RD2) {
267
+ return A.getSourceManager ().isBeforeInTranslationUnit (
268
+ RD1->getEndLoc (), RD2->getEndLoc ());
269
+ });
270
+ for (RecordDecl *RD : RecordDeclsToDenest) {
271
+ // rewriteMultiDecl replaced the final "}" in the original source range with
272
+ // "};\n", so the new content of the source range should include the ";\n",
273
+ // which is what we want here. Except the rewriter has a bug where it
274
+ // adjusts the token range to include the final token _after_ mapping the
275
+ // offset to account for previous edits (it should be before). We work
276
+ // around the bug by adjusting the token range before calling the rewriter
277
+ // at all.
278
+ CharSourceRange CSR = Lexer::makeFileCharRange (
279
+ CharSourceRange::getTokenRange (RD->getSourceRange ()), R.getSourceMgr (),
280
+ R.getLangOpts ());
281
+ std::string DefinitionStr = R.getRewrittenText (CSR);
282
+ // Delete the definition from the old location.
283
+ rewriteSourceRange (R, CSR, " " );
284
+ // We want to insert RD as a new child of its original semantic DeclContext,
285
+ // just before the existing child of that DeclContext of which RD was
286
+ // originally a descendant.
287
+ DeclContext *TopChild = RD;
288
+ while (TopChild->getLexicalParent () != RD->getDeclContext ()) {
289
+ TopChild = TopChild->getLexicalParent ();
290
+ }
291
+ // TODO: Use a wrapper like rewriteSourceRange.
292
+ R.InsertText (cast<Decl>(TopChild)->getBeginLoc (), DefinitionStr);
293
+ }
294
+ }
295
+
254
296
void DeclRewriter::rewriteParmVarDecl (ParmVarDeclReplacement *N) {
255
297
// First, find all the declarations of the containing function.
256
298
DeclContext *DF = N->getDecl ()->getParentFunctionOrMethod ();
@@ -398,6 +440,9 @@ void DeclRewriter::rewriteMultiDecl(DeclReplacement *N, RSet &ToRewrite,
398
440
R.InsertTextAfterToken (DL->getBeginLoc (), " " + Iter->second );
399
441
}
400
442
}
443
+ // Make a note if the RecordDecl needs to be de-nested later.
444
+ if (RD->getLexicalDeclContext () != RD->getDeclContext ())
445
+ RecordDeclsToDenest.push_back (RD);
401
446
} else if (IsFirst) {
402
447
// Rewriting the first declaration is easy. Nothing should change if its
403
448
// type does not to be rewritten. When rewriting is required, it is
0 commit comments