Comments
Patch
@@ -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:
deleted file mode 100644
@@ -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 <typename T> void *CreateA() {}
-B b = {CreateA<A>};
deleted file mode 100644
@@ -1,13 +0,0 @@
-// PR c++/46552
-// { dg-options -std=c++0x }
-
-struct S
-{
- int x;
-};
-
-template < typename >
-void f( void )
-{
- &S::x;
-}
new file mode 100644
@@ -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.
new file mode 100644
@@ -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 <typename T> void *CreateA() {}
+B b = {CreateA<A>};
new file mode 100644
@@ -0,0 +1,13 @@
+// PR c++/46552
+// { dg-options -std=c++0x }
+
+struct S
+{
+ int x;
+};
+
+template < typename >
+void f( void )
+{
+ &S::x;
+}
new file mode 100644
@@ -0,0 +1,13 @@
+// PR c++/47511
+// { dg-options -std=c++0x }
+
+namespace N {
+ template <typename T> bool g( T ) {
+ return true;
+ }
+ struct A { };
+}
+template <class T> void f(const T&) {
+ N::A x;
+ g(x) ;
+}
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 <jason@redhat.com> 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 <jason@redhat.com> 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 %<const%> 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 %<constexpr%> 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 %<constexpr%> 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 <jason@redhat.com> 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<int> void foo() { 0 ?: 0; } commit b097ae650bbfc6b67b66548149d2ebf65a2351ca Author: Jason Merrill <jason@redhat.com> 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<int N> 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<int N> 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 <jason@redhat.com> 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<const char *, int> struct A {}; +const char func[] = "abc"; +template<int N> struct A<func, N> {}; // { dg-error "cannot appear|is invalid|not a valid" } + +char a1[1]; +A<a1, 0> a; + +template<const char *, int> struct B {}; +template<int N> struct B<__FUNCTION__, N> {}; // { dg-error "cannot appear|is invalid|is not a valid" } + +char b1[1]; +B<b1, 0> b; + +template<const char *, int> struct C {}; +template<int N> struct C<__PRETTY_FUNCTION__, N> {}; // { dg-error "cannot appear|is invalid|is not a valid" } + +char c1[1]; +C<c1, 0> c; + +template<const char *, int> struct D {}; +template<int N> struct D<__func__, N> {}; // { dg-error "cannot appear|is invalid|is not a valid|function scope" } + +char d1[1]; +D<d1, 0> 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<const char *, int> struct A {}; const char func[] = "abc"; -template<int N> struct A<func, N> {}; // { dg-error "cannot appear|is invalid" } +template<int N> struct A<func, N> {}; // { dg-error "cannot appear|is invalid|not a valid" } char a1[1]; A<a1, 0> a; template<const char *, int> struct B {}; -template<int N> struct B<__FUNCTION__, N> {}; // { dg-error "cannot appear|is invalid" } +template<int N> struct B<__FUNCTION__, N> {}; // { dg-error "cannot appear|is invalid|is not a valid" } char b1[1]; B<b1, 0> b; template<const char *, int> struct C {}; -template<int N> struct C<__PRETTY_FUNCTION__, N> {}; // { dg-error "cannot appear|is invalid" } +template<int N> struct C<__PRETTY_FUNCTION__, N> {}; // { dg-error "cannot appear|is invalid|is not a valid" } char c1[1]; C<c1, 0> c; template<const char *, int> struct D {}; -template<int N> struct D<__func__, N> {}; // { dg-error "cannot appear|is invalid" } +template<int N> struct D<__func__, N> {}; // { dg-error "cannot appear|is invalid|is not a valid|function scope" } char d1[1]; D<d1, 0> d;