Skip to content

Commit bef3459

Browse files
alanzhao1tstellar
authored andcommitted
[clang] Fix default initializers being ignored when initializing templated aggregate types
Previously, when checking whether an in-class initializer exists when performing parenthesized aggregate initialization, Clang checks that the output of FieldDecl::getInClassInitializer() is non-null. This is incorrect; if the field is part of a templated type, then getInClassInitializer() will return nullptr if we haven't called Sem::BuildCXXDefaultInitExpr(...) before, even if FieldDecl::hasInClassInitializer() returns true. The end result is that Clang incorrectly ignores the in class initializer and value-initializes the field. The fix therefore is to instead call FieldDecl::hasInClassInitializer(), which is what we do for braced init lists [0]. Before this patch, Clang does correctly recognize the in-class field initializer in certain cases. This is Sema::BuildCXXDefaultInitExpr(...) populates the in class initializer of the corresponding FieldDecl object. Therefore, if that method was previously called with the same FieldDecl object, as can happen with a decltype(...) or a braced list initialization, FieldDecl::getInClassInitializer() will return a non-null expression, and the field becomes properly initialized. Fixes 62266 [0]: https://github.com/llvm/llvm-project/blob/be5f35e24f4c15caf3c4aeccddc54c52560c28a0/clang/lib/Sema/SemaInit.cpp#L685 Reviewed By: shafik Differential Revision: https://reviews.llvm.org/D149389
1 parent 83c2387 commit bef3459

File tree

3 files changed

+36
-7
lines changed

3 files changed

+36
-7
lines changed

clang/docs/ReleaseNotes.rst

+4
Original file line numberDiff line numberDiff line change
@@ -821,6 +821,10 @@ Bug Fixes to C++ Support
821821
- Do not hide templated base members introduced via using-decl in derived class
822822
(useful specially for constrained members). (`#50886 <https://github.com/llvm/llvm-project/issues/50886>`_)
823823

824+
- Fix default member initializers sometimes being ignored when performing
825+
parenthesized aggregate initialization of templated types.
826+
(`#62266 <https://github.com/llvm/llvm-project/issues/62266>`_)
827+
824828
Concepts Specific Fixes:
825829

826830
- Class member variables are now in scope when parsing a ``requires`` clause.

clang/lib/Sema/SemaInit.cpp

+9-7
Original file line numberDiff line numberDiff line change
@@ -5348,14 +5348,16 @@ static void TryOrBuildParenListInitialization(
53485348
// The remaining elements are initialized with their default member
53495349
// initializers, if any
53505350
auto *FD = cast<FieldDecl>(SubEntity.getDecl());
5351-
if (Expr *ICE = FD->getInClassInitializer(); ICE && !VerifyOnly) {
5352-
ExprResult DIE = S.BuildCXXDefaultInitExpr(FD->getLocation(), FD);
5353-
if (DIE.isInvalid())
5354-
return false;
5355-
S.checkInitializerLifetime(SubEntity, DIE.get());
5356-
InitExprs.push_back(DIE.get());
5351+
if (FD->hasInClassInitializer()) {
5352+
if (!VerifyOnly) {
5353+
ExprResult DIE = S.BuildCXXDefaultInitExpr(FD->getLocation(), FD);
5354+
if (DIE.isInvalid())
5355+
return false;
5356+
S.checkInitializerLifetime(SubEntity, DIE.get());
5357+
InitExprs.push_back(DIE.get());
5358+
}
53575359
continue;
5358-
};
5360+
}
53595361
}
53605362
// Remaining class elements without default member initializers and
53615363
// array elements are value initialized:

clang/test/CodeGen/paren-list-agg-init.cpp

+23
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,15 @@ namespace gh61145 {
9090
};
9191
}
9292

93+
namespace gh62266 {
94+
// CHECK-DAG: [[STRUCT_H:%.*H.*]] = type { i32, i32 }
95+
template <int J>
96+
struct H {
97+
int i;
98+
int j = J;
99+
};
100+
}
101+
93102
// CHECK-DAG: [[A1:@.*a1.*]] = internal constant [[STRUCT_A]] { i8 3, double 2.000000e+00 }, align 8
94103
constexpr A a1(3.1, 2.0);
95104
// CHECK-DAG: [[A2:@.*a2.*]] = internal constant [[STRUCT_A]] { i8 99, double 0.000000e+00 }, align 8
@@ -421,3 +430,17 @@ namespace gh61145 {
421430
make2<0>();
422431
}
423432
}
433+
434+
namespace gh62266 {
435+
// CHECK: define {{.*}} void {{.*foo20.*}}
436+
// CHECK-NEXT: entry:
437+
// CHECK-NEXT: [[H:%.*h.*]] = alloca [[STRUCT_H]], align 4
438+
// CHECK-NEXT: [[I:%.*i.*]] = getelementptr inbounds [[STRUCT_H]], ptr [[H]], i32 0, i32 0
439+
// CHECK-NEXT: store i32 1, ptr [[I]], align 4
440+
// CHECK-NEXT: [[J:%.*j.*]] = getelementptr inbounds [[STRUCT_H]], ptr [[H]], i32 0, i32 1
441+
// CHECK-NEXT: store i32 2, ptr [[J]], align 4
442+
// CHECK-NEXT: ret void
443+
void foo20() {
444+
H<2> h(1);
445+
}
446+
}

0 commit comments

Comments
 (0)