This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Declspecs patch 4


This fourth declspecs patch moves type qualifiers in the c_declspecs
structure from specbits to better-designed fields, with associated
changes to the c_declarator structure to store contained qualifiers
directly rather than as c_declspecs structures.

The only change to visible compiler behavior should be the more
specific diagnostic for useless type qualifiers in empty declarations.

Bootstrapped with no regressions on i686-pc-linux-gnu.  Applied to
mainline.

-- 
Joseph S. Myers               http://www.srcf.ucam.org/~jsm28/gcc/
  http://www.srcf.ucam.org/~jsm28/gcc/#c90status - status of C90 for GCC 4.0
    jsm@polyomino.org.uk (personal mail)
    jsm28@gcc.gnu.org (Bugzilla assignments and CCs)

2004-09-14  Joseph S. Myers  <jsm@polyomino.org.uk>

	* c-tree.h (struct c_declspecs): Add const_p, volatile_p and
	restrict_p.
	(struct c_declarator): Change u.array.quals and pointer_quals to
	int.  Add u.array.attrs.
	(quals_from_declspecs): New.
	* c-decl.c (quals_from_declspecs): New.
	(shadow_tag_warned): Give more specific message for useless type
	qualifiers.
	(build_array_declarator, set_array_declarator_inner,
	grokdeclarator, make_pointer_declarator, build_null_declspecs,
	declspecs_add_qual): Update for changed structures.

testsuite:
2004-09-14  Joseph S. Myers  <jsm@polyomino.org.uk>

	* gcc.dg/declspec-12.c: New test.

diff -rupN GCC.orig/gcc/c-decl.c GCC/gcc/c-decl.c
--- GCC.orig/gcc/c-decl.c	2004-09-14 08:20:37.000000000 +0000
+++ GCC/gcc/c-decl.c	2004-09-14 14:32:48.000000000 +0000
@@ -2771,6 +2771,14 @@ shadow_tag_warned (const struct c_declsp
       warned = 2;
     }
 
+  if (!warned && !in_system_header && (declspecs->const_p
+				       || declspecs->volatile_p
+				       || declspecs->restrict_p))
+    {
+      warning ("useless type qualifier in empty declaration");
+      warned = 2;
+    }
+
   if (!warned && !in_system_header && declspecs->specbits)
     {
       warning ("useless keyword or type name in empty declaration");
@@ -2784,6 +2792,32 @@ shadow_tag_warned (const struct c_declsp
     }
 }
 
+
+/* Return the qualifiers from SPECS as a bitwise OR of TYPE_QUAL_*
+   bits.  SPECS represents declaration specifiers that the grammar
+   only permits to contain type qualifiers and attributes.  */
+
+int
+quals_from_declspecs (const struct c_declspecs *specs)
+{
+  int quals = ((specs->const_p ? TYPE_QUAL_CONST : 0)
+	       | (specs->volatile_p ? TYPE_QUAL_VOLATILE : 0)
+	       | (specs->restrict_p ? TYPE_QUAL_RESTRICT : 0));
+  gcc_assert (!specs->type
+	      && !specs->decl_attr
+	      && !specs->specbits
+	      && specs->storage_class == csc_none
+	      && !specs->typedef_p
+	      && !specs->typedef_signed_p
+	      && !specs->deprecated_p
+	      && !specs->explicit_int_p
+	      && !specs->explicit_char_p
+	      && !specs->long_long_p
+	      && !specs->inline_p
+	      && !specs->thread_p);
+  return quals;
+}
+
 /* Construct an array declarator.  EXPR is the expression inside [], or
    NULL_TREE.  QUALS are the type qualifiers inside the [] (to be applied
    to the pointer to which a parameter array is converted).  STATIC_P is
@@ -2802,7 +2836,16 @@ build_array_declarator (tree expr, struc
   declarator->kind = cdk_array;
   declarator->declarator = 0;
   declarator->u.array.dimen = expr;
-  declarator->u.array.quals = quals;
+  if (quals)
+    {
+      declarator->u.array.attrs = quals->attrs;
+      declarator->u.array.quals = quals_from_declspecs (quals);
+    }
+  else
+    {
+      declarator->u.array.attrs = NULL_TREE;
+      declarator->u.array.quals = 0;
+    }
   declarator->u.array.static_p = static_p;
   declarator->u.array.vla_unspec_p = vla_unspec_p;
   if (pedantic && !flag_isoc99)
@@ -2830,7 +2873,8 @@ set_array_declarator_inner (struct c_dec
 			    struct c_declarator *inner, bool abstract_p)
 {
   decl->declarator = inner;
-  if (abstract_p && (decl->u.array.quals != NULL
+  if (abstract_p && (decl->u.array.quals != TYPE_UNQUALIFIED
+		     || decl->u.array.attrs != NULL_TREE
 		     || decl->u.array.static_p))
     error ("static or type qualifiers in abstract declarator");
   return decl;
@@ -3644,7 +3688,8 @@ grokdeclarator (const struct c_declarato
   bool funcdef_syntax = false;
   int size_varies = 0;
   tree decl_attr = NULL_TREE;
-  struct c_declspecs *array_ptr_quals = 0;
+  int array_ptr_quals = TYPE_UNQUALIFIED;
+  tree array_ptr_attrs = NULL_TREE;
   int array_parm_static = 0;
   tree returned_attrs = NULL_TREE;
   bool bitfield = width != NULL;
@@ -3897,11 +3942,9 @@ grokdeclarator (const struct c_declarato
      duplicate qualifiers should be diagnosed in this case, but it
      seems most appropriate to do so).  */
   element_type = strip_array_types (type);
