Here, since the condition for the constexpr if depends on the type of
'j', it's still dependent when we are partially instantiating the
inner lambda, so we need to defer instantiating the constexpr if.
When we instantiated the inner lambda, we tried to substitute into the
typename, which failed because we didn't have a declaration of 'i'
available.

Fixed by teaching extract_locals_r to capture local typedefs such as
'ar'; if we have the typedef handy, we don't need to substitute into
its  definition.

Tested x86_64-pc-linux-gnu, applying to trunk.
commit f55b3ab9ac0cd82137c4bdeca7304f8097da5c3d
Author: Jason Merrill <ja...@redhat.com>
Date:   Fri Apr 6 13:46:50 2018 -0400

            PR c++/85214 - ICE with alias, generic lambda, constexpr if.
    
    Here, since the condition for the constexpr if depends on the type of 'j',
    it's still dependent when we are partially instantiating the inner lambda,
    so we need to defer instantiating the constexpr if.  When we instantiated
    the inner lambda, we tried to substitute into the typename, which failed
    because we didn't have a declaration of 'i' available.
    
    Fixed by teaching extract_locals_r to capture local typedefs such as 'ar';
    if we have the typedef handy, we don't need to substitute into its
    definition.
    
            * pt.c (extract_locals_r): Remember local typedefs.

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 3bac7563992..6cd48c6688a 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -11610,6 +11610,11 @@ extract_locals_r (tree *tp, int */*walk_subtrees*/, void *data_)
   el_data &data = *reinterpret_cast<el_data*>(data_);
   tree *extra = &data.extra;
   tsubst_flags_t complain = data.complain;
+
+  if (TYPE_P (*tp) && typedef_variant_p (*tp))
+    /* Remember local typedefs (85214).  */
+    tp = &TYPE_NAME (*tp);
+
   if (TREE_CODE (*tp) == DECL_EXPR)
     data.internal.add (DECL_EXPR_DECL (*tp));
   else if (tree spec = retrieve_local_specialization (*tp))
diff --git a/gcc/testsuite/g++.dg/cpp1z/constexpr-if20.C b/gcc/testsuite/g++.dg/cpp1z/constexpr-if20.C
new file mode 100644
index 00000000000..24343adb748
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/constexpr-if20.C
@@ -0,0 +1,17 @@
+// PR c++/85214
+// { dg-additional-options -std=c++17 }
+
+struct g {
+  constexpr operator int() { return true; }
+};
+template <typename T, typename U> constexpr bool m = true;
+template <long L> struct C { typedef double q; };
+void ao() {
+  [](auto i) {
+      using ar = typename C<i>::q;
+      [](auto j) {
+	using as = typename C<j>::q;
+	if constexpr (m<ar, as>) {}
+      }(g());
+  }(g());
+}

Reply via email to