[clang] [Clang] Ensure zero-init is not overridden when initializing a base class in a constant expression context (PR #70150)

2023-10-25 Thread Shafik Yaghmour via cfe-commits

https://github.com/shafik closed https://github.com/llvm/llvm-project/pull/70150
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Ensure zero-init is not overridden when initializing a base class in a constant expression context (PR #70150)

2023-10-25 Thread Shafik Yaghmour via cfe-commits

shafik wrote:

The clang-format error is a false positive.

https://github.com/llvm/llvm-project/pull/70150
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Ensure zero-init is not overridden when initializing a base class in a constant expression context (PR #70150)

2023-10-24 Thread Richard Smith via cfe-commits

https://github.com/zygoloid approved this pull request.


https://github.com/llvm/llvm-project/pull/70150
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Ensure zero-init is not overridden when initializing a base class in a constant expression context (PR #70150)

2023-10-24 Thread Shafik Yaghmour via cfe-commits

https://github.com/shafik updated 
https://github.com/llvm/llvm-project/pull/70150

>From 1e7ec004102349a67519966bb7111838668ab2b4 Mon Sep 17 00:00:00 2001
From: Shafik Yaghmour 
Date: Tue, 24 Oct 2023 16:21:30 -0700
Subject: [PATCH] [Clang] Ensure zero-init is not overridden when intializing a
 base class in a constant expression context

During constant evaluation when value-initializing a class if the base class
was default-initialized it would undue the previously zero-initialized class
members. This fixes the way we handle default initialzation to avoid
initializing over an already initialized member to an indeterminate value.

Fixes: https://github.com/llvm/llvm-project/issues/69890
---
 clang/docs/ReleaseNotes.rst   |  4 +++
 clang/lib/AST/ExprConstant.cpp| 33 +++
 clang/test/AST/Interp/records.cpp |  7 ++--
 .../dcl.init/dcl.init.general/p16-cxx20.cpp   | 18 ++
 4 files changed, 44 insertions(+), 18 deletions(-)
 create mode 100644 
clang/test/CXX/dcl.decl/dcl.init/dcl.init.general/p16-cxx20.cpp

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index a063733e96cb74c..ae2f082ad323a78 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -622,6 +622,10 @@ Bug Fixes to C++ Support
   (`#46200 `_)
   (`#57812 `_)
 
+- Fix bug where we were overriding zero-initialization of class members when
+  default initializing a base class in a constant expression context. Fixes:
+  (`#69890 `_)
+
 Bug Fixes to AST Handling
 ^
 - Fixed an import failure of recursive friend class template.
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 6b47b8a1256477d..eea0827d6f7a8a1 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -4872,8 +4872,13 @@ static bool HandleBaseToDerivedCast(EvalInfo &Info, 
const CastExpr *E,
 
 /// Get the value to use for a default-initialized object of type T.
 /// Return false if it encounters something invalid.
-static bool getDefaultInitValue(QualType T, APValue &Result) {
+static bool handleDefaultInitValue(QualType T, APValue &Result) {
   bool Success = true;
+
+  // If there is already a value present don't overwrite it.
+  if (!Result.isAbsent())
+return true;
+
   if (auto *RD = T->getAsCXXRecordDecl()) {
 if (RD->isInvalidDecl()) {
   Result = APValue();
@@ -4890,13 +4895,14 @@ static bool getDefaultInitValue(QualType T, APValue 
&Result) {
 for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
   End = RD->bases_end();
  I != End; ++I, ++Index)
-  Success &= getDefaultInitValue(I->getType(), 
Result.getStructBase(Index));
+  Success &=
+  handleDefaultInitValue(I->getType(), Result.getStructBase(Index));
 
 for (const auto *I : RD->fields()) {
   if (I->isUnnamedBitfield())
 continue;
-  Success &= getDefaultInitValue(I->getType(),
- 
Result.getStructField(I->getFieldIndex()));
+  Success &= handleDefaultInitValue(
+  I->getType(), Result.getStructField(I->getFieldIndex()));
 }
 return Success;
   }
@@ -4906,7 +4912,7 @@ static bool getDefaultInitValue(QualType T, APValue 
&Result) {
 Result = APValue(APValue::UninitArray(), 0, AT->getSize().getZExtValue());
 if (Result.hasArrayFiller())
   Success &=
-  getDefaultInitValue(AT->getElementType(), Result.getArrayFiller());
+  handleDefaultInitValue(AT->getElementType(), 
Result.getArrayFiller());
 
 return Success;
   }
@@ -4947,7 +4953,7 @@ static bool EvaluateVarDecl(EvalInfo &Info, const VarDecl 
*VD) {
   if (!InitE) {
 if (VD->getType()->isDependentType())
   return Info.noteSideEffect();
-return getDefaultInitValue(VD->getType(), Val);
+return handleDefaultInitValue(VD->getType(), Val);
   }
   if (InitE->isValueDependent())
 return false;
@@ -6049,7 +6055,7 @@ struct StartLifetimeOfUnionMemberHandler {
   return false;
 }
 APValue Result;
-Failed = !getDefaultInitValue(Field->getType(), Result);
+Failed = !handleDefaultInitValue(Field->getType(), Result);
 Subobj.setUnion(Field, Result);
 return true;
   }
@@ -6401,7 +6407,7 @@ static bool HandleConstructorCall(const Expr *E, const 
LValue &This,
 for (; !declaresSameEntity(*FieldIt, FD); ++FieldIt) {
   assert(FieldIt != RD->field_end() && "missing field?");
   if (!FieldIt->isUnnamedBitfield())
-Success &= getDefaultInitValue(
+Success &= handleDefaultInitValue(
 FieldIt->getType(),
 Result.getStructField(FieldIt->getFieldIndex()));
 }
@@ -6458,7 +6464,8 @@ static bool HandleConstructorCall(const Expr *E, const 
LVa

[clang] [Clang] Ensure zero-init is not overridden when initializing a base class in a constant expression context (PR #70150)

2023-10-24 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-clang

Author: Shafik Yaghmour (shafik)


Changes

During constant evaluation when value-initializing a class if the base class 
was default-initialized it would undue the previously zero-initialized class 
members. This fixes the way we handle default initialization to avoid 
initializing over an already initialized member to an indeterminate value.

Fixes: https://github.com/llvm/llvm-project/issues/69890

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


3 Files Affected:

- (modified) clang/docs/ReleaseNotes.rst (+4) 
- (modified) clang/lib/AST/ExprConstant.cpp (+20-13) 
- (added) clang/test/CXX/dcl.decl/dcl.init/dcl.init.general/p16-cxx20.cpp (+18) 


``diff
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index a063733e96cb74c..ae2f082ad323a78 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -622,6 +622,10 @@ Bug Fixes to C++ Support
   (`#46200 `_)
   (`#57812 `_)
 
+- Fix bug where we were overriding zero-initialization of class members when
+  default initializing a base class in a constant expression context. Fixes:
+  (`#69890 `_)
+
 Bug Fixes to AST Handling
 ^
 - Fixed an import failure of recursive friend class template.
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 6b47b8a1256477d..eea0827d6f7a8a1 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -4872,8 +4872,13 @@ static bool HandleBaseToDerivedCast(EvalInfo &Info, 
const CastExpr *E,
 
 /// Get the value to use for a default-initialized object of type T.
 /// Return false if it encounters something invalid.
-static bool getDefaultInitValue(QualType T, APValue &Result) {
+static bool handleDefaultInitValue(QualType T, APValue &Result) {
   bool Success = true;
+
+  // If there is already a value present don't overwrite it.
+  if (!Result.isAbsent())
+return true;
+
   if (auto *RD = T->getAsCXXRecordDecl()) {
 if (RD->isInvalidDecl()) {
   Result = APValue();
@@ -4890,13 +4895,14 @@ static bool getDefaultInitValue(QualType T, APValue 
&Result) {
 for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
   End = RD->bases_end();
  I != End; ++I, ++Index)
-  Success &= getDefaultInitValue(I->getType(), 
Result.getStructBase(Index));
+  Success &=
+  handleDefaultInitValue(I->getType(), Result.getStructBase(Index));
 
 for (const auto *I : RD->fields()) {
   if (I->isUnnamedBitfield())
 continue;
-  Success &= getDefaultInitValue(I->getType(),
- 
Result.getStructField(I->getFieldIndex()));
+  Success &= handleDefaultInitValue(
+  I->getType(), Result.getStructField(I->getFieldIndex()));
 }
 return Success;
   }
@@ -4906,7 +4912,7 @@ static bool getDefaultInitValue(QualType T, APValue 
&Result) {
 Result = APValue(APValue::UninitArray(), 0, AT->getSize().getZExtValue());
 if (Result.hasArrayFiller())
   Success &=
-  getDefaultInitValue(AT->getElementType(), Result.getArrayFiller());
+  handleDefaultInitValue(AT->getElementType(), 
Result.getArrayFiller());
 
 return Success;
   }
@@ -4947,7 +4953,7 @@ static bool EvaluateVarDecl(EvalInfo &Info, const VarDecl 
*VD) {
   if (!InitE) {
 if (VD->getType()->isDependentType())
   return Info.noteSideEffect();
-return getDefaultInitValue(VD->getType(), Val);
+return handleDefaultInitValue(VD->getType(), Val);
   }
   if (InitE->isValueDependent())
 return false;
@@ -6049,7 +6055,7 @@ struct StartLifetimeOfUnionMemberHandler {
   return false;
 }
 APValue Result;
-Failed = !getDefaultInitValue(Field->getType(), Result);
+Failed = !handleDefaultInitValue(Field->getType(), Result);
 Subobj.setUnion(Field, Result);
 return true;
   }
@@ -6401,7 +6407,7 @@ static bool HandleConstructorCall(const Expr *E, const 
LValue &This,
 for (; !declaresSameEntity(*FieldIt, FD); ++FieldIt) {
   assert(FieldIt != RD->field_end() && "missing field?");
   if (!FieldIt->isUnnamedBitfield())
-Success &= getDefaultInitValue(
+Success &= handleDefaultInitValue(
 FieldIt->getType(),
 Result.getStructField(FieldIt->getFieldIndex()));
 }
@@ -6458,7 +6464,8 @@ static bool HandleConstructorCall(const Expr *E, const 
LValue &This,
 // FIXME: This immediately starts the lifetime of all members of
 // an anonymous struct. It would be preferable to strictly start
 // member lifetime in initialization order.
-Success &= getDefaultInitValue(Info.Ctx.getRecordType(CD), *Value);
+Success &=
+ha

[clang] [Clang] Ensure zero-init is not overridden when initializing a base class in a constant expression context (PR #70150)

2023-10-24 Thread Shafik Yaghmour via cfe-commits

https://github.com/shafik created 
https://github.com/llvm/llvm-project/pull/70150

During constant evaluation when value-initializing a class if the base class 
was default-initialized it would undue the previously zero-initialized class 
members. This fixes the way we handle default initialization to avoid 
initializing over an already initialized member to an indeterminate value.

Fixes: https://github.com/llvm/llvm-project/issues/69890

>From 54190bf0805df23037bbe2929282c958d609375f Mon Sep 17 00:00:00 2001
From: Shafik Yaghmour 
Date: Tue, 24 Oct 2023 16:21:30 -0700
Subject: [PATCH] [Clang] Ensure zero-init is not overridden when intializing a
 base class in a constant expression context

During constant evaluation when value-initializing a class if the base class
was default-initialized it would undue the previously zero-initialized class
members. This fixes the way we handle default initialzation to avoid
initializing over an already initialized member to an indeterminate value.

Fixes: https://github.com/llvm/llvm-project/issues/69890
---
 clang/docs/ReleaseNotes.rst   |  4 +++
 clang/lib/AST/ExprConstant.cpp| 33 +++
 .../dcl.init/dcl.init.general/p16-cxx20.cpp   | 18 ++
 3 files changed, 42 insertions(+), 13 deletions(-)
 create mode 100644 
clang/test/CXX/dcl.decl/dcl.init/dcl.init.general/p16-cxx20.cpp

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index a063733e96cb74c..ae2f082ad323a78 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -622,6 +622,10 @@ Bug Fixes to C++ Support
   (`#46200 `_)
   (`#57812 `_)
 
+- Fix bug where we were overriding zero-initialization of class members when
+  default initializing a base class in a constant expression context. Fixes:
+  (`#69890 `_)
+
 Bug Fixes to AST Handling
 ^
 - Fixed an import failure of recursive friend class template.
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 6b47b8a1256477d..eea0827d6f7a8a1 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -4872,8 +4872,13 @@ static bool HandleBaseToDerivedCast(EvalInfo &Info, 
const CastExpr *E,
 
 /// Get the value to use for a default-initialized object of type T.
 /// Return false if it encounters something invalid.
-static bool getDefaultInitValue(QualType T, APValue &Result) {
+static bool handleDefaultInitValue(QualType T, APValue &Result) {
   bool Success = true;
+
+  // If there is already a value present don't overwrite it.
+  if (!Result.isAbsent())
+return true;
+
   if (auto *RD = T->getAsCXXRecordDecl()) {
 if (RD->isInvalidDecl()) {
   Result = APValue();
@@ -4890,13 +4895,14 @@ static bool getDefaultInitValue(QualType T, APValue 
&Result) {
 for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
   End = RD->bases_end();
  I != End; ++I, ++Index)
-  Success &= getDefaultInitValue(I->getType(), 
Result.getStructBase(Index));
+  Success &=
+  handleDefaultInitValue(I->getType(), Result.getStructBase(Index));
 
 for (const auto *I : RD->fields()) {
   if (I->isUnnamedBitfield())
 continue;
-  Success &= getDefaultInitValue(I->getType(),
- 
Result.getStructField(I->getFieldIndex()));
+  Success &= handleDefaultInitValue(
+  I->getType(), Result.getStructField(I->getFieldIndex()));
 }
 return Success;
   }
@@ -4906,7 +4912,7 @@ static bool getDefaultInitValue(QualType T, APValue 
&Result) {
 Result = APValue(APValue::UninitArray(), 0, AT->getSize().getZExtValue());
 if (Result.hasArrayFiller())
   Success &=
-  getDefaultInitValue(AT->getElementType(), Result.getArrayFiller());
+  handleDefaultInitValue(AT->getElementType(), 
Result.getArrayFiller());
 
 return Success;
   }
@@ -4947,7 +4953,7 @@ static bool EvaluateVarDecl(EvalInfo &Info, const VarDecl 
*VD) {
   if (!InitE) {
 if (VD->getType()->isDependentType())
   return Info.noteSideEffect();
-return getDefaultInitValue(VD->getType(), Val);
+return handleDefaultInitValue(VD->getType(), Val);
   }
   if (InitE->isValueDependent())
 return false;
@@ -6049,7 +6055,7 @@ struct StartLifetimeOfUnionMemberHandler {
   return false;
 }
 APValue Result;
-Failed = !getDefaultInitValue(Field->getType(), Result);
+Failed = !handleDefaultInitValue(Field->getType(), Result);
 Subobj.setUnion(Field, Result);
 return true;
   }
@@ -6401,7 +6407,7 @@ static bool HandleConstructorCall(const Expr *E, const 
LValue &This,
 for (; !declaresSameEntity(*FieldIt, FD); ++FieldIt) {
   assert(FieldIt != RD->field_end() && "missing field?");