From patchwork Thu Feb 10 16:27:09 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Merrill X-Patchwork-Id: 82624 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 46B27B710C for ; Fri, 11 Feb 2011 03:27:26 +1100 (EST) Received: (qmail 10732 invoked by alias); 10 Feb 2011 16:27:20 -0000 Received: (qmail 10723 invoked by uid 22791); 10 Feb 2011 16:27:18 -0000 X-SWARE-Spam-Status: No, hits=-6.2 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_HI, SPF_HELO_PASS, TW_FN, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Thu, 10 Feb 2011 16:27:12 +0000 Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id p1AGRA3W017209 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Thu, 10 Feb 2011 11:27:10 -0500 Received: from [127.0.0.1] (ovpn-113-44.phx2.redhat.com [10.3.113.44]) by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id p1AGR9eD005275 for ; Thu, 10 Feb 2011 11:27:10 -0500 Message-ID: <4D5411DD.6090701@redhat.com> Date: Thu, 10 Feb 2011 11:27:09 -0500 From: Jason Merrill User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.13) Gecko/20101209 Fedora/3.1.7-0.35.b3pre.fc14 Lightning/1.0b2 Thunderbird/3.1.7 MIME-Version: 1.0 To: gcc-patches List Subject: C++ PATCHes for various C++0x regressions (c++/47511, etc) Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org After fixing 47511 it occurred to me that I hadn't run the testsuite in c++0x mode in a while, so I did that and found some more regressions. These patches fix some of them, and I added the testcases in question to the cpp0x directory to improve coverage while we aren't regularly running the testsuite in C++0x mode. Tested x86_64-pc-linux-gnu, applied to trunk. commit b048451177448edc495c16913cabe4d7441f2029 Author: Jason Merrill Date: Sat Jan 29 18:18:07 2011 -0500 PR c++/47511 * semantics.c (potential_constant_expression_1): Handle TEMPLATE_DECL. commit 02af4f0e2c11907a318c780ff9aee8bbd0a7b4ab Author: Jason Merrill Date: Sat Jan 29 18:19:59 2011 -0500 * class.c (type_has_constexpr_default_constructor): Make sure the caller stripped an enclosing array. * init.c (perform_member_init): Strip arrays before calling it. diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 03951cf..66c85bd 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -4349,7 +4349,11 @@ type_has_constexpr_default_constructor (tree t) tree fns; if (!CLASS_TYPE_P (t)) - return false; + { + /* The caller should have stripped an enclosing array. */ + gcc_assert (TREE_CODE (t) != ARRAY_TYPE); + return false; + } if (CLASSTYPE_LAZY_DEFAULT_CTOR (t)) return synthesized_default_constructor_is_constexpr (t); fns = locate_ctor (t); diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 6ffdc2f..e590118 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -535,16 +535,17 @@ perform_member_init (tree member, tree init) "uninitialized member %qD with % type %qT", member, type); - if (DECL_DECLARED_CONSTEXPR_P (current_function_decl) - && !type_has_constexpr_default_constructor (type)) - { - if (!DECL_TEMPLATE_INSTANTIATION (current_function_decl)) - error ("uninitialized member %qD in % constructor", - member); - DECL_DECLARED_CONSTEXPR_P (current_function_decl) = false; - } - core_type = strip_array_types (type); + + if (DECL_DECLARED_CONSTEXPR_P (current_function_decl) + && !type_has_constexpr_default_constructor (core_type)) + { + if (!DECL_TEMPLATE_INSTANTIATION (current_function_decl)) + error ("uninitialized member %qD in % constructor", + member); + DECL_DECLARED_CONSTEXPR_P (current_function_decl) = false; + } + if (CLASS_TYPE_P (core_type) && (CLASSTYPE_READONLY_FIELDS_NEED_INIT (core_type) || CLASSTYPE_REF_FIELDS_NEED_INIT (core_type))) diff --git a/gcc/testsuite/g++.dg/cpp0x/regress/abi-empty7.C b/gcc/testsuite/g++.dg/cpp0x/regress/abi-empty7.C new file mode 100644 index 0000000..adc7127 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/regress/abi-empty7.C @@ -0,0 +1,20 @@ +// Copy of abi/empty7.C. +// { dg-do run { target i?86-*-* x86_64-*-* } } +// { dg-require-effective-target ilp32 } +// { dg-options "-fabi-version=0 -std=c++0x" } + +struct S1 {}; +struct S2 { virtual void f () {} S1 s1[4]; }; +struct S3 : virtual public S2 {}; +struct S4 : virtual public S2 { int i; }; +struct S5 : public S3, virtual public S4 {}; +struct S6 { S5 s5; }; +struct S7 { S1 s1[5]; }; +struct S8 : public S1, public S6, virtual public S7 { }; + +S8 s8; + +int main () { + if ((char *)(S7 *)&s8 - (char *)&s8 != 24) + return 1; +} commit f2e39118c53b0720264a3a6e147e56e12ce4436c Author: Jason Merrill Date: Sat Jan 29 19:27:11 2011 -0500 * cvt.c (convert_to_void): Handle null op1. diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c index 029aec3..36c0703 100644 --- a/gcc/cp/cvt.c +++ b/gcc/cp/cvt.c @@ -892,20 +892,24 @@ convert_to_void (tree expr, impl_conv_void implicit, tsubst_flags_t complain) /* The two parts of a cond expr might be separate lvalues. */ tree op1 = TREE_OPERAND (expr,1); tree op2 = TREE_OPERAND (expr,2); - bool side_effects = TREE_SIDE_EFFECTS (op1) || TREE_SIDE_EFFECTS (op2); + bool side_effects = ((op1 && TREE_SIDE_EFFECTS (op1)) + || TREE_SIDE_EFFECTS (op2)); tree new_op1, new_op2; + new_op1 = NULL_TREE; if (implicit != ICV_CAST && !side_effects) { - new_op1 = convert_to_void (op1, ICV_SECOND_OF_COND, complain); + if (op1) + new_op1 = convert_to_void (op1, ICV_SECOND_OF_COND, complain); new_op2 = convert_to_void (op2, ICV_THIRD_OF_COND, complain); } else { - new_op1 = convert_to_void (op1, ICV_CAST, complain); + if (op1) + new_op1 = convert_to_void (op1, ICV_CAST, complain); new_op2 = convert_to_void (op2, ICV_CAST, complain); } - expr = build3 (COND_EXPR, TREE_TYPE (new_op1), + expr = build3 (COND_EXPR, TREE_TYPE (new_op2), TREE_OPERAND (expr, 0), new_op1, new_op2); break; } diff --git a/gcc/testsuite/g++.dg/cpp0x/regress/ext-cond1.C b/gcc/testsuite/g++.dg/cpp0x/regress/ext-cond1.C new file mode 100644 index 0000000..dc9814e --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/regress/ext-cond1.C @@ -0,0 +1,4 @@ +// PR c++/12515 +// { dg-do compile } +// { dg-options "-std=gnu++0x" } +template void foo() { 0 ?: 0; } commit b097ae650bbfc6b67b66548149d2ebf65a2351ca Author: Jason Merrill Date: Sun Jan 30 00:45:42 2011 -0500 * decl.c (build_enumerator): Don't perform integral promotions on non-integral constants. diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 6a13cc4..866069d 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -11869,7 +11869,8 @@ build_enumerator (tree name, tree value, tree enumtype, location_t loc) { value = cxx_constant_value (value); - if (TREE_CODE (value) == INTEGER_CST) + if (TREE_CODE (value) == INTEGER_CST + && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (value))) { value = perform_integral_promotions (value); } diff --git a/gcc/testsuite/g++.dg/cpp0x/regress/ext-label10.C b/gcc/testsuite/g++.dg/cpp0x/regress/ext-label10.C new file mode 100644 index 0000000..652d94a --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/regress/ext-label10.C @@ -0,0 +1,17 @@ +// PR c++/33836 +// { dg-do compile } +// { dg-options "-std=gnu++0x" } + +template struct A +{ + enum { M = && N }; // { dg-error "referenced outside|cannot appear in|not an integer constant" } +}; + +A<0> a; + +void foo () +{ + __label__ P; + enum { O = && P }; // { dg-error "cannot appear in|not an integer constant" } + P:; +} diff --git a/gcc/testsuite/g++.dg/ext/label10.C b/gcc/testsuite/g++.dg/ext/label10.C index 735fe06..632b242 100644 --- a/gcc/testsuite/g++.dg/ext/label10.C +++ b/gcc/testsuite/g++.dg/ext/label10.C @@ -1,10 +1,10 @@ // PR c++/33836 // { dg-do compile } -// { dg-options "-std=gnu++98" } +// { dg-options "" } template struct A { - enum { M = && N }; // { dg-error "referenced outside|cannot appear in" } + enum { M = && N }; // { dg-error "referenced outside|cannot appear in|not an integer constant" } }; A<0> a; @@ -12,6 +12,6 @@ A<0> a; void foo () { __label__ P; - enum { O = && P }; // { dg-error "cannot appear in" } + enum { O = && P }; // { dg-error "cannot appear in|not an integer constant" } P:; } commit 1f3a5e579af929a334fbb1d80382a5855b43e609 Author: Jason Merrill Date: Mon Jan 31 18:19:35 2011 -0500 * decl.c (cp_make_fname_decl): Set DECL_THIS_STATIC at toplevel. * semantics.c (finish_fname): Only return the name if we're in a function. diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 866069d..663ca8f 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -3706,7 +3706,10 @@ cp_make_fname_decl (location_t loc, tree id, int type_dep) LOOKUP_ONLYCONVERTING); } else - pushdecl_top_level_and_finish (decl, init); + { + DECL_THIS_STATIC (decl) = true; + pushdecl_top_level_and_finish (decl, init); + } return decl; } diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 7c06cc3..58a59ee 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -2324,7 +2324,7 @@ finish_fname (tree id) tree decl; decl = fname_decl (input_location, C_RID_CODE (id), id); - if (processing_template_decl) + if (processing_template_decl && current_function_decl) decl = DECL_NAME (decl); return decl; } diff --git a/gcc/testsuite/g++.dg/cpp0x/regress/template-function1.C b/gcc/testsuite/g++.dg/cpp0x/regress/template-function1.C new file mode 100644 index 0000000..ec686ee --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/regress/template-function1.C @@ -0,0 +1,28 @@ +// PR c++/38647 +// { dg-do compile } +// { dg-options "-std=c++0x" } + +template struct A {}; +const char func[] = "abc"; +template struct A {}; // { dg-error "cannot appear|is invalid|not a valid" } + +char a1[1]; +A a; + +template struct B {}; +template struct B<__FUNCTION__, N> {}; // { dg-error "cannot appear|is invalid|is not a valid" } + +char b1[1]; +B b; + +template struct C {}; +template struct C<__PRETTY_FUNCTION__, N> {}; // { dg-error "cannot appear|is invalid|is not a valid" } + +char c1[1]; +C c; + +template struct D {}; +template struct D<__func__, N> {}; // { dg-error "cannot appear|is invalid|is not a valid|function scope" } + +char d1[1]; +D d; diff --git a/gcc/testsuite/g++.dg/template/function1.C b/gcc/testsuite/g++.dg/template/function1.C index 1097c5b..3f82d53 100644 --- a/gcc/testsuite/g++.dg/template/function1.C +++ b/gcc/testsuite/g++.dg/template/function1.C @@ -3,25 +3,25 @@ template struct A {}; const char func[] = "abc"; -template struct A {}; // { dg-error "cannot appear|is invalid" } +template struct A {}; // { dg-error "cannot appear|is invalid|not a valid" } char a1[1]; A a; template struct B {}; -template struct B<__FUNCTION__, N> {}; // { dg-error "cannot appear|is invalid" } +template struct B<__FUNCTION__, N> {}; // { dg-error "cannot appear|is invalid|is not a valid" } char b1[1]; B b; template struct C {}; -template struct C<__PRETTY_FUNCTION__, N> {}; // { dg-error "cannot appear|is invalid" } +template struct C<__PRETTY_FUNCTION__, N> {}; // { dg-error "cannot appear|is invalid|is not a valid" } char c1[1]; C c; template struct D {}; -template struct D<__func__, N> {}; // { dg-error "cannot appear|is invalid" } +template struct D<__func__, N> {}; // { dg-error "cannot appear|is invalid|is not a valid|function scope" } char d1[1]; D d; diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 6d45fb9..7c06cc3 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -7263,6 +7263,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags) { case FUNCTION_DECL: case BASELINK: + case TEMPLATE_DECL: case OVERLOAD: case TEMPLATE_ID_EXPR: case LABEL_DECL: diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-regress1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-regress1.C deleted file mode 100644 index a6fe399..0000000 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-regress1.C +++ /dev/null @@ -1,10 +0,0 @@ -// PR c++/46903 -// This isn't C++0x code, but it was breaking in C++0x mode. -// { dg-options -std=c++0x } - -struct A {}; -struct B { - void *(*a)(); -}; -template void *CreateA() {} -B b = {CreateA}; diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-regress2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-regress2.C deleted file mode 100644 index 470ee1c..0000000 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-regress2.C +++ /dev/null @@ -1,13 +0,0 @@ -// PR c++/46552 -// { dg-options -std=c++0x } - -struct S -{ - int x; -}; - -template < typename > -void f( void ) -{ - &S::x; -} diff --git a/gcc/testsuite/g++.dg/cpp0x/regress/README b/gcc/testsuite/g++.dg/cpp0x/regress/README new file mode 100644 index 0000000..5c3402e --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/regress/README @@ -0,0 +1,3 @@ +This directory contains tests that were passing in C++98 mode but failing +in C++0x mode; it should be replaced by an improvement to the test harness +to run all tests in both modes. diff --git a/gcc/testsuite/g++.dg/cpp0x/regress/regress1.C b/gcc/testsuite/g++.dg/cpp0x/regress/regress1.C new file mode 100644 index 0000000..a6fe399 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/regress/regress1.C @@ -0,0 +1,10 @@ +// PR c++/46903 +// This isn't C++0x code, but it was breaking in C++0x mode. +// { dg-options -std=c++0x } + +struct A {}; +struct B { + void *(*a)(); +}; +template void *CreateA() {} +B b = {CreateA}; diff --git a/gcc/testsuite/g++.dg/cpp0x/regress/regress2.C b/gcc/testsuite/g++.dg/cpp0x/regress/regress2.C new file mode 100644 index 0000000..470ee1c --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/regress/regress2.C @@ -0,0 +1,13 @@ +// PR c++/46552 +// { dg-options -std=c++0x } + +struct S +{ + int x; +}; + +template < typename > +void f( void ) +{ + &S::x; +} diff --git a/gcc/testsuite/g++.dg/cpp0x/regress/regress3.C b/gcc/testsuite/g++.dg/cpp0x/regress/regress3.C new file mode 100644 index 0000000..ffbb97f --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/regress/regress3.C @@ -0,0 +1,13 @@ +// PR c++/47511 +// { dg-options -std=c++0x } + +namespace N { + template bool g( T ) { + return true; + } + struct A { }; +} +template void f(const T&) { + N::A x; + g(x) ; +}