[clang] [clang-tools-extra] [Clang] [Sema] Diagnose unknown std::initializer_list layout in SemaInit (PR #95580)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Jun 14 11:23:42 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-modules
@llvm/pr-subscribers-clang
Author: Mital Ashok (MitalAshok)
<details>
<summary>Changes</summary>
This checks if the layout of `std::initializer_list` is something Clang can handle much earlier and deduplicates the checks in CodeGen/CGExprAgg.cpp and AST/ExprConstant.cpp
Also now diagnose `union initializer_list` (Fixes #<!-- -->95495) and unnamed bit-field for the size (Fixes a crash that would happen during codegen)
---
Patch is 27.79 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/95580.diff
29 Files Affected:
- (modified) clang-tools-extra/clangd/unittests/HoverTests.cpp (+1-1)
- (modified) clang-tools-extra/clangd/unittests/InlayHintTests.cpp (+1-1)
- (modified) clang-tools-extra/test/clang-tidy/checkers/modernize/min-max-use-initializer-list.cpp (+1)
- (modified) clang-tools-extra/test/clang-tidy/checkers/modernize/use-emplace-ignore-implicit-constructors.cpp (+2-1)
- (modified) clang-tools-extra/test/clang-tidy/checkers/modernize/use-emplace.cpp (+2-1)
- (modified) clang-tools-extra/test/clang-tidy/checkers/performance/inefficient-vector-operation.cpp (+3-1)
- (modified) clang-tools-extra/test/clang-tidy/checkers/readability/isolate-declaration-cxx17.cpp (+1-1)
- (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+3)
- (modified) clang/lib/AST/ExprConstant.cpp (+20-31)
- (modified) clang/lib/CodeGen/CGExprAgg.cpp (+18-26)
- (modified) clang/lib/Sema/SemaInit.cpp (+51)
- (modified) clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p4.cpp (+1-1)
- (modified) clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p7-cxx14.cpp (+1-3)
- (modified) clang/test/CodeCompletion/ctor-signature.cpp (+1-1)
- (modified) clang/test/Coverage/unresolved-ctor-expr.cpp (+1-1)
- (modified) clang/test/Modules/Inputs/initializer_list/direct.h (+1-1)
- (modified) clang/test/Modules/pr60775.cppm (+3-2)
- (modified) clang/test/OpenMP/declare_reduction_codegen_in_templates.cpp (+1-1)
- (modified) clang/test/Preprocessor/macro_with_initializer_list.cpp (+1-1)
- (modified) clang/test/SemaCXX/PR20334-std_initializer_list_diagnosis_assertion.cpp (+6-11)
- (modified) clang/test/SemaCXX/auto-invalid-init-crash.cpp (+2-2)
- (modified) clang/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp (+34-5)
- (modified) clang/test/SemaCXX/cxx11-call-to-deleted-constructor.cpp (+1-1)
- (modified) clang/test/SemaCXX/cxx98-compat.cpp (+4-4)
- (modified) clang/test/SemaCXX/invalid-member-expr.cpp (+1-1)
- (modified) clang/test/SemaTemplate/instantiate-init.cpp (+2-2)
- (modified) clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp (+2-2)
- (modified) clang/unittests/Analysis/FlowSensitive/TransferTest.cpp (+1-1)
- (modified) clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp (+1)
``````````diff
diff --git a/clang-tools-extra/clangd/unittests/HoverTests.cpp b/clang-tools-extra/clangd/unittests/HoverTests.cpp
index d9e97e5215a26..8d6d4223d7260 100644
--- a/clang-tools-extra/clangd/unittests/HoverTests.cpp
+++ b/clang-tools-extra/clangd/unittests/HoverTests.cpp
@@ -2284,7 +2284,7 @@ TEST(Hover, All) {
namespace std
{
template<class _E>
- class initializer_list {};
+ class initializer_list { const _E *a, *b; };
}
void foo() {
^[[auto]] i = {1,2};
diff --git a/clang-tools-extra/clangd/unittests/InlayHintTests.cpp b/clang-tools-extra/clangd/unittests/InlayHintTests.cpp
index 5b1531eb2fa60..a5a349e93037a 100644
--- a/clang-tools-extra/clangd/unittests/InlayHintTests.cpp
+++ b/clang-tools-extra/clangd/unittests/InlayHintTests.cpp
@@ -945,7 +945,7 @@ TEST(ParameterHints, ConstructorStdInitList) {
// Do not show hints for std::initializer_list constructors.
assertParameterHints(R"cpp(
namespace std {
- template <typename> class initializer_list {};
+ template <typename E> class initializer_list { const E *a, *b; };
}
struct S {
S(std::initializer_list<int> param);
diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/min-max-use-initializer-list.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/min-max-use-initializer-list.cpp
index 1f2dad2b933ca..c7632fe007a4f 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/modernize/min-max-use-initializer-list.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/min-max-use-initializer-list.cpp
@@ -11,6 +11,7 @@ T max(T a, T b) {
namespace std {
template< class T >
struct initializer_list {
+ const T *a, *b;
initializer_list()=default;
initializer_list(T*,int){}
const T* begin() const {return nullptr;}
diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-emplace-ignore-implicit-constructors.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-emplace-ignore-implicit-constructors.cpp
index 2004993ebde51..150e3ac6494e3 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-emplace-ignore-implicit-constructors.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-emplace-ignore-implicit-constructors.cpp
@@ -4,10 +4,11 @@
// RUN: true}}"
namespace std {
-template <typename>
+template <typename E>
class initializer_list
{
public:
+ const E *a, *b;
initializer_list() noexcept {}
};
diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-emplace.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-emplace.cpp
index f7b1ad55f5df5..3f4a14cd9bb64 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-emplace.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-emplace.cpp
@@ -8,9 +8,10 @@
// RUN: '::std::make_pair; ::std::make_tuple; ::test::MakeSingle'}}"
namespace std {
-template <typename>
+template <typename E>
class initializer_list {
public:
+ const E *a, *b;
initializer_list() noexcept {}
};
diff --git a/clang-tools-extra/test/clang-tidy/checkers/performance/inefficient-vector-operation.cpp b/clang-tools-extra/test/clang-tidy/checkers/performance/inefficient-vector-operation.cpp
index c28592f4d6368..c295f48f89aed 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/performance/inefficient-vector-operation.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/performance/inefficient-vector-operation.cpp
@@ -5,7 +5,7 @@
namespace std {
-typedef int size_t;
+typedef decltype(sizeof 0) size_t;
template<class E> class initializer_list {
public:
@@ -15,6 +15,8 @@ template<class E> class initializer_list {
using size_type = size_t;
using iterator = const E*;
using const_iterator = const E*;
+ iterator ptr;
+ size_type sz;
initializer_list();
size_t size() const; // number of elements
const E* begin() const; // first element
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/isolate-declaration-cxx17.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/isolate-declaration-cxx17.cpp
index f42f2f37155af..b50ad4ce25839 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/isolate-declaration-cxx17.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/isolate-declaration-cxx17.cpp
@@ -31,7 +31,7 @@ struct SomeClass {
namespace std {
template <typename T>
-class initializer_list {};
+class initializer_list { const T *a, *b; };
template <typename T>
class vector {
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index ab223f2b806d5..d27c61f511afa 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -12216,6 +12216,9 @@ def err_std_source_location_impl_not_found : Error<
def err_std_source_location_impl_malformed : Error<
"'std::source_location::__impl' must be standard-layout and have only two 'const char *' fields '_M_file_name' and '_M_function_name', and two integral fields '_M_line' and '_M_column'">;
+def err_std_initializer_list_malformed : Error<
+ "%0 layout not recognized. Must be a struct with two fields, a 'const E *' and either another 'const E *' or a 'std::size_t'">;
+
// HLSL Diagnostics
def err_hlsl_attr_unsupported_in_stage : Error<"attribute %0 is unsupported in '%1' shaders, requires %select{|one of the following: }2%3">;
def err_hlsl_attr_invalid_type : Error<
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 7178f081d9cf3..4aa19793fa099 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -10528,48 +10528,37 @@ bool RecordExprEvaluator::VisitCXXStdInitializerListExpr(
// Get a pointer to the first element of the array.
Array.addArray(Info, E, ArrayType);
- auto InvalidType = [&] {
- Info.FFDiag(E, diag::note_constexpr_unsupported_layout)
- << E->getType();
- return false;
- };
-
- // FIXME: Perform the checks on the field types in SemaInit.
- RecordDecl *Record = E->getType()->castAs<RecordType>()->getDecl();
- RecordDecl::field_iterator Field = Record->field_begin();
- if (Field == Record->field_end())
- return InvalidType();
-
- // Start pointer.
- if (!Field->getType()->isPointerType() ||
- !Info.Ctx.hasSameType(Field->getType()->getPointeeType(),
- ArrayType->getElementType()))
- return InvalidType();
-
// FIXME: What if the initializer_list type has base classes, etc?
Result = APValue(APValue::UninitStruct(), 0, 2);
Array.moveInto(Result.getStructField(0));
- if (++Field == Record->field_end())
- return InvalidType();
-
- if (Field->getType()->isPointerType() &&
- Info.Ctx.hasSameType(Field->getType()->getPointeeType(),
- ArrayType->getElementType())) {
+ RecordDecl *Record = E->getType()->castAs<RecordType>()->getDecl();
+ RecordDecl::field_iterator Field = Record->field_begin();
+ assert(Field != Record->field_end() &&
+ Info.Ctx.hasSameType(Field->getType()->getPointeeType(),
+ ArrayType->getElementType()) &&
+ "Expected std::initializer_list first field to be const E *");
+ ++Field;
+ assert(Field != Record->field_end() &&
+ "Expected std::initializer_list to have two fields");
+
+ if (Info.Ctx.hasSameType(Field->getType(), Info.Ctx.getSizeType())) {
+ // Length.
+ Result.getStructField(1) = APValue(APSInt(ArrayType->getSize()));
+ } else {
// End pointer.
+ assert(Info.Ctx.hasSameType(Field->getType()->getPointeeType(),
+ ArrayType->getElementType()) &&
+ "Expected std::initializer_list second field to be const E *");
if (!HandleLValueArrayAdjustment(Info, E, Array,
ArrayType->getElementType(),
ArrayType->getZExtSize()))
return false;
Array.moveInto(Result.getStructField(1));
- } else if (Info.Ctx.hasSameType(Field->getType(), Info.Ctx.getSizeType()))
- // Length.
- Result.getStructField(1) = APValue(APSInt(ArrayType->getSize()));
- else
- return InvalidType();
+ }
- if (++Field != Record->field_end())
- return InvalidType();
+ assert(++Field == Record->field_end() &&
+ "Expected std::initializer_list to only have two fields");
return true;
}
diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp
index b2a5ceeeae08b..aeb72385515c4 100644
--- a/clang/lib/CodeGen/CGExprAgg.cpp
+++ b/clang/lib/CodeGen/CGExprAgg.cpp
@@ -429,53 +429,45 @@ AggExprEmitter::VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E) {
Ctx.getAsConstantArrayType(E->getSubExpr()->getType());
assert(ArrayType && "std::initializer_list constructed from non-array");
- // FIXME: Perform the checks on the field types in SemaInit.
RecordDecl *Record = E->getType()->castAs<RecordType>()->getDecl();
RecordDecl::field_iterator Field = Record->field_begin();
- if (Field == Record->field_end()) {
- CGF.ErrorUnsupported(E, "weird std::initializer_list");
- return;
- }
+ assert(Field != Record->field_end() &&
+ Ctx.hasSameType(Field->getType()->getPointeeType(),
+ ArrayType->getElementType()) &&
+ "Expected std::initializer_list first field to be const E *");
// Start pointer.
- if (!Field->getType()->isPointerType() ||
- !Ctx.hasSameType(Field->getType()->getPointeeType(),
- ArrayType->getElementType())) {
- CGF.ErrorUnsupported(E, "weird std::initializer_list");
- return;
- }
-
AggValueSlot Dest = EnsureSlot(E->getType());
LValue DestLV = CGF.MakeAddrLValue(Dest.getAddress(), E->getType());
LValue Start = CGF.EmitLValueForFieldInitialization(DestLV, *Field);
llvm::Value *ArrayStart = ArrayPtr.emitRawPointer(CGF);
CGF.EmitStoreThroughLValue(RValue::get(ArrayStart), Start);
++Field;
-
- if (Field == Record->field_end()) {
- CGF.ErrorUnsupported(E, "weird std::initializer_list");
- return;
- }
+ assert(Field != Record->field_end() &&
+ "Expected std::initializer_list to have two fields");
llvm::Value *Size = Builder.getInt(ArrayType->getSize());
LValue EndOrLength = CGF.EmitLValueForFieldInitialization(DestLV, *Field);
- if (Field->getType()->isPointerType() &&
- Ctx.hasSameType(Field->getType()->getPointeeType(),
- ArrayType->getElementType())) {
+ if (Ctx.hasSameType(Field->getType(), Ctx.getSizeType())) {
+ // Length.
+ CGF.EmitStoreThroughLValue(RValue::get(Size), EndOrLength);
+
+ } else {
// End pointer.
+ assert(Field->getType()->isPointerType() &&
+ Ctx.hasSameType(Field->getType()->getPointeeType(),
+ ArrayType->getElementType()) &&
+ "Expected std::initializer_list second field to be const E *");
llvm::Value *Zero = llvm::ConstantInt::get(CGF.PtrDiffTy, 0);
llvm::Value *IdxEnd[] = { Zero, Size };
llvm::Value *ArrayEnd = Builder.CreateInBoundsGEP(
ArrayPtr.getElementType(), ArrayPtr.emitRawPointer(CGF), IdxEnd,
"arrayend");
CGF.EmitStoreThroughLValue(RValue::get(ArrayEnd), EndOrLength);
- } else if (Ctx.hasSameType(Field->getType(), Ctx.getSizeType())) {
- // Length.
- CGF.EmitStoreThroughLValue(RValue::get(Size), EndOrLength);
- } else {
- CGF.ErrorUnsupported(E, "weird std::initializer_list");
- return;
}
+
+ assert(++Field == Record->field_end() &&
+ "Expected std::initializer_list to only have two fields");
}
/// Determine if E is a trivial array filler, that is, one that is
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index e805834c0fd38..404495f4cdfd3 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -9392,6 +9392,57 @@ ExprResult InitializationSequence::Perform(Sema &S,
// Wrap it in a construction of a std::initializer_list<T>.
CurInit = new (S.Context) CXXStdInitializerListExpr(Step->Type, MTE);
+ if (!Step->Type->isDependentType()) {
+ assert(S.isCompleteType(CurInit.get()->getExprLoc(), Step->Type,
+ Sema::CompleteTypeKind::Normal) &&
+ "std::initializer_list<E> incomplete when used during "
+ "initialization");
+ QualType ElementType;
+ [[maybe_unused]] bool IsStdInitializerList =
+ S.isStdInitializerList(Step->Type, &ElementType);
+ assert(IsStdInitializerList &&
+ "StdInitializerList step to non-std::initializer_list");
+ RecordDecl *Record = Step->Type->castAs<RecordType>()->getDecl();
+
+ auto InvalidType = [&] {
+ S.Diag(Record->getLocation(),
+ diag::err_std_initializer_list_malformed)
+ << Step->Type.getUnqualifiedType();
+ return ExprError();
+ };
+
+ // FIXME: What if the initializer_list type has base classes, etc?
+ if (Record->isUnion())
+ return InvalidType();
+
+ RecordDecl::field_iterator Field = Record->field_begin();
+ if (Field == Record->field_end())
+ return InvalidType();
+
+ // Start pointer
+ if (!Field->getType()->isPointerType() ||
+ !S.Context.hasSameType(Field->getType()->getPointeeType(),
+ ElementType.withConst()))
+ return InvalidType();
+
+ if (++Field == Record->field_end())
+ return InvalidType();
+
+ // Size or end pointer
+ if (Field->getType()->isPointerType()) {
+ if (!S.Context.hasSameType(Field->getType()->getPointeeType(),
+ ElementType.withConst()))
+ return InvalidType();
+ } else {
+ if (Field->isUnnamedBitField() ||
+ !S.Context.hasSameType(Field->getType(), S.Context.getSizeType()))
+ return InvalidType();
+ }
+
+ if (++Field != Record->field_end())
+ return InvalidType();
+ }
+
// Bind the result, in case the library has given initializer_list a
// non-trivial destructor.
if (shouldBindAsTemporary(Entity))
diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p4.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p4.cpp
index bf1b3092e08e8..cad42014802e7 100644
--- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p4.cpp
+++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p4.cpp
@@ -43,7 +43,7 @@ struct S {
const int S::b;
const auto S::c = 0;
-namespace std { template<typename T> struct initializer_list { initializer_list(); }; }
+namespace std { template<typename T> struct initializer_list { const T *a, *b; initializer_list(); }; }
// In an initializer of the form ( expression-list ), the expression-list
// shall be a single assigment-expression.
diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p7-cxx14.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p7-cxx14.cpp
index 97e860f91dcd3..89fa6ec670a65 100644
--- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p7-cxx14.cpp
+++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p7-cxx14.cpp
@@ -4,9 +4,7 @@
namespace std {
template<typename T> struct initializer_list {
- const T *p;
- unsigned long n;
- initializer_list(const T *p, unsigned long n);
+ const T *a, *b;
};
}
diff --git a/clang/test/CodeCompletion/ctor-signature.cpp b/clang/test/CodeCompletion/ctor-signature.cpp
index d9bb2e566c51b..556fc4db0136f 100644
--- a/clang/test/CodeCompletion/ctor-signature.cpp
+++ b/clang/test/CodeCompletion/ctor-signature.cpp
@@ -17,7 +17,7 @@ void foo() {
}
namespace std {
-template <typename> struct initializer_list {};
+template <typename E> struct initializer_list { const E *a, *b; };
} // namespace std
struct Bar {
diff --git a/clang/test/Coverage/unresolved-ctor-expr.cpp b/clang/test/Coverage/unresolved-ctor-expr.cpp
index 10286c79f569d..2c57320949f7b 100644
--- a/clang/test/Coverage/unresolved-ctor-expr.cpp
+++ b/clang/test/Coverage/unresolved-ctor-expr.cpp
@@ -4,7 +4,7 @@
// GH62105 demonstrated a crash with this example code when calculating
// coverage mapping because some source location information was being dropped.
// Demonstrate that we do not crash on this code.
-namespace std { template <typename> class initializer_list {}; }
+namespace std { template <typename E> class initializer_list { const E *a, *b; }; }
template <typename> struct T {
T(std::initializer_list<int>, int = int());
diff --git a/clang/test/Modules/Inputs/initializer_list/direct.h b/clang/test/Modules/Inputs/initializer_list/direct.h
index 6058f803a3dde..6f3978ef13284 100644
--- a/clang/test/Modules/Inputs/initializer_list/direct.h
+++ b/clang/test/Modules/Inputs/initializer_list/direct.h
@@ -2,7 +2,7 @@ namespace std {
using size_t = decltype(sizeof(0));
template<typename T> struct initializer_list {
- initializer_list(T*, size_t);
+ const T* ptr; size_t sz;
};
template<typename T> int min(initializer_list<T>);
diff --git a/clang/test/Modules/pr60775.cppm b/clang/test/Modules/pr60775.cppm
index 35eb92512f427..76aec48808867 100644
--- a/clang/test/Modules/pr60775.cppm
+++ b/clang/test/Modules/pr60775.cppm
@@ -29,9 +29,10 @@
namespace std {
typedef decltype(sizeof(int)) size_t;
template<typename T> struct initializer_list {
+ const T* ptr; size_t sz;
initializer_list(const T *, size_t);
- T* begin();
- T* end();
+ const T* begin();
+ const T* end();
};
}
diff --git a/clang/test/OpenMP/declare_reduction_codegen_in_templates.cpp b/clang/test/OpenMP/declare_reduction_codegen_in_templates.cpp
index 7689cfc11f627..76c5675c83856 100644
--- a/clang/test/OpenMP/declare_reduction_codegen_in_templates.cpp
+++ b/clang/test/OpenMP/declare_reduction_codegen_in_templates.cpp
@@ -16,7 +16,7 @@
#ifndef HEADER
#define HEADER
-typedef long unsigned a;
+typedef decltype(sizeof 0) a;
namespace std {
template <class> class initializer_list {
const int *b;
diff --git a/clang/test/Preprocessor/macro_with_initializer_list.cpp b/clang/test/Preprocessor/macro_with_initializer_list.cpp
index 287eeb4a843cb..40f53164b263d 100644
--- a/clang/test/Preprocessor/macro_with_initializer_list.cpp
+++ b/clang/test/Preprocessor/macro_with_initializer_list.cpp
@@ -3,7 +3,7 @@
namespace std {
template <class X>
class initializer_list {
- public:
+ public: const X *a, *b;
initializer_list();
};
}
diff --git a/clang/test/SemaCXX/PR20334-std_initializer_list_diagnosis_assertion.cpp b/clang/test/SemaCXX/PR20334-std_initializer_list_diagnosis_assertion.cpp
index fb1feee01b29f..0df5d2e7f0aec 100644
--- a/clang/test/SemaCXX/PR20334-std_initializer_list_diagnosis_assertion.cpp
+++ b/clang/test/SemaCXX/PR20334-std_initializer_list_diagnosis_assertion.cpp
@@ -1,23 +1,18 @@
-// RUN: %clang_cc1 -std=c++11 -verify -emit-llvm-only %s
-// RUN: %clang_cc1 -std=c++98 -fsyntax-only -verify %s -DCPP98
-// RUN: %clang_cc1 -std=c++11 -verify -emit-llvm-only %s -fexperimental-new-constant-interpreter
-// RUN: %clang_cc1 -std=c++98 -fsyntax-only -verify %s -DCPP98 -fexperimental-new-constant-interpreter
+// RUN: %clang_cc1 -std=c++11 -verify=cxx11 -emit-llvm-only %s
+// RUN: %clang_cc1 -std=c++98 -fsyntax-only -verify=cxx98 %s -DCPP98
+// RUN: %clang_cc1 -std=c++11 -verify=cxx11 -emit-llvm-only %s -fexperimental-new-constant-interpreter
+// RUN: %clang_cc1 -std=c++98 -fsyntax-only -verify=cxx98 %s -DCPP98 -fexperimental-new-constant-interpreter
namespace std {
template <class _E>
class initializer_list
{};
+ // cxx11-error at -2 {{'std::initializer_list<int>' layout not recognized}}
}
template<class E> int f(std::initializer_list<E> il);
int F = f({1, 2, 3});
-#ifdef CPP98
-//expected-error at -2{{expected expression}}
-#else
-//expected-error at -4{{cannot compile}}
-#endif
-
-
+// cxx98-error at -1 {{expected expression}}
diff --git a/clang/test/SemaCXX/auto-invalid-init-crash.cpp b/clang/test/SemaCXX/auto-invalid-init-crash.cpp
index f727473dd6085..ec921a4286aa2 100644
--- a/clang/test/SemaCXX/auto-invalid-init-crash.cpp
+++ b/clang/test/SemaCXX/auto-invalid-init-crash.c...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/95580
More information about the cfe-commits
mailing list