C++ PATCH:

Mark Mitchell mark@codesourcery.com
Wed Feb 23 15:54:00 GMT 2005


This patch fixes a few more C++ regressions:

In PR 1991, integral_constant_value failed to be recursive; if the
DECL_INITIAL of a VAR_DECL was itself a constant, we did not continue
to chase the value.  Outside of templates, this works OK because we
(incorrectly, IMO) fold these things aggressively.  In templates, we
do not, so we really need the function to recur.

In PR 20152, we were destroying information about base classes when
encountering an invalid redefinition of a class.  Fixed by moving the
redefinition error before the base class processing, and then ignoring
the base classes.

In PR 20153, build_anon_union_vars was failing to understand that
expression in templates do not always have valid types, and therefore,
that using TREE_TYPE on an expression is not always reliable.

In PR 20148, we were trying to dump statement-expressions in our
diagnostic machinery, which is neither going to work nor be helpful to
users.  Fixed by printing just "({...})" instead.  Also, we were
failing to handle some of the representations we can get these days.   

Tested on x86_64-unknown-linux-gnu, applied on the mainline.

--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com
  

2005-02-22  Mark Mitchell  <mark@codesourcery.com>

	PR c++/19991
	* init.c (integral_constant_value): Iterate if the value of a decl
	is itself a constant.

	PR c++/20152
	* parser.c (cp_parser_class_head): Check for redefintions here.
	* semantics.c (begin_class_definition): Not here.
	
	PR c++/20153
	* decl2.c (build_anon_union_vars): Add type parameter.
	(finish_anon_union): Pass it.

	PR c++/20148
	* error.c (dump_expr): Do not print the body of a BIND_EXPR.
	Handle STATEMENT_LIST.

2005-02-22  Mark Mitchell  <mark@codesourcery.com>

	PR c++/19991
	* g++.dg/parse/constant7.C: New test.

	PR c++/20152
	* g++.dg/parse/error27.C: New test.
	* g++.dg/template/qualttp15.C: Adjust error markers.
	* g++.old-deja/g++.other/struct1.C: Likewise.
	
	PR c++/20153
	* g++.dg/template/error17.C: New test.

	PR c++/20148
	* g++.dg/parser/error26.C: New test.

Index: cp/decl2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl2.c,v
retrieving revision 1.768
diff -c -5 -p -r1.768 decl2.c
*** cp/decl2.c	21 Feb 2005 23:12:26 -0000	1.768
--- cp/decl2.c	23 Feb 2005 05:22:12 -0000
*************** typedef struct priority_info_s {
*** 63,73 ****
    int destructions_p;
  } *priority_info;
  
  static void mark_vtable_entries (tree);
  static bool maybe_emit_vtables (tree);
- static tree build_anon_union_vars (tree);
  static bool acceptable_java_type (tree);
  static tree start_objects (int, int);
  static void finish_objects (int, int, tree);
  static tree start_static_storage_duration_function (unsigned);
  static void finish_static_storage_duration_function (tree);
--- 63,72 ----
*************** cplus_decl_attributes (tree *decl, tree 
*** 1070,1087 ****
  
    if (TREE_CODE (*decl) == TYPE_DECL)
      SET_IDENTIFIER_TYPE_VALUE (DECL_NAME (*decl), TREE_TYPE (*decl));
  }
  
! /* Walks through the namespace- or function-scope anonymous union OBJECT,
!    building appropriate ALIAS_DECLs.  Returns one of the fields for use in
!    the mangled name.  */
  
  static tree
! build_anon_union_vars (tree object)
  {
-   tree type = TREE_TYPE (object);
    tree main_decl = NULL_TREE;
    tree field;
  
    /* Rather than write the code to handle the non-union case,
       just give an error.  */
--- 1069,1085 ----
  
    if (TREE_CODE (*decl) == TYPE_DECL)
      SET_IDENTIFIER_TYPE_VALUE (DECL_NAME (*decl), TREE_TYPE (*decl));
  }
  
! /* Walks through the namespace- or function-scope anonymous union
!    OBJECT, with the indicated TYPE, building appropriate ALIAS_DECLs.
!    Returns one of the fields for use in the mangled name.  */
  
  static tree
! build_anon_union_vars (tree type, tree object)
  {
    tree main_decl = NULL_TREE;
    tree field;
  
    /* Rather than write the code to handle the non-union case,
       just give an error.  */
*************** build_anon_union_vars (tree object)
*** 1125,1135 ****
  	  TREE_STATIC (decl) = 0;
  	  DECL_EXTERNAL (decl) = 1;
  	  decl = pushdecl (decl);
  	}
        else if (ANON_AGGR_TYPE_P (TREE_TYPE (field)))
