Skip to content

Commit 56679a8

Browse files
Include [[clang::require_explicit_initialization]] warnings in system headers (#141133)
Fixes #141103
1 parent 896d900 commit 56679a8

File tree

5 files changed

+41
-13
lines changed

5 files changed

+41
-13
lines changed

clang/include/clang/Basic/AttrDocs.td

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1750,9 +1750,9 @@ to guard against use of uninitialized memory.
17501750

17511751
Rather, it is intended for use in "parameter-objects", used to simulate,
17521752
for example, the passing of named parameters.
1753-
The attribute generates a warning when explicit initializers for such
1754-
variables are not provided (this occurs regardless of whether any in-class field
1755-
initializers exist):
1753+
Except inside unevaluated contexts, the attribute generates a warning when
1754+
explicit initializers for such variables are not provided (this occurs
1755+
regardless of whether any in-class field initializers exist):
17561756

17571757
.. code-block:: c++
17581758

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2479,7 +2479,8 @@ def note_uninit_reference_member : Note<
24792479
"uninitialized reference member is here">;
24802480
def warn_field_requires_explicit_init : Warning<
24812481
"field %select{%1|in %1}0 requires explicit initialization but is not "
2482-
"explicitly initialized">, InGroup<UninitializedExplicitInit>;
2482+
"explicitly initialized">, InGroup<UninitializedExplicitInit>,
2483+
ShowInSystemHeader;
24832484
def warn_field_is_uninit : Warning<"field %0 is uninitialized when used here">,
24842485
InGroup<Uninitialized>;
24852486
def warn_base_class_is_uninit : Warning<

clang/lib/Sema/SemaInit.cpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -790,7 +790,8 @@ void InitListChecker::FillInEmptyInitForField(unsigned Init, FieldDecl *Field,
790790
return;
791791
}
792792

793-
if (!VerifyOnly && Field->hasAttr<ExplicitInitAttr>()) {
793+
if (!VerifyOnly && Field->hasAttr<ExplicitInitAttr>() &&
794+
!SemaRef.isUnevaluatedContext()) {
794795
SemaRef.Diag(ILE->getExprLoc(), diag::warn_field_requires_explicit_init)
795796
<< /* Var-in-Record */ 0 << Field;
796797
SemaRef.Diag(Field->getLocation(), diag::note_entity_declared_at)
@@ -4631,7 +4632,8 @@ static void TryConstructorInitialization(Sema &S,
46314632
Kind.getKind() == InitializationKind::IK_Direct) &&
46324633
!(CtorDecl->isCopyOrMoveConstructor() && CtorDecl->isImplicit()) &&
46334634
DestRecordDecl->isAggregate() &&
4634-
DestRecordDecl->hasUninitializedExplicitInitFields()) {
4635+
DestRecordDecl->hasUninitializedExplicitInitFields() &&
4636+
!S.isUnevaluatedContext()) {
46354637
S.Diag(Kind.getLocation(), diag::warn_field_requires_explicit_init)
46364638
<< /* Var-in-Record */ 1 << DestRecordDecl;
46374639
emitUninitializedExplicitInitFields(S, DestRecordDecl);
@@ -5995,7 +5997,8 @@ static void TryOrBuildParenListInitialization(
59955997
} else {
59965998
// We've processed all of the args, but there are still members that
59975999
// have to be initialized.
5998-
if (!VerifyOnly && FD->hasAttr<ExplicitInitAttr>()) {
6000+
if (!VerifyOnly && FD->hasAttr<ExplicitInitAttr>() &&
6001+
!S.isUnevaluatedContext()) {
59996002
S.Diag(Kind.getLocation(), diag::warn_field_requires_explicit_init)
60006003
<< /* Var-in-Record */ 0 << FD;
60016004
S.Diag(FD->getLocation(), diag::note_entity_declared_at) << FD;
@@ -6617,7 +6620,7 @@ void InitializationSequence::InitializeFrom(Sema &S,
66176620
if (RecordDecl *Rec = DestType->getAsRecordDecl()) {
66186621
VarDecl *Var = dyn_cast_or_null<VarDecl>(Entity.getDecl());
66196622
if (Rec->hasUninitializedExplicitInitFields()) {
6620-
if (Var && !Initializer) {
6623+
if (Var && !Initializer && !S.isUnevaluatedContext()) {
66216624
S.Diag(Var->getLocation(), diag::warn_field_requires_explicit_init)
66226625
<< /* Var-in-Record */ 1 << Rec;
66236626
emitUninitializedExplicitInitFields(S, Rec);
@@ -7481,7 +7484,8 @@ PerformConstructorInitialization(Sema &S,
74817484
if (RD && RD->isAggregate() && RD->hasUninitializedExplicitInitFields()) {
74827485
unsigned I = 0;
74837486
for (const FieldDecl *FD : RD->fields()) {
7484-
if (I >= ConstructorArgs.size() && FD->hasAttr<ExplicitInitAttr>()) {
7487+
if (I >= ConstructorArgs.size() && FD->hasAttr<ExplicitInitAttr>() &&
7488+
!S.isUnevaluatedContext()) {
74857489
S.Diag(Loc, diag::warn_field_requires_explicit_init)
74867490
<< /* Var-in-Record */ 0 << FD;
74877491
S.Diag(FD->getLocation(), diag::note_entity_declared_at) << FD;

clang/test/Sema/uninit-variables.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -580,4 +580,6 @@ void aggregate() {
580580

581581
struct with_explicit_flex_array f = {2}; // expected-warning {{field 'flex_arr' requires explicit initialization but is not explicitly initialized}} expected-note@#FIELD_FLEX_ARR {{'flex_arr' declared here}}
582582
(void)f;
583+
584+
(void)sizeof({ struct with_explicit_field a; a; }); // no warning -- unevaluated operand
583585
}

clang/test/SemaCXX/uninitialized.cpp

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,23 @@
22
// RUN: %clang_cc1 -fsyntax-only -Wall -Wc++20-compat -Wuninitialized -Wno-unused-value -Wno-unused-lambda-capture -Wno-uninitialized-const-reference -std=c++1z -verify %s -fexperimental-new-constant-interpreter
33
// RUN: %clang_cc1 -fsyntax-only -Wall -Wc++20-compat -Wuninitialized -Wno-unused-value -Wno-unused-lambda-capture -Wno-uninitialized-const-reference -std=c++20 -verify %s
44

5+
#if defined(BE_THE_HEADER)
6+
7+
// Wuninitialized-explicit-init should warn in system headers (std::construct_at...) too.
8+
9+
#pragma clang system_header
10+
namespace std {
11+
template <class T, class... U>
12+
constexpr T* construct_at(T* ptr, U&&... args) {
13+
return ::new (static_cast<void*>(ptr)) T(static_cast<U&&>(args)...); // #FIELD_EMBED2_CONSTRUCT_AT
14+
}
15+
}
16+
17+
#else
18+
19+
#define BE_THE_HEADER
20+
#include __FILE__
21+
522
void* operator new(__SIZE_TYPE__, void*);
623

724
// definitions for std::move
@@ -1564,11 +1581,11 @@ void aggregate() {
15641581
explicit F(const char(&)[1]) : f1() {
15651582
// expected-warning@+1 {{field in 'Embed' requires explicit initialization but is not explicitly initialized}} expected-note@#FIELD_EMBED2 {{'embed2' declared here}}
15661583
::new(static_cast<void*>(&f1)) decltype(f1);
1567-
// expected-warning@+1 {{field in 'Embed' requires explicit initialization but is not explicitly initialized}} expected-note@#FIELD_EMBED2 {{'embed2' declared here}}
1568-
::new(static_cast<void*>(&f1)) decltype(f1)();
1584+
// expected-warning@#FIELD_EMBED2_CONSTRUCT_AT {{field in 'Embed' requires explicit initialization but is not explicitly initialized}} expected-note@+1 {{in instantiation of function template specialization 'std::construct_at<Embed>' requested here}} expected-note@#FIELD_EMBED2 {{'embed2' declared here}}
1585+
std::construct_at(&f1);
15691586
#if __cplusplus >= 202002L
1570-
// expected-warning@+1 {{field 'embed2' requires explicit initialization but is not explicitly initialized}} expected-note@#FIELD_EMBED2 {{'embed2' declared here}}
1571-
::new(static_cast<void*>(&f1)) decltype(f1)(1);
1587+
// expected-warning@#FIELD_EMBED2_CONSTRUCT_AT {{field 'embed2' requires explicit initialization but is not explicitly initialized}} expected-note@+1 {{in instantiation of function template specialization 'std::construct_at<Embed, int>' requested here}} expected-note@#FIELD_EMBED2 {{'embed2' declared here}}
1588+
std::construct_at(&f1, 1);
15721589
#endif
15731590
// expected-warning@+1 {{field 'embed2' requires explicit initialization but is not explicitly initialized}} expected-note@#FIELD_EMBED2 {{'embed2' declared here}}
15741591
::new(static_cast<void*>(&f1)) decltype(f1){1};
@@ -1625,6 +1642,8 @@ void aggregate() {
16251642
S::foo(S{.s1 = 100, .s4 = 100});
16261643
S::foo(S{.s1 = 100}); // expected-warning {{field 's4' requires explicit initialization but is not explicitly initialized}} expected-note@#FIELD_S4 {{'s4' declared here}}
16271644

1645+
(void)sizeof(S{}); // no warning -- unevaluated operand
1646+
16281647
S s{.s1 = 100, .s4 = 100};
16291648
(void)s;
16301649

@@ -1726,3 +1745,5 @@ void aggregate() {
17261745
InheritWithExplicit<Special> specialized_implicit; // no-warning
17271746
(void)specialized_implicit;
17281747
}
1748+
1749+
#endif

0 commit comments

Comments
 (0)