https://github.com/tbaederr updated https://github.com/llvm/llvm-project/pull/230388
>From ad5c16897f5cd61a96b1413747cc4c1786d4b6cb 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/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 a0324240ce34da..827585946c9cb5 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -1097,6 +1097,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))); } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