! 	decl = build_anon_union_vars (ref);
        else
  	decl = 0;
  
        if (main_decl == NULL_TREE)
  	main_decl = decl;
--- 1123,1133 ----
  	  TREE_STATIC (decl) = 0;
  	  DECL_EXTERNAL (decl) = 1;
  	  decl = pushdecl (decl);
  	}
        else if (ANON_AGGR_TYPE_P (TREE_TYPE (field)))
! 	decl = build_anon_union_vars (TREE_TYPE (field), ref);
        else
  	decl = 0;
  
        if (main_decl == NULL_TREE)
  	main_decl = decl;
*************** finish_anon_union (tree anon_union_decl)
*** 1165,1175 ****
      {
        error ("namespace-scope anonymous aggregates must be static");
        return;
      }
  
!   main_decl = build_anon_union_vars (anon_union_decl);
    if (main_decl == NULL_TREE)
      {
        warning ("anonymous union with no members");
        return;
      }
--- 1163,1173 ----
      {
        error ("namespace-scope anonymous aggregates must be static");
        return;
      }
  
!   main_decl = build_anon_union_vars (type, anon_union_decl);
    if (main_decl == NULL_TREE)
      {
        warning ("anonymous union with no members");
        return;
      }
Index: cp/error.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/error.c,v
retrieving revision 1.276
diff -c -5 -p -r1.276 error.c
*** cp/error.c	21 Feb 2005 23:12:26 -0000	1.276
--- cp/error.c	23 Feb 2005 05:22:12 -0000
*************** dump_expr (tree t, int flags)
*** 1813,1834 ****
  
      case TEMPLATE_ID_EXPR:
        dump_decl (t, flags);
        break;
  
      case STMT_EXPR:
        /* We don't yet have a way of dumping statements in a
  	 human-readable format.  */
        pp_string (cxx_pp, "({...})");
        break;
  
-     case BIND_EXPR:
-       pp_cxx_left_brace (cxx_pp);
-       dump_expr (TREE_OPERAND (t, 1), flags & ~TFF_EXPR_IN_PARENS);
-       pp_cxx_right_brace (cxx_pp);
-       break;
- 
      case LOOP_EXPR:
        pp_string (cxx_pp, "while (1) { ");
        dump_expr (TREE_OPERAND (t, 0), flags & ~TFF_EXPR_IN_PARENS);
        pp_cxx_right_brace (cxx_pp);
        break;
--- 1813,1830 ----
  
      case TEMPLATE_ID_EXPR:
        dump_decl (t, flags);
        break;
  
+     case BIND_EXPR:
      case STMT_EXPR:
+     case STATEMENT_LIST:
        /* We don't yet have a way of dumping statements in a
  	 human-readable format.  */
        pp_string (cxx_pp, "({...})");
        break;
  
      case LOOP_EXPR:
        pp_string (cxx_pp, "while (1) { ");
        dump_expr (TREE_OPERAND (t, 0), flags & ~TFF_EXPR_IN_PARENS);
        pp_cxx_right_brace (cxx_pp);
        break;
