[clang] [clang][bytecode] Add special handling for union copy assign operators (PR #125476)
Timm Baeder via cfe-commits
cfe-commits at lists.llvm.org
Mon Feb 3 02:46:06 PST 2025
https://github.com/tbaederr created https://github.com/llvm/llvm-project/pull/125476
None
>From 1b01d45dbb9141d91ddb45344dd977122c19bcd8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbaeder at redhat.com>
Date: Mon, 3 Feb 2025 11:43:05 +0100
Subject: [PATCH] [clang][bytecode] Add special handling for union copy assign
operators
---
clang/lib/AST/ByteCode/Compiler.cpp | 29 ++++++++++++++++++++++++----
clang/lib/AST/ByteCode/Compiler.h | 1 +
clang/test/AST/ByteCode/unions.cpp | 30 ++++++++++++++++++++++++++++-
3 files changed, 55 insertions(+), 5 deletions(-)
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index b9e22ebb7a41a9..f23472f99ac1b5 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -4676,7 +4676,7 @@ bool Compiler<Emitter>::VisitCallExpr(const CallExpr *E) {
OCE && OCE->isAssignmentOp()) {
// Just like with regular assignments, we need to special-case assignment
// operators here and evaluate the RHS (the second arg) before the LHS (the
- // first arg. We fix this by using a Flip op later.
+ // first arg). We fix this by using a Flip op later.
assert(Args.size() == 2);
IsAssignmentOperatorCall = true;
std::reverse(Args.begin(), Args.end());
@@ -5664,6 +5664,21 @@ bool Compiler<Emitter>::compileDestructor(const CXXDestructorDecl *Dtor) {
return this->emitPopPtr(Dtor) && this->emitRetVoid(Dtor);
}
+template <class Emitter>
+bool Compiler<Emitter>::compileUnionCopyAssignmentOperator(
+ const CXXMethodDecl *MD) {
+ if (!this->emitThis(MD))
+ return false;
+
+ auto PVD = MD->getParamDecl(0);
+ ParamOffset PO = this->Params[PVD]; // Must exist.
+
+ if (!this->emitGetParam(PT_Ptr, PO.Offset, MD))
+ return false;
+
+ return this->emitMemcpy(MD) && this->emitRet(PT_Ptr, MD);
+}
+
template <class Emitter>
bool Compiler<Emitter>::visitFunc(const FunctionDecl *F) {
// Classify the return type.
@@ -5675,9 +5690,15 @@ bool Compiler<Emitter>::visitFunc(const FunctionDecl *F) {
return this->compileDestructor(Dtor);
// Emit custom code if this is a lambda static invoker.
- if (const auto *MD = dyn_cast<CXXMethodDecl>(F);
- MD && MD->isLambdaStaticInvoker())
- return this->emitLambdaStaticInvokerBody(MD);
+ if (const auto *MD = dyn_cast<CXXMethodDecl>(F)) {
+ const RecordDecl *RD = MD->getParent();
+
+ if (RD->isUnion() && MD->isCopyAssignmentOperator())
+ return this->compileUnionCopyAssignmentOperator(MD);
+
+ if (MD->isLambdaStaticInvoker())
+ return this->emitLambdaStaticInvokerBody(MD);
+ }
// Regular functions.
if (const auto *Body = F->getBody())
diff --git a/clang/lib/AST/ByteCode/Compiler.h b/clang/lib/AST/ByteCode/Compiler.h
index 5a02f38d78dec8..ecf50662d617bc 100644
--- a/clang/lib/AST/ByteCode/Compiler.h
+++ b/clang/lib/AST/ByteCode/Compiler.h
@@ -383,6 +383,7 @@ class Compiler : public ConstStmtVisitor<Compiler<Emitter>, bool>,
bool emitBuiltinBitCast(const CastExpr *E);
bool compileConstructor(const CXXConstructorDecl *Ctor);
bool compileDestructor(const CXXDestructorDecl *Dtor);
+ bool compileUnionCopyAssignmentOperator(const CXXMethodDecl *MD);
bool checkLiteralType(const Expr *E);
diff --git a/clang/test/AST/ByteCode/unions.cpp b/clang/test/AST/ByteCode/unions.cpp
index e90b123c90de0e..0a1f0f88650f27 100644
--- a/clang/test/AST/ByteCode/unions.cpp
+++ b/clang/test/AST/ByteCode/unions.cpp
@@ -402,7 +402,6 @@ namespace UnionInBase {
static_assert(return_uninit().a.x == 2);
}
-/// FIXME: Our diagnostic here is a little off.
namespace One {
struct A { long x; };
@@ -421,4 +420,33 @@ namespace One {
// both-note {{constinit}}
}
+namespace CopyAssign {
+ union A {
+ int a;
+ int b;
+ };
+
+ constexpr int f() {
+ A a{12};
+ A b{13};
+
+ b.b = 32;
+ b = a ;
+ return b.a;
+ }
+ static_assert(f()== 12);
+
+
+ constexpr int f2() {
+ A a{12};
+ A b{13};
+
+ b.b = 32;
+ b = a ;
+ return b.b; // both-note {{read of member 'b' of union with active member 'a'}}
+ }
+ static_assert(f2() == 12); // both-error {{not an integral constant expression}} \
+ // both-note {{in call to}}
+
+}
#endif
More information about the cfe-commits
mailing list