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