Index: cp/init.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/init.c,v
retrieving revision 1.410
diff -c -5 -p -r1.410 init.c
*** cp/init.c	9 Feb 2005 02:53:37 -0000	1.410
--- cp/init.c	23 Feb 2005 05:22:12 -0000
*************** build_offset_ref (tree type, tree name, 
*** 1568,1588 ****
     [5.19/1].  FIXME:If we did lazy folding, this could be localized.  */
  
  tree
  integral_constant_value (tree decl)
  {
!   if ((TREE_CODE (decl) == CONST_DECL
!       || (TREE_CODE (decl) == VAR_DECL
! 	  /* And so are variables with a 'const' type -- unless they
! 	     are also 'volatile'.  */
! 	  && CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (decl))
! 	  && DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl)))
!       && DECL_INITIAL (decl)
!       && DECL_INITIAL (decl) != error_mark_node
!       && TREE_TYPE (DECL_INITIAL (decl))
!       && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (decl)))
!     return DECL_INITIAL (decl);
    return decl;
  }
  
  /* A more relaxed version of integral_constant_value, for which type
     is not considered.  This is used by the common C/C++ code, and not
--- 1568,1588 ----
     [5.19/1].  FIXME:If we did lazy folding, this could be localized.  */
  
  tree
  integral_constant_value (tree decl)
  {
!   while ((TREE_CODE (decl) == CONST_DECL
! 	  || (TREE_CODE (decl) == VAR_DECL
! 	      /* And so are variables with a 'const' type -- unless they
! 		 are also 'volatile'.  */
! 	      && CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (decl))
! 	      && DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl)))
! 	 && DECL_INITIAL (decl)
! 	 && DECL_INITIAL (decl) != error_mark_node
! 	 && TREE_TYPE (DECL_INITIAL (decl))
! 	 && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (decl)))
!     decl = DECL_INITIAL (decl);
    return decl;
  }
  
  /* A more relaxed version of integral_constant_value, for which type
     is not considered.  This is used by the common C/C++ code, and not
Index: cp/parser.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/parser.c,v
retrieving revision 1.317
diff -c -5 -p -r1.317 parser.c
*** cp/parser.c	22 Feb 2005 21:43:47 -0000	1.317
--- cp/parser.c	23 Feb 2005 05:22:12 -0000
*************** cp_parser_class_head (cp_parser* parser,
*** 12840,12852 ****
       `struct'.  */
    if (TREE_CODE (type) == RECORD_TYPE)
      CLASSTYPE_DECLARED_CLASS (type) = (class_key == class_type);
    cp_parser_check_class_key (class_key, type);
  
    /* We will have entered the scope containing the class; the names of
!      base classes should be looked up in that context.  For example,
!      given:
  
         struct A { struct B {}; struct C; };
         struct A::C : B {};
  
       is valid.  */
