llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Aditya Chaudhary (aditya-chaudhary1) <details> <summary>Changes</summary> A bit-field has no address, so a reference cannot bind to it directly. As per [[expr.static.cast]](https://en.cppreference.com/cpp/language/static_cast), the lvalue-to-rvalue conversion must be applied to the bit-field first, and the reference must then bind to a materialized temporary holding the resulting value. Clang does not do this today. `TryLValueToRValueCast` in SemaCast.cpp accepts the cast as a `CK_NoOp` xvalue cast without checking for a bit-field, which produces this AST: ``` CXXStaticCastExpr <NoOp> xvalue `-MemberExpr lvalue bitfield .a ``` There is no `LValueToRValue` conversion and no `MaterializeTemporaryExpr`. As a result, CodeGen reaches `EmitReferenceBindingToExpr` with a bit-field LValue and hits `assert(LV.isSimple())`. [N4971 Document](https://isocpp.org/files/papers/N4971.pdf) --- Full diff: https://github.com/llvm/llvm-project/pull/231092.diff 2 Files Affected: - (added) clang/test/AST/ast-dump-rvalue-ref-bitfield.cpp (+29) - (added) clang/test/CodeGenCXX/rvalue-ref-bitfield.cpp (+23) ``````````diff diff --git a/clang/test/AST/ast-dump-rvalue-ref-bitfield.cpp b/clang/test/AST/ast-dump-rvalue-ref-bitfield.cpp new file mode 100644 index 0000000000000..38ed402ef3898 --- /dev/null +++ b/clang/test/AST/ast-dump-rvalue-ref-bitfield.cpp @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -std=c++11 -fsyntax-only \ +// RUN: -ast-dump -ast-dump-filter test %s | FileCheck %s + +// static_cast<T&&> applied to a bit-field lvalue. A bit-field has no address, +// so the reference has to bind to a materialized temporary. +// +// FIXME: Clang currently binds the reference directly to the bit-field. No +// MaterializeTemporaryExpr or LValueToRValue conversion is created, and this +// AST crashes CodeGen (see CodeGenCXX/rvalue-ref-bitfield.cpp). + +struct A { + int a : 4; + int b : 1; +}; + +void test(A obj) { + int &&r = static_cast<int &&>(obj.a); + const int &&cr = static_cast<const int &&>(obj.a); +} + +// CHECK-LABEL: FunctionDecl {{.*}} test 'void (A)' +// CHECK: VarDecl {{.*}} r 'int &&' cinit +// CHECK-NEXT: `-CXXStaticCastExpr {{.*}} 'int' xvalue static_cast<int &&> <NoOp> +// CHECK-NEXT: `-MemberExpr {{.*}} 'int' lvalue bitfield .a +// CHECK-NEXT: `-DeclRefExpr {{.*}} 'A' lvalue ParmVar {{.*}} 'obj' 'A' +// CHECK: VarDecl {{.*}} cr 'const int &&' cinit +// CHECK-NEXT: `-CXXStaticCastExpr {{.*}} 'const int' xvalue static_cast<const int &&> <NoOp> +// CHECK-NEXT: `-MemberExpr {{.*}} 'int' lvalue bitfield .a +// CHECK-NEXT: `-DeclRefExpr {{.*}} 'A' lvalue ParmVar {{.*}} 'obj' 'A' diff --git a/clang/test/CodeGenCXX/rvalue-ref-bitfield.cpp b/clang/test/CodeGenCXX/rvalue-ref-bitfield.cpp new file mode 100644 index 0000000000000..0c0c60ad3a6d5 --- /dev/null +++ b/clang/test/CodeGenCXX/rvalue-ref-bitfield.cpp @@ -0,0 +1,23 @@ +// REQUIRES: asserts +// RUN: not --crash %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown \ +// RUN: -emit-llvm -o - %s -DNONCONST 2>&1 | FileCheck %s --check-prefix=CHECK-NONCONST +// RUN: not --crash %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown \ +// RUN: -emit-llvm -o - %s -DCONST 2>&1 | FileCheck %s --check-prefix=CHECK-CONST + +// static_cast<T&&> of a bit-field lvalue should materialize a temporary. +// FIXME: Sema binds the reference directly to the bit-field, so CodeGen +// receives a bit-field LValue and asserts in EmitReferenceBindingToExpr. +// Each case is guarded by its own macro because the crash aborts the whole +// compilation. + +struct S { int a : 4; }; + +#ifdef NONCONST +// CHECK-NONCONST: {{Assertion.*LV.isSimple\(\)}} +int &&f(S s) { return static_cast<int &&>(s.a); } +#endif + +#ifdef CONST +// CHECK-CONST: {{Assertion.*LV.isSimple\(\)}} +const int &&g(const S &s) { return static_cast<const int &&>(s.a); } +#endif `````````` </details> https://github.com/llvm/llvm-project/pull/231092 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
