[PATCH] D152548: [Clang][Interp] Diagnose uninitialized ctor of global record arrays

2023-06-21 Thread Takuya Shimizu via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rGdfb85c3ce09a: [Clang][Interp] Diagnose uninitialized ctor of 
global record arrays (authored by hazohelet).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D152548/new/

https://reviews.llvm.org/D152548

Files:
  clang/lib/AST/Interp/ByteCodeExprGen.h
  clang/lib/AST/Interp/Interp.cpp
  clang/test/AST/Interp/cxx20.cpp


Index: clang/test/AST/Interp/cxx20.cpp
===
--- clang/test/AST/Interp/cxx20.cpp
+++ clang/test/AST/Interp/cxx20.cpp
@@ -138,14 +138,43 @@
 namespace UninitializedFields {
   class A {
   public:
-int a; // expected-note 3{{subobject declared here}} \
-   // ref-note 3{{subobject declared here}}
+int a; // expected-note 4{{subobject declared here}} \
+   // ref-note 4{{subobject declared here}}
 constexpr A() {}
   };
   constexpr A a; // expected-error {{must be initialized by a constant 
expression}} \
  // expected-note {{subobject 'a' is not initialized}} \
  // ref-error {{must be initialized by a constant expression}} 
\
  // ref-note {{subobject 'a' is not initialized}}
