[clang] [clang][ExprConst] Add another missing `NoteLValueLocation()` call (PR #195098)

Timm Baeder via cfe-commits cfe-commits at lists.llvm.org
Thu Apr 30 21:29:51 PDT 2026


https://github.com/tbaederr updated https://github.com/llvm/llvm-project/pull/195098

>From 80137c5cc91eee7f8fcad8e06f65f15e223ae11e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbaeder at redhat.com>
Date: Thu, 30 Apr 2026 16:39:16 +0200
Subject: [PATCH] Declared here

---
 clang/lib/AST/ExprConstant.cpp                | 29 ++++++++++++-------
 .../SemaCXX/constant-expression-cxx14.cpp     |  8 +++--
 2 files changed, 24 insertions(+), 13 deletions(-)

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..0f7478ba30057 100644
--- a/clang/test/SemaCXX/constant-expression-cxx14.cpp
+++ b/clang/test/SemaCXX/constant-expression-cxx14.cpp
@@ -1284,7 +1284,8 @@ namespace TemporaryWithBadPointer {
 
 namespace UninitCompoundAssign {
 constexpr int scalar(int a) {
-  int sum; // cxx14-warning {{uninitialized variable in a constexpr function is a C++20 extension}}
+  int sum; // cxx14-warning {{uninitialized variable in a constexpr function is a C++20 extension}} \
+           // expected-note {{declared here}}
   sum += a; // expected-note {{read of uninitialized object}};
   return 0;
 }
@@ -1292,7 +1293,8 @@ 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}}
+  int arr[3]; // cxx14-warning {{uninitialized variable in a constexpr function is a C++20 extension}} \
+              // expected-note {{declared here}}
   arr[1] += a; // expected-note {{read of uninitialized object}};
   return 0;
 }
@@ -1304,7 +1306,7 @@ 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;
+  Foo f; // expected-note {{declared here}}
   f.val += a; // expected-note {{read of uninitialized object}};
   return 0;
 }



More information about the cfe-commits mailing list