-  constp = !! (specbits & 1 << (int) RID_CONST) + TYPE_READONLY (element_type);
-  restrictp
-    = !! (specbits & 1 << (int) RID_RESTRICT) + TYPE_RESTRICT (element_type);
-  volatilep
-    = !! (specbits & 1 << (int) RID_VOLATILE) + TYPE_VOLATILE (element_type);
+  constp = declspecs->const_p + TYPE_READONLY (element_type);
+  restrictp = declspecs->restrict_p + TYPE_RESTRICT (element_type);
+  volatilep = declspecs->volatile_p + TYPE_VOLATILE (element_type);
   if (pedantic && !flag_isoc99)
     {
       if (constp > 1)
@@ -4021,13 +4064,16 @@ grokdeclarator (const struct c_declarato
 	 array or function or pointer, and DECLARATOR has had its
 	 outermost layer removed.  */
 
-      if (array_ptr_quals != NULL || array_parm_static)
+      if (array_ptr_quals != TYPE_UNQUALIFIED
+	  || array_ptr_attrs != NULL_TREE
+	  || array_parm_static)
 	{
 	  /* Only the innermost declarator (making a parameter be of
 	     array type which is converted to pointer type)
 	     may have static or type qualifiers.  */
 	  error ("static or type qualifiers in non-parameter array declarator");
-	  array_ptr_quals = NULL;
+	  array_ptr_quals = TYPE_UNQUALIFIED;
+	  array_ptr_attrs = NULL_TREE;
 	  array_parm_static = 0;
 	}
 
@@ -4062,6 +4108,7 @@ grokdeclarator (const struct c_declarato
 	    tree index_type = c_common_signed_type (sizetype);
 
 	    array_ptr_quals = declarator->u.array.quals;
+	    array_ptr_attrs = declarator->u.array.attrs;
 	    array_parm_static = declarator->u.array.static_p;
 	    
 	    declarator = declarator->declarator;
@@ -4214,10 +4261,13 @@ grokdeclarator (const struct c_declarato
 	      layout_type (type);
 
 	    if (decl_context != PARM
-		&& (array_ptr_quals != NULL || array_parm_static))
+		&& (array_ptr_quals != TYPE_UNQUALIFIED
+		    || array_ptr_attrs != NULL_TREE
+		    || array_parm_static))
 	      {
 		error ("static or type qualifiers in non-parameter array declarator");
-		array_ptr_quals = NULL;
+		array_ptr_quals = TYPE_UNQUALIFIED;
+		array_ptr_attrs = NULL_TREE;
 		array_parm_static = 0;
 	      }
 	    break;
@@ -4306,31 +4356,13 @@ grokdeclarator (const struct c_declarato
 	      pedwarn ("ISO C forbids qualified function types");
 	    if (type_quals)
 	      type = c_build_qualified_type (type, type_quals);
-	    type_quals = TYPE_UNQUALIFIED;
 	    size_varies = 0;
-	    
+
 	    type = build_pointer_type (type);
 	    
 	    /* Process type qualifiers (such as const or volatile)
 	       that were given inside the `*'.  */
-	    if (declarator->u.pointer_quals)
-	      {
-		int pbits = declarator->u.pointer_quals->specbits;
-
-		/* The grammar should only permit qualifiers here.  */
-		gcc_assert (!declarator->u.pointer_quals->type
-			    && !(pbits & ~((1 << (int) RID_CONST)
-					   | (1 << (int) RID_VOLATILE)
-					   | (1 << (int) RID_RESTRICT))));
-
-		constp = !!(pbits & (1 << (int) RID_CONST));
-		volatilep = !!(pbits & (1 << (int) RID_VOLATILE));
-		restrictp = !!(pbits & (1 << (int) RID_RESTRICT));
-
-		type_quals = ((constp ? TYPE_QUAL_CONST : 0)
-			      | (restrictp ? TYPE_QUAL_RESTRICT : 0)
-			      | (volatilep ? TYPE_QUAL_VOLATILE : 0));
-	      }
+	    type_quals = declarator->u.pointer_quals;
 
 	    declarator = declarator->declarator;
 	    break;
@@ -4445,29 +4477,12 @@ grokdeclarator (const struct c_declarato
 	    if (type_quals)
 	      type = c_build_qualified_type (type, type_quals);
 	    type = build_pointer_type (type);
-	    type_quals = TYPE_UNQUALIFIED;
-	    if (array_ptr_quals)
-	      {
-		int apqbits = array_ptr_quals->specbits;
+	    type_quals = array_ptr_quals;
+
+	    /* We don't yet implement attributes in this context.  */
+	    if (array_ptr_attrs != NULL_TREE)
+	      warning ("attributes in parameter array declarator ignored");
 
-		/* We don't yet implement attributes in this context.  */
-		if (array_ptr_quals->attrs != NULL_TREE)
-		  warning ("attributes in parameter array declarator ignored");
-
-		/* The grammar should only permit qualifiers here.  */
-		gcc_assert (!array_ptr_quals->type
-			    && !(apqbits & ~((1 << (int) RID_CONST)
-					     | (1 << (int) RID_VOLATILE)
-					     | (1 << (int) RID_RESTRICT))));
-
-		constp = !!(apqbits & (1 << (int) RID_CONST));
-		volatilep = !!(apqbits & (1 << (int) RID_VOLATILE));
-		restrictp = !!(apqbits & (1 << (int) RID_RESTRICT));
-
-		type_quals = ((constp ? TYPE_QUAL_CONST : 0)
-			      | (restrictp ? TYPE_QUAL_RESTRICT : 0)
-			      | (volatilep ? TYPE_QUAL_VOLATILE : 0));
-	      }
 	    size_varies = 0;
 	  }
 	else if (TREE_CODE (type) == FUNCTION_TYPE)
@@ -6724,18 +6739,19 @@ make_pointer_declarator (struct c_declsp
 			 struct c_declarator *target)
 {
   tree attrs;
+  int quals = 0;
   struct c_declarator *itarget = target;
   struct c_declarator *ret = XOBNEW (&parser_obstack, struct c_declarator);
   if (type_quals_attrs)
     {
       attrs = type_quals_attrs->attrs;
-      type_quals_attrs->attrs = NULL_TREE;
+      quals = quals_from_declspecs (type_quals_attrs);
       if (attrs != NULL_TREE)
 	itarget = build_attrs_declarator (attrs, target);
     }
   ret->kind = cdk_pointer;
   ret->declarator = itarget;
-  ret->u.pointer_quals = type_quals_attrs;
+  ret->u.pointer_quals = quals;
   return ret;
 }
 
@@ -6760,6 +6776,9 @@ build_null_declspecs (void)
   ret->long_long_p = false;
   ret->inline_p = false;
   ret->thread_p = false;
+  ret->const_p = false;
+  ret->volatile_p = false;
+  ret->restrict_p = false;
   return ret;
 }
 
@@ -6770,14 +6789,30 @@ struct c_declspecs *
 declspecs_add_qual (struct c_declspecs *specs, tree qual)
 {
   enum rid i;
+  bool dupe = false;
   specs->non_sc_seen_p = true;
   gcc_assert (TREE_CODE (qual) == IDENTIFIER_NODE
 	      && C_IS_RESERVED_WORD (qual));
   i = C_RID_CODE (qual);
-  gcc_assert (i == RID_CONST || i == RID_VOLATILE || i == RID_RESTRICT);
-  if ((specs->specbits & (1 << (int) i)) && pedantic && !flag_isoc99)
+  switch (i)
+    {
+    case RID_CONST:
+      dupe = specs->const_p;
+      specs->const_p = true;
+      break;
+    case RID_VOLATILE:
+      dupe = specs->volatile_p;
+      specs->volatile_p = true;
+      break;
+    case RID_RESTRICT:
+      dupe = specs->restrict_p;
+      specs->restrict_p = true;
+      break;
+    default:
+      gcc_unreachable ();
+    }
+  if (dupe && pedantic && !flag_isoc99)
     pedwarn ("duplicate %qs", IDENTIFIER_POINTER (qual));
-  specs->specbits |= 1 << (int) i;
   return specs;
 }
 
diff -rupN GCC.orig/gcc/c-tree.h GCC/gcc/c-tree.h
--- GCC.orig/gcc/c-tree.h	2004-09-12 23:48:33.000000000 +0000
+++ GCC/gcc/c-tree.h	2004-09-14 13:57:56.000000000 +0000
@@ -180,6 +180,12 @@ struct c_declspecs {
   BOOL_BITFIELD inline_p : 1;
   /* Whether "__thread" was specified.  */
   BOOL_BITFIELD thread_p : 1;
+  /* Whether "const" was specified.  */
+  BOOL_BITFIELD const_p : 1;
+  /* Whether "volatile" was specified.  */
+  BOOL_BITFIELD volatile_p : 1;
+  /* Whether "restrict" was specified.  */
+  BOOL_BITFIELD restrict_p : 1;
 };
 
 /* The various kinds of declarators in C.  */
@@ -225,15 +231,17 @@ struct c_declarator {
     struct {
       /* The array dimension, or NULL for [] and [*].  */
       tree dimen;
-      /* The qualifiers (and attributes, currently ignored) inside [].  */
-      struct c_declspecs *quals;
+      /* The qualifiers inside [].  */
+      int quals;
+      /* The attributes (currently ignored) inside [].  */
+      tree attrs;
       /* Whether [static] was used.  */
       BOOL_BITFIELD static_p : 1;
       /* Whether [*] was used.  */
       BOOL_BITFIELD vla_unspec_p : 1;
     } array;
     /* For pointers, the qualifiers on the pointer type.  */
-    struct c_declspecs *pointer_quals;
+    int pointer_quals;
     /* For attributes.  */
     tree attrs;
   } u;
@@ -297,6 +305,7 @@ extern void c_expand_body (tree);
 extern void c_init_decl_processing (void);
 extern void c_dup_lang_specific_decl (tree);
 extern void c_print_identifier (FILE *, tree, int);
+extern int quals_from_declspecs (const struct c_declspecs *);
 extern struct c_declarator *build_array_declarator (tree, struct c_declspecs *,
 						    bool, bool);
 extern tree build_enumerator (tree, tree);
diff -rupN GCC.orig/gcc/testsuite/gcc.dg/declspec-12.c GCC/gcc/testsuite/gcc.dg/declspec-12.c
--- GCC.orig/gcc/testsuite/gcc.dg/declspec-12.c	1970-01-01 00:00:00.000000000 +0000
+++ GCC/gcc/testsuite/gcc.dg/declspec-12.c	2004-09-14 14:20:17.000000000 +0000
@@ -0,0 +1,6 @@
+/* Test type qualifier in empty declaration: OK but useless.  */
+/* Origin: Joseph Myers <jsm@polyomino.org.uk> */
+/* { dg-do compile } */
+/* { dg-options "-pedantic-errors" } */
+
+const struct foo; /* { dg-warning "warning: useless type qualifier in empty declaration" } */


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]