+  constexpr A aarr[2]; // expected-error {{must be initialized by a constant 
expression}} \
+   // expected-note {{subobject 'a' is not initialized}} \
+   // ref-error {{must be initialized by a constant 
expression}} \
+   // ref-note {{subobject 'a' is not initialized}}
+  class F {
+public:
+  int f; // expected-note 3{{subobject declared here}} \
+ // ref-note 3{{subobject declared here}}
+
+  constexpr F() {}
+  constexpr F(bool b) {
+if (b)
+  f = 42;
+  }
+  };
+
+  constexpr F foo[2] = {true}; // expected-error {{must be initialized by a 
constant expression}} \
+   // expected-note {{subobject 'f' is not 
initialized}} \
+   // ref-error {{must be initialized by a 
constant expression}} \
+   // ref-note {{subobject 'f' is not initialized}}
+  constexpr F foo2[3] = {true, false, true}; // expected-error {{must be 
initialized by a constant expression}} \
+ // expected-note {{subobject 'f' 
is not initialized}} \
+ // ref-error {{must be 
initialized by a constant expression}} \
+ // ref-note {{subobject 'f' is 
not initialized}}
+  constexpr F foo3[3] = {true, true, F()}; // expected-error {{must be 
initialized by a constant expression}} \
+   // expected-note {{subobject 'f' is 
not initialized}} \
+   // ref-error {{must be initialized 
by a constant expression}} \
+   // ref-note {{subobject 'f' is not 
initialized}}
+
 
 
   class Base {
Index: clang/lib/AST/Interp/Interp.cpp
===
--- clang/lib/AST/Interp/Interp.cpp
+++ clang/lib/AST/Interp/Interp.cpp
@@ -456,8 +456,11 @@
 
 bool CheckCtorCall(InterpState , CodePtr OpPC, const Pointer ) {
   assert(!This.isZero());
-  const Record *R = This.getRecord();
-  return CheckFieldsInitialized(S, OpPC, This, R);
+  if (const Record *R = This.getRecord())
+return CheckFieldsInitialized(S, OpPC, This, R);
+  const auto *CAT =
+  cast(This.getType()->getAsArrayTypeUnsafe());
+  return CheckArrayInitialized(S, OpPC, This, CAT);
 }
 
 bool CheckFloatResult(InterpState , CodePtr OpPC, APFloat::opStatus Status) {
Index: clang/lib/AST/Interp/ByteCodeExprGen.h
===
--- clang/lib/AST/Interp/ByteCodeExprGen.h
+++ clang/lib/AST/Interp/ByteCodeExprGen.h
@@ -166,7 +166,8 @@
 if (!visitInitializer(Init))
   return false;
 
-if (Init->getType()->isRecordType() && !this->emitCheckGlobalCtor(Init))
+if ((Init->getType()->isArrayType() || Init->getType()->isRecordType()) &&
+!this->emitCheckGlobalCtor(Init))
   return false;
 
 return this->emitPopPtr(Init);


Index: clang/test/AST/Interp/cxx20.cpp
===
--- clang/test/AST/Interp/cxx20.cpp
+++ clang/test/AST/Interp/cxx20.cpp
@@ -138,14 +138,43 @@
 namespace UninitializedFields {
   class A {
   public:
-int a; // expected-note 3{{subobject declared here}} \
-   // ref-note 3{{subobject declared here}}
+int a; // expected-note 4{{subobject declared here}} \
+   // ref-note 4{{subobject declared here}}
 constexpr A() {}
   };
   constexpr A a; // expected-error {{must be initialized by a constant expression}} \
  // expected-note {{subobject 'a' is not 

[PATCH] D152548: [Clang][Interp] Diagnose uninitialized ctor of global record arrays

2023-06-19 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder accepted this revision.
tbaeder added a comment.
This revision is now accepted and ready to land.

LGTM


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D152548/new/

https://reviews.llvm.org/D152548

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D152548: [Clang][Interp] Diagnose uninitialized ctor of global record arrays

2023-06-19 Thread Takuya Shimizu via Phabricator via cfe-commits
hazohelet updated this revision to Diff 532554.
hazohelet marked an inline comment as done.
hazohelet added a comment.

Address comment from @tbaeder

- NFC stylistic change in test


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D152548/new/

https://reviews.llvm.org/D152548

Files:
  clang/lib/AST/Interp/ByteCodeExprGen.h
  clang/lib/AST/Interp/Interp.cpp
  clang/test/AST/Interp/cxx20.cpp


Index: clang/test/AST/Interp/cxx20.cpp
===
--- clang/test/AST/Interp/cxx20.cpp
+++ clang/test/AST/Interp/cxx20.cpp
@@ -138,14 +138,43 @@
 namespace UninitializedFields {
   class A {
   public:
-int a; // expected-note 3{{subobject declared here}} \
-   // ref-note 3{{subobject declared here}}
+int a; // expected-note 4{{subobject declared here}} \
+   // ref-note 4{{subobject declared here}}
 constexpr A() {}
   };
   constexpr A a; // expected-error {{must be initialized by a constant 
expression}} \
  // expected-note {{subobject 'a' is not initialized}} \
  // ref-error {{must be initialized by a constant expression}} 
\
  // ref-note {{subobject 'a' is not initialized}}
+  constexpr A aarr[2]; // expected-error {{must be initialized by a constant 
expression}} \
+   // expected-note {{subobject 'a' is not initialized}} \
+   // ref-error {{must be initialized by a constant 
expression}} \
+   // ref-note {{subobject 'a' is not initialized}}
+  class F {
+public:
+  int f; // expected-note 3{{subobject declared here}} \
+ // ref-note 3{{subobject declared here}}
+
+  constexpr F() {}
+  constexpr F(bool b) {
+if (b)
+  f = 42;
+  }
+  };
+
+  constexpr F foo[2] = {true}; // expected-error {{must be initialized by a 
constant expression}} \
+   // expected-note {{subobject 'f' is not 
initialized}} \
+   // ref-error {{must be initialized by a 
constant expression}} \
+   // ref-note {{subobject 'f' is not initialized}}
+  constexpr F foo2[3] = {true, false, true}; // expected-error {{must be 
initialized by a constant expression}} \
+ // expected-note {{subobject 'f' 
is not initialized}} \
+ // ref-error {{must be 
initialized by a constant expression}} \
+ // ref-note {{subobject 'f' is 
not initialized}}
+  constexpr F foo3[3] = {true, true, F()}; // expected-error {{must be 
initialized by a constant expression}} \
+   // expected-note {{subobject 'f' is 
not initialized}} \
+   // ref-error {{must be initialized 
by a constant expression}} \
+   // ref-note {{subobject 'f' is not 
initialized}}
+
 
 
   class Base {
Index: clang/lib/AST/Interp/Interp.cpp
===
--- clang/lib/AST/Interp/Interp.cpp
+++ clang/lib/AST/Interp/Interp.cpp
@@ -456,8 +456,11 @@
 
 bool CheckCtorCall(InterpState , CodePtr OpPC, const Pointer ) {
   assert(!This.isZero());
-  const Record *R = This.getRecord();
-  return CheckFieldsInitialized(S, OpPC, This, R);
+  if (const Record *R = This.getRecord())
+return CheckFieldsInitialized(S, OpPC, This, R);
+  const auto *CAT =
+  cast(This.getType()->getAsArrayTypeUnsafe());
+  return CheckArrayInitialized(S, OpPC, This, CAT);
 }
 
 bool CheckFloatResult(InterpState , CodePtr OpPC, APFloat::opStatus Status) {
Index: clang/lib/AST/Interp/ByteCodeExprGen.h
===
--- clang/lib/AST/Interp/ByteCodeExprGen.h
+++ clang/lib/AST/Interp/ByteCodeExprGen.h
@@ -166,7 +166,8 @@
 if (!visitInitializer(Init))
   return false;
 
-if (Init->getType()->isRecordType() && !this->emitCheckGlobalCtor(Init))
+if ((Init->getType()->isArrayType() || Init->getType()->isRecordType()) &&
+!this->emitCheckGlobalCtor(Init))
   return false;
 
 return this->emitPopPtr(Init);


Index: clang/test/AST/Interp/cxx20.cpp
===
--- clang/test/AST/Interp/cxx20.cpp
+++ clang/test/AST/Interp/cxx20.cpp
@@ -138,14 +138,43 @@
 namespace UninitializedFields {
   class A {
   public:
-int a; // expected-note 3{{subobject declared here}} \
-   // ref-note 3{{subobject declared here}}
+int a; // expected-note 4{{subobject declared here}} \
+   // ref-note 4{{subobject declared here}}
 constexpr A() {}
   };
   constexpr A a; // expected-error {{must be initialized by a constant expression}} \
  // expected-note {{subobject 'a' is not initialized}} \
  // ref-error {{must be 

[PATCH] D152548: [Clang][Interp] Diagnose uninitialized ctor of global record arrays

2023-06-15 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added inline comments.



Comment at: clang/test/AST/Interp/cxx20.cpp:177
+ // ref-note {{subobject 'f' is not initialized}}
+
 

We usually have a space after the `;` and keep the comments aligned on the `//`.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D152548/new/

https://reviews.llvm.org/D152548

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D152548: [Clang][Interp] Diagnose uninitialized ctor of global record arrays

2023-06-09 Thread Takuya Shimizu via Phabricator via cfe-commits
hazohelet created this revision.
hazohelet added reviewers: aaron.ballman, tbaeder, shafik.
Herald added a project: All.
hazohelet requested review of this revision.
Herald added a project: clang.

This patch adds a check for uninitialized subobjects of global variables that 
are record arrays.
e.g. `constexpr Foo f[2];`


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D152548

Files:
  clang/lib/AST/Interp/ByteCodeExprGen.h
  clang/lib/AST/Interp/Interp.cpp
  clang/test/AST/Interp/cxx20.cpp


Index: clang/test/AST/Interp/cxx20.cpp
===
--- clang/test/AST/Interp/cxx20.cpp
+++ clang/test/AST/Interp/cxx20.cpp
@@ -138,14 +138,43 @@
 namespace UninitializedFields {
   class A {
   public:
-int a; // expected-note 3{{subobject declared here}} \
-   // ref-note 3{{subobject declared here}}
+int a; // expected-note 4{{subobject declared here}} \
+   // ref-note 4{{subobject declared here}}
 constexpr A() {}
   };
   constexpr A a; // expected-error {{must be initialized by a constant 
expression}} \
  // expected-note {{subobject 'a' is not initialized}} \
  // ref-error {{must be initialized by a constant expression}} 
\
  // ref-note {{subobject 'a' is not initialized}}
+  constexpr A aarr[2]; // expected-error {{must be initialized by a constant 
expression}} \
+   // expected-note {{subobject 'a' is not initialized}} \
+   // ref-error {{must be initialized by a constant 
expression}} \
+   // ref-note {{subobject 'a' is not initialized}}
+  class F {
+public:
+  int f;// expected-note 3{{subobject declared here}} \
+// ref-note 3{{subobject declared here}}
+
+  constexpr F() {}
+  constexpr F(bool b) {
+if (b)
+  f = 42;
+  }
+  };
+
+  constexpr F foo[2] = {true};// expected-error {{must be initialized by a 
constant expression}} \
+ // expected-note {{subobject 'f' is not initialized}} \
+ // ref-error {{must be initialized by a constant 
expression}} \
+ // ref-note {{subobject 'f' is not initialized}}
+  constexpr F foo2[3] = {true, false, true};// expected-error {{must be 
initialized by a constant expression}} \
+ // expected-note {{subobject 'f' is not initialized}} \
+ // ref-error {{must be initialized by a constant 
expression}} \
+ // ref-note {{subobject 'f' is not initialized}}
+  constexpr F foo3[3] = {true, true, F()};// expected-error {{must be 
initialized by a constant expression}} \
+ // expected-note {{subobject 'f' is not initialized}} \
+ // ref-error {{must be initialized by a constant 
expression}} \
+ // ref-note {{subobject 'f' is not initialized}}
+
 
 
   class Base {
Index: clang/lib/AST/Interp/Interp.cpp
===
--- clang/lib/AST/Interp/Interp.cpp
+++ clang/lib/AST/Interp/Interp.cpp
@@ -455,8 +455,11 @@
 
 bool CheckCtorCall(InterpState , CodePtr OpPC, const Pointer ) {
   assert(!This.isZero());
-  const Record *R = This.getRecord();
-  return CheckFieldsInitialized(S, OpPC, This, R);
+  if (const Record *R = This.getRecord())
+return CheckFieldsInitialized(S, OpPC, This, R);
+  const auto *CAT =
+  cast(This.getType()->getAsArrayTypeUnsafe());
+  return CheckArrayInitialized(S, OpPC, This, CAT);
 }
 
 bool CheckFloatResult(InterpState , CodePtr OpPC, APFloat::opStatus Status) {
Index: clang/lib/AST/Interp/ByteCodeExprGen.h
===
--- clang/lib/AST/Interp/ByteCodeExprGen.h
+++ clang/lib/AST/Interp/ByteCodeExprGen.h
@@ -164,7 +164,8 @@
 if (!visitInitializer(Init))
   return false;
 
-if (Init->getType()->isRecordType() && !this->emitCheckGlobalCtor(Init))
+if ((Init->getType()->isArrayType() || Init->getType()->isRecordType()) &&
+!this->emitCheckGlobalCtor(Init))
   return false;
 
 return this->emitPopPtr(Init);


Index: clang/test/AST/Interp/cxx20.cpp
===
--- clang/test/AST/Interp/cxx20.cpp
+++ clang/test/AST/Interp/cxx20.cpp
@@ -138,14 +138,43 @@
 namespace UninitializedFields {
   class A {
   public:
-int a; // expected-note 3{{subobject declared here}} \
-   // ref-note 3{{subobject declared here}}
+int a; // expected-note 4{{subobject declared here}} \
+   // ref-note 4{{subobject declared here}}
 constexpr A() {}
   };
   constexpr A a; // expected-error {{must be initialized by a constant expression}} \
  // expected-note {{subobject 'a' is not initialized}} \
  // ref-error {{must be initialized by a constant expression}} \
  //