https://github.com/tbaederr updated https://github.com/llvm/llvm-project/pull/192206
>From a8f446b05342c434620cad67a75a619d81182034 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/dcl.decl/dcl.decomp/p3.cpp | 2 +- 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 +- 34 files changed, 189 insertions(+), 122 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/dcl.decl/dcl.decomp/p3.cpp b/clang/test/CXX/dcl.decl/dcl.decomp/p3.cpp index b7fef12a40b38..b9d19c1eb4371 100644 --- a/clang/test/CXX/dcl.decl/dcl.decomp/p3.cpp +++ b/clang/test/CXX/dcl.decl/dcl.decomp/p3.cpp @@ -235,7 +235,7 @@ namespace constant { constexpr int g() { int *p = nullptr; { - auto [a, b, c] = q; + auto [a, b, c] = q; // expected-note {{temporary created here}} p = &c; } return *p; // expected-note {{read of object outside its lifetime}} 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
