nickdesaulniers added inline comments.

================
Comment at: clang/lib/AST/ExprConstant.cpp:8360
+  // Do not constant fold an R-value.
+  if (Info.EvalMode == EvalInfo::EM_ConstantFold && !E->isLValue())
+    return false;
----------------
efriedma wrote:
> efriedma wrote:
> > nickdesaulniers wrote:
> > > efriedma wrote:
> > > > nickdesaulniers wrote:
> > > > > nickdesaulniers wrote:
> > > > > > efriedma wrote:
> > > > > > > nickdesaulniers wrote:
> > > > > > > > efriedma wrote:
> > > > > > > > > Checking isLValue() doesn't make sense; consider:
> > > > > > > > > 
> > > > > > > > > ```
> > > > > > > > > struct R { mutable long x; };
> > > > > > > > > struct Z { const R &x, y; };
> > > > > > > > > Z z = { R{1}, z.x.x=10 };
> > > > > > > > > ```
> > > > > > > > > 
> > > > > > > > > Maybe also want to check for EM_IgnoreSideEffects?  Not sure 
> > > > > > > > > what cases, if any, that would affect.
> > > > > > > > > 
> > > > > > > > > We should probably check `E->getStorageDuration() == 
> > > > > > > > > SD_Static`.  The cases where it's a local temporary don't hit 
> > > > > > > > > the getOrCreateValue() codepath, so the evaluated value 
> > > > > > > > > should be handled correctly.
> > > > > > > > > 
> > > > > > > > > Checking EvalMode feels a little weird, but I guess it should 
> > > > > > > > > do the right thing in the cases I can think of?  I'd like a 
> > > > > > > > > second opinion on this.
> > > > > > > > Changing this condition to:
> > > > > > > > ```
> > > > > > > > if (E->getStorageDuration() == SD_Static &&                     
> > > > > > > >               
> > > > > > > >     Info.EvalMode == EvalInfo::EM_ConstantFold &&               
> > > > > > > >               
> > > > > > > >     E->isXValue())                                              
> > > > > > > >               
> > > > > > > >   return false;
> > > > > > > > ```
> > > > > > > > allows all tests in tree to pass, but messes up the test case 
> > > > > > > > you posted above. I'm trying to sus out what else might be 
> > > > > > > > different about that test case...we should return `false` for 
> > > > > > > > that, but I'm not sure what's different about that case.
> > > > > > > > 
> > > > > > > > In particular, I was playing with 
> > > > > > > > `E->isUsableInConstantExpressions` and 
> > > > > > > > `E->getLifetimeExtendedTemporaryDecl()`, but getting your case 
> > > > > > > > to work, I end up regressing 
> > > > > > > > clang/test/SemaCXX/attr-require-constant-initialization.cpp...argh!!
> > > > > > > Shouldn't that just be the following?
> > > > > > > 
> > > > > > > ```
> > > > > > > if (E->getStorageDuration() == SD_Static &&                       
> > > > > > >             
> > > > > > >     Info.EvalMode == EvalInfo::EM_ConstantFold)                   
> > > > > > >                                          
> > > > > > >   return false;
> > > > > > > ```
> > > > > > > 
> > > > > > > A materialized temporary is always going to be either an LValue 
> > > > > > > or an XValue, and the difference between the two isn't relevant 
> > > > > > > here.
> > > > > > I wish it were that simple. Checking those two alone will produce 
> > > > > > failures in the following tests:
> > > > > > 
> > > > > > Failed Tests (2):
> > > > > >   Clang :: CodeGenCXX/mangle-ms.cpp
> > > > > >   Clang :: SemaCXX/attr-require-constant-initialization.cpp
> > > > > > 
> > > > > > error: 'error' diagnostics seen but not expected: 
> > > > > >   File 
> > > > > > /android0/llvm-project/clang/test/SemaCXX/attr-require-constant-initialization.cpp
> > > > > >  Line 92: variable does not have a constant initializer
> > > > > > 
> > > > > > as an example of one failure, which is basically:
> > > > > > 
> > > > > > ```
> > > > > > void foo(void) {
> > > > > >   __attribute__((require_constant_initialization)) static const int 
> > > > > > &temp_init = 42;
> > > > > > }
> > > > > > ```
> > > > > > specifically, `-std=c++03` is the only language version that fails.
> > > > > > 
> > > > > Oh, perhaps it should simply be:
> > > > > 
> > > > > ```
> > > > > if (Info.EvalMode == EvalInfo::EM_ConstantFold && E->isXValue())
> > > > >   return false;
> > > > > ```
> > > > > 
> > > > > let me add your test case for that, too.
> > > > It looks like that case is using Expr::isConstantInitializer, which 
> > > > uses EM_ConstantFold, which then blows up.  No combination of the 
> > > > checks you're trying will let you distinguish between that case and the 
> > > > case you're trying to bail out; in both cases, the EvalMode is 
> > > > EvalMode, it's an lvalue, and the storage duration is static.
> > > > 
> > > > Maybe the code in question shouldn't be using isConstantInitializer at 
> > > > all.
> > > > 
> > > > Checking for a reference type doesn't solve anything; it just makes the 
> > > > issues more complicated to reproduce.
> > > d572f82e490b alludes to `Expr::isConstantInitializer` being error 
> > > prone...back in 2011...
> > > 
> > > > Maybe the code in question shouldn't be using isConstantInitializer at 
> > > > all.
> > > 
> > > Which code? My patch doesn't introduce explicit calls to that method.
> > > Which code?
> > 
> > Sema::CheckCompleteVariableDeclaration
> Maybe we can add a special case for binding SD_Static 
> MaterializeTemporaryExpr to references in Expr::isConstantInitializer, so it 
> doesn't try to evaluate them.  (Before the call to EvaluteAsLValue.)
`Expr::isConstantInitializer` is invoked for:

```
#define ATTR __attribute__((require_constant_initialization))
void x (void) {
  ATTR static const int &temp_init = 42;
}
```
it is not invoked for
```
struct R { mutable long x; };
struct Z { const R &x, y; };
Z z = { R{1}, z.x.x=10 };
```
so modifying `Expr::isConstantInitializer` rather than 
`LValueExprEvaluator::VisitMaterializeTemporaryExpr` will do nothing for the 
latter-case and produce incorrect results.


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