@@ -240,6 +240,8 @@ void DeclRewriter::rewriteDecls(ASTContext &Context, ProgramInfo &Info,
240
240
241
241
for (auto Pair : RewriteThese)
242
242
delete Pair.second ;
243
+
244
+ DeclR.denestRecordDecls ();
243
245
}
244
246
245
247
void DeclRewriter::rewrite (RSet &ToRewrite) {
@@ -268,6 +270,46 @@ void DeclRewriter::rewrite(RSet &ToRewrite) {
268
270
}
269
271
}
270
272
273
+ void DeclRewriter::denestRecordDecls () {
274
+ // When there are multiple levels of nested RecordDecls, we need to process
275
+ // all the children of a RecordDecl RD before RD itself so that (1) the
276
+ // definitions of the children end up before the definition of RD (since the
277
+ // rewriter preserves order of insertions) and (2) the definitions of the
278
+ // children have been removed from the body of RD before we read the body of
279
+ // RD to move it. In effect, we want to process the RecordDecls in postorder.
280
+ // The easiest way to achieve this is to process them in order of their _end_
281
+ // locations.
282
+ std::sort (RecordDeclsToDenest.begin (), RecordDeclsToDenest.end (),
283
+ [&](RecordDecl *RD1, RecordDecl *RD2) {
284
+ return A.getSourceManager ().isBeforeInTranslationUnit (
285
+ RD1->getEndLoc (), RD2->getEndLoc ());
286
+ });
287
+ for (RecordDecl *RD : RecordDeclsToDenest) {
288
+ // rewriteMultiDecl replaced the final "}" in the original source range with
289
+ // "};\n", so the new content of the source range should include the ";\n",
290
+ // which is what we want here. Except the rewriter has a bug where it
291
+ // adjusts the token range to include the final token _after_ mapping the
292
+ // offset to account for previous edits (it should be before). We work
293
+ // around the bug by adjusting the token range before calling the rewriter
294
+ // at all.
295
+ CharSourceRange CSR = Lexer::makeFileCharRange (
296
+ CharSourceRange::getTokenRange (RD->getSourceRange ()), R.getSourceMgr (),
297
+ R.getLangOpts ());
298
+ std::string DefinitionStr = R.getRewrittenText (CSR);
299
+ // Delete the definition from the old location.
300
+ rewriteSourceRange (R, CSR, " " );
301
+ // We want to insert RD as a new child of its original semantic DeclContext,
302
+ // just before the existing child of that DeclContext of which RD was
303
+ // originally a descendant.
304
+ DeclContext *TopChild = RD;
305
+ while (TopChild->getLexicalParent () != RD->getDeclContext ()) {
306
+ TopChild = TopChild->getLexicalParent ();
307
+ }
308
+ // TODO: Use a wrapper like rewriteSourceRange.
309
+ R.InsertText (cast<Decl>(TopChild)->getBeginLoc (), DefinitionStr);
310
+ }
311
+ }
312
+
271
313
void DeclRewriter::rewriteTypedefDecl (TypedefDeclReplacement *TDR,
272
314
RSet &ToRewrite) {
273
315
rewriteSingleDecl (TDR, ToRewrite);
@@ -384,6 +426,9 @@ void DeclRewriter::rewriteMultiDecl(DeclReplacement *N, RSet &ToRewrite,
384
426
R.InsertTextAfterToken (DL->getBeginLoc (), " " + Iter->second );
385
427
}
386
428
}
429
+ // Make a note if the RecordDecl needs to be de-nested later.
430
+ if (RD->getLexicalDeclContext () != RD->getDeclContext ())
431
+ RecordDeclsToDenest.push_back (RD);
387
432
} else if (IsFirst) {
388
433
// Rewriting the first declaration is easy. Nothing should change if its
389
434
// type does not to be rewritten. When rewriting is required, it is
0 commit comments