nickdesaulniers added inline comments.

================
Comment at: clang/lib/CodeGen/CGExprConstant.cpp:1324
     // This is a string literal initializing an array in an initializer.
-    return CGM.GetConstantArrayFromStringLiteral(E);
+    return E->isLValue() ?
+      CGM.GetAddrOfConstantStringFromLiteral(E).getPointer() :
----------------
efriedma wrote:
> nickdesaulniers wrote:
> > nickdesaulniers wrote:
> > > efriedma wrote:
> > > > nickdesaulniers wrote:
> > > > > efriedma wrote:
> > > > > > Maybe we should have a separate ConstExprEmitterLValue... trying to 
> > > > > > handle both LValues and RValues on the same codepath has been 
> > > > > > problematic in the past.  It's very easy for code to get confused 
> > > > > > what it's actually trying to emit.
> > > > > So we'd have a `ConstExprEmitterLValue` class with some visitor 
> > > > > methods, and a `ConstExprEmitterRValue` with other methods 
> > > > > implemented?
> > > > Something like that.
> > > > 
> > > > Actually thinking about it a bit more, not sure you need to actually 
> > > > implement ConstExprEmitterLValue for now.  You might just be able to 
> > > > ensure we don't ever call ConstExprEmitter with an lvalue.  The current 
> > > > ConstExprEmitter doesn't expect lvalues, and shouldn't call itself with 
> > > > lvalues.  (We bail on explicit LValueToRValue conversions.)  And 
> > > > Evaluate() shouldn't actually evaluate the contents of an lvalue if it 
> > > > isn't dereferenced, so there hopefully aren't any performance issues 
> > > > using that codepath.
> > > > 
> > > > In terms of implementation, I guess that's basically restoring the 
> > > > destType->isReferenceType() that got removed?  (I know I suggested it, 
> > > > but I wasn't really thinking about it...)
> > > One thing I think we may need to add to `ConstExprEmitter` is the ability 
> > > to evaluate `CallExpr`s based on certain test case failures...does that 
> > > seem right?
> > See also the calls to `constexpr f()` in 
> > clang/test/CodeGenCXX/const-init-cxx1y.cpp
> The only things I know of that Evaluate() can't handle are CK_ToUnion, 
> CK_ReinterpretMemberPointer, and DesignatedInitUpdateExpr.  
> DesignatedInitUpdateExpr is related to the failures in 
> test/CodeGenCXX/designated-init.cpp; I don't think the others show up in any 
> of the testcases you've mentioned.  (CK_ToUnion can't appear in C++ code. 
> CK_ReinterpretMemberPointer is a `reinterpret_cast<T>` where T is a member 
> pointer type.)
> 
> Given none of those constructs show up in const-init-cxx1y.cpp, the only 
> reason for it to fail is if we aren't correctly falling back for a construct 
> the current code doesn't know how to handle.  You shouldn't need to implement 
> any new constructs.
in clang/test/CodeGenCXX/designated-init.cpp we have:
```
>> 22 namespace ModifyStaticTemporary {                                         
>>       
   23   struct A { int &&temporary; int x; };                                   
      
   24   constexpr int f(int &r) { r *= 9; return r - 12; }                      
      
   25   A a = { 6, f(a.temporary) };
```
In the AST, that looks like:
```
| |-VarDecl 0x562b77df39b0 <line:25:3, col:29> col:5 used a 
'A':'ModifyStaticTemporary::A' cinit
| | `-ExprWithCleanups 0x562b77df3c68 <col:9, col:29> 
'A':'ModifyStaticTemporary::A'
| |   `-InitListExpr 0x562b77df3bb8 <col:9, col:29> 
'A':'ModifyStaticTemporary::A'
| |     |-MaterializeTemporaryExpr 0x562b77df3c08 <col:11> 'int' xvalue 
extended by Var 0x562b77df39b0 'a' 'A':'ModifyStaticTemporary::A'
| |     | `-IntegerLiteral 0x562b77df3a18 <col:11> 'int' 6
| |     `-CallExpr 0x562b77df3b30 <col:14, col:27> 'int'
| |       |-ImplicitCastExpr 0x562b77df3b18 <col:14> 'int (*)(int &)' 
<FunctionToPointerDecay>
| |       | `-DeclRefExpr 0x562b77df3ad0 <col:14> 'int (int &)' lvalue Function 
0x562b77df37a0 'f' 'int (int &)'
| |       `-MemberExpr 0x562b77df3aa0 <col:16, col:18> 'int' lvalue .temporary 
0x562b77df35c0
| |         `-DeclRefExpr 0x562b77df3a80 <col:16> 
'A':'ModifyStaticTemporary::A' lvalue Var 0x562b77df39b0 'a' 
'A':'ModifyStaticTemporary::A'
```
(So, indeed no `DesignatedInitUpdateExpr`) but the call to the `constexpr` 
`f()` updates the reference (to `54`).  If I remove the visitor for 
`MaterializeTemporaryExpr`, we fail to evaluate `f` and end up emitting `6` 
rather than `54`.  Doesn't that mean that the fast path (`ConstExprEmitter`) 
needs to be able to evaluate `CallExpr`?

Or should `VisitInitListExpr` bail if any of the inits 
`isa<MaterializeTemporaryExpr>` (or perhaps `isa<CallExpr>`)?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D151587

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

Reply via email to