[PATCH] D76420: Prevent IR-gen from emitting consteval declarations

Richard Smith - zygoloid via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Thu May 21 14:05:54 PDT 2020


rsmith accepted this revision.
rsmith marked an inline comment as done.
rsmith added a comment.
This revision is now accepted and ready to land.

Thanks! Looks good.

I'd like to eventually get to a point where every `ConstantExpr` that reaches code generation has `hasAPValueResult()` return `true`, but that doesn't need to be done now.



================
Comment at: clang/lib/AST/ExprConstant.cpp:6807-6808
 
+    llvm::SaveAndRestore<bool> InConstantContext(Info.InConstantContext, true);
     return StmtVisitorTy::Visit(E->getSubExpr());
   }
----------------
Tyker wrote:
> rsmith wrote:
> > I don't think this is really right, but perhaps the difference isn't observable right now. What I'm thinking of is a case like this:
> > 
> > ```
> > consteval int do_stuff() {
> >   __builtin_produce_diagnostic("hello world\n");
> >   return 42;
> > }
> > constexpr int f() {
> >   int n = do_stuff();
> >   return n;
> > }
> > int k = f();
> > ```
> > 
> > Here, I would expect that when we process the immediate invocation of `do_stuff()` in `f`, we would immediately evaluate it, including issuing its diagnostic. And then for all subsequent calls to `f()`, we would never re-evaluate it.
> > 
> > I can see a couple of ways this could work:
> > 
> >  * Whenever we create a `ConstantExpr`, we always evaluate it and fill in the `APValue` result; it's never absent except perhaps in a window of time between forming that AST node and deciding for sure that we want to keep it (for nested immediate invocation handling).
> >  * Whenever constant evaluation meets a `ConstantExpr` that doesn't have an associated result yet, it triggers that result to be computed and cached, as a separate evaluation.
> > 
> > I think the first of those two approaches is much better: lazily evaluating the `ConstantExpr` will require us to save update records if we're writing an AST file, and will mean we don't always have an obvious point where the side-effects from builtin consteval functions (eg, reflection-driven actions) happen.
> > 
> > So I think the right thing to do is probably to say that a `ConstantExpr` that hasn't yet had its `APValue` result filled in is non-constant for now, and to ensure that everywhere that creates a `ConstantExpr` always eventually either removes it again or fills in the result.
> ok seems reasonable.
> 
OK, so we're still evaluating through a not-yet-evaluated immediate invocation. This is subtle, but I think it's correct: when this happens, either we're in some enclosing immediate invocation, in which case we want to perform any side-effects from inside this `ConstantExpr`, or we're not, in which case those side-effects should be prohibited anyway.


================
Comment at: clang/lib/CodeGen/CGExprConstant.cpp:1374
+      emitAbstract(CE->getBeginLoc(), CE->getAPValueResult(), RetType);
+  return Res;
+}
----------------
Tyker wrote:
> rsmith wrote:
> > Can we assert that we succeeded here? This emission should never fail.
> from the comment on emitAbstract's declaration it seems to already be the case.
> ```
>   /// Emit the result of the given expression as an abstract constant,
>   /// asserting that it succeeded.  This is only safe to do when the
>   /// expression is known to be a constant expression with either a fairly
>   /// simple type or a known simple form.
>   llvm::Constant *emitAbstract(const Expr *E, QualType T);
>   llvm::Constant *emitAbstract(SourceLocation loc, const APValue &value,
>                                QualType T);
> ``` 
Given that this function can return `nullptr` on other control paths, I think it would be useful (as documentation of the intent) to `assert(Res);` here, even if `emitAbstract` already guarantees that.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D76420





More information about the cfe-commits mailing list