[PATCH] D23493: Fix PR28366: Teach the const-expression evaluator to be more fault tolerant with non-const enclosing local variables, or otherwise fold them if const.
Faisal Vali via cfe-commits
cfe-commits at lists.llvm.org
Mon Aug 15 15:21:05 PDT 2016
faisalv removed rL LLVM as the repository for this revision.
faisalv updated this revision to Diff 68091.
faisalv added a comment.
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.
https://reviews.llvm.org/D23493
Files:
lib/AST/ExprConstant.cpp
lib/Sema/SemaTemplateInstantiateDecl.cpp
test/SemaCXX/constant-expression-cxx11.cpp
Index: test/SemaCXX/constant-expression-cxx11.cpp
===================================================================
--- test/SemaCXX/constant-expression-cxx11.cpp
+++ test/SemaCXX/constant-expression-cxx11.cpp
@@ -2066,3 +2066,33 @@
constexpr Z z(1);
static_assert(z.w == 1 && z.x == 2 && z.y == 3 && z.z == 4, "");
}
+
+
+namespace PR28366 {
+namespace ns1 {
+
+void f(char c) { //expected-note2{{declared here}}
+ struct X {
+ static constexpr char f() { //expected-error{{never produces a constant expression}}
+ return c; //expected-error{{reference to local}} expected-note{{non-const variable}}
+ }
+ };
+ int I = X::f();
+}
+
+void g() {
+ const int c = 'c';
+ static const int d = 'd';
+ struct X {
+ static constexpr int f() {
+ return c + d;
+ }
+ };
+ constexpr int CD = X::f();
+}
+
+
+} // end ns1
+
+} //end ns PR28366
+
Index: lib/Sema/SemaTemplateInstantiateDecl.cpp
===================================================================
--- lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -187,7 +187,7 @@
SmallVector<PartialDiagnosticAt, 8> Diags;
if (A->getCond()->isValueDependent() && !Cond->isValueDependent() &&
- !Expr::isPotentialConstantExprUnevaluated(Cond, cast<FunctionDecl>(Tmpl),
+ !Expr::isPotentialConstantExprUnevaluated(Cond, cast<FunctionDecl>(New),
Diags)) {
S.Diag(A->getLocation(), diag::err_enable_if_never_constant_expr);
for (int I = 0, N = Diags.size(); I != N; ++I)
Index: lib/AST/ExprConstant.cpp
===================================================================
--- lib/AST/ExprConstant.cpp
+++ lib/AST/ExprConstant.cpp
@@ -4788,10 +4788,19 @@
return Error(E);
}
+
bool LValueExprEvaluator::VisitVarDecl(const Expr *E, const VarDecl *VD) {
CallStackFrame *Frame = nullptr;
- if (VD->hasLocalStorage() && Info.CurrentCall->Index > 1)
- Frame = Info.CurrentCall;
+ if (VD->hasLocalStorage() && Info.CurrentCall->Index > 1) {
+ // Only if the DeclContext of VD is the same as the called function do we
+ // set the Frame to the Current CallStackFrame, so that we can find its
+ // associated value from the variable-objects associated with that frame.
+ if (Info.CurrentCall->Callee && isa<FunctionDecl>(VD->getDeclContext()) &&
+ cast<FunctionDecl>(VD->getDeclContext()->getRedeclContext())
+ ->getFirstDecl() == Info.CurrentCall->Callee->getFirstDecl()) {
+ Frame = Info.CurrentCall;
+ }
+ }
if (!VD->getType()->isReferenceType()) {
if (Frame) {
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D23493.68091.patch
Type: text/x-patch
Size: 2615 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20160815/87313141/attachment.bin>
More information about the cfe-commits
mailing list