llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Timm Baeder (tbaederr)

<details>
<summary>Changes</summary>

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.

---
Full diff: https://github.com/llvm/llvm-project/pull/230388.diff


2 Files Affected:

- (modified) clang/lib/AST/Expr.cpp (+72) 
- (modified) clang/lib/Sema/SemaChecking.cpp (+2) 


``````````diff
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)));
   }

``````````

</details>


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

Reply via email to