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>
|
||||
|
||||
* 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)
|
||||
{
|
||||
/* Transfer const-ness of array into that of type pointed to. */
|
||||
type = build_pointer_type (TREE_TYPE (type));
|
||||
/* Withhold decaying a dependent array type so that that during
|
||||
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;
|
||||
array_parameter_p = true;
|
||||
}
|
||||
@ -11696,7 +11701,8 @@ grokparms (tree parmlist, tree *parms)
|
||||
|
||||
/* Top-level qualifiers on the parameters are
|
||||
ignored for function types. */
|
||||
type = cp_build_qualified_type (type, 0);
|
||||
type = strip_top_quals (type);
|
||||
|
||||
if (TREE_CODE (type) == METHOD_TYPE)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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
|
||||
[temp.deduct.call] and [temp.deduct.conv]. The rules in these two
|
||||
sections are symmetric. PARM is the type of a function parameter
|
||||
@ -18167,6 +18184,8 @@ type_unification_real (tree tparms,
|
||||
arg = args[ia];
|
||||
++ia;
|
||||
|
||||
parm = decay_dependent_array_parm_type (parm);
|
||||
|
||||
if (unify_one_argument (tparms, targs, parm, arg, subr, strict,
|
||||
explain_p))
|
||||
return 1;
|
||||
@ -20169,6 +20188,9 @@ more_specialized_fn (tree pat1, tree pat2, int len)
|
||||
len = 0;
|
||||
}
|
||||
|
||||
arg1 = decay_dependent_array_parm_type (arg1);
|
||||
arg2 = decay_dependent_array_parm_type (arg2);
|
||||
|
||||
if (TREE_CODE (arg1) == REFERENCE_TYPE)
|
||||
{
|
||||
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;
|
||||
arg != NULL_TREE && arg != void_list_node;
|
||||
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,
|
||||
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
|
||||
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
|
||||
(this is permitted if TYPE was introduced via a typedef or template
|
||||
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>
|
||||
|
||||
PR testsuite/69181
|
||||
|
5
gcc/testsuite/g++.dg/template/pr11858.C
Normal file
5
gcc/testsuite/g++.dg/template/pr11858.C
Normal file
@ -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" }
|
22
gcc/testsuite/g++.dg/template/pr24663.C
Normal file
22
gcc/testsuite/g++.dg/template/pr24663.C
Normal file
@ -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" }
|
46
gcc/testsuite/g++.dg/template/unify12.C
Normal file
46
gcc/testsuite/g++.dg/template/unify12.C
Normal file
@ -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);
|
||||
}
|
26
gcc/testsuite/g++.dg/template/unify13.C
Normal file
26
gcc/testsuite/g++.dg/template/unify13.C
Normal file
@ -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);
|
||||
}
|
5
gcc/testsuite/g++.dg/template/unify14.C
Normal file
5
gcc/testsuite/g++.dg/template/unify14.C
Normal file
@ -0,0 +1,5 @@
|
||||
template <typename T, int X>
|
||||
void bar (T [X]) { }
|
||||
|
||||
template <typename T, int X>
|
||||
void bar (const T [X]) { }
|
15
gcc/testsuite/g++.dg/template/unify15.C
Normal file
15
gcc/testsuite/g++.dg/template/unify15.C
Normal file
@ -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);
|
||||
}
|
56
gcc/testsuite/g++.dg/template/unify16.C
Normal file
56
gcc/testsuite/g++.dg/template/unify16.C
Normal file
@ -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);
|
||||
}
|
11
gcc/testsuite/g++.dg/template/unify17.C
Normal file
11
gcc/testsuite/g++.dg/template/unify17.C
Normal file
@ -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
Block a user