From: bonzini Date: Tue, 3 Feb 2009 16:26:28 +0000 (+0000) Subject: gcc/cp: X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=3cc2d970814fb1da8c1a357ab14a9e2972c75bd4;p=thirdparty%2Fgcc.git gcc/cp: 2009-02-03 Paolo Bonzini PR c++/36897 * pt.c (convert_nontype_argument_function): Expect expr to be an ADDR_EXPR. PR c++/37314 * typeck.c (merge_types): Call resolve_typename_type if only one type is a typename. gcc/testsuite: 2009-02-03 Paolo Bonzini PR c++/36897 * g++.dg/template/func2.C: New test. PR c++/37314 * g++.dg/template/typename15.C: New. * g++.dg/template/typename16.C: New. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@143898 138bc75d-0d04-0410-961f-82ee72b054a4 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 50fe9c2cbd95..39a5eb855a22 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,13 @@ +2009-02-03 Paolo Bonzini + + PR c++/36897 + * pt.c (convert_nontype_argument_function): Expect expr to be an + ADDR_EXPR. + + PR c++/37314 + * typeck.c (merge_types): Call resolve_typename_type if only + one type is a typename. + 2009-02-02 Jason Merrill PR c++/39054 diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index f6809f2bdf7d..c5b675faa164 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -4566,6 +4566,13 @@ convert_nontype_argument (tree type, tree expr) expr = convert_nontype_argument_function (type, expr); if (!expr || expr == error_mark_node) return expr; + + if (TREE_CODE (expr) != ADDR_EXPR) + { + error ("%qE is not a valid template argument for type %qT", expr, type); + error ("it must be the address of a function with external linkage"); + return NULL_TREE; + } } /* [temp.arg.nontype]/5, bullet 5 diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index bca72ce452c3..1c7df31c9bb2 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -637,6 +637,20 @@ merge_types (tree t1, tree t2) code1 = TREE_CODE (t1); code2 = TREE_CODE (t2); + if (code1 != code2) + { + gcc_assert (code1 == TYPENAME_TYPE || code2 == TYPENAME_TYPE); + if (code1 == TYPENAME_TYPE) + { + t1 = resolve_typename_type (t1, /*only_current_p=*/true); + code1 = TREE_CODE (t1); + } + else + { + t2 = resolve_typename_type (t2, /*only_current_p=*/true); + code2 = TREE_CODE (t2); + } + } switch (code1) { diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 254dab5ca000..ba77486a3e78 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,12 @@ +2009-02-03 Paolo Bonzini + + PR c++/36897 + * g++.dg/template/func2.C: New test. + + PR c++/37314 + * g++.dg/template/typename15.C: New. + * g++.dg/template/typename16.C: New. + 2009-02-03 Janis Johnson Ben Elliston diff --git a/gcc/testsuite/g++.dg/template/func2.C b/gcc/testsuite/g++.dg/template/func2.C new file mode 100644 index 000000000000..b0f691d242b9 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/func2.C @@ -0,0 +1,12 @@ +// { dg-do compile } + +typedef void (*fptr)(); +fptr zeroptr = 0; +template struct foo { }; +template struct foo { }; +// { dg-error "not a valid template argument" "not valid" { target *-*-* } 6 } +// { dg-error "must be the address" "must be the address " { target *-*-* } 6 } + +// The rest is needed to trigger the ICE in 4.0 to 4.3: +void f() { } +foo m_foo; diff --git a/gcc/testsuite/g++.dg/template/typename15.C b/gcc/testsuite/g++.dg/template/typename15.C new file mode 100644 index 000000000000..fece885ea78b --- /dev/null +++ b/gcc/testsuite/g++.dg/template/typename15.C @@ -0,0 +1,12 @@ +// PR37314 ice-on-valid-code, from w.doeringer +template +class Cdeque { + typedef T *pointer; + class iterator { + typedef typename Cdeque::pointer pointer; + pointer operator->(); + }; +}; +template T* Cdeque::iterator::operator->() { } + + diff --git a/gcc/testsuite/g++.dg/template/typename16.C b/gcc/testsuite/g++.dg/template/typename16.C new file mode 100644 index 000000000000..45da11162dbd --- /dev/null +++ b/gcc/testsuite/g++.dg/template/typename16.C @@ -0,0 +1,25 @@ +// PR37314 rejects-valid, from w.doeringer +template +struct A { + typedef __PTRDIFF_TYPE__ difference_type; + struct B { + typedef typename A::difference_type difference_type; + difference_type operator-(B const&) const; + T t; + }; +}; +// + +template +typename A::B::difference_type A::B::operator-(B const&) const { + return -1; +} + +// +int main() { + A::B i; + ++i.t; + return 0; +} + +