llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Timm Baeder (tbaederr) <details> <summary>Changes</summary> --- Full diff: https://github.com/llvm/llvm-project/pull/125476.diff 3 Files Affected: - (modified) clang/lib/AST/ByteCode/Compiler.cpp (+25-4) - (modified) clang/lib/AST/ByteCode/Compiler.h (+1) - (modified) clang/test/AST/ByteCode/unions.cpp (+29-1) ``````````diff 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 `````````` </details> https://github.com/llvm/llvm-project/pull/125476 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits