Skip to content

Include [[clang::require_explicit_initialization]] warnings in system headers #141133

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions clang/include/clang/Basic/AttrDocs.td
Original file line number Diff line number Diff line change
Expand Up @@ -1746,9 +1746,9 @@ to guard against use of uninitialized memory.

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

.. code-block:: c++

Expand Down
3 changes: 2 additions & 1 deletion clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -2446,7 +2446,8 @@ def note_uninit_reference_member : Note<
"uninitialized reference member is here">;
def warn_field_requires_explicit_init : Warning<
"field %select{%1|in %1}0 requires explicit initialization but is not "
"explicitly initialized">, InGroup<UninitializedExplicitInit>;
"explicitly initialized">, InGroup<UninitializedExplicitInit>,
ShowInSystemHeader;
def warn_field_is_uninit : Warning<"field %0 is uninitialized when used here">,
InGroup<Uninitialized>;
def warn_base_class_is_uninit : Warning<
Expand Down
14 changes: 9 additions & 5 deletions clang/lib/Sema/SemaInit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -779,7 +779,8 @@ void InitListChecker::FillInEmptyInitForField(unsigned Init, FieldDecl *Field,
return;
}

if (!VerifyOnly && Field->hasAttr<ExplicitInitAttr>()) {
if (!VerifyOnly && Field->hasAttr<ExplicitInitAttr>() &&
!SemaRef.isUnevaluatedContext()) {
SemaRef.Diag(ILE->getExprLoc(), diag::warn_field_requires_explicit_init)
<< /* Var-in-Record */ 0 << Field;
SemaRef.Diag(Field->getLocation(), diag::note_entity_declared_at)
Expand Down Expand Up @@ -4620,7 +4621,8 @@ static void TryConstructorInitialization(Sema &S,
Kind.getKind() == InitializationKind::IK_Direct) &&
!(CtorDecl->isCopyOrMoveConstructor() && CtorDecl->isImplicit()) &&
DestRecordDecl->isAggregate() &&
DestRecordDecl->hasUninitializedExplicitInitFields()) {
DestRecordDecl->hasUninitializedExplicitInitFields() &&
!S.isUnevaluatedContext()) {
S.Diag(Kind.getLocation(), diag::warn_field_requires_explicit_init)
<< /* Var-in-Record */ 1 << DestRecordDecl;
emitUninitializedExplicitInitFields(S, DestRecordDecl);
Expand Down Expand Up @@ -5984,7 +5986,8 @@ static void TryOrBuildParenListInitialization(
} else {
// We've processed all of the args, but there are still members that
// have to be initialized.
if (!VerifyOnly && FD->hasAttr<ExplicitInitAttr>()) {
if (!VerifyOnly && FD->hasAttr<ExplicitInitAttr>() &&
!S.isUnevaluatedContext()) {
S.Diag(Kind.getLocation(), diag::warn_field_requires_explicit_init)
<< /* Var-in-Record */ 0 << FD;
S.Diag(FD->getLocation(), diag::note_entity_declared_at) << FD;
Expand Down Expand Up @@ -6606,7 +6609,7 @@ void InitializationSequence::InitializeFrom(Sema &S,
if (RecordDecl *Rec = DestType->getAsRecordDecl()) {
VarDecl *Var = dyn_cast_or_null<VarDecl>(Entity.getDecl());
if (Rec->hasUninitializedExplicitInitFields()) {
if (Var && !Initializer) {
if (Var && !Initializer && !S.isUnevaluatedContext()) {
S.Diag(Var->getLocation(), diag::warn_field_requires_explicit_init)
<< /* Var-in-Record */ 1 << Rec;
emitUninitializedExplicitInitFields(S, Rec);
Expand Down Expand Up @@ -7470,7 +7473,8 @@ PerformConstructorInitialization(Sema &S,
if (RD && RD->isAggregate() && RD->hasUninitializedExplicitInitFields()) {
unsigned I = 0;
for (const FieldDecl *FD : RD->fields()) {
if (I >= ConstructorArgs.size() && FD->hasAttr<ExplicitInitAttr>()) {
if (I >= ConstructorArgs.size() && FD->hasAttr<ExplicitInitAttr>() &&
!S.isUnevaluatedContext()) {
S.Diag(Loc, diag::warn_field_requires_explicit_init)
<< /* Var-in-Record */ 0 << FD;
S.Diag(FD->getLocation(), diag::note_entity_declared_at) << FD;
Expand Down
2 changes: 2 additions & 0 deletions clang/test/Sema/uninit-variables.c
Original file line number Diff line number Diff line change
Expand Up @@ -580,4 +580,6 @@ void aggregate() {

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}}
(void)f;

(void)sizeof({ struct with_explicit_field a; a; }); // no warning -- unevaluated operand
}
29 changes: 25 additions & 4 deletions clang/test/SemaCXX/uninitialized.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,23 @@
// 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
// 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

#if defined(BE_THE_HEADER)

// Wuninitialized-explicit-init should warn in system headers (std::construct_at...) too.

#pragma clang system_header
namespace std {
template <class T, class... U>
constexpr T* construct_at(T* ptr, U&&... args) {
return ::new (static_cast<void*>(ptr)) T(static_cast<U&&>(args)...); // #FIELD_EMBED2_CONSTRUCT_AT
}
}

#else

#define BE_THE_HEADER
#include __FILE__

void* operator new(__SIZE_TYPE__, void*);

// definitions for std::move
Expand Down Expand Up @@ -1564,11 +1581,11 @@ void aggregate() {
explicit F(const char(&)[1]) : f1() {
// expected-warning@+1 {{field in 'Embed' requires explicit initialization but is not explicitly initialized}} expected-note@#FIELD_EMBED2 {{'embed2' declared here}}
::new(static_cast<void*>(&f1)) decltype(f1);
// expected-warning@+1 {{field in 'Embed' requires explicit initialization but is not explicitly initialized}} expected-note@#FIELD_EMBED2 {{'embed2' declared here}}
::new(static_cast<void*>(&f1)) decltype(f1)();
// 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}}
std::construct_at(&f1);
#if __cplusplus >= 202002L
// expected-warning@+1 {{field 'embed2' requires explicit initialization but is not explicitly initialized}} expected-note@#FIELD_EMBED2 {{'embed2' declared here}}
::new(static_cast<void*>(&f1)) decltype(f1)(1);
// 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}}
std::construct_at(&f1, 1);
#endif
// expected-warning@+1 {{field 'embed2' requires explicit initialization but is not explicitly initialized}} expected-note@#FIELD_EMBED2 {{'embed2' declared here}}
::new(static_cast<void*>(&f1)) decltype(f1){1};
Expand Down Expand Up @@ -1625,6 +1642,8 @@ void aggregate() {
S::foo(S{.s1 = 100, .s4 = 100});
S::foo(S{.s1 = 100}); // expected-warning {{field 's4' requires explicit initialization but is not explicitly initialized}} expected-note@#FIELD_S4 {{'s4' declared here}}

(void)sizeof(S{}); // no warning -- unevaluated operand

S s{.s1 = 100, .s4 = 100};
(void)s;

Expand Down Expand Up @@ -1726,3 +1745,5 @@ void aggregate() {
InheritWithExplicit<Special> specialized_implicit; // no-warning
(void)specialized_implicit;
}

#endif
Loading