summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog14
-rw-r--r--gcc/c-decl.c151
-rw-r--r--gcc/c-tree.h15
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.dg/declspec-12.c6
5 files changed, 129 insertions, 61 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 04439d01d17..d581ec834a3 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,17 @@
+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.
+
2004-09-14 Jeff Law <law@redhat.com>
* tree-ssa-dom.c (stmts_to_rescan): Move from a block-local
diff --git a/gcc/c-decl.c b/gcc/c-decl.c
index efed682dd84..b3bd689677b 100644
--- a/gcc/c-decl.c
+++ b/gcc/c-decl.c
@@ -2771,6 +2771,14 @@ shadow_tag_warned (const struct c_declspecs *declspecs, int warned)
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_declspecs *declspecs, int warned)
}
}
+
+/* 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, struct c_declspecs *quals, bool static_p,
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_declarator *decl,
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_declarator *declarator,
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_declarator *declarator,
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_declarator *declarator,
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_declarator *declarator,
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_declarator *declarator,
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_declarator *declarator,
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_declarator *declarator,
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;
-
- /* We don't yet implement attributes in this context. */
- if (array_ptr_quals->attrs != NULL_TREE)
- warning ("attributes in parameter array declarator ignored");
+ type_quals = array_ptr_quals;
- /* 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))));
+ /* We don't yet implement attributes in this context. */
+ if (array_ptr_attrs != NULL_TREE)
+ warning ("attributes in parameter array declarator ignored");
- 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_declspecs *type_quals_attrs,
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 --git a/gcc/c-tree.h b/gcc/c-tree.h
index f8601754791..5d1ec30425c 100644
--- a/gcc/c-tree.h
+++ b/gcc/c-tree.h
@@ -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 --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index aee35fe7ddd..2a7f9d41d2d 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2004-09-14 Joseph S. Myers <jsm@polyomino.org.uk>
+
+ * gcc.dg/declspec-12.c: New test.
+
2004-09-14 Bud Davis <bdavis9659@comcast.net>
* gfortran.dg/pr17090.f90: Add directives to test.
diff --git a/gcc/testsuite/gcc.dg/declspec-12.c b/gcc/testsuite/gcc.dg/declspec-12.c
new file mode 100644
index 00000000000..a1373efa3f1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/declspec-12.c
@@ -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" } */