Timm =?utf-8?q?Bäder?= <[email protected]>
Message-ID:
In-Reply-To: <llvm.org/llvm/llvm-project/pull/[email protected]>


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

>From 56cdc3d732126f91f1fdd2b0581cde7c88de3fbd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <[email protected]>
Date: Fri, 9 Oct 2026 09:28:23 +0200
Subject: [PATCH 1/2] [clang][AST] Assert that ConstantExpr type and APValue
 kind match

---
 clang/include/clang/AST/Expr.h  |   4 ++
 clang/lib/AST/Expr.cpp          | 102 ++++++++++++++++++++++++++++++++
 clang/lib/Sema/SemaChecking.cpp |   2 +
 3 files changed, 108 insertions(+)

diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 6863d9c2633df8..21ec78c5992502 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -1101,6 +1101,10 @@ enum class ConstantResultStorageKind { None, Int64, 
APValue };
 
 /// ConstantExpr - An expression that occurs in a constant context and
 /// optionally the result of evaluating the expression.
+///
+/// Note that the subexpression of a ConstantExpr and its APValue result are
+/// supposed to be interchaneable. That means, in particular, that the kind of
+/// the stored result and the type of the ConstantExpr need to match.
 class ConstantExpr final
     : public FullExpr,
       private llvm::TrailingObjects<ConstantExpr, APValue, uint64_t> {
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 6b9aef5d479a61..5b4d18c0c1a9bc 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -319,6 +319,107 @@ ConstantResultStorageKind 
ConstantExpr::getStorageKind(const APValue &Value) {
   }
 }
 