--- 12840,12860 ----
       `struct'.  */
    if (TREE_CODE (type) == RECORD_TYPE)
      CLASSTYPE_DECLARED_CLASS (type) = (class_key == class_type);
    cp_parser_check_class_key (class_key, type);
  
+   /* If this type was already complete, and we see another definition,
+      that's an error.  */
+   if (type != error_mark_node && COMPLETE_TYPE_P (type))
+     {
+       error ("redefinition of %q#T", type);
+       cp_error_at ("previous definition of %q#T", type);
+       type = error_mark_node;
+     }
+ 
    /* We will have entered the scope containing the class; the names of
!      base classes should be looked up in that context.  For example:
  
         struct A { struct B {}; struct C; };
         struct A::C : B {};
  
       is valid.  */
Index: cp/semantics.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/semantics.c,v
retrieving revision 1.462
diff -c -5 -p -r1.462 semantics.c
*** cp/semantics.c	22 Feb 2005 21:43:48 -0000	1.462
--- cp/semantics.c	23 Feb 2005 05:22:12 -0000
*************** begin_class_definition (tree t)
*** 2123,2141 ****
      {
        t = make_aggr_type (RECORD_TYPE);
        pushtag (make_anon_name (), t, 0);
      }
  
-   /* If this type was already complete, and we see another definition,
-      that's an error.  */
-   if (COMPLETE_TYPE_P (t))
-     {
-       error ("redefinition of %q#T", t);
-       cp_error_at ("previous definition of %q#T", t);
-       return error_mark_node;
-     }
- 
    /* Update the location of the decl.  */
    DECL_SOURCE_LOCATION (TYPE_NAME (t)) = input_location;
    
    if (TYPE_BEING_DEFINED (t))
      {
--- 2123,2132 ----
Index: testsuite/g++.dg/parse/constant7.C
===================================================================
RCS file: testsuite/g++.dg/parse/constant7.C
diff -N testsuite/g++.dg/parse/constant7.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/parse/constant7.C	23 Feb 2005 05:22:11 -0000
***************
*** 0 ****
--- 1,9 ----
+ // PR c++/19991
+  
+ enum { e = 1 };
+ 
+ template<typename> struct A
+ {
+   static const int i = e;
+   char a[i];
+ };
Index: testsuite/g++.dg/parse/error27.C
===================================================================
RCS file: testsuite/g++.dg/parse/error27.C
diff -N testsuite/g++.dg/parse/error27.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/parse/error27.C	23 Feb 2005 05:22:11 -0000
***************
*** 0 ****
--- 1,7 ----
+ // PR c++/20152
+ 
+ struct KrSelectionMode {  virtual void init() = 0; }; // { dg-error "previous definition" }
+ struct KrKDESelectionMode : public KrSelectionMode { void init() { } }; // { dg-error "previous definition" }
+ struct KrSelectionMode {  virtual void init() = 0; }; // { dg-error "" }
+ struct KrKDESelectionMode : public KrSelectionMode { void init() { } }; // { dg-error "" }
+ KrKDESelectionMode krKDESelectionMode;
Index: testsuite/g++.dg/parse/error26.C
===================================================================
RCS file: testsuite/g++.dg/parse/error26.C
diff -N testsuite/g++.dg/parse/error26.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/parse/error26.C	23 Feb 2005 05:22:11 -0000
***************
*** 0 ****
--- 1,12 ----
+ // PR c++/20148
+ // { dg-options "" }
+ 
+ void foo()
+ {
+   if (({int c[2];})) ; // { dg-error "\{\.\.\.\}" }
+ }
+ 
+ void bar()
+ {
+   if (({})); // { dg-error "\{\.\.\.\}" }
+ }
Index: testsuite/g++.dg/template/qualttp15.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.dg/template/qualttp15.C,v
retrieving revision 1.1
diff -c -5 -p -r1.1 qualttp15.C
*** testsuite/g++.dg/template/qualttp15.C	23 Oct 2001 09:14:15 -0000	1.1
--- testsuite/g++.dg/template/qualttp15.C	23 Feb 2005 05:22:11 -0000
*************** template <template <class> class TT> str
*** 15,26 ****
  template <class T> struct X<T::template B>
  {	// { dg-error "previous" }
  	T z;
  };
  
! template <class T> struct X<T::template B>
! {	// { dg-error "redefinition" }
  	T z;
  };
  
  template <class T> struct C
  {
--- 15,26 ----
  template <class T> struct X<T::template B>
  {	// { dg-error "previous" }
  	T z;
  };
  
! template <class T> struct X<T::template B> // { dg-error "redefinition" }
! {	
  	T z;
  };
  
  template <class T> struct C
  {
Index: testsuite/g++.dg/template/error17.C
===================================================================
RCS file: testsuite/g++.dg/template/error17.C
diff -N testsuite/g++.dg/template/error17.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/template/error17.C	23 Feb 2005 05:22:11 -0000
***************
*** 0 ****
--- 1,8 ----
+ // PR c++/20153
+ 
+ template <typename T>
+ void
+ foo()
+ {
+   union { struct { }; }; // { dg-error "" }
+ }
Index: testsuite/g++.old-deja/g++.other/struct1.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.old-deja/g++.other/struct1.C,v
retrieving revision 1.3
diff -c -5 -p -r1.3 struct1.C
*** testsuite/g++.old-deja/g++.other/struct1.C	1 May 2003 02:02:52 -0000	1.3
--- testsuite/g++.old-deja/g++.other/struct1.C	23 Feb 2005 05:22:11 -0000
***************
*** 7,42 ****
  // politely, but we used to die horribly.
  
  class Y
  {   // { dg-error "" } previous definition
  };
! class Y
! {   // { dg-error "" } redefinition
  };
  
  template<class T> class X
  {   // { dg-error "" } previous definition
  };
! template<class T> class X
! {   // { dg-error "" } redefinition
  };
  
  template<class T> class X<T *>
  {   // { dg-error "" } previous definition
  };
! template<class T> class X<T *>
! {   // { dg-error "" } redefinition
  };
  
  template<> class X<int>
  {   // { dg-error "" } previous definition
  };
! template<> class X<int>
! {   // { dg-error "" } redefinition
  };
  
  template<> class X<int *>
  {   // { dg-error "" } previous definition
  };
! template<> class X<int *>
! {   // { dg-error "" } redefinition
  };
--- 7,42 ----
  // politely, but we used to die horribly.
  
  class Y
  {   // { dg-error "" } previous definition
  };
! class Y // { dg-error "" } redefinition
! {   
  };
  
  template<class T> class X
  {   // { dg-error "" } previous definition
  };
! template<class T> class X // { dg-error "" } redefinition
! {   
  };
  
  template<class T> class X<T *>
  {   // { dg-error "" } previous definition
  };
! template<class T> class X<T *> // { dg-error "" } redefinition
! {   
  };
  
  template<> class X<int>
  {   // { dg-error "" } previous definition
  };
! template<> class X<int> // { dg-error "" } redefinition
! {   
  };
  
  template<> class X<int *>
  {   // { dg-error "" } previous definition
  };
! template<> class X<int *> // { dg-error "" } redefinition
! {   
  };



More information about the Gcc-patches mailing list