mirror of git://gcc.gnu.org/git/gcc.git
Fix the remaining PR c++/24666 blockers (arrays decay to pointers too early)
gcc/cp/ChangeLog: PR c++/11858 PR c++/24663 PR c++/24664 * decl.c (grokdeclarator): Don't decay array parameter type to a pointer type if it's dependent. (grokparms): Invoke strip_top_quals instead of directly invoking cp_build_qualified_type. * pt.c (decay_dependent_array_parm_type): New static function. (type_unification_real): Call decay_dependent_array_parm_type to decay a dependent array parameter type to its corresponding pointer type before unification. (more_specialized_fn): Likewise. (get_bindings): Likewise. * tree.c (cp_build_qualified_type): Trivial typofix in documentation. gcc/testsuite/ChangeLog: PR c++/11858 PR c++/24663 PR c++/24664 * g++.dg/template/pr11858.C: New test. * g++.dg/template/pr24663.C: New test. * g++.dg/template/unify12.C: New test. * g++.dg/template/unify13.C: New test. * g++.dg/template/unify14.C: New test. * g++.dg/template/unify15.C: New test. * g++.dg/template/unify16.C: New test. * g++.dg/template/unify17.C: New test. From-SVN: r232547
This commit is contained in:
parent
49f8a19186
commit
17c15cb932
|
|
@ -1,3 +1,21 @@
|
||||||
|
2016-01-18 Patrick Palka <ppalka@gcc.gnu.org>
|
||||||
|
|
||||||
|
PR c++/11858
|
||||||
|
PR c++/24663
|
||||||
|
PR c++/24664
|
||||||
|
* decl.c (grokdeclarator): Don't decay array parameter type to
|
||||||
|
a pointer type if it's dependent.
|
||||||
|
(grokparms): Invoke strip_top_quals instead of directly invoking
|
||||||
|
cp_build_qualified_type.
|
||||||
|
* pt.c (decay_dependent_array_parm_type): New static function.
|
||||||
|
(type_unification_real): Call decay_dependent_array_parm_type
|
||||||
|
to decay a dependent array parameter type to its corresponding
|
||||||
|
pointer type before unification.
|
||||||
|
(more_specialized_fn): Likewise.
|
||||||
|
(get_bindings): Likewise.
|
||||||
|
* tree.c (cp_build_qualified_type): Trivial typofix in
|
||||||
|
documentation.
|
||||||
|
|
||||||
2016-01-18 Jason Merrill <jason@redhat.com>
|
2016-01-18 Jason Merrill <jason@redhat.com>
|
||||||
|
|
||||||
* cp-gimplify.c (cp_fold) [CONSTRUCTOR]: Don't clobber the input.
|
* cp-gimplify.c (cp_fold) [CONSTRUCTOR]: Don't clobber the input.
|
||||||
|
|
|
||||||
|
|
@ -10898,8 +10898,13 @@ grokdeclarator (const cp_declarator *declarator,
|
||||||
|
|
||||||
if (TREE_CODE (type) == ARRAY_TYPE)
|
if (TREE_CODE (type) == ARRAY_TYPE)
|
||||||
{
|
{
|
||||||
/* Transfer const-ness of array into that of type pointed to. */
|
/* Withhold decaying a dependent array type so that that during
|
||||||
type = build_pointer_type (TREE_TYPE (type));
|
instantiation we can detect type deduction failure cases such as
|
||||||
|
creating an array of void, creating a zero-size array, etc. */
|
||||||
|
if (dependent_type_p (type))
|
||||||
|
;
|
||||||
|
else
|
||||||
|
type = build_pointer_type (TREE_TYPE (type));
|
||||||
type_quals = TYPE_UNQUALIFIED;
|
type_quals = TYPE_UNQUALIFIED;
|
||||||
array_parameter_p = true;
|
array_parameter_p = true;
|
||||||
}
|
}
|
||||||
|
|
@ -11696,7 +11701,8 @@ grokparms (tree parmlist, tree *parms)
|
||||||
|
|
||||||
/* Top-level qualifiers on the parameters are
|
/* Top-level qualifiers on the parameters are
|
||||||
ignored for function types. */
|
ignored for function types. */
|
||||||
type = cp_build_qualified_type (type, 0);
|
type = strip_top_quals (type);
|
||||||
|
|
||||||
if (TREE_CODE (type) == METHOD_TYPE)
|
if (TREE_CODE (type) == METHOD_TYPE)
|
||||||
{
|
{
|
||||||
error ("parameter %qD invalidly declared method type", decl);
|
error ("parameter %qD invalidly declared method type", decl);
|
||||||
|
|
|
||||||
27
gcc/cp/pt.c
27
gcc/cp/pt.c
|
|
@ -17729,6 +17729,23 @@ fn_type_unification (tree fn,
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* TYPE is the type of a function parameter. If TYPE is a (dependent)
|
||||||
|
ARRAY_TYPE, return the corresponding POINTER_TYPE to which it decays.
|
||||||
|
Otherwise return TYPE. (We shouldn't see non-dependent ARRAY_TYPE
|
||||||
|
parameters because they get decayed as soon as they are declared.) */
|
||||||
|
|
||||||
|
static tree
|
||||||
|
decay_dependent_array_parm_type (tree type)
|
||||||
|
{
|
||||||
|
if (TREE_CODE (type) == ARRAY_TYPE)
|
||||||
|
{
|
||||||
|
gcc_assert (uses_template_parms (type));
|
||||||
|
return type_decays_to (type);
|
||||||
|
}
|
||||||
|
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
/* Adjust types before performing type deduction, as described in
|
/* Adjust types before performing type deduction, as described in
|
||||||
[temp.deduct.call] and [temp.deduct.conv]. The rules in these two
|
[temp.deduct.call] and [temp.deduct.conv]. The rules in these two
|
||||||
sections are symmetric. PARM is the type of a function parameter
|
sections are symmetric. PARM is the type of a function parameter
|
||||||
|
|
@ -18167,6 +18184,8 @@ type_unification_real (tree tparms,
|
||||||
arg = args[ia];
|
arg = args[ia];
|
||||||
++ia;
|
++ia;
|
||||||
|
|
||||||
|
parm = decay_dependent_array_parm_type (parm);
|
||||||
|
|
||||||
if (unify_one_argument (tparms, targs, parm, arg, subr, strict,
|
if (unify_one_argument (tparms, targs, parm, arg, subr, strict,
|
||||||
explain_p))
|
explain_p))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
@ -20169,6 +20188,9 @@ more_specialized_fn (tree pat1, tree pat2, int len)
|
||||||
len = 0;
|
len = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
arg1 = decay_dependent_array_parm_type (arg1);
|
||||||
|
arg2 = decay_dependent_array_parm_type (arg2);
|
||||||
|
|
||||||
if (TREE_CODE (arg1) == REFERENCE_TYPE)
|
if (TREE_CODE (arg1) == REFERENCE_TYPE)
|
||||||
{
|
{
|
||||||
ref1 = TYPE_REF_IS_RVALUE (arg1) + 1;
|
ref1 = TYPE_REF_IS_RVALUE (arg1) + 1;
|
||||||
|
|
@ -20454,7 +20476,10 @@ get_bindings (tree fn, tree decl, tree explicit_args, bool check_rettype)
|
||||||
for (arg = decl_arg_types, ix = 0;
|
for (arg = decl_arg_types, ix = 0;
|
||||||
arg != NULL_TREE && arg != void_list_node;
|
arg != NULL_TREE && arg != void_list_node;
|
||||||
arg = TREE_CHAIN (arg), ++ix)
|
arg = TREE_CHAIN (arg), ++ix)
|
||||||
args[ix] = TREE_VALUE (arg);
|
{
|
||||||
|
args[ix] = TREE_VALUE (arg);
|
||||||
|
args[ix] = decay_dependent_array_parm_type (args[ix]);
|
||||||
|
}
|
||||||
|
|
||||||
if (fn_type_unification (fn, explicit_args, targs,
|
if (fn_type_unification (fn, explicit_args, targs,
|
||||||
args, ix,
|
args, ix,
|
||||||
|
|
|
||||||
|
|
@ -1012,7 +1012,7 @@ c_build_qualified_type (tree type, int type_quals, tree /* orig_qual_type */,
|
||||||
arrays correctly. In particular, if TYPE is an array of T's, and
|
arrays correctly. In particular, if TYPE is an array of T's, and
|
||||||
TYPE_QUALS is non-empty, returns an array of qualified T's.
|
TYPE_QUALS is non-empty, returns an array of qualified T's.
|
||||||
|
|
||||||
FLAGS determines how to deal with ill-formed qualifications. If
|
COMPLAIN determines how to deal with ill-formed qualifications. If
|
||||||
tf_ignore_bad_quals is set, then bad qualifications are dropped
|
tf_ignore_bad_quals is set, then bad qualifications are dropped
|
||||||
(this is permitted if TYPE was introduced via a typedef or template
|
(this is permitted if TYPE was introduced via a typedef or template
|
||||||
type parameter). If bad qualifications are dropped and tf_warning
|
type parameter). If bad qualifications are dropped and tf_warning
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,17 @@
|
||||||
|
2016-01-18 Patrick Palka <ppalka@gcc.gnu.org>
|
||||||
|
|
||||||
|
PR c++/11858
|
||||||
|
PR c++/24663
|
||||||
|
PR c++/24664
|
||||||
|
* g++.dg/template/pr11858.C: New test.
|
||||||
|
* g++.dg/template/pr24663.C: New test.
|
||||||
|
* g++.dg/template/unify12.C: New test.
|
||||||
|
* g++.dg/template/unify13.C: New test.
|
||||||
|
* g++.dg/template/unify14.C: New test.
|
||||||
|
* g++.dg/template/unify15.C: New test.
|
||||||
|
* g++.dg/template/unify16.C: New test.
|
||||||
|
* g++.dg/template/unify17.C: New test.
|
||||||
|
|
||||||
2016-01-18 David Malcolm <dmalcolm@redhat.com>
|
2016-01-18 David Malcolm <dmalcolm@redhat.com>
|
||||||
|
|
||||||
PR testsuite/69181
|
PR testsuite/69181
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
// PR c++/11858
|
||||||
|
|
||||||
|
template <typename T> struct S { static typename T::x f (); }; // { dg-error "" }
|
||||||
|
template <class T> int f (int [sizeof(T::f())]);
|
||||||
|
int const i = f<S<int> >(0); // { dg-error "no matching function" }
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
// PR c++/24663
|
||||||
|
|
||||||
|
template<int I> int f1 (char[I]);
|
||||||
|
template<int I> int f1 (char p1 = I);
|
||||||
|
int i = f1<0>(0);
|
||||||
|
|
||||||
|
template<typename T, int I> int f2 (T[I]); // { dg-error "" }
|
||||||
|
int j = f2<int, 0>(0); // { dg-error "no matching function" }
|
||||||
|
int k = f2<void, 1>(0); // { dg-error "no matching function" }
|
||||||
|
|
||||||
|
int o[5];
|
||||||
|
int l = f2<int[5], 1>(&o);
|
||||||
|
|
||||||
|
template<int I> int f3 (char [][I]);
|
||||||
|
template<int I> int f3 (char p1 = I);
|
||||||
|
int x1 = f3<1>(0); // { dg-error "is ambiguous" }
|
||||||
|
int x2 = f3<1>();
|
||||||
|
|
||||||
|
template<typename T, int I> int f4 (T [][I]); // { dg-error "" }
|
||||||
|
int y1 = f4<void, 1>(0); // { dg-error "no matching function" }
|
||||||
|
int y2 = f4<int (void), 1>(0); // { dg-error "no matching function" }
|
||||||
|
int y3 = f4<int&, 1>(0); // { dg-error "no matching function" }
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
// { dg-do run }
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
template<typename T, int I> int foo (T [I][I]) { return 0; }
|
||||||
|
|
||||||
|
template int foo (char [][6]);
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
int foo (T *)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
int foo (T [3][3])
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <int I>
|
||||||
|
int foo (bool [I][I])
|
||||||
|
{
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
int foo (bool [3][2])
|
||||||
|
{
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
char x[3];
|
||||||
|
bool y[4];
|
||||||
|
bool z[3][2];
|
||||||
|
|
||||||
|
int a = foo (&x);
|
||||||
|
int b = foo (&y);
|
||||||
|
int c = foo (z);
|
||||||
|
|
||||||
|
int
|
||||||
|
main ()
|
||||||
|
{
|
||||||
|
assert (a == 1);
|
||||||
|
assert (b == 2);
|
||||||
|
assert (c == 3);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
// { dg-do run }
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
template<typename T, int I> int foo (T [I][I]) { return 0; }
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
int foo (T [3][2])
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
int foo (bool [3][2])
|
||||||
|
{
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool z[3][2];
|
||||||
|
|
||||||
|
int a = foo (z);
|
||||||
|
|
||||||
|
int
|
||||||
|
main ()
|
||||||
|
{
|
||||||
|
assert (a == 2);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
template <typename T, int X>
|
||||||
|
void bar (T [X]) { }
|
||||||
|
|
||||||
|
template <typename T, int X>
|
||||||
|
void bar (const T [X]) { }
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
// { dg-do run }
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
template <typename T, int N>
|
||||||
|
int bar (T (&) [N]) { return 0; }
|
||||||
|
|
||||||
|
template <typename T, int N>
|
||||||
|
int bar (const T (&) [N]) { return 1; }
|
||||||
|
|
||||||
|
int
|
||||||
|
main ()
|
||||||
|
{
|
||||||
|
const int s[2] = { 0 };
|
||||||
|
assert (bar (s) == 1);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
// { dg-do run }
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct Foo
|
||||||
|
{
|
||||||
|
static int foo (T) { return 0; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, int I>
|
||||||
|
struct Foo<T[I]>
|
||||||
|
{
|
||||||
|
static int foo (T[I]) { return 1; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <int I>
|
||||||
|
struct Foo<char[I]>
|
||||||
|
{
|
||||||
|
static int foo (char[I]) { return 2; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct Foo<T[5]>
|
||||||
|
{
|
||||||
|
static int foo (T[5]) { return 3; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct Foo<char[5]>
|
||||||
|
{
|
||||||
|
static int foo (char[5]) { return 4; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct Foo<const char[5]>
|
||||||
|
{
|
||||||
|
static int foo (const char[5]) { return 5; }
|
||||||
|
};
|
||||||
|
|
||||||
|
int a = Foo<const char[5]>::foo (0);
|
||||||
|
int b = Foo<char[5]>::foo (0);
|
||||||
|
int c = Foo<bool[5]>::foo (0);
|
||||||
|
int d = Foo<char[4]>::foo (0);
|
||||||
|
int e = Foo<bool[4]>::foo (0);
|
||||||
|
int f = Foo<char[]>::foo (0);
|
||||||
|
|
||||||
|
int
|
||||||
|
main (void)
|
||||||
|
{
|
||||||
|
assert (a == 5);
|
||||||
|
assert (b == 4);
|
||||||
|
assert (c == 3);
|
||||||
|
assert (d == 2);
|
||||||
|
assert (e == 1);
|
||||||
|
assert (f == 0);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
void foo (int *);
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void bar (void (T[5])); // { dg-error "array of 'void'" }
|
||||||
|
|
||||||
|
void
|
||||||
|
baz (void)
|
||||||
|
{
|
||||||
|
bar (foo); // { dg-bogus "" }
|
||||||
|
bar<void> (0); // { dg-error "no matching function" }
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue