Skip to content

Commit 4ce2cfb

Browse files
Fix de-nesting of unnamed TagDecls and improve some comments.
1 parent a4cf721 commit 4ce2cfb

File tree

2 files changed

+36
-12
lines changed

2 files changed

+36
-12
lines changed

clang/lib/3C/DeclRewriter.cpp

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -274,15 +274,30 @@ void DeclRewriter::denestTagDecls() {
274274
std::string DefinitionStr = R.getRewrittenText(CSR);
275275
// Delete the definition from the old location.
276276
rewriteSourceRange(R, CSR, "");
277-
// We want to insert RD as a new child of its original semantic DeclContext,
278-
// just before the existing child of that DeclContext of which RD was
279-
// originally a descendant.
280-
DeclContext *TopChild = TD;
281-
while (TopChild->getLexicalParent() != TD->getDeclContext()) {
282-
TopChild = TopChild->getLexicalParent();
277+
// We want to find the nearest ancestor DeclContext of TD that is _not_ a
278+
// TagDecl and make TD a child of that DeclContext (named `Parent` below),
279+
// just before the child `TopTagDecl` of `Parent` of which TD was originally
280+
// a descendant.
281+
//
282+
// As of this writing, it seems that if TD is named, we get
283+
// `Parent == TD->getDeclContext()` due to the code at
284+
// https://github.com/correctcomputation/checkedc-clang/blob/fd4d8af4383d40af10ee8bc92b7bf88061a11035/clang/lib/Sema/SemaDecl.cpp#L16980-L16981,
285+
// But that code doesn't run if TD is unnamed (which makes some sense
286+
// because name visibility isn't an issue for TagDecls that have no name),
287+
// and we want to de-nest TagDecls with names we assigned just like ones
288+
// that were originally named, so we can't just use `TD->getDeclContext()`.
289+
// In any event, maybe we wouldn't want to rely on this kind of internal
290+
// Clang behavior.
291+
DeclContext *TopTagDecl = TD;
292+
for (;;) {
293+
DeclContext *Parent = TopTagDecl->getLexicalParent();
294+
if (!isa<TagDecl>(Parent))
295+
break;
296+
TopTagDecl = Parent;
283297
}
284-
// TODO: Use a wrapper like rewriteSourceRange.
285-
R.InsertText(cast<Decl>(TopChild)->getBeginLoc(), DefinitionStr);
298+
// TODO: Use a wrapper like rewriteSourceRange that tries harder with
299+
// macros, reports failure, etc.
300+
R.InsertText(cast<Decl>(TopTagDecl)->getBeginLoc(), DefinitionStr);
286301
}
287302
}
288303

@@ -332,8 +347,8 @@ void DeclRewriter::rewriteMultiDecl(MultiDeclInfo &MDI, RSet &ToRewrite) {
332347
llvm_unreachable("Failed to find place to insert assigned TagDecl name.");
333348
}
334349
}
335-
// Make a note if the RecordDecl needs to be de-nested later.
336-
if (TD->getLexicalDeclContext() != TD->getDeclContext())
350+
// Make a note if the TagDecl needs to be de-nested later.
351+
if (isa<TagDecl>(TD->getLexicalDeclContext()))
337352
TagDeclsToDenest.push_back(TD);
338353
// `struct T { ... } foo;` -> `struct T { ... };\nfoo;`
339354
rewriteSourceRange(R, TD->getEndLoc(), "};\n");

clang/lib/3C/MultiDecls.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ void MultiDeclsInfo::findMultiDecls(DeclContext *DC, ASTContext &Context) {
133133
// Otherwise, just generate a new tag name based on the member name.
134134
// Example: `struct { ... } foo;` ->
135135
// `struct foo_struct_1 { ... }; struct foo_struct_1 foo;`
136+
// If `foo_struct_1` is already taken, use `foo_struct_2`, etc.
136137
std::string KindName = std::string(LastTagDef->getKindName());
137138
std::string NewName;
138139
for (int Num = 1; ; Num++) {
@@ -142,8 +143,16 @@ void MultiDeclsInfo::findMultiDecls(DeclContext *DC, ASTContext &Context) {
142143
}
143144
AssignedTagTypeStrs.insert(std::make_pair(TagDefPSL, KindName + " " + NewName));
144145
TagDefNeedsName = false;
145-
// This name is now taken; other automatically generated names must not
146-
// collide with it.
146+
// Consider this name taken and ensure that other automatically
147+
// generated names do not collide with it.
148+
//
149+
// If the multi-decl doesn't end up getting rewritten, this name
150+
// ultimately may not be used, creating a gap in the numbering in 3C's
151+
// output. But this cosmetic inconsistency is a small price to pay for
152+
// the architectural convenience of being able to store the assigned
153+
// names in the PointerVariableConstraints when they are constructed
154+
// rather than trying to assign and store the names after we know
155+
// which multi-decls will be rewritten.
147156
UsedTagNames.insert(NewName);
148157
}
149158
}

0 commit comments

Comments
 (0)