Skip to content

Conversation

@Lokesh-Reddy011
Copy link

@Lokesh-Reddy011 Lokesh-Reddy011 commented Nov 7, 2025

Description

This patch fixes an issue where constexpr evaluation failed for bitcasts between vector and integer types of equal bit width (e.g., __m64long long).

The change updates ExprConstant.cpp to allow reinterpretation when source and destination types have matching bit sizes. In that case, the APValue is copied directly instead of producing an error.

Fixes #159905

Example

The following code previously failed but now compiles successfully with the patch:

#include <immintrin.h>

constexpr __m64 foo(__m64 a, int b) {
    return (__m64)(long long)a << b;
}

int main() {
    foo((__m64){5}, 1);
    return 0;
}

Testing

  • Verified using clang++ -std=c++20 — works correctly after the patch.
  • Test not added to clang/test since it requires <immintrin.h>, whose path varies across systems.

@github-actions
Copy link

github-actions bot commented Nov 7, 2025

Thank you for submitting a Pull Request (PR) to the LLVM Project!

This PR will be automatically labeled and the relevant teams will be notified.

If you wish to, you can add reviewers by using the "Reviewers" section on this page.

If this is not working for you, it is probably because you do not have write permissions for the repository. In which case you can instead tag reviewers by name in a comment by using @ followed by their GitHub username.

If you have received no comments on your PR for a week, you can request a review by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate is once a week. Please remember that you are asking for valuable time from other developers.

If you have further questions, they may be answered by the LLVM GitHub User Guide.

You can also ask questions in a comment on this PR, on the LLVM Discord or on the forums.

@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Nov 7, 2025
@llvmbot
Copy link
Member

llvmbot commented Nov 7, 2025

@llvm/pr-subscribers-clang

Author: None (Lokesh-Reddy011)

Changes

Description

This patch fixes an issue where constexpr evaluation failed for bitcasts between vector and integer types of equal bit width (e.g., __m64long long).

The change updates ExprConstant.cpp to allow reinterpretation when source and destination types have matching bit sizes. In that case, the APValue is copied directly instead of producing an error.

Example

The following code previously failed but now compiles successfully with the patch:

#include &lt;immintrin.h&gt;

constexpr __m64 foo(__m64 a, int b) {
    return (__m64)(long long)a &lt;&lt; b;
}

int main() {
    foo((__m64){5}, 1);
    return 0;
}

Testing

  • Verified using clang++ -std=c++20 — works correctly after the patch.
  • Test not added to clang/test since it requires &lt;immintrin.h&gt;, whose path varies across systems.

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

1 Files Affected:

  • (modified) clang/lib/AST/ExprConstant.cpp (+18-1)
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 97eeba8b9d6cc..5b8900f02aeb9 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -17078,7 +17078,24 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) {
   case CK_HLSLAggregateSplatCast:
     llvm_unreachable("invalid cast kind for integral value");
 
-  case CK_BitCast:
+  case CK_BitCast:{
+  APValue Sub;
+  if (!Evaluate(Sub, Info, E->getSubExpr()))
+    return false;
+
+  QualType SrcTy = E->getSubExpr()->getType();
+  QualType DstTy = E->getType();
+
+  // Allow reinterpretation if bit widths match
+  if (Info.Ctx.getTypeSize(SrcTy) == Info.Ctx.getTypeSize(DstTy)) {
+    // Use APValue::BitCast if available, else just copy value bits
+    Result = Sub;
+    return true;
+  }
+
+  return Error(E);
+}
+
   case CK_Dependent:
   case CK_LValueBitCast:
   case CK_ARCProduceObject:

@Lokesh-Reddy011
Copy link
Author

Please let me know if further modifications or additional test coverage are recommended.

@zwuis
Copy link
Contributor

zwuis commented Nov 10, 2025

Thank you for your patch! Please reference the issue fixed by this PR in PR description.

Please let me know if further modifications or additional test coverage are recommended.

Tests are required. You might refer to PRs solving sub-issues of #30794 for writing tests.

@zwuis zwuis requested a review from RKSimon November 10, 2025 09:05
@RKSimon RKSimon requested a review from tbaederr November 10, 2025 10:34
@github-actions
Copy link

⚠️ C/C++ code formatter, clang-format found issues in your code. ⚠️

You can test this locally with the following command:
git-clang-format --diff origin/main HEAD --extensions cpp -- clang/lib/AST/ExprConstant.cpp --diff_from_common_commit

⚠️
The reproduction instructions above might return results for more than one PR
in a stack if you are using a stacked PR workflow. You can limit the results by
changing origin/main to the base branch/commit you want to compare against.
⚠️

View the diff from clang-format here.
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 9c958c0e1..fd20bcd0c 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -17724,23 +17724,23 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) {
   case CK_HLSLAggregateSplatCast:
     llvm_unreachable("invalid cast kind for integral value");
 
-  case CK_BitCast:{
-  APValue Sub;
-  if (!Evaluate(Sub, Info, E->getSubExpr()))
-    return false;
+  case CK_BitCast: {
+    APValue Sub;
+    if (!Evaluate(Sub, Info, E->getSubExpr()))
+      return false;
 
-  QualType SrcTy = E->getSubExpr()->getType();
-  QualType DstTy = E->getType();
+    QualType SrcTy = E->getSubExpr()->getType();
+    QualType DstTy = E->getType();
 
-  // Allow reinterpretation if bit widths match
-  if (Info.Ctx.getTypeSize(SrcTy) == Info.Ctx.getTypeSize(DstTy)) {
-    // Use APValue::BitCast if available, else just copy value bits
-    Result = Sub;
-    return true;
-  }
+    // Allow reinterpretation if bit widths match
+    if (Info.Ctx.getTypeSize(SrcTy) == Info.Ctx.getTypeSize(DstTy)) {
+      // Use APValue::BitCast if available, else just copy value bits
+      Result = Sub;
+      return true;
+    }
 
-  return Error(E);
-}
+    return Error(E);
+  }
 
   case CK_Dependent:
   case CK_LValueBitCast:

@RKSimon
Copy link
Collaborator

RKSimon commented Nov 10, 2025

You should be able to create a generic test without including anything:

typedef long long __m64 __attribute__((__vector_size__(8), __aligned__(8)));

constexpr __m64 PR159905(__m64 a, int b) {
    return (__m64)(long long)a << b;
}


// Allow reinterpretation if bit widths match
if (Info.Ctx.getTypeSize(SrcTy) == Info.Ctx.getTypeSize(DstTy)) {
// Use APValue::BitCast if available, else just copy value bits
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is APValue::BitCast?

case CK_BitCast:
case CK_BitCast:{
APValue Sub;
if (!Evaluate(Sub, Info, E->getSubExpr()))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We know the types before evaluating the subexpression, so we don't have to do this unless the sizes match.

Copy link
Collaborator

@RKSimon RKSimon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

test coverage

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[clang] Bitcasts from vectors to integers not supported at compile time

5 participants