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 01edda57c798992ee4ac4ef4515cff4298c054c0 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 6863d9c2633df..21ec78c599250 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 6b9aef5d479a6..5b4d18c0c1a9b 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 0531dfa877fbd..4d5b5d909fcbf 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 a5e0929a76e8c2f283108f4477569621885868ce 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 21ec78c599250..c50c411f61af6 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 5b4d18c0c1a9b..196bd1e8d1426 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
