This is an archive of the discontinued LLVM Phabricator instance.

Fix PR28366: Teach the const-expression evaluator to be more fault tolerant with non-const enclosing local variables, or otherwise fold them if const.
ClosedPublic

Authored by faisalv on Aug 14 2016, 3:41 PM.

Details

Reviewers
hans
rsmith
Summary

Fix the following Bug:
https://llvm.org/bugs/show_bug.cgi?id=28366

This patch teaches the constant expression evaluator to search the frame stack for a local variable (instead of assuming a local variable is on the current frame).

This has the following benefits:

  • if the local variable from an enclosing scope was an error during parsing/instantiation - it remains an error (instead of a compiler crash) during constant expression evaluation
  • a local variable that is a constant expression from an enclosing scope is now evaluatable

Additionally, fix SemaTemplateInstantiateDecl so that when it instantiates the enable_if attribute it uses the instantiated declaration (instead of the template) when evaluating the condition (so that the instantiated param's decl context is correctly found). This was done to fix the following regression:

template <typename T> T templatedBar(T m) attribute((enable_if(m > 0, ""))) { return T(); }

Diff Detail

Event Timeline

faisalv updated this revision to Diff 67990.Aug 14 2016, 3:41 PM
faisalv retitled this revision from to Fix PR28366: Teach the const-expression evaluator to be more fault tolerant with non-const enclosing local variables, or otherwise fold them if const..
faisalv updated this object.
faisalv added reviewers: rsmith, hans.
faisalv set the repository for this revision to rL LLVM.
faisalv added a subscriber: cfe-commits.
rsmith added inline comments.Aug 15 2016, 1:19 PM
lib/AST/ExprConstant.cpp
4791–4802

This doesn't seem right to me: in the case where the variable is not in the expected frame, there seems to be no reason to expect it would be in a caller's frame rather than in some unrelated place, nor to special-case that situation. (And this does the wrong thing for constexpr lambdas, where the captured variable need not be in the *innermost* call frame for the function in which the variable was declared.)

Instead, how about changing the VD->hasLocalStorage() && ... condition below to also check that the DeclContext of the VarDecl is the callee of the current call, and leave Frame null otherwise.

faisalv updated this revision to Diff 68091.Aug 15 2016, 3:21 PM
faisalv removed rL LLVM as the repository for this revision.

Updated the patch per Richard's direction (which helped clarify my thinking about this): Check only the current call frame - if the VarDecl is contained within the current callee - only then does it make sense to dig into the stack-variables of the frame. No other scenario really makes sense (even for lambdas, we care about the parent decl-contexts (static binding), not variables within the call-frame stack (run-time binding).

Thanks Richard.

faisalv marked an inline comment as done.Aug 15 2016, 3:21 PM
rsmith added inline comments.Aug 17 2016, 3:53 PM
lib/AST/ExprConstant.cpp
4795–4797

This is talking too much about the what and not enough about the why. "We expect to find a value for a local variable in the current frame, unless the variable was actually declared in a lexically-enclosing context." or something like that?

4798–4800

This can be specified more simply as:

if (Info.CurrentCall->Callee &&
    Info.CurrentCall->Callee->Equals(VD->getDeclContext()))
lib/Sema/SemaTemplateInstantiateDecl.cpp
190

Do we have existing test coverage for this (tests that fail with the ExprConstant change if we don't fix this at the same time)?

test/SemaCXX/constant-expression-cxx11.cpp
2091

Maybe also static_assert that we get the correct value here?

faisalv updated this revision to Diff 68644.Aug 18 2016, 8:06 PM
faisalv marked 4 inline comments as done.

Address Richard's comments.

Address Richard's comments.

lib/Sema/SemaTemplateInstantiateDecl.cpp
190

Yes we do. That's how I realized it needed to be fixed - it's enable_if.cpp in SemaCXX that has the following test:
template <typename T> T templatedBar(T m) attribute((enable_if(m > 0, ""))) { return T(); }

rsmith accepted this revision.Aug 22 2016, 4:53 PM
rsmith edited edge metadata.

LGTM, thanks!

test/SemaCXX/constant-expression-cxx11.cpp
2091

I would use 'c' + 'd' here, just in case we get the same incorrect value evaluating one of these in both places. (That is, if d incorrectly evaluated to 0 both here and on line 2088, this assert would still pass.)

This revision is now accepted and ready to land.Aug 22 2016, 4:53 PM

Looks like patch was not committed.