https://github.com/tbaederr created
https://github.com/llvm/llvm-project/pull/192206
E.g. for
```c++
constexpr int unInitLocal() {
int a;
return a; // both-note {{read of uninitialized object}}
}
static_assert(unInitLocal() == 0, ""); // both-error {{not an integral constant
expression}} \
// both-note {{in call to
'unInitLocal()'}}
```
we now diagnose:
```console
array.cpp:896:15: error: static assertion expression is not an integral
constant expression
896 | static_assert(unInitLocal() == 0, ""); // both-error {{not an integral
constant expression}} \
| ^~~~~~~~~~~~~~~~~~
array.cpp:894:10: note: read of uninitialized object is not allowed in a
constant expression
894 | return a; // both-note {{read of uninitialized object}}
| ^
array.cpp:896:15: note: in call to 'unInitLocal()'
896 | static_assert(unInitLocal() == 0, ""); // both-error {{not an integral
constant expression}} \
| ^~~~~~~~~~~~~
array.cpp:893:7: note: declared here
893 | int a;
| ^
1 warning and 1 error generated.
```
and point at the object that we were trying to read from. This adds an
`NoteLValueLocation()` call to the emission of `note_constexpr_access_uninit`,
which is already done in other places:
https://github.com/llvm/llvm-project/blob/7ae5fe63dd979eae13ea04e166f94056ec1306ca/clang/lib/AST/ExprConstant.cpp#L4565-L4570
>From 2f99d81347c73d08af896de4b755f9ce43f186ef Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <[email protected]>
Date: Wed, 15 Apr 2026 09:55:41 +0200
Subject: [PATCH] [clang][ExprConst]
---
clang/lib/AST/ByteCode/Interp.cpp | 60 +++++++++++--------
clang/lib/AST/ByteCode/Interp.h | 5 +-
clang/lib/AST/ExprConstant.cpp | 4 +-
.../ByteCode/builtin-bit-cast-bitfields.cpp | 10 ++--
.../ByteCode/builtin-bit-cast-long-double.cpp | 2 +-
clang/test/AST/ByteCode/builtin-functions.cpp | 2 +-
clang/test/AST/ByteCode/constexpr-nqueens.cpp | 4 +-
clang/test/AST/ByteCode/cxx11.cpp | 3 +-
clang/test/AST/ByteCode/cxx17.cpp | 3 +-
clang/test/AST/ByteCode/cxx20.cpp | 21 ++++---
clang/test/AST/ByteCode/cxx2a.cpp | 3 +-
clang/test/AST/ByteCode/lifetimes.cpp | 6 +-
clang/test/AST/ByteCode/lifetimes26.cpp | 8 +--
clang/test/AST/ByteCode/literals.cpp | 2 +-
clang/test/AST/ByteCode/new-delete.cpp | 11 ++--
clang/test/AST/ByteCode/placement-new.cpp | 9 +--
clang/test/AST/ByteCode/records.cpp | 2 +-
clang/test/AST/ByteCode/unions.cpp | 4 +-
clang/test/C/C23/n3006.c | 5 +-
clang/test/CXX/drs/cwg2026.cpp | 6 ++
clang/test/CXX/drs/cwg3xx.cpp | 1 +
clang/test/CXX/expr/expr.const/p2-0x.cpp | 2 +-
clang/test/Sema/constexpr.c | 5 +-
.../SemaCXX/builtin-is-within-lifetime.cpp | 6 +-
.../SemaCXX/constant-expression-cxx11.cpp | 31 ++++++----
.../SemaCXX/constant-expression-cxx14.cpp | 23 ++++---
.../SemaCXX/constant-expression-cxx2a.cpp | 29 +++++----
.../SemaCXX/constexpr-builtin-bit-cast.cpp | 6 +-
clang/test/SemaCXX/constexpr-printing.cpp | 4 +-
clang/test/SemaCXX/constexpr-value-init.cpp | 20 +++++--
.../test/SemaCXX/cxx2a-constexpr-dynalloc.cpp | 6 +-
.../SemaCXX/cxx2c-constexpr-placement-new.cpp | 4 +-
clang/test/SemaCXX/static-assert-cxx26.cpp | 2 +-
33 files changed, 188 insertions(+), 121 deletions(-)
diff --git a/clang/lib/AST/ByteCode/Interp.cpp
b/clang/lib/AST/ByteCode/Interp.cpp
index abcf55bfa670d..5bc1067518558 100644
--- a/clang/lib/AST/ByteCode/Interp.cpp
+++ b/clang/lib/AST/ByteCode/Interp.cpp
@@ -83,6 +83,17 @@ static void diagnoseMissingInitializer(InterpState &S,
CodePtr OpPC,
S.Note(VD->getLocation(), diag::note_declared_at) << VD->getSourceRange();
}
+static void noteValueLocation(InterpState &S, const Block *B) {
+ const Descriptor *Desc = B->getDescriptor();
+
+ if (B->isDynamic())
+ S.Note(Desc->getLocation(), diag::note_constexpr_dynamic_alloc_here);
+ else if (B->isTemporary())
+ S.Note(Desc->getLocation(), diag::note_constexpr_temporary_here);
+ else
+ S.Note(Desc->getLocation(), diag::note_declared_at);
+}
+
static void diagnoseNonConstVariable(InterpState &S, CodePtr OpPC,
const ValueDecl *VD);
static bool diagnoseUnknownDecl(InterpState &S, CodePtr OpPC,
@@ -185,8 +196,7 @@ static bool CheckTemporary(InterpState &S, CodePtr OpPC,
const Block *B,
!MTE->isUsableInConstantExpressions(S.getASTContext())) {
const SourceInfo &E = S.Current->getSource(OpPC);
S.FFDiag(E, diag::note_constexpr_access_static_temporary, 1) << AK;
- S.Note(B->getDescriptor()->getLocation(),
- diag::note_constexpr_temporary_here);
+ noteValueLocation(S, B);
return false;
}
}
@@ -418,14 +428,9 @@ bool CheckLive(InterpState &S, CodePtr OpPC, const Pointer
&Ptr,
if (Ptr.isDynamic()) {
S.FFDiag(Src, diag::note_constexpr_access_deleted_object) << AK;
} else if (!S.checkingPotentialConstantExpression()) {
- bool IsTemp = Ptr.isTemporary();
S.FFDiag(Src, diag::note_constexpr_access_uninit)
<< AK << /*uninitialized=*/false << S.Current->getRange(OpPC);
-
- if (IsTemp)
- S.Note(Ptr.getDeclLoc(), diag::note_constexpr_temporary_here);
- else
- S.Note(Ptr.getDeclLoc(), diag::note_declared_at);
+ noteValueLocation(S, Ptr.block());
}
return false;
@@ -648,14 +653,16 @@ bool DiagnoseUninitialized(InterpState &S, CodePtr OpPC,
const Pointer &Ptr,
AccessKinds AK) {
assert(Ptr.isLive());
assert(!Ptr.isInitialized());
- return DiagnoseUninitialized(S, OpPC, Ptr.isExtern(), Ptr.getDeclDesc(), AK);
+ return DiagnoseUninitialized(S, OpPC, Ptr.isExtern(), Ptr.block(), AK);
}
bool DiagnoseUninitialized(InterpState &S, CodePtr OpPC, bool Extern,
- const Descriptor *Desc, AccessKinds AK) {
+ const Block *B, AccessKinds AK) {
if (Extern && S.checkingPotentialConstantExpression())
return false;
+ const Descriptor *Desc = B->getDescriptor();
+
if (const auto *VD = Desc->asVarDecl();
VD && (VD->isConstexpr() || VD->hasGlobalStorage())) {
@@ -670,6 +677,7 @@ bool DiagnoseUninitialized(InterpState &S, CodePtr OpPC,
bool Extern,
// Diagnose as "read of object outside its lifetime".
S.FFDiag(Loc, diag::note_constexpr_access_uninit)
<< AK << /*IsIndeterminate=*/false;
+ S.Note(VD->getLocation(), diag::note_declared_at);
}
return false;
}
@@ -687,21 +695,27 @@ bool DiagnoseUninitialized(InterpState &S, CodePtr OpPC,
bool Extern,
if (!S.checkingPotentialConstantExpression()) {
S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_access_uninit)
<< AK << /*uninitialized=*/true << S.Current->getRange(OpPC);
+ noteValueLocation(S, B);
}
return false;
}
static bool CheckLifetime(InterpState &S, CodePtr OpPC, Lifetime LT,
- AccessKinds AK) {
+ const Block *B, AccessKinds AK) {
if (LT == Lifetime::Started)
return true;
if (!S.checkingPotentialConstantExpression()) {
S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_access_uninit)
<< AK << /*uninitialized=*/false << S.Current->getRange(OpPC);
+ noteValueLocation(S, B);
}
return false;
}
+static bool CheckLifetime(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
+ AccessKinds AK) {
+ return CheckLifetime(S, OpPC, Ptr.getLifetime(), Ptr.block(), AK);
+}
static bool CheckWeak(InterpState &S, CodePtr OpPC, const Block *B) {
if (!B->isWeak())
@@ -733,8 +747,7 @@ bool CheckGlobalLoad(InterpState &S, CodePtr OpPC, const
Block *B) {
if (!CheckConstant(S, OpPC, B->getDescriptor()))
return false;
if (Desc.InitState != GlobalInitState::Initialized)
- return DiagnoseUninitialized(S, OpPC, B->isExtern(), B->getDescriptor(),
- AK_Read);
+ return DiagnoseUninitialized(S, OpPC, B->isExtern(), B, AK_Read);
if (!CheckTemporary(S, OpPC, B, AK_Read))
return false;
if (B->getDescriptor()->IsVolatile) {
@@ -755,11 +768,10 @@ bool CheckGlobalLoad(InterpState &S, CodePtr OpPC, const
Block *B) {
bool CheckLocalLoad(InterpState &S, CodePtr OpPC, const Block *B) {
assert(!B->isExtern());
const auto &Desc = *reinterpret_cast<const InlineDescriptor *>(B->rawData());
- if (!CheckLifetime(S, OpPC, Desc.LifeState, AK_Read))
+ if (!CheckLifetime(S, OpPC, Desc.LifeState, B, AK_Read))
return false;
if (!Desc.IsInitialized)
- return DiagnoseUninitialized(S, OpPC, /*Extern=*/false, B->getDescriptor(),
- AK_Read);
+ return DiagnoseUninitialized(S, OpPC, /*Extern=*/false, B, AK_Read);
if (B->getDescriptor()->IsVolatile) {
if (!S.getLangOpts().CPlusPlus)
return Invalid(S, OpPC);
@@ -805,7 +817,7 @@ bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer
&Ptr,
return false;
if (!CheckActive(S, OpPC, Ptr, AK))
return false;
- if (!CheckLifetime(S, OpPC, Ptr.getLifetime(), AK))
+ if (!CheckLifetime(S, OpPC, Ptr, AK))
return false;
if (!Ptr.isInitialized())
return DiagnoseUninitialized(S, OpPC, Ptr, AK);
@@ -843,7 +855,7 @@ bool CheckFinalLoad(InterpState &S, CodePtr OpPC, const
Pointer &Ptr) {
if (!CheckActive(S, OpPC, Ptr, AK_Read))
return false;
- if (!CheckLifetime(S, OpPC, Ptr.getLifetime(), AK_Read))
+ if (!CheckLifetime(S, OpPC, Ptr, AK_Read))
return false;
if (!Ptr.isInitialized())
return DiagnoseUninitialized(S, OpPC, Ptr, AK_Read);
@@ -868,7 +880,7 @@ bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer
&Ptr,
return false;
return CheckDummy(S, OpPC, Ptr.block(), AK_Assign);
}
- if (!CheckLifetime(S, OpPC, Ptr.getLifetime(), AK_Assign))
+ if (!CheckLifetime(S, OpPC, Ptr, AK_Assign))
return false;
if (!CheckRange(S, OpPC, Ptr, AK_Assign))
return false;
@@ -1138,11 +1150,7 @@ bool CheckDeleteSource(InterpState &S, CodePtr OpPC,
const Expr *Source,
const SourceInfo &Loc = S.Current->getSource(OpPC);
S.FFDiag(Loc, diag::note_constexpr_delete_not_heap_alloc)
<< Ptr.toDiagnosticString(S.getASTContext());
-
- if (Ptr.isTemporary())
- S.Note(Ptr.getDeclLoc(), diag::note_constexpr_temporary_here);
- else
- S.Note(Ptr.getDeclLoc(), diag::note_declared_at);
+ noteValueLocation(S, Ptr.block());
return false;
}
@@ -1505,7 +1513,7 @@ bool CheckDestructor(InterpState &S, CodePtr OpPC, const
Pointer &Ptr) {
return false;
if (!CheckRange(S, OpPC, Ptr, AK_Destroy))
return false;
- if (!CheckLifetime(S, OpPC, Ptr.getLifetime(), AK_Destroy))
+ if (!CheckLifetime(S, OpPC, Ptr, AK_Destroy))
return false;
// Can't call a dtor on a global variable.
@@ -2028,7 +2036,7 @@ bool CheckNewTypeMismatch(InterpState &S, CodePtr OpPC,
const Expr *E,
// CheckLifetime for this and all base pointers.
for (Pointer P = Ptr;;) {
- if (!CheckLifetime(S, OpPC, P.getLifetime(), AK_Construct))
+ if (!CheckLifetime(S, OpPC, P, AK_Construct))
return false;
if (P.isRoot())
diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h
index 99651ca98ea6d..ea94df2c90187 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -82,7 +82,7 @@ bool CheckFinalLoad(InterpState &S, CodePtr OpPC, const
Pointer &Ptr);
bool DiagnoseUninitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
AccessKinds AK);
bool DiagnoseUninitialized(InterpState &S, CodePtr OpPC, bool Extern,
- const Descriptor *Desc, AccessKinds AK);
+ const Block *B, AccessKinds AK);
/// Checks a direct load of a primitive value from a global or local variable.
bool CheckGlobalLoad(InterpState &S, CodePtr OpPC, const Block *B);
@@ -1663,8 +1663,7 @@ bool GetGlobalUnchecked(InterpState &S, CodePtr OpPC,
uint32_t I) {
const Block *B = S.P.getGlobal(I);
const auto &Desc = B->getBlockDesc<GlobalInlineDescriptor>();
if (Desc.InitState != GlobalInitState::Initialized)
- return DiagnoseUninitialized(S, OpPC, B->isExtern(), B->getDescriptor(),
- AK_Read);
+ return DiagnoseUninitialized(S, OpPC, B->isExtern(), B, AK_Read);
S.Stk.push<T>(B->deref<T>());
return true;
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 4f45fa728c605..a185f1b631cf8 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -4180,10 +4180,12 @@ findSubobject(EvalInfo &Info, const Expr *E, const
CompleteObject &Obj,
// IsWithinLifetime, resulting in false.
if (I != 0 && handler.AccessKind == AK_IsWithinLifetime)
return false;
- if (!Info.checkingPotentialConstantExpression())
+ if (!Info.checkingPotentialConstantExpression()) {
Info.FFDiag(E, diag::note_constexpr_access_uninit)
<< handler.AccessKind << O->isIndeterminate()
<< E->getSourceRange();
+ NoteLValueLocation(Info, Obj.Base);
+ }
return handler.failed();
}
diff --git a/clang/test/AST/ByteCode/builtin-bit-cast-bitfields.cpp
b/clang/test/AST/ByteCode/builtin-bit-cast-bitfields.cpp
index 5aa4e256e4638..2eefa138f7f0a 100644
--- a/clang/test/AST/ByteCode/builtin-bit-cast-bitfields.cpp
+++ b/clang/test/AST/ByteCode/builtin-bit-cast-bitfields.cpp
@@ -156,8 +156,9 @@ namespace BitFields {
static_assert(f()[0] + f()[1] + f()[2] == 0xc0 + 0xff + 0xee);
{
- // expected-error@+2 {{initialized by a constant expression}}
- // expected-note@+1 {{in call to}}
+ // expected-error@+3 {{initialized by a constant expression}}
+ // expected-note@+2 {{in call to}}
+ // expected-note@+1 {{temporary created here}}
constexpr auto _bad = f()[3];
}
@@ -173,8 +174,9 @@ namespace BitFields {
};
static_assert(g().s0 + g().s1 + g().b0 + g().b1 == 0xc0 + 0xff + 0xe +
0xe);
{
- // expected-error@+2 {{initialized by a constant expression}}
- // expected-note@+1 {{read of uninitialized object is not allowed in a
constant expression}}
+ // expected-error@+3 {{initialized by a constant expression}}
+ // expected-note@+2 {{read of uninitialized object is not allowed in a
constant expression}}
+ // expected-note@+1 {{temporary created here}}
constexpr auto _bad = g().b2;
}
}
diff --git a/clang/test/AST/ByteCode/builtin-bit-cast-long-double.cpp
b/clang/test/AST/ByteCode/builtin-bit-cast-long-double.cpp
index 1013a771d13b4..7e34c3ff9d755 100644
--- a/clang/test/AST/ByteCode/builtin-bit-cast-long-double.cpp
+++ b/clang/test/AST/ByteCode/builtin-bit-cast-long-double.cpp
@@ -61,7 +61,7 @@ constexpr long double foo() {
static_assert(foo() == ld);
constexpr bool f(bool read_uninit) {
- bytes b = bit_cast<bytes>(ld);
+ bytes b = bit_cast<bytes>(ld); // both-note {{declared here}}
unsigned char ld_bytes[10] = {
0x0, 0x48, 0x9f, 0x49, 0xf0,
0x3c, 0x20, 0xc9, 0x0, 0x40,
diff --git a/clang/test/AST/ByteCode/builtin-functions.cpp
b/clang/test/AST/ByteCode/builtin-functions.cpp
index 93b6e06490e61..f423ef1c8b301 100644
--- a/clang/test/AST/ByteCode/builtin-functions.cpp
+++ b/clang/test/AST/ByteCode/builtin-functions.cpp
@@ -1216,7 +1216,7 @@ namespace shufflevector {
#if __cplusplus >= 202002L
constexpr int discarded3() {
int i = 0;
- vector4char a;
+ vector4char a; // both-note {{declared here}}
__builtin_shufflevector((++i, a), a, 0); // both-note {{read of
uninitialized object}} \
// both-warning {{expression
result unused}}
return i;
diff --git a/clang/test/AST/ByteCode/constexpr-nqueens.cpp
b/clang/test/AST/ByteCode/constexpr-nqueens.cpp
index ed038dbc9b077..63a3e63c3765c 100644
--- a/clang/test/AST/ByteCode/constexpr-nqueens.cpp
+++ b/clang/test/AST/ByteCode/constexpr-nqueens.cpp
@@ -60,7 +60,9 @@ constexpr Board buildBoardRecurse(int N, int Col, const Board
&B) {
}
constexpr Board buildBoard(int N) {
return buildBoardRecurse(N, 0, Board()); // ref-note {{in call to
'buildBoardRecurse(8, 0, Board())'}} \
- // expected-note {{in call to
'buildBoardRecurse(8, 0, Board())'}}
+ // expected-note {{in call to
'buildBoardRecurse(8, 0, Board())'}} \
+ // ref-note {{temporary created
here}} \
+ // expected-note {{temporary
created here}}
}
constexpr Board q8 = buildBoard(8); // ref-error {{must be initialized by a
constant expression}} \
diff --git a/clang/test/AST/ByteCode/cxx11.cpp
b/clang/test/AST/ByteCode/cxx11.cpp
index 668228e2dc166..a4c4be14775b3 100644
--- a/clang/test/AST/ByteCode/cxx11.cpp
+++ b/clang/test/AST/ByteCode/cxx11.cpp
@@ -24,7 +24,8 @@ int array2[recurse2]; // both-warning {{variable length
arrays in C++}} \
// ref-warning {{variable length array folded to
constant array as an extension}}
constexpr int b = b; // both-error {{must be initialized by a constant
expression}} \
- // both-note {{read of object outside its lifetime is not
allowed in a constant expression}}
+ // both-note {{read of object outside its lifetime is not
allowed in a constant expression}} \
+ // both-note {{declared here}}
[[clang::require_constant_initialization]] int c = c; // both-error {{variable
does not have a constant initializer}} \
diff --git a/clang/test/AST/ByteCode/cxx17.cpp
b/clang/test/AST/ByteCode/cxx17.cpp
index 583d9879ad245..166638b0f5211 100644
--- a/clang/test/AST/ByteCode/cxx17.cpp
+++ b/clang/test/AST/ByteCode/cxx17.cpp
@@ -3,7 +3,8 @@
[[clang::require_constant_initialization]] int cc = cc; // both-error
{{variable does not have a constant initializer}} \
// both-note
{{attribute here}} \
- // both-note {{ead of
object outside its lifetime}}
+ // both-note {{ead of
object outside its lifetime}} \
+ // both-note
{{declared here}}
struct F { int a; int b;};
diff --git a/clang/test/AST/ByteCode/cxx20.cpp
b/clang/test/AST/ByteCode/cxx20.cpp
index 9800fe01fcaf5..27ba0349d634e 100644
--- a/clang/test/AST/ByteCode/cxx20.cpp
+++ b/clang/test/AST/ByteCode/cxx20.cpp
@@ -57,7 +57,7 @@ constexpr int pointerAssign2() {
static_assert(pointerAssign2() == 12, "");
constexpr int unInitLocal() {
- int a;
+ int a; // both-note {{declared here}}
return a; // both-note {{read of uninitialized object}}
}
static_assert(unInitLocal() == 0, ""); // both-error {{not an integral
constant expression}} \
@@ -71,7 +71,7 @@ constexpr int initializedLocal() {
static_assert(initializedLocal() == 20);
constexpr int initializedLocal2() {
- int a[2];
+ int a[2]; // both-note {{declared here}}
return *a; // both-note {{read of uninitialized object is not allowed in a
constant expression}}
}
static_assert(initializedLocal2() == 20); // both-error {{not an integral
constant expression}} \
@@ -80,7 +80,7 @@ static_assert(initializedLocal2() == 20); // both-error {{not
an integral consta
struct Int { int a; };
constexpr int initializedLocal3() {
- Int i;
+ Int i; // both-note {{declared here}}
return i.a; // both-note {{read of uninitialized object is not allowed in a
constant expression}}
}
static_assert(initializedLocal3() == 20); // both-error {{not an integral
constant expression}} \
@@ -274,7 +274,8 @@ namespace BaseInit {
static_assert(Final{1, 2, 3}.c == 3, ""); // OK
static_assert(Final{1, 2, 3}.a == 0, ""); // both-error {{not an integral
constant expression}} \
- // both-note {{read of
uninitialized object}}
+ // both-note {{read of
uninitialized object}} \
+ // both-note {{temporary created
here}}
struct Mixin {
@@ -294,7 +295,8 @@ namespace BaseInit {
static_assert(Final2{1, 2, 3}.c == 3, ""); // OK
static_assert(Final2{1, 2, 3}.b == 2, ""); // OK
static_assert(Final2{1, 2, 3}.a == 0, ""); // both-error {{not an integral
constant expression}} \
- // both-note {{read of
uninitialized object}}
+ // both-note {{read of
uninitialized object}} \
+ // both-note {{temporary created
here}}
struct Mixin3 {
@@ -311,7 +313,8 @@ namespace BaseInit {
static_assert(Final3{1, 2, 3}.c == 3, ""); // OK
static_assert(Final3{1, 2, 3}.b == 2, ""); // OK
static_assert(Final3{1, 2, 3}.a == 0, ""); // both-error {{not an integral
constant expression}} \
- // both-note {{read of
uninitialized object}}
+ // both-note {{read of
uninitialized object}} \
+ // both-note {{temporary created
here}}
};
namespace Destructors {
@@ -584,7 +587,7 @@ namespace ImplicitFunction {
};
constexpr int callMe() {
- A a;
+ A a; // expected-note {{declared here}}
A b{12};
/// The operator= call here will fail and the diagnostics should be fine.
@@ -969,7 +972,7 @@ namespace LocalDestroy {
namespace PseudoDtor {
constexpr int f1() {
using T = int;
- int a = 0;
+ int a = 0; // both-note {{declared here}}
a.~T();
return a; // both-note {{read of object outside its lifetime}}
}
@@ -978,7 +981,7 @@ namespace PseudoDtor {
constexpr int f2() {
using T = int;
- int a = 0;
+ int a = 0; // both-note {{declared here}}
a.~T();
a = 0; // both-note {{assignment to object outside its lifetime}}
return a;
diff --git a/clang/test/AST/ByteCode/cxx2a.cpp
b/clang/test/AST/ByteCode/cxx2a.cpp
index 533173d84792f..78769a4def5b0 100644
--- a/clang/test/AST/ByteCode/cxx2a.cpp
+++ b/clang/test/AST/ByteCode/cxx2a.cpp
@@ -210,7 +210,8 @@ namespace PureVirtual {
namespace Dtor {
constexpr bool pseudo(bool read, bool recreate) {
using T = bool;
- bool b = false; // both-note {{lifetime has already ended}}
+ bool b = false; // both-note {{lifetime has already ended}} \
+ // both-note {{declared here}}
// This evaluates the store to 'b'...
(b = true).~T();
// ... and ends the lifetime of the object.
diff --git a/clang/test/AST/ByteCode/lifetimes.cpp
b/clang/test/AST/ByteCode/lifetimes.cpp
index 96c868209c5b2..e775bed751821 100644
--- a/clang/test/AST/ByteCode/lifetimes.cpp
+++ b/clang/test/AST/ByteCode/lifetimes.cpp
@@ -11,7 +11,7 @@ constexpr int dead1() {
Foo *F2 = nullptr;
{
- Foo F{12}; // expected-note {{declared here}}
+ Foo F{12}; // both-note {{declared here}}
F2 = &F;
} // Ends lifetime of F.
@@ -27,7 +27,7 @@ struct S {
int t;
constexpr S() : r(0), t(r) {} // both-error {{reference member 'r' binds to
a temporary object whose lifetime would be shorter than the lifetime of the
constructed object}} \
// both-note {{read of object outside its
lifetime is not allowed in a constant expression}} \
- // expected-note {{temporary created here}}
+ // both-note {{temporary created here}}
};
constexpr int k1 = S().t; // both-error {{must be initialized by a constant
expression}} \
// both-note {{in call to}}
@@ -94,7 +94,7 @@ namespace CallScope {
constexpr int f() const { return 0; }
};
constexpr Q *out_of_lifetime(Q q) { return &q; } // both-warning {{address
of stack}} \
- // expected-note
2{{declared here}}
+ // both-note 2{{declared
here}}
constexpr int k3 = out_of_lifetime({})->n; // both-error {{must be
initialized by a constant expression}} \
// expected-note {{read of object
outside its lifetime}} \
// ref-note {{read of object
outside its lifetime}}
diff --git a/clang/test/AST/ByteCode/lifetimes26.cpp
b/clang/test/AST/ByteCode/lifetimes26.cpp
index 8db4ddb1ec51d..7906ef7fca67e 100644
--- a/clang/test/AST/ByteCode/lifetimes26.cpp
+++ b/clang/test/AST/ByteCode/lifetimes26.cpp
@@ -73,8 +73,7 @@ namespace DestroyArrayElem {
// both-note {{in call to}}
constexpr int test2() {
-
- int a[4] = {};
+ int a[4] = {}; // both-note {{declared here}}
std::destroy_at(&a[1]);
int r = a[1]; // both-note {{read of object outside its lifetime}}
std::construct_at(&a[1]);
@@ -85,6 +84,7 @@ namespace DestroyArrayElem {
constexpr int test3() {
int a[4]; /// Array with no init map.
+ // both-note@-1 {{declared here}}
std::construct_at(&a[3]);
return a[3]; // both-note {{read of uninitialized object}}
}
@@ -92,7 +92,7 @@ namespace DestroyArrayElem {
// both-note {{in call to}}
constexpr int test4(bool b) {
- int a[4];
+ int a[4]; // both-note {{declared here}}
a[0] = 12;
std::construct_at(&a[3]);
return b ? a[0] : a[3]; // both-note {{read of uninitialized object}}
@@ -103,7 +103,7 @@ namespace DestroyArrayElem {
constexpr int test5() {
- int *a = std::allocator<int>{}.allocate(3);
+ int *a = std::allocator<int>{}.allocate(3); // both-note {{heap allocation
performed here}}
a[0] = 1; // both-note {{assignment to object outside its lifetime}}
int b = a[1];
std::allocator<int>{}.deallocate(a);
diff --git a/clang/test/AST/ByteCode/literals.cpp
b/clang/test/AST/ByteCode/literals.cpp
index d637eccc448c4..f7eae07c8060a 100644
--- a/clang/test/AST/ByteCode/literals.cpp
+++ b/clang/test/AST/ByteCode/literals.cpp
@@ -541,7 +541,7 @@ namespace IncDec {
/// current interpreter. But they are stil OK.
template<typename T, bool Inc, bool Pre>
constexpr int uninit() {
- T a;
+ T a; // both-note 10{{declared here}}
if constexpr (Inc) {
if (Pre)
++a; // ref-note 3{{increment of uninitialized}} \
diff --git a/clang/test/AST/ByteCode/new-delete.cpp
b/clang/test/AST/ByteCode/new-delete.cpp
index bf892e79a67ac..3eb0d1a13bf49 100644
--- a/clang/test/AST/ByteCode/new-delete.cpp
+++ b/clang/test/AST/ByteCode/new-delete.cpp
@@ -703,7 +703,7 @@ namespace OperatorNewDelete {
static_assert(zeroAlloc());
constexpr int arrayAlloc() {
- int *F = std::allocator<int>().allocate(2);
+ int *F = std::allocator<int>().allocate(2); // both-note {{heap allocation
performed here}}
F[0] = 10; // both-note {{assignment to object outside its lifetime is not
allowed in a constant expression}}
F[1] = 13;
int Res = F[1] + F[0];
@@ -721,7 +721,7 @@ namespace OperatorNewDelete {
/// FIXME: This is broken in the current interpreter.
constexpr bool structAlloc() {
- S *s = std::allocator<S>().allocate(1);
+ S *s = std::allocator<S>().allocate(1); // ref-note {{heap allocation
performed here}}
s->i = 12; // ref-note {{assignment to object outside its lifetime is not
allowed in a constant expression}}
@@ -734,7 +734,7 @@ namespace OperatorNewDelete {
// ref-note {{in call to}}
constexpr bool structAllocArray() {
- S *s = std::allocator<S>().allocate(9);
+ S *s = std::allocator<S>().allocate(9); // ref-note {{heap allocation
performed here}}
s[2].i = 12; // ref-note {{assignment to object outside its lifetime is
not allowed in a constant expression}}
bool Res = (s[2].i == 12);
@@ -900,7 +900,7 @@ namespace IncompleteArray {
};
constexpr int test1() {
int n = 5;
- int* a = new int[n];
+ int* a = new int[n]; // both-note {{heap allocation performed here}}
int c = a[0]; // both-note {{read of uninitialized object}}
delete[] a;
return c;
@@ -1155,6 +1155,7 @@ static_assert(a() == 1, ""); // both-error {{not an
integral constant expression
static_assert(true ? *new int : 4, ""); // both-error {{expression is not an
integral constant expression}} \
- // both-note {{read of uninitialized
object is not allowed in a constant expression}}
+ // both-note {{read of uninitialized
object is not allowed in a constant expression}} \
+ // both-note {{heap allocation
performed here}}
#endif
diff --git a/clang/test/AST/ByteCode/placement-new.cpp
b/clang/test/AST/ByteCode/placement-new.cpp
index 5bad616a0d359..a05a4a18eed61 100644
--- a/clang/test/AST/ByteCode/placement-new.cpp
+++ b/clang/test/AST/ByteCode/placement-new.cpp
@@ -27,7 +27,8 @@ void *operator new(std::size_t, void *p) { return p; }
void* operator new[] (std::size_t, void* p) {return p;}
constexpr int no_lifetime_start = (*std::allocator<int>().allocate(1) = 1); //
both-error {{constant expression}} \
- //
both-note {{assignment to object outside its lifetime}}
+ //
both-note {{assignment to object outside its lifetime}} \
+ //
both-note {{heap allocation performed here}}
consteval auto ok1() {
bool b;
@@ -119,7 +120,7 @@ static_assert(fail2() == 0); // both-error {{not an
integral constant expression
// both-note {{in call to}}
consteval int indeterminate() {
- int * indeterminate;
+ int * indeterminate; // both-note {{declared here}}
new (indeterminate) int(0); // both-note {{read of uninitialized object is
not allowed in a constant expression}}
return 0;
}
@@ -178,7 +179,7 @@ static_assert(blah()); // both-error {{not an integral
constant expression}} \
constexpr int *get_indeterminate() {
- int *evil;
+ int *evil; // both-note {{declared here}}
return evil; // both-note {{read of uninitialized object is not allowed in a
constant expression}}
}
@@ -416,7 +417,7 @@ namespace PlacementNewAfterDelete {
namespace SubObj {
constexpr bool construct_after_lifetime_2() {
struct A { struct B {} b; };
- A a;
+ A a; // both-note {{declared here}}
a.~A();
std::construct_at<A::B>(&a.b); // both-note {{in call}}
return true;
diff --git a/clang/test/AST/ByteCode/records.cpp
b/clang/test/AST/ByteCode/records.cpp
index db02a7d23151e..29f4f424d7707 100644
--- a/clang/test/AST/ByteCode/records.cpp
+++ b/clang/test/AST/ByteCode/records.cpp
@@ -605,7 +605,7 @@ namespace Destructors {
struct A { int n; };
constexpr void double_destroy() {
- A a;
+ A a; // both-note {{declared here}}
a.~A();
a.~A(); // both-note {{destruction of object outside its lifetime}}
}
diff --git a/clang/test/AST/ByteCode/unions.cpp
b/clang/test/AST/ByteCode/unions.cpp
index 2123a932fce10..8cf1d414b70b1 100644
--- a/clang/test/AST/ByteCode/unions.cpp
+++ b/clang/test/AST/ByteCode/unions.cpp
@@ -121,7 +121,7 @@ namespace SimpleActivate {
float x,y;
} a;
int b;
- } Z;
+ } Z; // both-note {{declared here}}
Z.a.y = 10;
@@ -410,7 +410,7 @@ namespace UnionInBase {
static_assert(read_wrong_member_indirect() == 1); // both-error {{not an
integral constant expression}} \
// both-note {{in call to}}
constexpr int read_uninitialized() {
- B b = {.b = 1};
+ B b = {.b = 1}; // both-note {{declared here}}
int *p = &b.a.y;
b.a.x = 1;
return *p; // both-note {{read of uninitialized object}}
diff --git a/clang/test/C/C23/n3006.c b/clang/test/C/C23/n3006.c
index 69674d8e8f4b2..16352c3752427 100644
--- a/clang/test/C/C23/n3006.c
+++ b/clang/test/C/C23/n3006.c
@@ -58,7 +58,8 @@ void constexpr_test(void) {
void self_reference_test(void) {
constexpr int i = i; // expected-error {{constexpr variable 'i' must be
initialized by a constant expression}} \
- expected-note {{read of object outside its lifetime
is not allowed in a constant expression}}
+ expected-note {{read of object outside its lifetime
is not allowed in a constant expression}} \
+ expected-note {{declared here}}
auto j = j; // expected-error {{variable 'j' declared with deduced
type 'auto' cannot appear in its own initializer}}
}
@@ -103,7 +104,7 @@ void misc_struct_test(void) {
constexpr struct {
int b;
- } b = (struct S { int x; }){ 0 }; // expected-error-re {{initializing
'const struct (unnamed at {{.*}}n3006.c:104:13)' with an expression of
incompatible type 'struct S'}}
+ } b = (struct S { int x; }){ 0 }; // expected-error-re {{initializing
'const struct (unnamed at {{.*}}n3006.c:105:13)' with an expression of
incompatible type 'struct S'}}
auto z = ({
int a = 12;
diff --git a/clang/test/CXX/drs/cwg2026.cpp b/clang/test/CXX/drs/cwg2026.cpp
index 23469f999b773..a9d04308c10e8 100644
--- a/clang/test/CXX/drs/cwg2026.cpp
+++ b/clang/test/CXX/drs/cwg2026.cpp
@@ -23,12 +23,14 @@ namespace cwg2026 { // cwg2026: 11
constexpr int b = b;
// since-cxx11-error@-1 {{constexpr variable 'b' must be initialized by a
constant expression}}
// since-cxx11-note@-2 {{read of object outside its lifetime is not
allowed in a constant expression}}
+ // since-cxx11-note@-3 {{declared here}}
[[clang::require_constant_initialization]] int c = c;
// since-cxx11-error@-1 {{variable does not have a constant initializer}}
// since-cxx11-note@-2 {{required by 'require_constant_initialization'
attribute here}}
// cxx11-note@-3 {{read of non-const variable 'c' is not allowed in a
constant expression}}
// cxx11-note@-4 {{declared here}}
// since-cxx14-note@-5 {{read of object outside its lifetime is not
allowed in a constant expression}}
+ // since-cxx14-note@-6 {{declared here}}
#endif
#if __cplusplus >= 202002L
@@ -36,6 +38,7 @@ namespace cwg2026 { // cwg2026: 11
// since-cxx20-error@-1 {{variable does not have a constant initializer}}
// since-cxx20-note@-2 {{required by 'constinit' specifier here}}
// since-cxx20-note@-3 {{read of object outside its lifetime is not
allowed in a constant expression}}
+ // since-cxx20-note@-4 {{declared here}}
#endif
void f() {
@@ -53,12 +56,14 @@ namespace cwg2026 { // cwg2026: 11
static constexpr int f = f;
// since-cxx11-error@-1 {{constexpr variable 'f' must be initialized by a
constant expression}}
// since-cxx11-note@-2 {{read of object outside its lifetime is not
allowed in a constant expression}}
+ // since-cxx11-note@-3 {{declared here}}
[[clang::require_constant_initialization]] static int g = g;
// since-cxx11-error@-1 {{variable does not have a constant initializer}}
// since-cxx11-note@-2 {{required by 'require_constant_initialization'
attribute here}}
// cxx11-note@-3 {{read of non-const variable 'g' is not allowed in a
constant expression}}
// cxx11-note@-4 {{declared here}}
// since-cxx14-note@-5 {{read of object outside its lifetime is not
allowed in a constant expression}}
+ // since-cxx14-note@-6 {{declared here}}
#endif
#if __cplusplus >= 202002L
@@ -66,6 +71,7 @@ namespace cwg2026 { // cwg2026: 11
// since-cxx20-error@-1 {{variable does not have a constant initializer}}
// since-cxx20-note@-2 {{required by 'constinit' specifier here}}
// since-cxx20-note@-3 {{read of object outside its lifetime is not
allowed in a constant expression}}
+ // since-cxx20-note@-4 {{declared here}}
#endif
}
} // namespace cwg2026
diff --git a/clang/test/CXX/drs/cwg3xx.cpp b/clang/test/CXX/drs/cwg3xx.cpp
index 041d56ea3a1db..1b7b273f76b66 100644
--- a/clang/test/CXX/drs/cwg3xx.cpp
+++ b/clang/test/CXX/drs/cwg3xx.cpp
@@ -1124,6 +1124,7 @@ namespace cwg367 { // cwg367: 2.7
static_assert(__enable_constant_folding(true ? *new int : 4), "");
// expected-error@-1 {{static assertion expression is not an integral
constant expression}}
// expected-note@-2 {{read of uninitialized object is not allowed in a
constant expression}}
+ // expected-note@-3 {{heap allocation performed here}}
static_assert(__enable_constant_folding(true ? 4 : *new int), "");
} // namespace cwg367
diff --git a/clang/test/CXX/expr/expr.const/p2-0x.cpp
b/clang/test/CXX/expr/expr.const/p2-0x.cpp
index 8401d3033eda9..01535786655a2 100644
--- a/clang/test/CXX/expr/expr.const/p2-0x.cpp
+++ b/clang/test/CXX/expr/expr.const/p2-0x.cpp
@@ -62,7 +62,7 @@ namespace NonConstExprReturn {
constexpr const int *address_of(const int &a) {
return &a;
}
- constexpr const int *return_param(int n) {
+ constexpr const int *return_param(int n) { // expected-note {{declared here}}
return address_of(n);
}
struct S {
diff --git a/clang/test/Sema/constexpr.c b/clang/test/Sema/constexpr.c
index 0b8de906e1838..19f9033cf924e 100644
--- a/clang/test/Sema/constexpr.c
+++ b/clang/test/Sema/constexpr.c
@@ -426,8 +426,9 @@ void gh173847_test() {
}
int gh173605(int x) {
- static constexpr int c = c; // expected-error {{constexpr variable 'c' must
be initialized by a constant expression}}\
- // expected-note {{read of object outside its
lifetime is not allowed in a constant expression}}
+ static constexpr int c = c; // expected-error {{constexpr variable 'c' must
be initialized by a constant expression}} \
+ // expected-note {{read of object outside its
lifetime is not allowed in a constant expression}} \
+ // expected-note {{declared here}}
static int justincase = justincase; // expected-error {{initializer element
is not a compile-time constant}}
return x;
}
diff --git a/clang/test/SemaCXX/builtin-is-within-lifetime.cpp
b/clang/test/SemaCXX/builtin-is-within-lifetime.cpp
index b47efc9f79630..c7ebce55c5c95 100644
--- a/clang/test/SemaCXX/builtin-is-within-lifetime.cpp
+++ b/clang/test/SemaCXX/builtin-is-within-lifetime.cpp
@@ -111,7 +111,7 @@ static_assert(test_dynamic(true));
consteval bool test_automatic(int read_dangling) {
int* p;
{
- int x = 0;
+ int x = 0; // expected-note 2{{declared here}}
p = &x;
if (!__builtin_is_within_lifetime(p))
return false;
@@ -124,7 +124,7 @@ consteval bool test_automatic(int read_dangling) {
if (read_dangling == 2)
__builtin_is_within_lifetime(p); // expected-note {{read of object outside
its lifetime is not allowed in a constant expression}}
{
- int x[4];
+ int x[4]; // expected-note {{declared here}}
p = &x[2];
if (!__builtin_is_within_lifetime(p))
return false;
@@ -133,7 +133,7 @@ consteval bool test_automatic(int read_dangling) {
__builtin_is_within_lifetime(p); // expected-note {{read of object outside
its lifetime is not allowed in a constant expression}}
std::nullptr_t* q;
{
- std::nullptr_t np = nullptr;
+ std::nullptr_t np = nullptr; // expected-note {{declared here}}
q = &np;
if (!__builtin_is_within_lifetime(q))
return false;
diff --git a/clang/test/SemaCXX/constant-expression-cxx11.cpp
b/clang/test/SemaCXX/constant-expression-cxx11.cpp
index 91c4ff1cb520d..47a064c4026b4 100644
--- a/clang/test/SemaCXX/constant-expression-cxx11.cpp
+++ b/clang/test/SemaCXX/constant-expression-cxx11.cpp
@@ -232,7 +232,7 @@ namespace ParameterScopes {
const int k = 42;
constexpr const int &ObscureTheTruth(const int &a) { return a; }
- constexpr const int &MaybeReturnJunk(bool b, const int a) {
+ constexpr const int &MaybeReturnJunk(bool b, const int a) { // expected-note
2{{declared here}}
return ObscureTheTruth(b ? a : k);
}
static_assert(MaybeReturnJunk(false, 0) == 42, ""); // ok
@@ -694,7 +694,8 @@ static_assert(selfref[1][0][1] == 3, "");
static_assert(selfref[1][1][0] == 0, "");
static_assert(selfref[1][1][1] == 0, "");
-constexpr int badselfref[2][2][2] = { // expected-error {{constant expression}}
+constexpr int badselfref[2][2][2] = { // expected-error {{constant
expression}} \
+ // expected-note {{declared here}}
badselfref[1][0][0] // expected-note {{outside its lifetime}}
};
@@ -1378,7 +1379,7 @@ namespace ExternConstexpr {
constexpr int k; // expected-error {{constexpr variable 'k' must be
initialized by a constant expression}}
}
- extern const int q;
+ extern const int q; // expected-note {{declared here}}
constexpr int g() { return q; } // expected-note {{outside its lifetime}}
constexpr int q = g(); // expected-error {{constant expression}}
expected-note {{in call}}
@@ -1386,7 +1387,7 @@ namespace ExternConstexpr {
constexpr int h() { return r; } // cxx11_20-error {{never produces a
constant}} cxx11_20-note {{read of non-const}}
struct S { int n; };
- extern const S s;
+ extern const S s; // expected-note {{declared here}}
constexpr int x() { return s.n; } // expected-note {{outside its lifetime}}
constexpr S s = {x()}; // expected-error {{constant expression}}
expected-note {{in call}}
}
@@ -2014,7 +2015,9 @@ namespace Lifetime {
void f() {
constexpr int &n = n; // expected-error {{constant expression}} cxx23-note
{{reference to 'n' is not a constant expression}} cxx23-note {{address of
non-static constexpr variable 'n' may differ}} expected-warning {{not yet bound
to a value}}
// cxx11_20-note@-1 {{use of reference outside its
lifetime is not allowed in a constant expression}}
- constexpr int m = m; // expected-error {{constant expression}}
expected-note {{read of object outside its lifetime}}
+ constexpr int m = m; // expected-error {{constant expression}} \
+ // expected-note {{read of object outside its
lifetime}} \
+ // expected-note {{declared here}}
}
constexpr int &get(int &&n) { return n; }
@@ -2024,8 +2027,10 @@ namespace Lifetime {
int &&r;
int &s;
int t;
- constexpr S() : r(get_rv(0)), s(get(0)), t(r) {} // cxx11_20-note {{read
of object outside its lifetime}}
- constexpr S(int) : r(get_rv(0)), s(get(0)), t(s) {} // cxx11_20-note
{{read of object outside its lifetime}}
+ constexpr S() : r(get_rv(0)), s(get(0)), t(r) {} // cxx11_20-note {{read
of object outside its lifetime}} \
+ // cxx11_20-note
{{temporary created here}}
+ constexpr S(int) : r(get_rv(0)), s(get(0)), t(s) {} // cxx11_20-note
{{read of object outside its lifetime}} \
+ // cxx11_20-note
{{temporary created here}}
};
constexpr int k1 = S().t; // expected-error {{constant expression}}
cxx11_20-note {{in call}}
constexpr int k2 = S(0).t; // expected-error {{constant expression}}
cxx11_20-note {{in call}}
@@ -2034,7 +2039,8 @@ namespace Lifetime {
int n = 0;
constexpr int f() const { return 0; }
};
- constexpr Q *out_of_lifetime(Q q) { return &q; } // expected-warning
{{address of stack}}
+ constexpr Q *out_of_lifetime(Q q) { return &q; } // expected-warning
{{address of stack}} \
+ // expected-note
2{{declared here}}
constexpr int k3 = out_of_lifetime({})->n; // expected-error {{constant
expression}} expected-note {{read of object outside its lifetime}}
constexpr int k4 = out_of_lifetime({})->f(); // expected-error {{constant
expression}} expected-note {{member call on object outside its lifetime}}
@@ -2070,9 +2076,14 @@ namespace Lifetime {
int a = b.f(); // expected-warning {{uninitialized}} expected-note
2{{member call on object outside its lifetime}}
Inner b;
};
- constexpr R r; // expected-error {{constant expression}} expected-note {{in
call}} expected-note {{implicit default constructor for 'Lifetime::R' first
required here}}
+ constexpr R r; // expected-error {{constant expression}} \
+ // expected-note {{in call}} \
+ // expected-note {{implicit default constructor for
'Lifetime::R' first required here}} \
+ // expected-note {{declared here}}
void rf() {
- constexpr R r; // expected-error {{constant expression}} expected-note
{{in call}}
+ constexpr R r; // expected-error {{constant expression}} \
+ // expected-note {{in call}} \
+ // expected-note {{declared here}}
}
}
diff --git a/clang/test/SemaCXX/constant-expression-cxx14.cpp
b/clang/test/SemaCXX/constant-expression-cxx14.cpp
index a917837410ee5..9c0e87cac54cf 100644
--- a/clang/test/SemaCXX/constant-expression-cxx14.cpp
+++ b/clang/test/SemaCXX/constant-expression-cxx14.cpp
@@ -842,7 +842,8 @@ namespace StmtExpr {
static_assert(f(1) == 1, ""); // expected-error {{constant expression}}
expected-note {{in call}}
constexpr int g() {
- return ({ int n; n; }); // expected-note {{read of uninitialized object}}
+ return ({ int n; n; }); // expected-note {{read of uninitialized object}} \
+ // expected-note {{declared here}}
}
static_assert(g() == 0, ""); // expected-error {{constant expression}}
expected-note {{in call}}
@@ -881,7 +882,7 @@ namespace Lifetime {
constexpr int &get(int &&r) { return r; }
// cxx23-error@-1 {{non-const lvalue reference to type 'int' cannot bind to
a temporary of type 'int'}}
constexpr int f() {
- int &r = get(123);
+ int &r = get(123); // cxx14_20-note {{temporary created here}}
return r;
// cxx14_20-note@-1 {{read of object outside its lifetime}}
}
@@ -890,7 +891,7 @@ namespace Lifetime {
constexpr int g() {
int *p = 0;
{
- int n = 0;
+ int n = 0; // expected-note {{declared here}}
p = &n;
n = 42;
}
@@ -903,9 +904,9 @@ namespace Lifetime {
int *p[4] = {};
int &&r = 1;
p[0] = &r;
- while (int a = 1) {
+ while (int a = 1) { // expected-note {{declared here}}
p[1] = &a;
- for (int b = 1; int c = 1; ) {
+ for (int b = 1; int c = 1; ) { // expected-note 2{{declared here}}
p[2] = &b, p[3] = &c;
break;
}
@@ -923,7 +924,7 @@ namespace Lifetime {
int *p = 0;
for (int i = 0; i != 2; ++i) {
int *q = p;
- int n = 0;
+ int n = 0; // expected-note {{declared here}}
p = &n;
if (i)
// This modifies the 'n' from the previous iteration of the loop
outside
@@ -955,7 +956,7 @@ namespace PR17615 {
struct A {
int &&r;
constexpr A(int &&r) : r(static_cast<int &&>(r)) {}
- constexpr A() : A(0) {
+ constexpr A() : A(0) { // expected-note {{temporary created here}}
(void)+r; // expected-note {{outside its lifetime}}
}
};
@@ -1124,7 +1125,9 @@ struct A {
};
constexpr A() {}
};
-static_assert(A().x == 3, ""); // cxx14-error{{not an integral constant
expression}} cxx14-note{{in call to 'A()'}}
+static_assert(A().x == 3, ""); // cxx14-error{{not an integral constant
expression}} \
+ // cxx14-note{{in call to 'A()'}} \
+ // cxx14-note {{temporary created here}}
// Reference another indirect field, with different 'this'.
struct B {
@@ -1239,7 +1242,9 @@ namespace ObjectsUnderConstruction {
static_assert(aggr2.x == 1 && aggr2.y == 1, "");
// The lifetime of 'n' begins at the initialization, not before.
- constexpr int n = ++const_cast<int&>(n); // expected-error {{constant
expression}} expected-note {{increment of object outside its lifetime}}
+ constexpr int n = ++const_cast<int&>(n); // expected-error {{constant
expression}} \
+ // expected-note {{increment of
object outside its lifetime}} \
+ // expected-note {{declared here}}
}
namespace PR39728 {
diff --git a/clang/test/SemaCXX/constant-expression-cxx2a.cpp
b/clang/test/SemaCXX/constant-expression-cxx2a.cpp
index fb60b5300c362..396a8df21a3e3 100644
--- a/clang/test/SemaCXX/constant-expression-cxx2a.cpp
+++ b/clang/test/SemaCXX/constant-expression-cxx2a.cpp
@@ -372,7 +372,7 @@ namespace Union {
return *p; // expected-note {{read of member 'a' of union with active
member 'b'}}
}
constexpr int read_uninitialized() {
- B b = {.b = 1};
+ B b = {.b = 1}; // expected-note {{declared here}}
int *p = &b.a.y;
b.a.x = 1;
return *p; // expected-note {{read of uninitialized object}}
@@ -542,7 +542,7 @@ namespace TwosComplementShifts {
namespace Uninit {
constexpr int f(bool init) {
- int a;
+ int a; // expected-note {{declared here}}
if (init)
a = 1;
return a; // expected-note {{read of uninitialized object}}
@@ -576,20 +576,26 @@ namespace Uninit {
};
// FIXME: This is working around clang not implementing DR2026. With that
// fixed, we should be able to test this without the injected copy.
- constexpr Y copy(Y y) { return y; } // expected-note {{in call to 'Y(y)'}}
expected-note {{subobject 'n' is not initialized}}
+ constexpr Y copy(Y y) { return y; } // expected-note {{in call to 'Y(y)'}} \
+ // expected-note {{subobject 'n' is not
initialized}} \
+ // expected-note {{declared here}}
constexpr Y y1 = copy(Y());
static_assert(y1.z1.n == 1 && y1.z2.n == 2 && y1.z3.n == 3);
constexpr Y y2 = copy(Y(0)); // expected-error {{constant expression}}
expected-note {{in call}}
static_assert(Y(0,0).z2.n == 0);
- static_assert(Y(0,0).z1.n == 0); // expected-error {{constant expression}}
expected-note {{read of uninitialized object}}
- static_assert(Y(0,0).z3.n == 0); // expected-error {{constant expression}}
expected-note {{read of uninitialized object}}
+ static_assert(Y(0,0).z1.n == 0); // expected-error {{constant expression}} \
+ // expected-note {{read of uninitialized
object}} \
+ // expected-note {{temporary created here}}
+ static_assert(Y(0,0).z3.n == 0); // expected-error {{constant expression}} \
+ // expected-note {{read of uninitialized
object}} \
+ // expected-note {{temporary created here}}
static_assert(copy(Y(0,0)).z2.n == 0); // expected-error {{constant
expression}} expected-note {{in call}}
constexpr unsigned char not_even_unsigned_char() {
- unsigned char c;
+ unsigned char c; // expected-note {{declared here}}
return c; // expected-note {{read of uninitialized object}}
}
constexpr unsigned char x = not_even_unsigned_char(); // expected-error
{{constant expression}} expected-note {{in call}}
@@ -1086,7 +1092,8 @@ namespace dtor_call {
constexpr bool pseudo(bool read, bool recreate) {
using T = bool;
- bool b = false; // expected-note {{lifetime has already ended}}
+ bool b = false; // expected-note {{lifetime has already ended}} \
+ // expected-note {{declared here}}
// This evaluates the store to 'b'...
(b = true).~T();
// ... and ends the lifetime of the object.
@@ -1102,14 +1109,14 @@ namespace dtor_call {
static_assert(pseudo(false, true));
constexpr void use_after_destroy() {
- A a;
+ A a; // expected-note {{declared here}}
a.~A();
A b = a; // expected-note {{in call}} expected-note {{read of object
outside its lifetime}}
}
static_assert((use_after_destroy(), true)); // expected-error {{}}
expected-note {{in call}}
constexpr void double_destroy() {
- A a;
+ A a; // expected-note {{declared here}}
a.~A();
a.~A(); // expected-note {{destruction of object outside its lifetime}}
}
@@ -1176,7 +1183,7 @@ namespace dtor_call {
constexpr void use_after_virt_destroy() {
char buff[4] = {};
- VU vu;
+ VU vu; // expected-note {{declared here}}
vu.z.p = buff;
((Y&)vu.z).~Y();
((Z&)vu.z).z = 1; // expected-note {{assignment to object outside its
lifetime}}
@@ -1186,7 +1193,7 @@ namespace dtor_call {
constexpr void destroy_after_lifetime() {
A *p;
{
- A a;
+ A a; // expected-note {{declared here}}
p = &a;
}
p->~A(); // expected-note {{destruction of object outside its lifetime}}
diff --git a/clang/test/SemaCXX/constexpr-builtin-bit-cast.cpp
b/clang/test/SemaCXX/constexpr-builtin-bit-cast.cpp
index 0a7668b1ed1fe..839de82744379 100644
--- a/clang/test/SemaCXX/constexpr-builtin-bit-cast.cpp
+++ b/clang/test/SemaCXX/constexpr-builtin-bit-cast.cpp
@@ -278,7 +278,7 @@ constexpr int test_indeterminate(bool read_indet) {
};
pad p{1, 2};
- no_pad np = bit_cast<no_pad>(p);
+ no_pad np = bit_cast<no_pad>(p); // expected-note {{declared here}}
int tmp = np.a + np.b;
@@ -343,7 +343,7 @@ constexpr B one() {
constexpr char good_one = one().x[0] + one().x[2] + one().x[3];
// expected-error@+2 {{constexpr variable 'bad_one' must be initialized by a
constant expression}}
// expected-note@+1 {{read of uninitialized object is not allowed in a
constant expression}}
-constexpr char bad_one = one().x[1];
+constexpr char bad_one = one().x[1]; // expected-note {{temporary created
here}}
constexpr A two() {
B b = one(); // b.x[1] is indeterminate.
@@ -433,7 +433,7 @@ static_assert(round_trip<bytes>(ld), "");
static_assert(round_trip<long double>(10.0L));
constexpr bool f(bool read_uninit) {
- bytes b = bit_cast<bytes>(ld);
+ bytes b = bit_cast<bytes>(ld); // expected-note {{declared here}}
unsigned char ld_bytes[10] = {
0x0, 0x48, 0x9f, 0x49, 0xf0,
0x3c, 0x20, 0xc9, 0x0, 0x40,
diff --git a/clang/test/SemaCXX/constexpr-printing.cpp
b/clang/test/SemaCXX/constexpr-printing.cpp
index 08c80a0bb7fdb..b5aa050aea25f 100644
--- a/clang/test/SemaCXX/constexpr-printing.cpp
+++ b/clang/test/SemaCXX/constexpr-printing.cpp
@@ -12,7 +12,9 @@ struct S {
constexpr int extract(const S &s) { return s.n; } // expected-note {{read of
object outside its lifetime is not allowed in a constant expression}}
void f() {
- constexpr S s1; // expected-error {{constant expression}} expected-note {{in
call to 'S()'}}
+ constexpr S s1; // expected-error {{constant expression}} \
+ // expected-note {{in call to 'S()'}} \
+ // expected-note {{declared here}}
constexpr S s2(10);
}
diff --git a/clang/test/SemaCXX/constexpr-value-init.cpp
b/clang/test/SemaCXX/constexpr-value-init.cpp
index 18fa9cf0736a6..bd1c254dd200a 100644
--- a/clang/test/SemaCXX/constexpr-value-init.cpp
+++ b/clang/test/SemaCXX/constexpr-value-init.cpp
@@ -10,13 +10,21 @@ struct B { // expected-note {{in call to 'A()'}}
A a;
};
-constexpr A a1; // expected-error {{constant expression}} expected-note {{in
call to 'A()'}}
-constexpr A a2 = A(); // expected-error {{constant expression}} expected-note
{{in call to 'A()'}}
+constexpr A a1; // expected-error {{constant expression}} \
+ // expected-note {{in call to 'A()'}} \
+ // expected-note {{declared here}}
+constexpr A a2 = A(); // expected-error {{constant expression}} \
+ // expected-note {{in call to 'A()'}} \
+ // expected-note {{declared here}}
void f() {
- constexpr A a; // expected-error {{constant expression}} expected-note {{in
call to 'A()'}}
+ constexpr A a; // expected-error {{constant expression}} \
+ // expected-note {{in call to 'A()'}} \
+ // expected-note {{declared here}}
}
-constexpr B b1; // expected-error {{constant expression}} expected-note {{in
call to 'B()'}}
+constexpr B b1; // expected-error {{constant expression}} \
+ // expected-note {{in call to 'B()'}} \
+ // expected-note {{declared here}}
constexpr B b2 = B(); // ok
static_assert(b2.a.a == 1, "");
static_assert(b2.a.b == 2, "");
@@ -41,7 +49,9 @@ constexpr int n = Z<V>().c; // expected-error {{constant
expression}} expected-n
struct E { // expected-note {{in call to 'A()'}}
A a[2];
};
-constexpr E e1; // expected-error {{constant expression}} expected-note {{in
call to 'E()'}}
+constexpr E e1; // expected-error {{constant expression}} \
+ // expected-note {{in call to 'E()'}} \
+ // expected-note {{declared here}}
constexpr E e2 = E();
static_assert(e2.a[0].a == 1, "");
static_assert(e2.a[0].b == 2, "");
diff --git a/clang/test/SemaCXX/cxx2a-constexpr-dynalloc.cpp
b/clang/test/SemaCXX/cxx2a-constexpr-dynalloc.cpp
index 25cd2c9538a90..3088923c009ae 100644
--- a/clang/test/SemaCXX/cxx2a-constexpr-dynalloc.cpp
+++ b/clang/test/SemaCXX/cxx2a-constexpr-dynalloc.cpp
@@ -89,7 +89,9 @@ constexpr int *escape = std::allocator<int>().allocate(3); //
expected-error {{c
// expected-note
{{heap allocation performed here}}
constexpr int leak = (std::allocator<int>().allocate(3), 0); // expected-error
{{constant expression}} \
// expected-note
{{not deallocated}}
-constexpr int no_lifetime_start = (*std::allocator<int>().allocate(1) = 1); //
expected-error {{constant expression}} expected-note {{assignment to object
outside its lifetime}}
+constexpr int no_lifetime_start = (*std::allocator<int>().allocate(1) = 1); //
expected-error {{constant expression}} \
+ //
expected-note {{assignment to object outside its lifetime}} \
+ //
expected-note {{heap allocation performed here}}
constexpr int no_deallocate_nullptr =
(std::allocator<int>().deallocate(nullptr), 1); // expected-error {{constant
expression}} expected-note {{in call}}
// expected-note@#dealloc {{'std::allocator<...>::deallocate' used to delete a
null pointer}}
constexpr int no_deallocate_nonalloc =
(std::allocator<int>().deallocate((int*)&no_deallocate_nonalloc), 1); //
expected-error {{constant expression}} expected-note {{in call}}
@@ -182,7 +184,7 @@ static_assert(construct_after_lifetime()); //
expected-error {{}} expected-note
constexpr bool construct_after_lifetime_2() {
struct A { struct B {} b; };
- A a;
+ A a; // expected-note {{declared here}}
a.~A();
std::construct_at<A::B>(&a.b); // expected-note {{in call}}
// expected-note@#new {{construction of subobject of object outside its
lifetime is not allowed in a constant expression}}
diff --git a/clang/test/SemaCXX/cxx2c-constexpr-placement-new.cpp
b/clang/test/SemaCXX/cxx2c-constexpr-placement-new.cpp
index 4cf0e9ffe1d64..7034a45231281 100644
--- a/clang/test/SemaCXX/cxx2c-constexpr-placement-new.cpp
+++ b/clang/test/SemaCXX/cxx2c-constexpr-placement-new.cpp
@@ -26,7 +26,7 @@ consteval int conversion() {
}
consteval int indeterminate() {
- int * indeterminate;
+ int * indeterminate; // expected-note {{declared here}}
new (indeterminate) int(0);
// expected-note@-1 {{read of uninitialized object is not allowed in a
constant expression}}
return 0;
@@ -105,7 +105,7 @@ static_assert(blah()); // expected-error {{not an integral
constant expression}}
// expected-note {{in call to 'blah()'}}
constexpr int *get_indeterminate() {
- int *evil;
+ int *evil; // expected-note {{declared here}}
return evil; // expected-note {{read of uninitialized object is not allowed
in a constant expression}}
}
diff --git a/clang/test/SemaCXX/static-assert-cxx26.cpp
b/clang/test/SemaCXX/static-assert-cxx26.cpp
index b2ebd2abb785e..5dbe2c37307bd 100644
--- a/clang/test/SemaCXX/static-assert-cxx26.cpp
+++ b/clang/test/SemaCXX/static-assert-cxx26.cpp
@@ -271,7 +271,7 @@ struct InvalidPtr {
return 42;
}
consteval const char *data() {
- const char *ptr; // Garbage
+ const char *ptr; // expected-note {{declared here}}
return ptr; // expected-note {{read of uninitialized object is not allowed
in a constant expression}}
}
};
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits