]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR c++/54575 (ICE with std::vector::insert and -std=c++11)
authorJason Merrill <jason@redhat.com>
Tue, 18 Sep 2012 03:47:35 +0000 (23:47 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Tue, 18 Sep 2012 03:47:35 +0000 (23:47 -0400)
PR c++/54575
* pt.c (instantiate_alias_template): New.
(tsubst): Use it.
(push_access_scope): Allow TYPE_DECL.

From-SVN: r191412

gcc/cp/ChangeLog
gcc/cp/pt.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/alias-decl-21.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/alias-decl-22.C [new file with mode: 0644]

index c11a8c20c6b5e2aebab231730a7c5f790b9e5c38..676c1669298c05cb29040db2b472d8c2b602bd65 100644 (file)
@@ -1,3 +1,10 @@
+2012-09-17  Jason Merrill  <jason@redhat.com>
+
+       PR c++/54575
+       * pt.c (instantiate_alias_template): New.
+       (tsubst): Use it.
+       (push_access_scope): Allow TYPE_DECL.
+
 2012-09-14  Jason Merrill  <jason@redhat.com>
 
        PR c++/53661
index 7924dff519fb58fc70eef10ea743374e1c2fd69c..16952bffa0c7b5a695d9fd05f798bae1a1465786 100644 (file)
@@ -205,16 +205,18 @@ static tree template_parm_to_arg (tree t);
 static bool arg_from_parm_pack_p (tree, tree);
 static tree current_template_args (void);
 static tree tsubst_template_parm (tree, tree, tsubst_flags_t);
+static tree instantiate_alias_template (tree, tree, tsubst_flags_t);
 
 /* Make the current scope suitable for access checking when we are
    processing T.  T can be FUNCTION_DECL for instantiated function
-   template, or VAR_DECL for static member variable (need by
-   instantiate_decl).  */
+   template, VAR_DECL for static member variable, or TYPE_DECL for
+   alias template (needed by instantiate_decl).  */
 
 static void
 push_access_scope (tree t)
 {
   gcc_assert (TREE_CODE (t) == FUNCTION_DECL
+             || TREE_CODE (t) == TYPE_DECL
              || TREE_CODE (t) == VAR_DECL);
 
   if (DECL_FRIEND_CONTEXT (t))
@@ -10949,10 +10951,10 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
          && PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (decl)))
        {
          /* DECL represents an alias template and we want to
-            instantiate it.  Let's substitute our arguments for the
-            template parameters into the declaration and get the
-            resulting type.  */
-         r = tsubst (decl, args, complain, decl);
+            instantiate it.  */
+         tree tmpl = most_general_template (DECL_TI_TEMPLATE (decl));
+         tree gen_args = tsubst (DECL_TI_ARGS (decl), args, complain, in_decl);
+         r = instantiate_alias_template (tmpl, gen_args, complain);
        }
       else if (DECL_CLASS_SCOPE_P (decl)
               && CLASSTYPE_TEMPLATE_INFO (DECL_CONTEXT (decl))
@@ -14377,7 +14379,7 @@ recheck_decl_substitution (tree d, tree tmpl, tree args)
   pop_access_scope (d);
 }
 
-/* Instantiate the indicated variable or function template TMPL with
+/* Instantiate the indicated variable, function, or alias template TMPL with
    the template arguments in TARG_PTR.  */
 
 static tree
@@ -14526,6 +14528,35 @@ instantiate_template (tree tmpl, tree orig_args, tsubst_flags_t complain)
   return ret;
 }
 
+/* Instantiate the alias template TMPL with ARGS.  Also push a template
+   instantiation level, which instantiate_template doesn't do because
+   functions and variables have sufficient context established by the
+   callers.  */
+
+static tree
+instantiate_alias_template (tree tmpl, tree args, tsubst_flags_t complain)
+{
+  struct pending_template *old_last_pend = last_pending_template;
+  struct tinst_level *old_error_tinst = last_error_tinst_level;
+  if (tmpl == error_mark_node || args == error_mark_node)
+    return error_mark_node;
+  tree tinst = build_tree_list (tmpl, args);
+  if (!push_tinst_level (tinst))
+    {
+      ggc_free (tinst);
+      return error_mark_node;
+    }
+  tree r = instantiate_template (tmpl, args, complain);
+  pop_tinst_level ();
+  /* We can't free this if a pending_template entry or last_error_tinst_level
+     is pointing at it.  */
+  if (last_pending_template == old_last_pend
+      && last_error_tinst_level == old_error_tinst)
+    ggc_free (tinst);
+
+  return r;
+}
+
 /* PARM is a template parameter pack for FN.  Returns true iff
    PARM is used in a deducible way in the argument list of FN.  */
 
index 6bebf2eaa92e90d929dd00eb30889e4638055792..19e2719367163c90dc2f381786e48b61b7405d7f 100644 (file)
@@ -1,3 +1,9 @@
+2012-09-17  Jason Merrill  <jason@redhat.com>
+
+       PR c++/54575
+       * g++.dg/cpp0x/alias-decl-21.C: New.
+       * g++.dg/cpp0x/alias-decl-22.C: New.
+
 2012-09-17  Tobias Burnus  <burnus@net-b.de>
 
        PR fortran/54608
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-21.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-21.C
new file mode 100644 (file)
index 0000000..463f539
--- /dev/null
@@ -0,0 +1,23 @@
+// PR c++/54575
+// { dg-do compile { target c++11 } }
+
+template<typename _From, typename _To>
+struct is_convertible { static const bool value = true; };
+
+template<bool> struct enable_if       { };
+template<>     struct enable_if<true> { typedef int type; };
+
+template<typename _InIter>
+using _RequireInputIter
+= typename enable_if<is_convertible<_InIter,bool>::value>::type;
+
+template<typename _Tp> struct X {
+    template<typename _InputIterator,
+         typename = _RequireInputIter<_InputIterator>>
+      void insert(_InputIterator) {}
+};
+
+template<typename> void foo() {
+  X<int> subdomain_indices;
+  subdomain_indices.insert(0);
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-22.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-22.C
new file mode 100644 (file)
index 0000000..1f6cb8f
--- /dev/null
@@ -0,0 +1,12 @@
+// The standard is unclear about whether this testcase is well-formed.
+// Clang considers it well-formed, EDG not.  Let's go with EDG for now.
+// { dg-do compile { target c++11 } }
+
+template <class T>
+using foo = typename T::bar;   // { dg-error "this context" }
+
+class B
+{
+  typedef int bar;             // { dg-error "private" }
+  foo<B> f;                    // { dg-message "required" }
+};