erik.pilkington added inline comments.

================
Comment at: clang/lib/AST/ExprConstant.cpp:5461-5469
+    case APValue::LValue: {
+      LValue LVal;
+      LVal.setFrom(Info.Ctx, Val);
+      APValue RVal;
+      if (!handleLValueToRValueConversion(Info, BCE, Ty.withConst(),
+                                          LVal, RVal))
+        return false;
----------------
rsmith wrote:
> This looks wrong: bitcasting a pointer should not dereference the pointer and 
> store its pointee! (Likewise for a reference member.) But I think this should 
> actually simply be unreachable: we already checked for pointers and reference 
> members in `checkBitCastConstexprEligibilityType`.
> 
> (However, I think it currently *is* reached, because there's also some cases 
> where the operand of the bitcast is an lvalue, and the resulting lvalue gets 
> misinterpreted as a value of the underlying type, landing us here. See below.)
Okay, the new patch moves the read to handleBitCast. I added an unreachable 
here. 


================
Comment at: clang/lib/AST/ExprConstant.cpp:5761-5764
+    for (FieldDecl *FD : Record->fields()) {
+      if (!checkBitCastConstexprEligibilityType(Loc, FD->getType(), Info, Ctx))
+        return note(0, FD->getType(), FD->getBeginLoc());
+    }
----------------
rsmith wrote:
> The spec for `bit_cast` also asks us to check for members of reference type. 
> That can't happen because a type with reference members can never be 
> trivially-copyable, but please include an assert here to demonstrate to a 
> reader that we've thought about and handled that case.
Oh, it looks like the old patch crashed in this case! Turns out structs with 
reference members are trivially copyable.


================
Comment at: clang/lib/AST/ExprConstant.cpp:7098-7099
   case CK_BitCast:
+    // CK_BitCast originating from a __builtin_bit_cast have different 
constexpr
+    // semantics. This is only reachable when bit casting to nullptr_t.
+    if (isa<BuiltinBitCastExpr>(E))
----------------
rsmith wrote:
> I think this is reversed from the way I'd think about it: casts to `void*` 
> are modeled as bit-casts, and so need special handling here. (Theoretically 
> it'd be preferable to call the base class function for all other kinds of 
> bitcast we encounter, but it turns out to not matter because only bitcasts to 
> `nullptr_t` are ever evaluatable currently. In future we might want to 
> support bit-casts between integers and pointers (for constant folding only), 
> and then it might matter.)
The new patch creates a special cast kind for this, so no changes here are 
necessary here.


================
Comment at: clang/test/CodeGenCXX/builtin-bit-cast.cpp:100-112
+void test_array(int (&ary)[2]) {
+  // CHECK-LABEL: define void @_Z10test_arrayRA2_i
+  __builtin_bit_cast(unsigned long, ary);
+
+  // CHECK: [[ARY_PTR:%.*]] = alloca [2 x i32]*, align 8
+  // CHECK-NEXT: [[TEMP]] = alloca [2 x i32], align 8
+  // store ary into ARY_PTR
----------------
rsmith wrote:
> If we remove the `DefaultLvalueConversion` from building the bitcast 
> expression, we should be able to avoid the unnecessary extra alloca here, and 
> instead `memcpy` directly from `ary` to the `unsigned long`. (This is the 
> most important testcase in this file, since it's the only one that gives 
> `__builtin_bit_cast` an lvalue operand, which is what `std::bit_cast` will 
> do.)
`ScalarExprEmitter::VisitCastExpr` has to return a Value of type `i32` here 
though, so we don't know where to memcpy the array to when emitting the cast. I 
guess we could bitcast the pointer and load from it if the alignments are 
compatible, and fall back to a temporary otherwise (such as this case, where 
alignof(ary) is 4, but alignof(unsigned long) is 8). I think its more in the 
spirit of clang CodeGen to just emit simple code that always works though, then 
leave any optimizations to, well, the optimizer (assuming the `-O0` output 
isn't too horrible). We can use this CodeGen strategy for aggregate 
destinations, which the new patch does.

> This is the most important testcase in this file, since it's the only one 
> that gives __builtin_bit_cast an lvalue operand

Yeah, good point. New patch gives lvalue operands to the other calls.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D62825/new/

https://reviews.llvm.org/D62825



_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to