@@ -238,6 +238,8 @@ void DeclRewriter::rewriteDecls(ASTContext &Context, ProgramInfo &Info,
238238
239239 for (auto Pair : RewriteThese)
240240 delete Pair.second ;
241+
242+ DeclR.denestRecordDecls ();
241243}
242244
243245void DeclRewriter::rewrite (RSet &ToRewrite) {
@@ -266,6 +268,46 @@ void DeclRewriter::rewrite(RSet &ToRewrite) {
266268 }
267269}
268270
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+
269311void DeclRewriter::rewriteTypedefDecl (TypedefDeclReplacement *TDR,
270312 RSet &ToRewrite) {
271313 rewriteSingleDecl (TDR, ToRewrite);
@@ -381,6 +423,9 @@ void DeclRewriter::rewriteMultiDecl(DeclReplacement *N, RSet &ToRewrite,
381423 R.InsertTextAfterToken (DL->getBeginLoc (), " " + Iter->second );
382424 }
383425 }
426+ // Make a note if the RecordDecl needs to be de-nested later.
427+ if (RD->getLexicalDeclContext () != RD->getDeclContext ())
428+ RecordDeclsToDenest.push_back (RD);
384429 } else if (IsFirst) {
385430 // Rewriting the first declaration is easy. Nothing should change if its
386431 // type does not to be rewritten. When rewriting is required, it is
0 commit comments