aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2012-09-17 23:47:35 -0400
committerJason Merrill <jason@gcc.gnu.org>2012-09-17 23:47:35 -0400
commit4d3999876e3c70b0d6bea7884b24953404055778 (patch)
tree1dc1e080b46aebb2ea058ed99dded5a56ee5f668
parent342ebbda0f9050e1a12784c23ce73182aa991e27 (diff)
downloadgcc-4d3999876e3c70b0d6bea7884b24953404055778.zip
gcc-4d3999876e3c70b0d6bea7884b24953404055778.tar.gz
gcc-4d3999876e3c70b0d6bea7884b24953404055778.tar.bz2
re PR c++/54575 (ICE with std::vector::insert and -std=c++11)
PR c++/54575 * pt.c (instantiate_alias_template): New. (tsubst): Use it. (push_access_scope): Allow TYPE_DECL. From-SVN: r191412
-rw-r--r--gcc/cp/ChangeLog7
-rw-r--r--gcc/cp/pt.c45
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/alias-decl-21.C23
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/alias-decl-22.C12
5 files changed, 86 insertions, 7 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index c11a8c2..676c166 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 7924dff..16952bf 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -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. */
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 6bebf2e..19e2719 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..463f539
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-21.C
@@ -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
index 0000000..1f6cb8f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-22.C
@@ -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" }
+};