https://github.com/tbaederr created https://github.com/llvm/llvm-project/pull/230388
A constant expression gets its type from its subexpression, but if it has an APValue result, that result kind might not match the ast node type at all. E.g. it is currently perfectly possible to create a `ConstantExpr` of int type, but give it a float result. Such a mismatch can cause problems in later compilation stages since the value of a node and its evaluated result should match, in other words, the cached result and the subexpr should be interchangeable. This helps finding problems such as https://github.com/llvm/llvm-project/pull/227998 or the missing lvalue-to-rvalue conversion I added in this patch. >From 3066eaa6046823b1fef7175f47192f9ed148335d 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] [clang][AST] Assert that ConstantExpr type and APValue kind match --- clang/lib/AST/Expr.cpp | 72 +++++++++++++++++++++++++++++++++ clang/lib/Sema/SemaChecking.cpp | 2 + 2 files changed, 74 insertions(+) diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 6b9aef5d479a61..5b6d3bf83c9936 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -319,6 +319,77 @@ 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()) { + assert((V.isInt() || V.isAddrLabelDiff()) && + "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->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; + } +} + ConstantResultStorageKind ConstantExpr::getStorageKind(const Type *T, const ASTContext &Context) { if (T->isIntegralOrEnumerationType() && Context.getTypeInfo(T).Width <= 64) @@ -384,6 +455,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))); } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
