Skip to content

Commit 701fe51

Browse files
authored
[Clang] Fix an inadvertent overwrite of sub-initializers (llvm#140714)
When using InitChecker with VerifyOnly, we create a new designated initializer to handle anonymous fields. However in the last call to CheckDesignatedInitializer, the subinitializer isn't properly preserved but it gets overwritten by the cloned one. Which causes the initializer to reference the dependent field, breaking assumptions when we initialize the instantiated specialization. Fixes llvm#67173
1 parent 0649122 commit 701fe51

File tree

3 files changed

+36
-4
lines changed

3 files changed

+36
-4
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -703,6 +703,7 @@ Bug Fixes to C++ Support
703703
certain differences in qualifiers (this could happen during template argument
704704
deduction or when building a ternary operator). (#GH97005)
705705
- Fixed type alias CTAD issues involving default template arguments. (#GH134471)
706+
- Fixed CTAD issues when initializing anonymous fields with designated initializers. (#GH67173)
706707
- The initialization kind of elements of structured bindings
707708
direct-list-initialized from an array is corrected to direct-initialization.
708709
- Clang no longer crashes when a coroutine is declared ``[[noreturn]]``. (#GH127327)

clang/lib/Sema/SemaInit.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2791,16 +2791,20 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
27912791
// initializer list that the child calls see, so that we don't try
27922792
// to re-process the designator.
27932793
unsigned OldIndex = Index;
2794-
IList->setInit(OldIndex, DIE->getInit());
2794+
auto *OldDIE =
2795+
dyn_cast_if_present<DesignatedInitExpr>(IList->getInit(OldIndex));
2796+
if (!OldDIE)
2797+
OldDIE = DIE;
2798+
IList->setInit(OldIndex, OldDIE->getInit());
27952799

27962800
CheckSubElementType(Entity, IList, CurrentObjectType, Index, StructuredList,
27972801
StructuredIndex, /*DirectlyDesignated=*/true);
27982802

27992803
// Restore the designated initializer expression in the syntactic
28002804
// form of the initializer list.
2801-
if (IList->getInit(OldIndex) != DIE->getInit())
2802-
DIE->setInit(IList->getInit(OldIndex));
2803-
IList->setInit(OldIndex, DIE);
2805+
if (IList->getInit(OldIndex) != OldDIE->getInit())
2806+
OldDIE->setInit(IList->getInit(OldIndex));
2807+
IList->setInit(OldIndex, OldDIE);
28042808

28052809
return hadError && !prevHadError;
28062810
}

clang/test/SemaTemplate/deduction-guide.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -886,3 +886,30 @@ CC c{};
886886
// CHECK-NEXT: `-ClassTemplateSpecialization {{.+}} 'A'
887887

888888
}
889+
890+
namespace GH67173 {
891+
892+
template <class T> struct Vec2d {
893+
struct {
894+
T x;
895+
T y;
896+
};
897+
};
898+
899+
void f() {
900+
Vec2d v{.x = 1, .y = 2};
901+
}
902+
903+
// CHECK-LABEL: Dumping GH67173::<deduction guide for Vec2d>:
904+
// CHECK-NEXT: FunctionTemplateDecl {{.+}} implicit <deduction guide for Vec2d>
905+
// CHECK-NEXT: |-TemplateTypeParmDecl {{.+}} referenced class depth 0 index 0 T
906+
// CHECK: |-CXXDeductionGuideDecl {{.+}} implicit <deduction guide for Vec2d> 'auto (T, T) -> Vec2d<T>' aggregate
907+
// CHECK-NEXT: | |-ParmVarDecl {{.+}} col:27 'T'
908+
// CHECK-NEXT: | `-ParmVarDecl {{.+}} col:27 'T'
909+
// CHECK-NEXT: `-CXXDeductionGuideDecl {{.+}} implicit used <deduction guide for Vec2d> 'auto (int, int) -> GH67173::Vec2d<int>' implicit_instantiation aggregate
910+
// CHECK-NEXT: |-TemplateArgument type 'int'
911+
// CHECK-NEXT: | `-BuiltinType {{.+}} 'int'
912+
// CHECK-NEXT: |-ParmVarDecl {{.+}} 'int'
913+
// CHECK-NEXT: `-ParmVarDecl {{.+}} 'int'
914+
915+
}

0 commit comments

Comments
 (0)