This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH for c++/85200, ICE with constexpr if in generic lambda
- From: Jason Merrill <jason at redhat dot com>
- To: gcc-patches List <gcc-patches at gcc dot gnu dot org>
- Date: Wed, 4 Apr 2018 14:57:07 -0400
- Subject: C++ PATCH for c++/85200, ICE with constexpr if in generic lambda
Since, during partial instantiation of a generic lambda, we don't
substitute into the body of a constexpr if, we don't do lambda capture
as part of substitution. But extract_locals_r is supposed to do it as
part of remembering the substitution context to be used later.
As it turns out, this was failing because walk_tree_1 expects the
DECL_INITIAL of a local variable to be walked in the context of the
BIND_EXPR, but we don't build BIND_EXPRs for compound-statements in a
template. So in a template, let's walk the fields of a VAR_DECL from
its DECL_EXPR.
Tested x86_64-pc-linux-gnu, applying to trunk.
commit a99a47e6326b7278d660dcebba8ebcbec863f04a
Author: Jason Merrill <jason@redhat.com>
Date: Wed Apr 4 14:24:34 2018 -0400
PR c++/85200 - ICE with constexpr if in generic lambda.
* tree.c (cp_walk_subtrees): Walk into DECL_EXPR in templates.
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 7ddc2cb5e2d..d0835cfaa29 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -4894,10 +4894,12 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func,
/* User variables should be mentioned in BIND_EXPR_VARS
and their initializers and sizes walked when walking
the containing BIND_EXPR. Compiler temporaries are
- handled here. */
+ handled here. And also normal variables in templates,
+ since do_poplevel doesn't build a BIND_EXPR then. */
if (VAR_P (TREE_OPERAND (*tp, 0))
- && DECL_ARTIFICIAL (TREE_OPERAND (*tp, 0))
- && !TREE_STATIC (TREE_OPERAND (*tp, 0)))
+ && (processing_template_decl
+ || (DECL_ARTIFICIAL (TREE_OPERAND (*tp, 0))
+ && !TREE_STATIC (TREE_OPERAND (*tp, 0)))))
{
tree decl = TREE_OPERAND (*tp, 0);
WALK_SUBTREE (DECL_INITIAL (decl));
diff --git a/gcc/testsuite/g++.dg/cpp1z/constexpr-if18.C b/gcc/testsuite/g++.dg/cpp1z/constexpr-if18.C
new file mode 100644
index 00000000000..03ad620e8d9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/constexpr-if18.C
@@ -0,0 +1,15 @@
+// PR c++/85200
+// { dg-additional-options -std=c++17 }
+
+template <typename T>
+void f(){
+ [](auto v, auto b){
+ if constexpr (sizeof(v) == sizeof(int)) {
+ auto x = b;
+ }
+ }(0, 1);
+}
+
+int main(){
+ f<int>();
+}