llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Timm Baeder (tbaederr)
<details>
<summary>Changes</summary>
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
---
Patch is 56.01 KiB, truncated to 20.00 KiB below, full version:
https://github.com/llvm/llvm-project/pull/192206.diff
33 Files Affected:
- (modified) clang/lib/AST/ByteCode/Interp.cpp (+34-26)
- (modified) clang/lib/AST/ByteCode/Interp.h (+2-3)
- (modified) clang/lib/AST/ExprConstant.cpp (+3-1)
- (modified) clang/test/AST/ByteCode/builtin-bit-cast-bitfields.cpp (+6-4)
- (modified) clang/test/AST/ByteCode/builtin-bit-cast-long-double.cpp (+1-1)
- (modified) clang/test/AST/ByteCode/builtin-functions.cpp (+1-1)
- (modified) clang/test/AST/ByteCode/constexpr-nqueens.cpp (+3-1)
- (modified) clang/test/AST/ByteCode/cxx11.cpp (+2-1)
- (modified) clang/test/AST/ByteCode/cxx17.cpp (+2-1)
- (modified) clang/test/AST/ByteCode/cxx20.cpp (+12-9)
- (modified) clang/test/AST/ByteCode/cxx2a.cpp (+2-1)
- (modified) clang/test/AST/ByteCode/lifetimes.cpp (+3-3)
- (modified) clang/test/AST/ByteCode/lifetimes26.cpp (+4-4)
- (modified) clang/test/AST/ByteCode/literals.cpp (+1-1)
- (modified) clang/test/AST/ByteCode/new-delete.cpp (+6-5)
- (modified) clang/test/AST/ByteCode/placement-new.cpp (+5-4)
- (modified) clang/test/AST/ByteCode/records.cpp (+1-1)
- (modified) clang/test/AST/ByteCode/unions.cpp (+2-2)
- (modified) clang/test/C/C23/n3006.c (+3-2)
- (modified) clang/test/CXX/drs/cwg2026.cpp (+6)
- (modified) clang/test/CXX/drs/cwg3xx.cpp (+1)
- (modified) clang/test/CXX/expr/expr.const/p2-0x.cpp (+1-1)
- (modified) clang/test/Sema/constexpr.c (+3-2)
- (modified) clang/test/SemaCXX/builtin-is-within-lifetime.cpp (+3-3)
- (modified) clang/test/SemaCXX/constant-expression-cxx11.cpp (+21-10)
- (modified) clang/test/SemaCXX/constant-expression-cxx14.cpp (+14-9)
- (modified) clang/test/SemaCXX/constant-expression-cxx2a.cpp (+18-11)
- (modified) clang/test/SemaCXX/constexpr-builtin-bit-cast.cpp (+3-3)
- (modified) clang/test/SemaCXX/constexpr-printing.cpp (+3-1)
- (modified) clang/test/SemaCXX/constexpr-value-init.cpp (+15-5)
- (modified) clang/test/SemaCXX/cxx2a-constexpr-dynalloc.cpp (+4-2)
- (modified) clang/test/SemaCXX/cxx2c-constexpr-placement-new.cpp (+2-2)
- (modified) clang/test/SemaCXX/static-assert-cxx26.cpp (+1-1)
``````````diff
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}} \
...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/192206
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits