Author: Timm Baeder Date: 2026-05-05T02:47:36+02:00 New Revision: 2b430502a2114b77e6495d90ac52359f73beb550
URL: https://github.com/llvm/llvm-project/commit/2b430502a2114b77e6495d90ac52359f73beb550 DIFF: https://github.com/llvm/llvm-project/commit/2b430502a2114b77e6495d90ac52359f73beb550.diff LOG: [clang][ExprConst] Add another missing `NoteLValueLocation()` call (#195098) This is a little more work since it requires a new parameter for all the `found()` handlers. Added: Modified: clang/lib/AST/ExprConstant.cpp clang/test/SemaCXX/constant-expression-cxx14.cpp Removed: ################################################################################ diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 1a4c962801077..3f3a80f5b77a3 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -4245,7 +4245,7 @@ findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj, } if (I == N) { - if (!handler.found(*O, ObjType)) + if (!handler.found(*O, ObjType, Obj.Base)) return false; // If we modified a bit-field, truncate it to the right width. @@ -4342,7 +4342,7 @@ findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj, expandVector(*O, NumElements); } assert(O->isVector() && "unexpected object during vector element access"); - return handler.found(O->getVectorElt(Index), ObjType); + return handler.found(O->getVectorElt(Index), ObjType, Obj.Base); } else if (const FieldDecl *Field = getAsField(Sub.Entries[I])) { if (Field->isMutable() && !Obj.mayAccessMutableMembers(Info, handler.AccessKind)) { @@ -4402,7 +4402,7 @@ struct ExtractSubobjectHandler { typedef bool result_type; bool failed() { return false; } - bool found(APValue &Subobj, QualType SubobjType) { + bool found(APValue &Subobj, QualType SubobjType, APValue::LValueBase Base) { Result = Subobj; if (AccessKind == AK_ReadObjectRepresentation) return true; @@ -4448,7 +4448,7 @@ struct ModifySubobjectHandler { } bool failed() { return false; } - bool found(APValue &Subobj, QualType SubobjType) { + bool found(APValue &Subobj, QualType SubobjType, APValue::LValueBase Base) { if (!checkConst(SubobjType)) return false; // We've been given ownership of NewVal, so just swap it in. @@ -4978,7 +4978,7 @@ struct CompoundAssignSubobjectHandler { } bool failed() { return false; } - bool found(APValue &Subobj, QualType SubobjType) { + bool found(APValue &Subobj, QualType SubobjType, APValue::LValueBase Base) { switch (Subobj.getKind()) { case APValue::Int: return found(Subobj.getInt(), SubobjType); @@ -4997,6 +4997,7 @@ struct CompoundAssignSubobjectHandler { Info.FFDiag(E, diag::note_constexpr_access_uninit) << /*read of=*/0 << /*uninitialized object=*/1 << E->getLHS()->getSourceRange(); + NoteLValueLocation(Info, Base); return false; default: // FIXME: can this happen? @@ -5125,7 +5126,7 @@ struct IncDecSubobjectHandler { } bool failed() { return false; } - bool found(APValue &Subobj, QualType SubobjType) { + bool found(APValue &Subobj, QualType SubobjType, APValue::LValueBase Base) { // Stash the old value. Also clear Old, so we don't clobber it later // if we're post-incrementing a complex. if (Old) { @@ -6412,7 +6413,9 @@ struct CheckDynamicTypeHandler { AccessKinds AccessKind; typedef bool result_type; bool failed() { return false; } - bool found(APValue &Subobj, QualType SubobjType) { return true; } + bool found(APValue &Subobj, QualType SubobjType, APValue::LValueBase Base) { + return true; + } bool found(APSInt &Value, QualType SubobjType) { return true; } bool found(APFloat &Value, QualType SubobjType) { return true; } }; @@ -6762,7 +6765,7 @@ struct StartLifetimeOfUnionMemberHandler { typedef bool result_type; bool failed() { return Failed; } - bool found(APValue &Subobj, QualType SubobjType) { + bool found(APValue &Subobj, QualType SubobjType, APValue::LValueBase Base) { // We are supposed to perform no initialization but begin the lifetime of // the object. We interpret that as meaning to do what default // initialization of the object would do if all constructors involved were @@ -7480,7 +7483,7 @@ struct DestroyObjectHandler { typedef bool result_type; bool failed() { return false; } - bool found(APValue &Subobj, QualType SubobjType) { + bool found(APValue &Subobj, QualType SubobjType, APValue::LValueBase Base) { return HandleDestructionImpl(Info, E->getSourceRange(), This, Subobj, SubobjType); } @@ -10865,7 +10868,8 @@ bool PointerExprEvaluator::VisitCXXNewExpr(const CXXNewExpr *E) { } return true; } - bool found(APValue &Subobj, QualType SubobjType) { + bool found(APValue &Subobj, QualType SubobjType, + APValue::LValueBase Base) { if (!checkConst(SubobjType)) return false; // FIXME: Reject the cases where [basic.life]p8 would not permit the @@ -22525,6 +22529,11 @@ struct IsWithinLifetimeHandler { using result_type = std::optional<bool>; std::optional<bool> failed() { return std::nullopt; } template <typename T> + std::optional<bool> found(T &Subobj, QualType SubobjType, + APValue::LValueBase) { + return true; + } + template <typename T> std::optional<bool> found(T &Subobj, QualType SubobjType) { return true; } diff --git a/clang/test/SemaCXX/constant-expression-cxx14.cpp b/clang/test/SemaCXX/constant-expression-cxx14.cpp index 9c0e87cac54cf..fb7fd5b528b05 100644 --- a/clang/test/SemaCXX/constant-expression-cxx14.cpp +++ b/clang/test/SemaCXX/constant-expression-cxx14.cpp @@ -1284,16 +1284,20 @@ namespace TemporaryWithBadPointer { namespace UninitCompoundAssign { constexpr int scalar(int a) { - int sum; // cxx14-warning {{uninitialized variable in a constexpr function is a C++20 extension}} - sum += a; // expected-note {{read of uninitialized object}}; + int sum; // cxx14-warning {{uninitialized variable in a constexpr function is a C++20 extension}} \ + // #sum-decl + sum += a; // expected-note {{read of uninitialized object}} \ + // expected-note@#sum-decl {{declared here}} return 0; } static_assert(scalar(3), ""); // expected-error {{constant expression}} \ // expected-note {{in call to 'scalar(3)'}} constexpr int array(int a) { - int arr[3]; // cxx14-warning {{uninitialized variable in a constexpr function is a C++20 extension}} - arr[1] += a; // expected-note {{read of uninitialized object}}; + int arr[3]; // cxx14-warning {{uninitialized variable in a constexpr function is a C++20 extension}} \ + // #arr-decl + arr[1] += a; // expected-note {{read of uninitialized object}} \ + // expected-note@#arr-decl {{declared here}} return 0; } static_assert(array(3), ""); // expected-error {{constant expression}} \ @@ -1304,8 +1308,9 @@ struct Foo { constexpr Foo() {} // cxx14-warning {{constexpr constructor that does not initialize all members is a C++20 extension}} }; constexpr int field(int a) { - Foo f; - f.val += a; // expected-note {{read of uninitialized object}}; + Foo f; // #f-decl + f.val += a; // expected-note {{read of uninitialized object}} \ + // expected-note@#f-decl {{declared here}} return 0; } static_assert(field(3), ""); // expected-error {{constant expression}} \ _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
