C++ PATCH: Fix PRs 16518, 16337
Mark Mitchell
mark@codesourcery.com
Wed Jul 14 02:06:00 GMT 2004
This patch fixes PRs 16518 and 16337, which are both regressions from
my recent decl-specifier changes.
I don't know how to do a fully portable test case for 16337. Any
suggestions?
Tested on i686-pc-linux-gnu, applied on the mainline.
--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com
2004-07-13 Mark Mitchell <mark@codesourcery.com>
PR c++/16518
PR c++/16337
* decl.c (grokvardecl): Make declspecs parameter const.
(grokdeclarator): Likewise. Adjust accordingly.
* decl.h (grokdeclarator): Adjust declaration.
* parser.c (cp_parser_init_declarator): Do not clear
decl_specifiers->attributes.
2004-07-13 Mark Mitchell <mark@codesourcery.com>
PR c++/16518
* g++.dg/parse/mutable1.C: New test.
Index: cp/decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.1247
diff -c -5 -p -r1.1247 decl.c
*** cp/decl.c 13 Jul 2004 16:22:04 -0000 1.1247
--- cp/decl.c 13 Jul 2004 21:08:53 -0000
*************** static int unary_op_p (enum tree_code);
*** 62,72 ****
static void push_local_name (tree);
static tree grok_reference_init (tree, tree, tree, tree *);
static tree grokfndecl (tree, tree, tree, tree, tree, int,
enum overload_flags, cp_cv_quals,
tree, int, int, int, int, int, int, tree);
! static tree grokvardecl (tree, tree, cp_decl_specifier_seq *, int, int, tree);
static void record_unknown_type (tree, const char *);
static tree builtin_function_1 (const char *, tree, tree, int,
enum built_in_class, const char *,
tree);
static tree build_library_fn_1 (tree, enum tree_code, tree);
--- 62,73 ----
static void push_local_name (tree);
static tree grok_reference_init (tree, tree, tree, tree *);
static tree grokfndecl (tree, tree, tree, tree, tree, int,
enum overload_flags, cp_cv_quals,
tree, int, int, int, int, int, int, tree);
! static tree grokvardecl (tree, tree, const cp_decl_specifier_seq *,
! int, int, tree);
static void record_unknown_type (tree, const char *);
static tree builtin_function_1 (const char *, tree, tree, int,
enum built_in_class, const char *,
tree);
static tree build_library_fn_1 (tree, enum tree_code, tree);
*************** grokfndecl (tree ctype,
*** 5706,5716 ****
the innermost enclosings scope. */
static tree
grokvardecl (tree type,
tree name,
! cp_decl_specifier_seq *declspecs,
int initialized,
int constp,
tree scope)
{
tree decl;
--- 5707,5717 ----
the innermost enclosings scope. */
static tree
grokvardecl (tree type,
tree name,
! const cp_decl_specifier_seq *declspecs,
int initialized,
int constp,
tree scope)
{
tree decl;
*************** check_special_function_return_type (spec
*** 6244,6254 ****
when grokdeclarator is called for `S::f', the CURRENT_CLASS_TYPE
should not be `S'. */
tree
grokdeclarator (const cp_declarator *declarator,
! cp_decl_specifier_seq *declspecs,
enum decl_context decl_context,
int initialized,
tree* attrlist)
{
tree type = NULL_TREE;
--- 6245,6255 ----
when grokdeclarator is called for `S::f', the CURRENT_CLASS_TYPE
should not be `S'. */
tree
grokdeclarator (const cp_declarator *declarator,
! const cp_decl_specifier_seq *declspecs,
enum decl_context decl_context,
int initialized,
tree* attrlist)
{
tree type = NULL_TREE;
*************** grokdeclarator (const cp_declarator *dec
*** 6297,6306 ****
--- 6298,6315 ----
located. If an unqualified name is used to declare the entity,
this value will be NULL_TREE, even if the entity is located at
namespace scope. */
tree in_namespace = NULL_TREE;
cp_decl_spec ds;
+ cp_storage_class storage_class;
+ bool unsigned_p, signed_p, short_p, long_p, thread_p;
+
+ signed_p = declspecs->specs[(int)ds_signed];
+ unsigned_p = declspecs->specs[(int)ds_unsigned];
+ short_p = declspecs->specs[(int)ds_short];
+ long_p = declspecs->specs[(int)ds_long];
+ thread_p = declspecs->specs[(int)ds_thread];
if (decl_context == FUNCDEF)
funcdef_flag = 1, decl_context = NORMAL;
else if (decl_context == MEMFUNCDEF)
funcdef_flag = -1, decl_context = FIELD;
*************** grokdeclarator (const cp_declarator *dec
*** 6505,6519 ****
typedef_decl = type;
type = TREE_TYPE (typedef_decl);
}
/* No type at all: default to `int', and set DEFAULTED_INT
because it was not a user-defined typedef. */
! if (type == NULL_TREE
! && (declspecs->specs[(int)ds_signed]
! || declspecs->specs[(int)ds_unsigned]
! || declspecs->specs[(int)ds_long]
! || declspecs->specs[(int)ds_short]))
{
/* These imply 'int'. */
type = integer_type_node;
defaulted_int = 1;
}
--- 6514,6524 ----
typedef_decl = type;
type = TREE_TYPE (typedef_decl);
}
/* No type at all: default to `int', and set DEFAULTED_INT
because it was not a user-defined typedef. */
! if (type == NULL_TREE && (signed_p || unsigned_p || long_p || short_p))
{
/* These imply 'int'. */
type = integer_type_node;
defaulted_int = 1;
}
*************** grokdeclarator (const cp_declarator *dec
*** 6602,6645 ****
/* Now process the modifiers that were specified
and check for invalid combinations. */
/* Long double is a special combination. */
! if (declspecs->specs[(int)ds_long]
! && TYPE_MAIN_VARIANT (type) == double_type_node)
{
! declspecs->specs[(int)ds_long] = 0;
type = build_qualified_type (long_double_type_node,
cp_type_quals (type));
}
/* Check all other uses of type modifiers. */
! if (declspecs->specs[(int)ds_unsigned]
! || declspecs->specs[(int)ds_signed]
! || declspecs->specs[(int)ds_long]
! || declspecs->specs[(int)ds_short])
{
int ok = 0;
if (TREE_CODE (type) == REAL_TYPE)
error ("short, signed or unsigned invalid for `%s'", name);
else if (TREE_CODE (type) != INTEGER_TYPE)
error ("long, short, signed or unsigned invalid for `%s'", name);
! else if (declspecs->specs[(int)ds_long]
! && declspecs->specs[(int)ds_short])
error ("long and short specified together for `%s'", name);
! else if ((declspecs->specs[(int)ds_long]
! || declspecs->specs[(int)ds_short])
! && explicit_char)
error ("long or short specified with char for `%s'", name);
! else if ((declspecs->specs[(int)ds_long]
! || declspecs->specs[(int)ds_short])
! && TREE_CODE (type) == REAL_TYPE)
error ("long or short specified with floating type for `%s'", name);
! else if (declspecs->specs[(int)ds_signed]
! && declspecs->specs[(int)ds_unsigned])
error ("signed and unsigned given together for `%s'", name);
else
{
ok = 1;
if (!explicit_int && !defaulted_int && !explicit_char && pedantic)
--- 6607,6640 ----
/* Now process the modifiers that were specified
and check for invalid combinations. */
/* Long double is a special combination. */
! if (long_p && TYPE_MAIN_VARIANT (type) == double_type_node)
{
! long_p = false;
type = build_qualified_type (long_double_type_node,
cp_type_quals (type));
}
/* Check all other uses of type modifiers. */
! if (unsigned_p || signed_p || long_p || short_p)
{
int ok = 0;
if (TREE_CODE (type) == REAL_TYPE)
error ("short, signed or unsigned invalid for `%s'", name);
else if (TREE_CODE (type) != INTEGER_TYPE)
error ("long, short, signed or unsigned invalid for `%s'", name);
! else if (long_p && short_p)
error ("long and short specified together for `%s'", name);
! else if ((long_p || short_p) && explicit_char)
error ("long or short specified with char for `%s'", name);
! else if ((long_p|| short_p) && TREE_CODE (type) == REAL_TYPE)
error ("long or short specified with floating type for `%s'", name);
! else if (signed_p && unsigned_p)
error ("signed and unsigned given together for `%s'", name);
else
{
ok = 1;
if (!explicit_int && !defaulted_int && !explicit_char && pedantic)
*************** grokdeclarator (const cp_declarator *dec
*** 6652,6689 ****
}
/* Discard the type modifiers if they are invalid. */
if (! ok)
{
! declspecs->specs[(int)ds_unsigned] = 0;
! declspecs->specs[(int)ds_signed] = 0;
! declspecs->specs[(int)ds_long] = 0;
! declspecs->specs[(int)ds_short] = 0;
longlong = 0;
}
}
- if (declspecs->specs[(int)ds_complex]
- && TREE_CODE (type) != INTEGER_TYPE && TREE_CODE (type) != REAL_TYPE)
- {
- error ("complex invalid for `%s'", name);
- declspecs->specs[(int)ds_complex] = 0;
- }
-
/* Decide whether an integer type is signed or not.
Optionally treat bitfields as signed by default. */
! if (declspecs->specs[(int)ds_unsigned]
/* [class.bit]
It is implementation-defined whether a plain (neither
explicitly signed or unsigned) char, short, int, or long
bit-field is signed or unsigned.
Naturally, we extend this to long long as well. Note that
this does not include wchar_t. */
|| (bitfield && !flag_signed_bitfields
! && !declspecs->specs[(int)ds_signed]
/* A typedef for plain `int' without `signed' can be
controlled just like plain `int', but a typedef for
`signed int' cannot be so controlled. */
&& !(typedef_decl
&& C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl))
--- 6647,6677 ----
}
/* Discard the type modifiers if they are invalid. */
if (! ok)
{
! unsigned_p = false;
! signed_p = false;
! long_p = false;
! short_p = false;
longlong = 0;
}
}
/* Decide whether an integer type is signed or not.
Optionally treat bitfields as signed by default. */
! if (unsigned_p
/* [class.bit]
It is implementation-defined whether a plain (neither
explicitly signed or unsigned) char, short, int, or long
bit-field is signed or unsigned.
Naturally, we extend this to long long as well. Note that
this does not include wchar_t. */
|| (bitfield && !flag_signed_bitfields
! && !signed_p
/* A typedef for plain `int' without `signed' can be
controlled just like plain `int', but a typedef for
`signed int' cannot be so controlled. */
&& !(typedef_decl
&& C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl))
*************** grokdeclarator (const cp_declarator *dec
*** 6691,6733 ****
|| TREE_CODE (type) == CHAR_TYPE)
&& !same_type_p (TYPE_MAIN_VARIANT (type), wchar_type_node)))
{
if (longlong)
type = long_long_unsigned_type_node;
! else if (declspecs->specs[(int)ds_long])
type = long_unsigned_type_node;
! else if (declspecs->specs[(int)ds_short])
type = short_unsigned_type_node;
else if (type == char_type_node)
type = unsigned_char_type_node;
else if (typedef_decl)
type = c_common_unsigned_type (type);
else
type = unsigned_type_node;
}
! else if (declspecs->specs[(int)ds_signed]
! && type == char_type_node)
type = signed_char_type_node;
else if (longlong)
type = long_long_integer_type_node;
! else if (declspecs->specs[(int)ds_long])
type = long_integer_type_node;
! else if (declspecs->specs[(int)ds_short])
type = short_integer_type_node;
if (declspecs->specs[(int)ds_complex])
{
/* If we just have "complex", it is equivalent to
"complex double", but if any modifiers at all are specified it is
the complex form of TYPE. E.g, "complex short" is
"complex short int". */
! if (defaulted_int && ! longlong
! && ! (declspecs->specs[(int)ds_long]
! || declspecs->specs[(int)ds_short]
! || declspecs->specs[(int)ds_signed]
! || declspecs->specs[(int)ds_unsigned]))
type = complex_double_type_node;
else if (type == integer_type_node)
type = complex_integer_type_node;
else if (type == float_type_node)
type = complex_float_type_node;
--- 6679,6719 ----
|| TREE_CODE (type) == CHAR_TYPE)
&& !same_type_p (TYPE_MAIN_VARIANT (type), wchar_type_node)))
{
if (longlong)
type = long_long_unsigned_type_node;
! else if (long_p)
type = long_unsigned_type_node;
! else if (short_p)
type = short_unsigned_type_node;
else if (type == char_type_node)
type = unsigned_char_type_node;
else if (typedef_decl)
type = c_common_unsigned_type (type);
else
type = unsigned_type_node;
}
! else if (signed_p && type == char_type_node)
type = signed_char_type_node;
else if (longlong)
type = long_long_integer_type_node;
! else if (long_p)
type = long_integer_type_node;
! else if (short_p)
type = short_integer_type_node;
if (declspecs->specs[(int)ds_complex])
{
+ if (TREE_CODE (type) != INTEGER_TYPE && TREE_CODE (type) != REAL_TYPE)
+ error ("complex invalid for `%s'", name);
/* If we just have "complex", it is equivalent to
"complex double", but if any modifiers at all are specified it is
the complex form of TYPE. E.g, "complex short" is
"complex short int". */
! else if (defaulted_int && ! longlong
! && ! (long_p || short_p || signed_p || unsigned_p))
type = complex_double_type_node;
else if (type == integer_type_node)
type = complex_integer_type_node;
else if (type == float_type_node)
type = complex_float_type_node;
*************** grokdeclarator (const cp_declarator *dec
*** 6760,6770 ****
staticp = 0;
inlinep = !! declspecs->specs[(int)ds_inline];
virtualp = !! declspecs->specs[(int)ds_virtual];
explicitp = !! declspecs->specs[(int)ds_explicit];
! if (declspecs->storage_class == sc_static)
staticp = 1 + (decl_context == FIELD);
if (virtualp && staticp == 2)
{
error ("member `%D' cannot be declared both virtual and static",
--- 6746,6757 ----
staticp = 0;
inlinep = !! declspecs->specs[(int)ds_inline];
virtualp = !! declspecs->specs[(int)ds_virtual];
explicitp = !! declspecs->specs[(int)ds_explicit];
! storage_class = declspecs->storage_class;
! if (storage_class == sc_static)
staticp = 1 + (decl_context == FIELD);
if (virtualp && staticp == 2)
{
error ("member `%D' cannot be declared both virtual and static",
*************** grokdeclarator (const cp_declarator *dec
*** 6782,6794 ****
/* Issue errors about use of storage classes for parameters. */
if (decl_context == PARM)
{
if (declspecs->specs[(int)ds_typedef])
error ("typedef declaration invalid in parameter declaration");
! else if (declspecs->storage_class == sc_static
! || declspecs->storage_class == sc_extern
! || declspecs->specs[(int)ds_thread])
error ("storage class specifiers invalid in parameter declarations");
}
/* Give error if `virtual' is used outside of class declaration. */
if (virtualp
--- 6769,6781 ----
/* Issue errors about use of storage classes for parameters. */
if (decl_context == PARM)
{
if (declspecs->specs[(int)ds_typedef])
error ("typedef declaration invalid in parameter declaration");
! else if (storage_class == sc_static
! || storage_class == sc_extern
! || thread_p)
error ("storage class specifiers invalid in parameter declarations");
}
/* Give error if `virtual' is used outside of class declaration. */
if (virtualp
*************** grokdeclarator (const cp_declarator *dec
*** 6806,6838 ****
/* Warn about storage classes that are invalid for certain
kinds of declarations (parameters, typenames, etc.). */
if (declspecs->multiple_storage_classes_p)
error ("multiple storage classes in declaration of `%s'", name);
! else if (declspecs->specs[(int)ds_thread]
! && ((declspecs->storage_class
! && declspecs->storage_class != sc_extern
! && declspecs->storage_class != sc_static)
|| declspecs->specs[(int)ds_typedef]))
{
error ("multiple storage classes in declaration of `%s'", name);
! declspecs->specs[(int)ds_thread] = 0;
}
else if (decl_context != NORMAL
! && ((declspecs->storage_class != sc_none
! && declspecs->storage_class != sc_mutable)
! || declspecs->specs[(int)ds_thread]))
{
if ((decl_context == PARM || decl_context == CATCHPARM)
! && (declspecs->storage_class == sc_register
! || declspecs->storage_class == sc_auto))
;
else if (declspecs->specs[(int)ds_typedef])
;
else if (decl_context == FIELD
/* C++ allows static class elements. */
! && declspecs->storage_class == sc_static)
/* C++ also allows inlines and signed and unsigned elements,
but in those cases we don't come in here. */
;
else
{
--- 6793,6825 ----
/* Warn about storage classes that are invalid for certain
kinds of declarations (parameters, typenames, etc.). */
if (declspecs->multiple_storage_classes_p)
error ("multiple storage classes in declaration of `%s'", name);
! else if (thread_p
! && ((storage_class
! && storage_class != sc_extern
! && storage_class != sc_static)
|| declspecs->specs[(int)ds_typedef]))
{
error ("multiple storage classes in declaration of `%s'", name);
! thread_p = false;
}
else if (decl_context != NORMAL
! && ((storage_class != sc_none
! && storage_class != sc_mutable)
! || thread_p))
{
if ((decl_context == PARM || decl_context == CATCHPARM)
! && (storage_class == sc_register
! || storage_class == sc_auto))
;
else if (declspecs->specs[(int)ds_typedef])
;
else if (decl_context == FIELD
/* C++ allows static class elements. */
! && storage_class == sc_static)
/* C++ also allows inlines and signed and unsigned elements,
but in those cases we don't come in here. */
;
else
{
*************** grokdeclarator (const cp_declarator *dec
*** 6866,6883 ****
if (decl_context == PARM || decl_context == CATCHPARM)
error ("storage class specified for parameter `%s'", name);
else
error ("storage class specified for typename");
}
! if (declspecs->storage_class == sc_register
! || declspecs->storage_class == sc_auto
! || declspecs->storage_class == sc_extern
! || declspecs->specs[(int)ds_thread])
! declspecs->storage_class = sc_none;
}
}
! else if (declspecs->storage_class == sc_extern && initialized
&& !funcdef_flag)
{
if (toplevel_bindings_p ())
{
/* It's common practice (and completely valid) to have a const
--- 6853,6870 ----
if (decl_context == PARM || decl_context == CATCHPARM)
error ("storage class specified for parameter `%s'", name);
else
error ("storage class specified for typename");
}
! if (storage_class == sc_register
! || storage_class == sc_auto
! || storage_class == sc_extern
! || thread_p)
! storage_class = sc_none;
}
}
! else if (storage_class == sc_extern && initialized
&& !funcdef_flag)
{
if (toplevel_bindings_p ())
{
/* It's common practice (and completely valid) to have a const
*************** grokdeclarator (const cp_declarator *dec
*** 6886,6913 ****
warning ("`%s' initialized and declared `extern'", name);
}
else
error ("`%s' has both `extern' and initializer", name);
}
! else if (declspecs->storage_class == sc_extern && funcdef_flag
&& ! toplevel_bindings_p ())
error ("nested function `%s' declared `extern'", name);
else if (toplevel_bindings_p ())
{
! if (declspecs->storage_class == sc_auto)
error ("top-level declaration of `%s' specifies `auto'", name);
}
! else if (declspecs->specs[(int)ds_thread]
! && declspecs->storage_class != sc_extern
! && declspecs->storage_class != sc_static)
{
error ("function-scope `%s' implicitly auto and declared `__thread'",
name);
! declspecs->specs[(int)ds_thread] = 0;
}
! if (declspecs->storage_class && friendp)
error ("storage class specifiers invalid in friend function declarations");
if (!id_declarator)
unqualified_id = NULL_TREE;
else
--- 6873,6900 ----
warning ("`%s' initialized and declared `extern'", name);
}
else
error ("`%s' has both `extern' and initializer", name);
}
! else if (storage_class == sc_extern && funcdef_flag
&& ! toplevel_bindings_p ())
error ("nested function `%s' declared `extern'", name);
else if (toplevel_bindings_p ())
{
! if (storage_class == sc_auto)
error ("top-level declaration of `%s' specifies `auto'", name);
}
! else if (thread_p
! && storage_class != sc_extern
! && storage_class != sc_static)
{
error ("function-scope `%s' implicitly auto and declared `__thread'",
name);
! thread_p = false;
}
! if (storage_class && friendp)
error ("storage class specifiers invalid in friend function declarations");
if (!id_declarator)
unqualified_id = NULL_TREE;
else
*************** grokdeclarator (const cp_declarator *dec
*** 7332,7368 ****
declarations of constructors within a class definition. */
error ("only declarations of constructors can be `explicit'");
explicitp = 0;
}
! if (declspecs->storage_class == sc_mutable)
{
if (decl_context != FIELD || friendp)
{
error ("non-member `%s' cannot be declared `mutable'", name);
! declspecs->storage_class = sc_none;
}
else if (decl_context == TYPENAME || declspecs->specs[(int)ds_typedef])
{
error ("non-object member `%s' cannot be declared `mutable'", name);
! declspecs->storage_class = sc_none;
}
else if (TREE_CODE (type) == FUNCTION_TYPE
|| TREE_CODE (type) == METHOD_TYPE)
{
error ("function `%s' cannot be declared `mutable'", name);
! declspecs->storage_class = sc_none;
}
else if (staticp)
{
error ("static `%s' cannot be declared `mutable'", name);
! declspecs->storage_class = sc_none;
}
else if (type_quals & TYPE_QUAL_CONST)
{
error ("const `%s' cannot be declared `mutable'", name);
! declspecs->storage_class = sc_none;
}
}
/* If this is declaring a typedef name, return a TYPE_DECL. */
if (declspecs->specs[(int)ds_typedef] && decl_context != TYPENAME)
--- 7319,7355 ----
declarations of constructors within a class definition. */
error ("only declarations of constructors can be `explicit'");
explicitp = 0;
}
! if (storage_class == sc_mutable)
{
if (decl_context != FIELD || friendp)
{
error ("non-member `%s' cannot be declared `mutable'", name);
! storage_class = sc_none;
}
else if (decl_context == TYPENAME || declspecs->specs[(int)ds_typedef])
{
error ("non-object member `%s' cannot be declared `mutable'", name);
! storage_class = sc_none;
}
else if (TREE_CODE (type) == FUNCTION_TYPE
|| TREE_CODE (type) == METHOD_TYPE)
{
error ("function `%s' cannot be declared `mutable'", name);
! storage_class = sc_none;
}
else if (staticp)
{
error ("static `%s' cannot be declared `mutable'", name);
! storage_class = sc_none;
}
else if (type_quals & TYPE_QUAL_CONST)
{
error ("const `%s' cannot be declared `mutable'", name);
! storage_class = sc_none;
}
}
/* If this is declaring a typedef name, return a TYPE_DECL. */
if (declspecs->specs[(int)ds_typedef] && decl_context != TYPENAME)
*************** grokdeclarator (const cp_declarator *dec
*** 7438,7448 ****
}
if (ctype != NULL_TREE)
grok_method_quals (ctype, decl, quals);
}
! if (declspecs->specs[(int)ds_signed]
|| (typedef_decl && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl)))
C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1;
bad_specifiers (decl, "type", virtualp, quals != TYPE_UNQUALIFIED,
inlinep, friendp, raises != NULL_TREE);
--- 7425,7435 ----
}
if (ctype != NULL_TREE)
grok_method_quals (ctype, decl, quals);
}
! if (signed_p
|| (typedef_decl && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl)))
C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1;
bad_specifiers (decl, "type", virtualp, quals != TYPE_UNQUALIFIED,
inlinep, friendp, raises != NULL_TREE);
*************** grokdeclarator (const cp_declarator *dec
*** 7855,7868 ****
}
else
{
decl = build_decl (FIELD_DECL, unqualified_id, type);
DECL_NONADDRESSABLE_P (decl) = bitfield;
! if (declspecs->storage_class == sc_mutable)
{
DECL_MUTABLE_P (decl) = 1;
! declspecs->storage_class = sc_none;
}
}
bad_specifiers (decl, "field", virtualp, quals != TYPE_UNQUALIFIED,
inlinep, friendp, raises != NULL_TREE);
--- 7842,7855 ----
}
else
{
decl = build_decl (FIELD_DECL, unqualified_id, type);
DECL_NONADDRESSABLE_P (decl) = bitfield;
! if (storage_class == sc_mutable)
{
DECL_MUTABLE_P (decl) = 1;
! storage_class = sc_none;
}
}
bad_specifiers (decl, "field", virtualp, quals != TYPE_UNQUALIFIED,
inlinep, friendp, raises != NULL_TREE);
*************** grokdeclarator (const cp_declarator *dec
*** 7880,7905 ****
if (TREE_CODE (unqualified_id) == TEMPLATE_ID_EXPR)
original_name = dname;
else
original_name = unqualified_id;
! if (declspecs->storage_class == sc_auto)
error ("storage class `auto' invalid for function `%s'", name);
! else if (declspecs->storage_class == sc_register)
error ("storage class `register' invalid for function `%s'", name);
! else if (declspecs->specs[(int)ds_thread])
error ("storage class `__thread' invalid for function `%s'", name);
/* Function declaration not at top level.
Storage classes other than `extern' are not allowed
and `extern' makes no difference. */
if (! toplevel_bindings_p ()
! && (declspecs->storage_class == sc_static
|| declspecs->specs[(int)ds_inline])
&& pedantic)
{
! if (declspecs->storage_class == sc_static)
pedwarn ("`static' specified invalid for function `%s' declared out of global scope", name);
else
pedwarn ("`inline' specifier invalid for function `%s' declared out of global scope", name);
}
--- 7867,7892 ----
if (TREE_CODE (unqualified_id) == TEMPLATE_ID_EXPR)
original_name = dname;
else
original_name = unqualified_id;
! if (storage_class == sc_auto)
error ("storage class `auto' invalid for function `%s'", name);
! else if (storage_class == sc_register)
error ("storage class `register' invalid for function `%s'", name);
! else if (thread_p)
error ("storage class `__thread' invalid for function `%s'", name);
/* Function declaration not at top level.
Storage classes other than `extern' are not allowed
and `extern' makes no difference. */
if (! toplevel_bindings_p ()
! && (storage_class == sc_static
|| declspecs->specs[(int)ds_inline])
&& pedantic)
{
! if (storage_class == sc_static)
pedwarn ("`static' specified invalid for function `%s' declared out of global scope", name);
else
pedwarn ("`inline' specifier invalid for function `%s' declared out of global scope", name);
}
*************** grokdeclarator (const cp_declarator *dec
*** 7917,7928 ****
TREE_TYPE (type),
TYPE_ARG_TYPES (type));
/* Record presence of `static'. */
publicp = (ctype != NULL_TREE
! || declspecs->storage_class == sc_extern
! || declspecs->storage_class != sc_static);
decl = grokfndecl (ctype, type, original_name, parms, unqualified_id,
virtualp, flags, quals, raises,
1, friendp,
publicp, inlinep, funcdef_flag,
--- 7904,7915 ----
TREE_TYPE (type),
TYPE_ARG_TYPES (type));
/* Record presence of `static'. */
publicp = (ctype != NULL_TREE
! || storage_class == sc_extern
! || storage_class != sc_static);
decl = grokfndecl (ctype, type, original_name, parms, unqualified_id,
virtualp, flags, quals, raises,
1, friendp,
publicp, inlinep, funcdef_flag,
*************** grokdeclarator (const cp_declarator *dec
*** 7949,7959 ****
}
if (invalid_static)
{
staticp = 0;
! declspecs->storage_class = sc_none;
}
}
}
else
{
--- 7936,7946 ----
}
if (invalid_static)
{
staticp = 0;
! storage_class = sc_none;
}
}
}
else
{
*************** grokdeclarator (const cp_declarator *dec
*** 7973,8006 ****
DECL_CONTEXT (decl) = ctype;
if (staticp == 1)
{
pedwarn ("`static' may not be used when defining (as opposed to declaring) a static data member");
staticp = 0;
! declspecs->storage_class = sc_none;
}
! if (declspecs->storage_class == sc_register && TREE_STATIC (decl))
{
error ("static member `%D' declared `register'", decl);
! declspecs->storage_class = sc_none;
}
! if (declspecs->storage_class == sc_extern && pedantic)
{
pedwarn ("cannot explicitly declare member `%#D' to have extern linkage",
decl);
! declspecs->storage_class = sc_none;
}
}
}
/* Record `register' declaration for warnings on &
and in case doing stupid register allocation. */
! if (declspecs->storage_class == sc_register)
DECL_REGISTER (decl) = 1;
! else if (declspecs->storage_class == sc_extern)
DECL_THIS_EXTERN (decl) = 1;
! else if (declspecs->storage_class == sc_static)
DECL_THIS_STATIC (decl) = 1;
/* Record constancy and volatility. There's no need to do this
when processing a template; we'll do this for the instantiated
declaration based on the type of DECL. */
--- 7960,7993 ----
DECL_CONTEXT (decl) = ctype;
if (staticp == 1)
{
pedwarn ("`static' may not be used when defining (as opposed to declaring) a static data member");
staticp = 0;
! storage_class = sc_none;
}
! if (storage_class == sc_register && TREE_STATIC (decl))
{
error ("static member `%D' declared `register'", decl);
! storage_class = sc_none;
}
! if (storage_class == sc_extern && pedantic)
{
pedwarn ("cannot explicitly declare member `%#D' to have extern linkage",
decl);
! storage_class = sc_none;
}
}
}
/* Record `register' declaration for warnings on &
and in case doing stupid register allocation. */
! if (storage_class == sc_register)
DECL_REGISTER (decl) = 1;
! else if (storage_class == sc_extern)
DECL_THIS_EXTERN (decl) = 1;
! else if (storage_class == sc_static)
DECL_THIS_STATIC (decl) = 1;
/* Record constancy and volatility. There's no need to do this
when processing a template; we'll do this for the instantiated
declaration based on the type of DECL. */
Index: cp/decl.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.h,v
retrieving revision 1.15
diff -c -5 -p -r1.15 decl.h
*** cp/decl.h 24 Jun 2004 06:48:43 -0000 1.15
--- cp/decl.h 13 Jul 2004 21:08:53 -0000
*************** enum decl_context
*** 30,40 ****
MEMFUNCDEF /* Member function definition */
};
/* We need this in here to get the decl_context definition. */
extern tree grokdeclarator (const cp_declarator *,
! cp_decl_specifier_seq *,
enum decl_context, int, tree*);
#ifdef DEBUG_CP_BINDING_LEVELS
/* Purely for debugging purposes. */
extern int debug_bindings_indentation;
--- 30,40 ----
MEMFUNCDEF /* Member function definition */
};
/* We need this in here to get the decl_context definition. */
extern tree grokdeclarator (const cp_declarator *,
! const cp_decl_specifier_seq *,
enum decl_context, int, tree*);
#ifdef DEBUG_CP_BINDING_LEVELS
/* Purely for debugging purposes. */
extern int debug_bindings_indentation;
Index: cp/parser.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/parser.c,v
retrieving revision 1.227
diff -c -5 -p -r1.227 parser.c
*** cp/parser.c 12 Jul 2004 19:10:03 -0000 1.227
--- cp/parser.c 13 Jul 2004 21:08:53 -0000
*************** cp_parser_init_declarator (cp_parser* pa
*** 10475,10485 ****
bool pop_p = false;
/* Gather the attributes that were provided with the
decl-specifiers. */
prefix_attributes = decl_specifiers->attributes;
- decl_specifiers->attributes = NULL_TREE;
/* Assume that this is not the declarator for a function
definition. */
if (function_definition_p)
*function_definition_p = false;
--- 10475,10484 ----
Index: testsuite/g++.dg/parse/mutable1.C
===================================================================
RCS file: testsuite/g++.dg/parse/mutable1.C
diff -N testsuite/g++.dg/parse/mutable1.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/parse/mutable1.C 13 Jul 2004 21:08:53 -0000
***************
*** 0 ****
--- 1,7 ----
+ // PR c++/16518
+
+ struct foo {
+ void bar() const { m1=1; m2=1;}
+ mutable int m1,m2;
+ };
+
More information about the Gcc-patches
mailing list