Patchwork C++ PATCHes for various C++0x regressions (c++/47511, etc)

login
register
mail settings
Submitter Jason Merrill
Date Feb. 10, 2011, 4:27 p.m.
Message ID <4D5411DD.6090701@redhat.com>
Download mbox | patch
Permalink /patch/82624/
State New
Headers show

Comments

Jason Merrill - Feb. 10, 2011, 4:27 p.m.
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;

Patch

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 <typename T> void *CreateA() {}
-B b = {CreateA<A>};
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 <typename T> void *CreateA() {}
+B b = {CreateA<A>};
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 <typename T> bool g( T ) {
+        return true;
+    }
+    struct A { };
+}
+template <class T> void f(const T&) {
+    N::A x;
+    g(x) ;
+}