+// Check that V is a valid APValue result of E, i.e. the node type needs to
+// match the APValue kind.
+static void assertAPValueKind(const ConstantExpr *E, const APValue &V) {
+  // FIXME: We shouldn't be creating ConstantExpr nodes for missing APValues in
+  // the first place, but for the time being, accept this for any type.
+  if (V.isAbsent())
+    return;
+
+  if (E->isGLValue()) {
+    // NOTE: The restrictions for lvalue expressions are not 100% clear. We
+    // can't assert(V.isLValue()) because some ConstantExprs are lvalue and
+    // their result is a string literal, so an Array.
+    assert((V.isLValue() || V.isArray()) &&
+           "a lvalue ConstantExpr needs an lvalue APValue");
+    return;
+  }
+
+  QualType T = E->getType();
+  if (T->isIntegralOrEnumerationType()) {
+    // An expression containing a PointerToIntegral cast gets evaluated to an
+    // LValue, so we have to allow LValue APValues here.
+    assert((V.isInt() || V.isAddrLabelDiff() || V.isLValue()) &&
+           "a ConstantExpr of integer type needs an int APValue result");
+    return;
+  }
+
+  if (T->isRealFloatingType()) {
+    assert(V.isFloat() &&
+           "a ConstantExpr of floating type needs a float APValue result");
+    return;
+  }
+
+  if (T->isAnyComplexType()) {
+    QualType ElemTy = T->getAs<ComplexType>()->getElementType();
+    if (ElemTy->isIntegralOrEnumerationType())
+      assert(V.isComplexInt() &&
+             "a complex int ConstantExpr needs a complex int APValue");
+    else if (ElemTy->isFloatingType())
+      assert(V.isComplexFloat() &&
+             "a complex float ConstantExpr needs a complex float APValue");
+    else
+      llvm_unreachable("Complex element types must be either float or int");
+    return;
+  }
+
+  if (T->isVectorType()) {
+    assert(V.isVector() && "a vector ConstantExpr needs a vector APValue");
+    return;
+  }
+
+  if (T->isMatrixType()) {
+    assert(V.isMatrix() && "a matrix ConstantExpr needs a matrix APValue");
+    return;
+  }
+
+  if (T->isPointerType()) {
+    assert(V.isLValue() && "a pointer ConstantExpr needs an lvalue APValue");
+    return;
+  }
+
+  if (T->isNullPtrType()) {
+    assert(V.isLValue() &&
+           "a nullptr_t pointer ConstantExpr needs an lvalue APValue");
+    assert(V.isNullPointer() &&
+           "a nullptr_t ConstantExpr needs a nullptr APValue");
+    return;
+  }
+
+  if (T->isFixedPointType()) {
+    assert(V.isFixedPoint() &&
+           "a fixed point ConstantExpr needs a fixed point APValue");
+    return;
+  }
+
+  if (T->isMemberPointerType()) {
+    assert(V.isMemberPointer() &&
+           "a member pointer ConstantExpr needs a member pointer APValue");
+    return;
+  }
+
+  if (T->isRecordType()) {
+    // Yes, this happens.
+    if (V.isArray())
+      return;
+    const RecordDecl *RD = T->getAsRecordDecl();
+    if (RD->isUnion())
+      assert(V.isUnion() && "a union ConstantExpr needs a union APValue");
+    else
+      assert(V.isStruct() && "a record ConstantExpr needs a struct APValue");
+    return;
+  }
+
+  if (T->isMetaInfoType()) {
+    assert(V.isReflection() &&
+           "a std::meta_info ConstantExpr needs a Reflection APValue");
+    return;
+  }
+
+  llvm_unreachable("");
+}
+
 ConstantResultStorageKind
 ConstantExpr::getStorageKind(const Type *T, const ASTContext &Context) {
   if (T->isIntegralOrEnumerationType() && Context.getTypeInfo(T).Width <= 64)
@@ -384,6 +485,7 @@ ConstantExpr *ConstantExpr::CreateEmpty(const ASTContext 
&Context,
 void ConstantExpr::MoveIntoResult(APValue &Value, const ASTContext &Context) {
   assert((unsigned)getStorageKind(Value) <= ConstantExprBits.ResultKind &&
          "Invalid storage for this value kind");
+  assertAPValueKind(this, Value);
   ConstantExprBits.APValueKind = Value.getKind();
   switch (getResultStorageKind()) {
   case ConstantResultStorageKind::None:
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 0531dfa877fbdf..4d5b5d909fcbf4 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -6908,6 +6908,8 @@ bool Sema::BuiltinAssumeAligned(CallExpr *TheCall) {
       Diag(TheCall->getBeginLoc(), diag::warn_assume_aligned_too_great)
           << SecondArg->getSourceRange() << Sema::MaximumAlignment;
 
+    SecondArg = DefaultLvalueConversion(SecondArg).get();
+
     TheCall->setArg(1,
                     ConstantExpr::Create(Context, SecondArg, APValue(Result)));
   }

>From d2d7506b900e383784f27562def355bb043b4203 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <[email protected]>
Date: Sat, 10 Oct 2026 07:34:03 +0200
Subject: [PATCH 2/2] typo

---
 clang/include/clang/AST/Expr.h | 2 +-
 clang/lib/AST/Expr.cpp         | 5 +++++
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 21ec78c5992502..c50c411f61af69 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -1103,7 +1103,7 @@ enum class ConstantResultStorageKind { None, Int64, 
APValue };
 /// optionally the result of evaluating the expression.
 ///
 /// Note that the subexpression of a ConstantExpr and its APValue result are
-/// supposed to be interchaneable. That means, in particular, that the kind of
+/// supposed to be interchangeable. That means, in particular, that the kind of
 /// the stored result and the type of the ConstantExpr need to match.
 class ConstantExpr final
     : public FullExpr,
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 5b4d18c0c1a9bc..d9bfb16219424b 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -417,6 +417,11 @@ static void assertAPValueKind(const ConstantExpr *E, const 
APValue &V) {
     return;
   }
 
+  if (T->isArrayType()){
+    assert(V.isArray()  && "an array ConstantExpr needs an array APValue");
+    return;
+  }
+
   llvm_unreachable("");
 }
 

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to