summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>2014-11-08 06:06:42 +0000
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>2014-11-08 06:06:42 +0000
commit996ae1f4f1d512b4ccad62c7d52eb2f14b3e814c (patch)
treeab788b854793bedbd2a4f41bebb0a2e56b901e73
parent019ba32b97d0c311e92d4f7802ae655a8e60c269 (diff)
downloadgcc-996ae1f4f1d512b4ccad62c7d52eb2f14b3e814c.tar.gz
DR 1558
* pt.c (dependent_alias_template_spec_p): New. (dependent_type_p_r): Handle dependent alias template specialization. (template_args_equal): A dependent alias template specializations is not equal to its underlying type as a template argument. * tree.c (strip_typedefs): Don't strip a dependent alias template-id. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@217250 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/cp/ChangeLog8
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/pt.c41
-rw-r--r--gcc/cp/tree.c5
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/alias-decl-dr1558.C14
5 files changed, 63 insertions, 6 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 132b9e1b859..a831d62d8c2 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,13 @@
2014-11-07 Jason Merrill <jason@redhat.com>
+ DR 1558
+ * pt.c (dependent_alias_template_spec_p): New.
+ (dependent_type_p_r): Handle dependent alias template specialization.
+ (template_args_equal): A dependent alias template specializations
+ is not equal to its underlying type as a template argument.
+ * tree.c (strip_typedefs): Don't strip a dependent alias
+ template-id.
+
* parser.c (cp_parser_unqualified_id): Handle __func__ here.
(cp_parser_primary_expression): Not here.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index abc3d6fd19f..74636dfbf8f 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -5692,6 +5692,7 @@ extern tree fold_non_dependent_expr (tree);
extern tree fold_non_dependent_expr_sfinae (tree, tsubst_flags_t);
extern bool alias_type_or_template_p (tree);
extern bool alias_template_specialization_p (const_tree);
+extern bool dependent_alias_template_spec_p (const_tree);
extern bool explicit_class_specialization_p (tree);
extern bool push_tinst_level (tree);
extern bool push_tinst_level_loc (tree, location_t);
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 2cf10f442f6..fa9652f748c 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -5268,7 +5268,7 @@ alias_type_or_template_p (tree t)
|| DECL_ALIAS_TEMPLATE_P (t));
}
-/* Return TRUE iff is a specialization of an alias template. */
+/* Return TRUE iff T is a specialization of an alias template. */
bool
alias_template_specialization_p (const_tree t)
@@ -5282,6 +5282,16 @@ alias_template_specialization_p (const_tree t)
&& DECL_ALIAS_TEMPLATE_P (TYPE_TI_TEMPLATE (t)));
}
+/* Return TRUE iff T is a specialization of an alias template with
+ dependent template-arguments. */
+
+bool
+dependent_alias_template_spec_p (const_tree t)
+{
+ return (alias_template_specialization_p (t)
+ && any_dependent_template_arguments_p (TYPE_TI_ARGS (t)));
+}
+
/* Return the number of innermost template parameters in TMPL. */
static int
@@ -7217,7 +7227,24 @@ template_args_equal (tree ot, tree nt)
return template_args_equal (ot, nt);
}
else if (TYPE_P (nt))
- return TYPE_P (ot) && same_type_p (ot, nt);
+ {
+ if (!TYPE_P (ot))
+ return false;
+ /* Don't treat an alias template specialization with dependent
+ arguments as equivalent to its underlying type when used as a
+ template argument; we need them to hash differently. */
+ bool ndep = dependent_alias_template_spec_p (nt);
+ ++processing_template_decl;
+ bool odep = dependent_alias_template_spec_p (ot);
+ --processing_template_decl;
+ if (ndep != odep)
+ return false;
+ else if (ndep)
+ return (TYPE_TI_TEMPLATE (nt) == TYPE_TI_TEMPLATE (ot)
+ && template_args_equal (TYPE_TI_ARGS (nt), TYPE_TI_ARGS (ot)));
+ else
+ return same_type_p (ot, nt);
+ }
else if (TREE_CODE (ot) == TREE_VEC || TYPE_P (ot))
return 0;
else
@@ -20719,8 +20746,10 @@ dependent_type_p_r (tree type)
if (TREE_CODE (type) == TYPENAME_TYPE)
return true;
/* -- a cv-qualified type where the cv-unqualified type is
- dependent. */
- type = TYPE_MAIN_VARIANT (type);
+ dependent.
+ No code is necessary for this bullet; the code below handles
+ cv-qualified types, and we don't want to strip aliases with
+ TYPE_MAIN_VARIANT because of DR 1558. */
/* -- a compound type constructed from any dependent type. */
if (TYPE_PTRMEM_P (type))
return (dependent_type_p (TYPE_PTRMEM_CLASS_TYPE (type))
@@ -20763,9 +20792,9 @@ dependent_type_p_r (tree type)
return true;
/* ... or any of the template arguments is a dependent type or
an expression that is type-dependent or value-dependent. */
- else if (CLASS_TYPE_P (type) && CLASSTYPE_TEMPLATE_INFO (type)
+ else if (TYPE_TEMPLATE_INFO (type)
&& (any_dependent_template_arguments_p
- (INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (type)))))
+ (INNERMOST_TEMPLATE_ARGS (TYPE_TI_ARGS (type)))))
return true;
/* All TYPEOF_TYPEs, DECLTYPE_TYPEs, and UNDERLYING_TYPEs are
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 32e7bd5499d..e0c2af1576c 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -1244,6 +1244,11 @@ strip_typedefs (tree t)
if (t == TYPE_CANONICAL (t))
return t;
+ if (dependent_alias_template_spec_p (t))
+ /* DR 1558: However, if the template-id is dependent, subsequent
+ template argument substitution still applies to the template-id. */
+ return t;
+
switch (TREE_CODE (t))
{
case POINTER_TYPE:
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-dr1558.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-dr1558.C
new file mode 100644
index 00000000000..2bbb138ec22
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-dr1558.C
@@ -0,0 +1,14 @@
+// DR 1558 still applies when using void_t as a template-argument.
+// { dg-do compile { target c++11 } }
+
+template<typename...> using void_t = void;
+template<class T> struct A { };
+struct B { typedef int foo; };
+template<typename T> A<void_t<typename T::foo>> f(); // { dg-error "int" }
+template<typename T> A<void> g();
+int main()
+{
+ f<B>();
+ g<int>();
+ f<int>(); // { dg-error "no match" }
+}