Skip to content

Conversation

@higher-performance
Copy link
Contributor

It turns out we weren't handling one case: the value-initialization of a field inside a struct.

I'm not sure why this falls under IK_Direct rather than IK_Value in Clang, but it seems to work.

@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Jan 24, 2025
@llvmbot
Copy link
Member

llvmbot commented Jan 24, 2025

@llvm/pr-subscribers-clang

Author: None (higher-performance)

Changes

It turns out we weren't handling one case: the value-initialization of a field inside a struct.

I'm not sure why this falls under IK_Direct rather than IK_Value in Clang, but it seems to work.


Full diff: https://github.com/llvm/llvm-project/pull/124329.diff

2 Files Affected:

  • (modified) clang/lib/Sema/SemaInit.cpp (+3-1)
  • (modified) clang/test/SemaCXX/uninitialized.cpp (+44)
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index b95cbbf4222056..450edcb52ae15b 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -4573,7 +4573,9 @@ static void TryConstructorInitialization(Sema &S,
 
   CXXConstructorDecl *CtorDecl = cast<CXXConstructorDecl>(Best->Function);
   if (Result != OR_Deleted) {
-    if (!IsListInit && Kind.getKind() == InitializationKind::IK_Default &&
+    if (!IsListInit &&
+        (Kind.getKind() == InitializationKind::IK_Default ||
+         Kind.getKind() == InitializationKind::IK_Direct) &&
         DestRecordDecl != nullptr && DestRecordDecl->isAggregate() &&
         DestRecordDecl->hasUninitializedExplicitInitFields()) {
       S.Diag(Kind.getLocation(), diag::warn_field_requires_explicit_init)
diff --git a/clang/test/SemaCXX/uninitialized.cpp b/clang/test/SemaCXX/uninitialized.cpp
index 52d9897cf9be6e..7578b288d7b3fe 100644
--- a/clang/test/SemaCXX/uninitialized.cpp
+++ b/clang/test/SemaCXX/uninitialized.cpp
@@ -2,6 +2,8 @@
 // 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
 
+void* operator new(__SIZE_TYPE__, void*);
+
 // definitions for std::move
 namespace std {
 inline namespace foo {
@@ -1540,6 +1542,48 @@ void aggregate() {
     };
   };
 
+  struct Embed {
+    int embed1;  // #FIELD_EMBED1
+    int embed2 [[clang::require_explicit_initialization]];  // #FIELD_EMBED2
+  };
+  struct EmbedDerived : Embed {};
+  struct F {
+    Embed f1;
+    // expected-warning@+1 {{field in 'Embed' requires explicit initialization but is not explicitly initialized}} expected-note@#FIELD_EMBED2 {{'embed2' declared here}}
+    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)();
+#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);
+#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};
+    }
+#if __cplusplus >= 202002L
+    // expected-warning@+1 {{field 'embed2' requires explicit initialization but is not explicitly initialized}} expected-note@#FIELD_EMBED2 {{'embed2' declared here}}
+    explicit F(const char(&)[2]) : f1(1) {}
+#else
+    explicit F(const char(&)[2]) : f1{1, 2} { }
+#endif
+    // expected-warning@+1 {{field 'embed2' requires explicit initialization but is not explicitly initialized}} expected-note@#FIELD_EMBED2 {{'embed2' declared here}}
+    explicit F(const char(&)[3]) : f1{} {}
+    // expected-warning@+1 {{field 'embed2' requires explicit initialization but is not explicitly initialized}} expected-note@#FIELD_EMBED2 {{'embed2' declared here}}
+    explicit F(const char(&)[4]) : f1{1} {}
+    // expected-warning@+1 {{field 'embed2' requires explicit initialization but is not explicitly initialized}} expected-note@#FIELD_EMBED2 {{'embed2' declared here}}
+    explicit F(const char(&)[5]) : f1{.embed1 = 1} {}
+  };
+  F ctors[] = {
+      F(""),
+      F("_"),
+      F("__"),
+      F("___"),
+      F("____")
+  };
+  (void)ctors;
+
   S::foo(S{1, 2, 3, 4});
   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}}

@higher-performance
Copy link
Contributor Author

@AaronBallman Could we get this into the 20.x release before branching? (Sorry for the last-minute PR, I just noticed the bug.)

@higher-performance
Copy link
Contributor Author

Note the build error appears unrelated:

# | /var/lib/buildkite-agent/builds/linux-56-59b8f5d88-gwhg7-1/llvm-project/github-pull-requests/build-runtimes/libcxxabi/test-suite-install/include/c++/v1/__chrono/utc_clock.h:94:11: error: unknown type name 'tzdb'
# |    94 |     const tzdb& __tzdb = chrono::get_tzdb();
# |       |           ^

@higher-performance
Copy link
Contributor Author

@AaronBallman just a bump (hope the branch isn't cut yet) :)

Copy link
Collaborator

@AaronBallman AaronBallman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the delayed review, this fell off my radar this week! :-/

Changes LGTM! The release branch did get cut, so this would need to be backported (https://releases.llvm.org/19.1.0/docs/GitHub.html#backporting-fixes-to-the-release-branches).

@erichkeane
Copy link
Collaborator

It turns out we weren't handling one case: the value-initialization of a field inside a struct.

I'm not sure why this falls under IK_Direct rather than IK_Value in Clang, but it seems to work.

Looks like (according to item 6 here) https://en.cppreference.com/w/cpp/language/direct_initialization

That member init is always 'direct' initialization.

@higher-performance
Copy link
Contributor Author

Sorry for the delayed review, this fell off my radar this week! :-/

Changes LGTM! The release branch did get cut, so this would need to be backported (https://releases.llvm.org/19.1.0/docs/GitHub.html#backporting-fixes-to-the-release-branches).

Ah okay no worries, thanks! So I guess you'll need to merge this into mainline and then I can make a PR to backport it?

@AaronBallman AaronBallman merged commit 20fd7df into llvm:main Jan 30, 2025
3 of 5 checks passed
@AaronBallman
Copy link
Collaborator

Sorry for the delayed review, this fell off my radar this week! :-/
Changes LGTM! The release branch did get cut, so this would need to be backported (https://releases.llvm.org/19.1.0/docs/GitHub.html#backporting-fixes-to-the-release-branches).

Ah okay no worries, thanks! So I guess you'll need to merge this into mainline and then I can make a PR to backport it?

Yup! I was just waiting on Erich for a second set of eyes on the changes before I landed, but it's pushed now.

@llvm-ci
Copy link
Collaborator

llvm-ci commented Jan 30, 2025

LLVM Buildbot has detected a new failure on builder flang-aarch64-dylib running on linaro-flang-aarch64-dylib while building clang at step 5 "build-unified-tree".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/50/builds/9651

Here is the relevant piece of the build log for the reference
Step 5 (build-unified-tree) failure: build (failure)
...
560.046 [1285/1/5514] Building CXX object tools/mlir/lib/Target/LLVMIR/Dialect/NVVM/CMakeFiles/obj.MLIRNVVMToLLVMIRTranslation.dir/NVVMToLLVMIRTranslation.cpp.o
560.166 [1284/1/5515] Building CXX object tools/mlir/lib/Target/LLVMIR/Dialect/ROCDL/CMakeFiles/obj.MLIRROCDLToLLVMIRTranslation.dir/ROCDLToLLVMIRTranslation.cpp.o
560.345 [1283/1/5516] Building CXX object tools/mlir/lib/Target/LLVMIR/Dialect/OpenMP/CMakeFiles/obj.MLIROpenMPToLLVMIRTranslation.dir/OpenMPToLLVMIRTranslation.cpp.o
560.478 [1282/1/5517] Building CXX object tools/mlir/lib/Target/LLVM/CMakeFiles/obj.MLIRTargetLLVM.dir/ModuleToObject.cpp.o
560.653 [1281/1/5518] Building CXX object tools/mlir/lib/Target/LLVM/CMakeFiles/obj.MLIRNVVMTarget.dir/NVVM/Target.cpp.o
560.784 [1280/1/5519] Building CXX object tools/mlir/lib/Target/LLVMIR/Dialect/VCIX/CMakeFiles/obj.MLIRVCIXToLLVMIRTranslation.dir/VCIXToLLVMIRTranslation.cpp.o
560.923 [1279/1/5520] Building CXX object tools/mlir/lib/Target/LLVMIR/Dialect/SPIRV/CMakeFiles/obj.MLIRSPIRVToLLVMIRTranslation.dir/SPIRVToLLVMIRTranslation.cpp.o
561.110 [1278/1/5521] Building CXX object tools/mlir/test/lib/Dialect/Linalg/CMakeFiles/MLIRLinalgTestPasses.dir/TestPadFusion.cpp.o
561.227 [1277/1/5522] Building CXX object tools/mlir/test/lib/IR/CMakeFiles/MLIRTestIR.dir/TestSlicing.cpp.o
575.778 [1276/1/5523] Building CXX object tools/mlir/test/lib/IR/CMakeFiles/MLIRTestIR.dir/TestSymbolUses.cpp.o
FAILED: tools/mlir/test/lib/IR/CMakeFiles/MLIRTestIR.dir/TestSymbolUses.cpp.o 
/usr/local/bin/c++ -DGTEST_HAS_RTTI=0 -DMLIR_INCLUDE_TESTS -D_DEBUG -D_GLIBCXX_ASSERTIONS -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -I/home/tcwg-buildbot/worker/flang-aarch64-dylib/build/tools/mlir/test/lib/IR -I/home/tcwg-buildbot/worker/flang-aarch64-dylib/llvm-project/mlir/test/lib/IR -I/home/tcwg-buildbot/worker/flang-aarch64-dylib/build/tools/mlir/include -I/home/tcwg-buildbot/worker/flang-aarch64-dylib/llvm-project/mlir/include -I/home/tcwg-buildbot/worker/flang-aarch64-dylib/build/include -I/home/tcwg-buildbot/worker/flang-aarch64-dylib/llvm-project/llvm/include -I/home/tcwg-buildbot/worker/flang-aarch64-dylib/llvm-project/mlir/test/lib/IR/../Dialect/Test -I/home/tcwg-buildbot/worker/flang-aarch64-dylib/build/tools/mlir/test/lib/IR/../Dialect/Test -fPIC -fno-semantic-interposition -fvisibility-inlines-hidden -Werror=date-time -Werror=unguarded-availability-new -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wmissing-field-initializers -pedantic -Wno-long-long -Wc++98-compat-extra-semi -Wimplicit-fallthrough -Wcovered-switch-default -Wno-noexcept-type -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -Wsuggest-override -Wstring-conversion -Wmisleading-indentation -Wctad-maybe-unsupported -fdiagnostics-color -ffunction-sections -fdata-sections -Wundef -Werror=mismatched-tags -O3 -DNDEBUG -std=c++17  -fno-exceptions -funwind-tables -fno-rtti -UNDEBUG -MD -MT tools/mlir/test/lib/IR/CMakeFiles/MLIRTestIR.dir/TestSymbolUses.cpp.o -MF tools/mlir/test/lib/IR/CMakeFiles/MLIRTestIR.dir/TestSymbolUses.cpp.o.d -o tools/mlir/test/lib/IR/CMakeFiles/MLIRTestIR.dir/TestSymbolUses.cpp.o -c /home/tcwg-buildbot/worker/flang-aarch64-dylib/llvm-project/mlir/test/lib/IR/TestSymbolUses.cpp
In file included from /home/tcwg-buildbot/worker/flang-aarch64-dylib/llvm-project/mlir/test/lib/IR/TestSymbolUses.cpp:9:
/home/tcwg-buildbot/worker/flang-aarch64-dylib/llvm-project/mlir/test/lib/IR/../Dialect/Test/TestOps.h:148:10: fatal error: 'TestOps.h.inc' file not found
  148 | #include "TestOps.h.inc"
      |          ^~~~~~~~~~~~~~~
1 error generated.
ninja: build stopped: subcommand failed.

@higher-performance
Copy link
Contributor Author

this would need to be backported (https://releases.llvm.org/19.1.0/docs/GitHub.html#backporting-fixes-to-the-release-branches).

Oh, @AaronBallman - would you mind adding this as a milestone so I can /cherry-pick here?

@llvmbot
Copy link
Member

llvmbot commented Jan 30, 2025

this would need to be backported (https://releases.llvm.org/19.1.0/docs/GitHub.html#backporting-fixes-to-the-release-branches).

Oh, @AaronBallman - would you mind adding this as a milestone so I can /cherry-pick here?

Error: Command failed due to missing milestone.

@AaronBallman
Copy link
Collaborator

There we go, added the right milestone this time. :-)

@higher-performance
Copy link
Contributor Author

/cherry-pick 20fd7df

@higher-performance higher-performance deleted the required-fields branch January 31, 2025 16:44
@llvmbot
Copy link
Member

llvmbot commented Jan 31, 2025

/pull-request #125249

swift-ci pushed a commit to swiftlang/llvm-project that referenced this pull request Feb 1, 2025
…lang::require_field_initialization]] (llvm#124329)

It turns out we weren't handling one case: the value-initialization of a
field inside a struct.

I'm not sure why this falls under `IK_Direct` rather than `IK_Value` in
Clang, but it seems to work.

(cherry picked from commit 20fd7df)
@alexfh
Copy link
Contributor

alexfh commented Feb 10, 2025

It looks like this commit introduces an undesired false-positive: https://gcc.godbolt.org/z/rEjzK63he

struct P {
  int a [[clang::require_explicit_initialization]];
};

struct S {
  P p;
  S(P p) : p(p) {}
};
<source>:7:12: warning: field in 'P' requires explicit initialization but is not explicitly initialized [-Wuninitialized-explicit-init]
    7 |   S(P p) : p(p) {}
      |            ^
<source>:2:7: note: 'a' declared here
    2 |   int a [[clang::require_explicit_initialization]];
      |       ^

I don't think it's helpful to warn about not explicitly initializing a field on copy or move.

Another example: https://gcc.godbolt.org/z/con9dTrPb

Please fix or revert (unless this indeed intended, which I hope is not the case).

@higher-performance
Copy link
Contributor Author

Thanks! This was reported in #126490, we'll track it there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category

Projects

Development

Successfully merging this pull request may close these issues.

6 participants