Skip to content

Conversation

asavonic
Copy link
Collaborator

@asavonic asavonic commented Sep 5, 2025

Clang warns about UB when a reinterpret_cast is dereferenced as an incompatible type:

  long l;
  *reinterpret_cast<double*>(&l) // UB

However, the code was too strict and did not handle extra parens around a reinterpret_cast, so the following case was not diagnosed:

  long l;
  *(reinterpret_cast<double*>(&l)) // UB, but no warning

The patch now skips ParenExpr when looking for a CXXReinterpretCastExpr to enable a diagnostic for the second case.

Clang warns about UB when a reinterpret_cast is dereferenced as an
incompatible type:

  long l;
  *reinterpret_cast<double*>(&l) // UB

However, the code was too strict and did not handle extra parens
around a reinterpret_cast, so the following case was not diagnosed:

  long l;
  *(reinterpret_cast<double*>(&l)) // UB, but no warning

The patch now skips ParenExpr when looking for a
CXXReinterpretCastExpr to enable a diagnostic for the second case.
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Sep 5, 2025
@llvmbot
Copy link
Member

llvmbot commented Sep 5, 2025

@llvm/pr-subscribers-clang

Author: Andrew Savonichev (asavonic)

Changes

Clang warns about UB when a reinterpret_cast is dereferenced as an incompatible type:

  long l;
  *reinterpret_cast&lt;double*&gt;(&amp;l) // UB

However, the code was too strict and did not handle extra parens around a reinterpret_cast, so the following case was not diagnosed:

  long l;
  *(reinterpret_cast&lt;double*&gt;(&amp;l)) // UB, but no warning

The patch now skips ParenExpr when looking for a CXXReinterpretCastExpr to enable a diagnostic for the second case.


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

2 Files Affected:

  • (modified) clang/lib/Sema/SemaExpr.cpp (+1-1)
  • (modified) clang/test/SemaCXX/reinterpret-cast.cpp (+3)
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 8565b18078185..f7e02805ae9d0 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -14774,7 +14774,7 @@ static QualType CheckIndirectionOperand(Sema &S, Expr *Op, ExprValueKind &VK,
   QualType OpTy = Op->getType();
   QualType Result;
 
-  if (isa<CXXReinterpretCastExpr>(Op)) {
+  if (isa<CXXReinterpretCastExpr>(Op->IgnoreParens())) {
     QualType OpOrigType = Op->IgnoreParenCasts()->getType();
     S.CheckCompatibleReinterpretCast(OpOrigType, OpTy, /*IsDereference*/true,
                                      Op->getSourceRange());
diff --git a/clang/test/SemaCXX/reinterpret-cast.cpp b/clang/test/SemaCXX/reinterpret-cast.cpp
index bfb808773b900..fdaa17a35eb8b 100644
--- a/clang/test/SemaCXX/reinterpret-cast.cpp
+++ b/clang/test/SemaCXX/reinterpret-cast.cpp
@@ -167,6 +167,9 @@ void dereference_reinterpret_cast() {
   (void)reinterpret_cast<float&>(d);  // expected-warning {{reinterpret_cast from 'double' to 'float &' has undefined behavior}}
   (void)*reinterpret_cast<float*>(&d);  // expected-warning {{dereference of type 'float *' that was reinterpret_cast from type 'double *' has undefined behavior}}
 
+  // Look through parens
+  (void)*(reinterpret_cast<double*>(&l));  // expected-warning {{dereference of type 'double *' that was reinterpret_cast from type 'long *' has undefined behavior}}
+
   // TODO: add warning for tag types
   (void)reinterpret_cast<A&>(b);
   (void)*reinterpret_cast<A*>(&b);

Copy link
Contributor

@Fznamznon Fznamznon left a comment

Choose a reason for hiding this comment

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

LGTM, thanks!

Copy link
Collaborator

@shafik shafik left a comment

Choose a reason for hiding this comment

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

Please add a release note.

@@ -167,6 +167,9 @@ void dereference_reinterpret_cast() {
(void)reinterpret_cast<float&>(d); // expected-warning {{reinterpret_cast from 'double' to 'float &' has undefined behavior}}
(void)*reinterpret_cast<float*>(&d); // expected-warning {{dereference of type 'float *' that was reinterpret_cast from type 'double *' has undefined behavior}}

// Look through parens
(void)*(reinterpret_cast<double*>(&l)); // expected-warning {{dereference of type 'double *' that was reinterpret_cast from type 'long *' has undefined behavior}}
Copy link
Collaborator

Choose a reason for hiding this comment

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

I am assuming this ignores multiple parens, maybe worth a test?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Sure, added a test.

@asavonic asavonic force-pushed the clang/reinterpret-cast-parens branch from b834be0 to 059fe2b Compare September 9, 2025 11:37
@asavonic
Copy link
Collaborator Author

asavonic commented Sep 9, 2025

Please add a release note.

Thanks! Done.

@asavonic asavonic merged commit 3ade874 into llvm:main Sep 12, 2025
10 checks passed
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.

4 participants