aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/decl.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/decl.c')
-rw-r--r--gcc/cp/decl.c271
1 files changed, 139 insertions, 132 deletions
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 45feb9f0c58..c7967c7709b 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -106,9 +106,6 @@ static void initialize_local_var (tree, tree);
static void expand_static_init (tree, tree);
static tree next_initializable_field (tree);
-/* Erroneous argument lists can use this *IFF* they do not modify it. */
-tree error_mark_list;
-
/* The following symbols are subsumed in the cp_global_trees array, and
listed here individually for documentation purposes.
@@ -3118,9 +3115,6 @@ cxx_init_decl_processing (void)
/* Initially, C. */
current_lang_name = lang_name_c;
- error_mark_list = build_tree_list (error_mark_node, error_mark_node);
- TREE_TYPE (error_mark_list) = error_mark_node;
-
/* Create the `std' namespace. */
push_namespace (std_identifier);
std_node = current_namespace;
@@ -5814,6 +5808,28 @@ check_class_member_definition_namespace (tree decl)
decl, DECL_CONTEXT (decl));
}
+/* Build a PARM_DECL for the "this" parameter. TYPE is the
+ METHOD_TYPE for a non-static member function; QUALS are the
+ cv-qualifiers that apply to the function. */
+
+tree
+build_this_parm (tree type, cp_cv_quals quals)
+{
+ tree this_type;
+ tree qual_type;
+ tree parm;
+ cp_cv_quals this_quals;
+
+ this_type = TREE_VALUE (TYPE_ARG_TYPES (type));
+ /* The `this' parameter is implicitly `const'; it cannot be
+ assigned to. */
+ this_quals = (quals & TYPE_QUAL_RESTRICT) | TYPE_QUAL_CONST;
+ qual_type = cp_build_qualified_type (this_type, this_quals);
+ parm = build_artificial_parm (this_identifier, qual_type);
+ cp_apply_type_quals_to_decl (this_quals, parm);
+ return parm;
+}
+
/* CTYPE is class type, or null if non-class.
TYPE is type this FUNCTION_DECL should have, either FUNCTION_TYPE
or METHOD_TYPE.
@@ -5860,6 +5876,13 @@ grokfndecl (tree ctype,
type = build_exception_variant (type, raises);
decl = build_lang_decl (FUNCTION_DECL, declarator, type);
+ if (TREE_CODE (type) == METHOD_TYPE)
+ {
+ tree parm;
+ parm = build_this_parm (type, quals);
+ TREE_CHAIN (parm) = parms;
+ parms = parm;
+ }
DECL_ARGUMENTS (decl) = parms;
/* Propagate volatile out from type to decl. */
if (TYPE_VOLATILE (type))
@@ -6063,7 +6086,7 @@ grokfndecl (tree ctype,
if (sfk == sfk_constructor)
DECL_CONSTRUCTOR_P (decl) = 1;
- grokclassfn (ctype, decl, flags, quals);
+ grokclassfn (ctype, decl, flags);
}
decl = check_explicit_specialization (orig_declarator, decl,
@@ -6771,12 +6794,11 @@ grokdeclarator (const cp_declarator *declarator,
{
tree type = NULL_TREE;
int longlong = 0;
- int type_quals;
int virtualp, explicitp, friendp, inlinep, staticp;
int explicit_int = 0;
int explicit_char = 0;
int defaulted_int = 0;
- tree dependant_name = NULL_TREE;
+ tree dependent_name = NULL_TREE;
tree typedef_decl = NULL_TREE;
const char *name = NULL;
@@ -6798,7 +6820,11 @@ grokdeclarator (const cp_declarator *declarator,
tree dname = NULL_TREE;
tree ctor_return_type = NULL_TREE;
enum overload_flags flags = NO_SPECIAL;
- cp_cv_quals quals = TYPE_UNQUALIFIED;
+ /* cv-qualifiers that apply to the declarator, for a declaration of
+ a member function. */
+ cp_cv_quals memfn_quals = TYPE_UNQUALIFIED;
+ /* cv-qualifiers that apply to the type specified by the DECLSPECS. */
+ int type_quals;
tree raises = NULL_TREE;
int template_count = 0;
tree returned_attrs = NULL_TREE;
@@ -6956,7 +6982,7 @@ grokdeclarator (const cp_declarator *declarator,
break;
case cdk_error:
- break;
+ return error_mark_node;
default:
gcc_unreachable ();
@@ -6966,11 +6992,15 @@ grokdeclarator (const cp_declarator *declarator,
break;
}
- /* A function definition's declarator must have the form of
- a function declarator. */
-
+ /* [dcl.fct.edf]
+
+ The declarator in a function-definition shall have the form
+ D1 ( parameter-declaration-clause) ... */
if (funcdef_flag && innermost_code != cdk_function)
- return NULL_TREE;
+ {
+ error ("function definition does not declare parameters");
+ return error_mark_node;
+ }
if (((dname && IDENTIFIER_OPNAME_P (dname)) || flags == TYPENAME_FLAG)
&& innermost_code != cdk_function
@@ -7252,9 +7282,9 @@ grokdeclarator (const cp_declarator *declarator,
}
friendp = !! declspecs->specs[(int)ds_friend];
- if (dependant_name && !friendp)
+ if (dependent_name && !friendp)
{
- error ("%<%T::%D%> is not a valid declarator", ctype, dependant_name);
+ error ("%<%T::%D%> is not a valid declarator", ctype, dependent_name);
return void_type_node;
}
@@ -7453,7 +7483,7 @@ grokdeclarator (const cp_declarator *declarator,
}
/* Pick up type qualifiers which should be applied to `this'. */
- quals = declarator->u.function.qualifiers;
+ memfn_quals = declarator->u.function.qualifiers;
/* Pick up the exception specifications. */
raises = declarator->u.function.exception_specification;
@@ -7475,53 +7505,44 @@ grokdeclarator (const cp_declarator *declarator,
is the same as the class name, and we are defining
a function, then it is a constructor/destructor, and
therefore returns a void type. */
-
- if (flags == DTOR_FLAG)
+
+ /* ISO C++ 12.4/2. A destructor may not be declared
+ const or volatile. A destructor may not be
+ static.
+
+ ISO C++ 12.1. A constructor may not be declared
+ const or volatile. A constructor may not be
+ virtual. A constructor may not be static. */
+ if (staticp == 2)
+ error ((flags == DTOR_FLAG)
+ ? "destructor cannot be static member function"
+ : "constructor cannot be static member function");
+ if (memfn_quals)
{
- /* ISO C++ 12.4/2. A destructor may not be
- declared const or volatile. A destructor may
- not be static. */
- if (staticp == 2)
- error ("destructor cannot be static member function");
- if (quals)
- {
- error ("destructors may not be cv-qualified");
- quals = TYPE_UNQUALIFIED;
- }
- if (decl_context == FIELD)
- {
- if (! member_function_or_else (ctype,
- current_class_type,
- flags))
- return void_type_node;
- }
+ error ((flags == DTOR_FLAG)
+ ? "destructors may not be cv-qualified"
+ : "constructors may not be cv-qualified");
+ memfn_quals = TYPE_UNQUALIFIED;
}
- else /* It's a constructor. */
+
+ if (decl_context == FIELD
+ && !member_function_or_else (ctype,
+ current_class_type,
+ flags))
+ return void_type_node;
+
+ if (flags != DTOR_FLAG)
{
+ /* It's a constructor. */
if (explicitp == 1)
explicitp = 2;
- /* ISO C++ 12.1. A constructor may not be
- declared const or volatile. A constructor may
- not be virtual. A constructor may not be
- static. */
- if (staticp == 2)
- error ("constructor cannot be static member function");
if (virtualp)
{
pedwarn ("constructors cannot be declared virtual");
virtualp = 0;
}
- if (quals)
- {
- error ("constructors may not be cv-qualified");
- quals = TYPE_UNQUALIFIED;
- }
if (decl_context == FIELD)
{
- if (! member_function_or_else (ctype,
- current_class_type,
- flags))
- return void_type_node;
TYPE_HAS_CONSTRUCTOR (ctype) = 1;
if (sfk != sfk_constructor)
return NULL_TREE;
@@ -7562,7 +7583,6 @@ grokdeclarator (const cp_declarator *declarator,
}
type = build_function_type (type, arg_types);
- type = cp_build_qualified_type (type, quals);
}
break;
@@ -7592,22 +7612,13 @@ grokdeclarator (const cp_declarator *declarator,
type_quals = TYPE_UNQUALIFIED;
if (declarator->kind == cdk_ptrmem
- && (TREE_CODE (type) == FUNCTION_TYPE
- || (quals && TREE_CODE (type) == METHOD_TYPE)))
+ && (TREE_CODE (type) == FUNCTION_TYPE || memfn_quals))
{
- tree dummy;
-
- /* If the type is a FUNCTION_TYPE, pick up the
- qualifiers from that function type. No other
- qualifiers may be supplied. */
- if (TREE_CODE (type) == FUNCTION_TYPE)
- quals = cp_type_quals (type);
-
- dummy = build_decl (TYPE_DECL, NULL_TREE, type);
- grok_method_quals (declarator->u.pointer.class_type,
- dummy, quals);
- type = TREE_TYPE (dummy);
- quals = TYPE_UNQUALIFIED;
+ memfn_quals |= cp_type_quals (type);
+ type = build_memfn_type (type,
+ declarator->u.pointer.class_type,
+ memfn_quals);
+ memfn_quals = TYPE_UNQUALIFIED;
}
if (declarator->kind == cdk_reference)
@@ -7619,15 +7630,9 @@ grokdeclarator (const cp_declarator *declarator,
type = build_ptrmemfunc_type (build_pointer_type (type));
else if (declarator->kind == cdk_ptrmem)
{
- /* We might have parsed a namespace as the class type. */
- if (TREE_CODE (declarator->u.pointer.class_type)
- == NAMESPACE_DECL)
- {
- error ("%qD is a namespace",
- declarator->u.pointer.class_type);
- type = build_pointer_type (type);
- }
- else if (declarator->u.pointer.class_type == error_mark_node)
+ gcc_assert (TREE_CODE (declarator->u.pointer.class_type)
+ != NAMESPACE_DECL);
+ if (declarator->u.pointer.class_type == error_mark_node)
/* We will already have complained. */
type = error_mark_node;
else
@@ -7717,6 +7722,20 @@ grokdeclarator (const cp_declarator *declarator,
pedwarn ("extra qualification %<%T::%> on member %qs",
ctype, name);
}
+ else if (/* If the qualifying type is already complete, then we
+ can skip the following checks. */
+ !COMPLETE_TYPE_P (ctype)
+ /* If a function is being defined, then the qualifying
+ type must be complete. The qualifying type may be
+ incomplete for a declaration only if the qualifying
+ type is one of the classes presently being defined,
+ or if it is a dependent type. */
+ && (funcdef_flag
+ || !(dependent_type_p (ctype)
+ || currently_open_class (ctype)))
+ /* Check that the qualifying type is complete. */
+ && !complete_type_or_else (ctype, NULL_TREE))
+ return error_mark_node;
else if (TREE_CODE (type) == FUNCTION_TYPE)
{
tree sname = declarator->u.id.unqualified_name;
@@ -7737,28 +7756,13 @@ grokdeclarator (const cp_declarator *declarator,
are always static functions. */
;
else
- type = build_method_type_directly (ctype,
- TREE_TYPE (type),
- TYPE_ARG_TYPES (type));
+ type = build_memfn_type (type, ctype, memfn_quals);
}
else if (declspecs->specs[(int)ds_typedef]
- || COMPLETE_TYPE_P (complete_type (ctype)))
+ && current_class_type)
{
- /* Have to move this code elsewhere in this function.
- this code is used for i.e., typedef int A::M; M *pm;
-
- It is? How? jason 10/2/94 */
-
- if (current_class_type)
- {
- error ("cannot declare member %<%T::%s%> within %qT",
- ctype, name, current_class_type);
- return void_type_node;
- }
- }
- else
- {
- cxx_incomplete_type_error (NULL_TREE, ctype);
+ error ("cannot declare member %<%T::%s%> within %qT",
+ ctype, name, current_class_type);
return error_mark_node;
}
}
@@ -7844,6 +7848,18 @@ grokdeclarator (const cp_declarator *declarator,
in typenames, fields or parameters. */
if (current_lang_name == lang_name_java)
TYPE_FOR_JAVA (type) = 1;
+
+ /* This declaration:
+
+ typedef void f(int) const;
+
+ declares a function type which is not a member of any
+ particular class, but which is cv-qualified; for
+ example "f S::*" declares a pointer to a const-qualified
+ member function of S. We record the cv-qualification in the
+ function type. */
+ if (memfn_quals && TREE_CODE (type) == FUNCTION_TYPE)
+ type = cp_build_qualified_type (type, memfn_quals);
if (decl_context == FIELD)
decl = build_lang_decl (TYPE_DECL, unqualified_id, type);
@@ -7905,26 +7921,17 @@ grokdeclarator (const cp_declarator *declarator,
type with external linkage have external linkage. */
}
- if (quals)
- {
- if (ctype == NULL_TREE)
- {
- if (TREE_CODE (type) == METHOD_TYPE)
- ctype = TYPE_METHOD_BASETYPE (type);
- /* Any qualifiers on a function type typedef have
- already been dealt with. */
- else if (TREE_CODE (type) == FUNCTION_TYPE)
- quals = TYPE_UNQUALIFIED;
- }
- if (ctype != NULL_TREE)
- grok_method_quals (ctype, decl, quals);
- }
+ /* Any qualifiers on a function type typedef have already been
+ dealt with. */
+ if (memfn_quals && !ctype && TREE_CODE (type) == FUNCTION_TYPE)
+ memfn_quals = TYPE_UNQUALIFIED;
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,
+ bad_specifiers (decl, "type", virtualp,
+ memfn_quals != TYPE_UNQUALIFIED,
inlinep, friendp, raises != NULL_TREE);
return decl;
@@ -7972,7 +7979,7 @@ grokdeclarator (const cp_declarator *declarator,
/* The qualifiers on the function type become the qualifiers on
the non-static member function. */
- quals |= cp_type_quals (type);
+ memfn_quals |= cp_type_quals (type);
}
}
@@ -8029,7 +8036,7 @@ grokdeclarator (const cp_declarator *declarator,
type = void_type_node;
}
}
- else if (quals)
+ else if (memfn_quals)
{
if (ctype == NULL_TREE)
{
@@ -8039,11 +8046,7 @@ grokdeclarator (const cp_declarator *declarator,
ctype = TYPE_METHOD_BASETYPE (type);
}
if (ctype)
- {
- tree dummy = build_decl (TYPE_DECL, unqualified_id, type);
- grok_method_quals (ctype, dummy, quals);
- type = TREE_TYPE (dummy);
- }
+ type = build_memfn_type (type, ctype, memfn_quals);
}
return type;
@@ -8101,7 +8104,8 @@ grokdeclarator (const cp_declarator *declarator,
{
decl = cp_build_parm_decl (unqualified_id, type);
- bad_specifiers (decl, "parameter", virtualp, quals != TYPE_UNQUALIFIED,
+ bad_specifiers (decl, "parameter", virtualp,
+ memfn_quals != TYPE_UNQUALIFIED,
inlinep, friendp, raises != NULL_TREE);
}
else if (decl_context == FIELD)
@@ -8163,9 +8167,7 @@ grokdeclarator (const cp_declarator *declarator,
}
}
else if (staticp < 2)
- type = build_method_type_directly (ctype,
- TREE_TYPE (type),
- TYPE_ARG_TYPES (type));
+ type = build_memfn_type (type, ctype, memfn_quals);
}
/* Check that the name used for a destructor makes sense. */
@@ -8200,7 +8202,7 @@ grokdeclarator (const cp_declarator *declarator,
? unqualified_id : dname,
parms,
unqualified_id,
- virtualp, flags, quals, raises,
+ virtualp, flags, memfn_quals, raises,
friendp ? -1 : 0, friendp, publicp, inlinep,
sfk,
funcdef_flag, template_count, in_namespace, attrlist);
@@ -8248,7 +8250,7 @@ grokdeclarator (const cp_declarator *declarator,
? unqualified_id : dname,
parms,
unqualified_id,
- virtualp, flags, quals, raises,
+ virtualp, flags, memfn_quals, raises,
friendp ? -1 : 0, friendp, 1, 0, sfk,
funcdef_flag, template_count, in_namespace,
attrlist);
@@ -8305,7 +8307,8 @@ grokdeclarator (const cp_declarator *declarator,
}
decl = do_friend (ctype, unqualified_id, decl,
- *attrlist, flags, quals, funcdef_flag);
+ *attrlist, flags,
+ funcdef_flag);
return decl;
}
else
@@ -8384,7 +8387,8 @@ grokdeclarator (const cp_declarator *declarator,
}
}
- bad_specifiers (decl, "field", virtualp, quals != TYPE_UNQUALIFIED,
+ bad_specifiers (decl, "field", virtualp,
+ memfn_quals != TYPE_UNQUALIFIED,
inlinep, friendp, raises != NULL_TREE);
}
}
@@ -8445,7 +8449,7 @@ grokdeclarator (const cp_declarator *declarator,
|| storage_class != sc_static);
decl = grokfndecl (ctype, type, original_name, parms, unqualified_id,
- virtualp, flags, quals, raises,
+ virtualp, flags, memfn_quals, raises,
1, friendp,
publicp, inlinep, sfk, funcdef_flag,
template_count, in_namespace, attrlist);
@@ -8488,7 +8492,8 @@ grokdeclarator (const cp_declarator *declarator,
initialized,
(type_quals & TYPE_QUAL_CONST) != 0,
ctype ? ctype : in_namespace);
- bad_specifiers (decl, "variable", virtualp, quals != TYPE_UNQUALIFIED,
+ bad_specifiers (decl, "variable", virtualp,
+ memfn_quals != TYPE_UNQUALIFIED,
inlinep, friendp, raises != NULL_TREE);
if (ctype)
@@ -10801,9 +10806,11 @@ finish_destructor_body (void)
an implicit definition), non-placement operator delete shall
be looked up in the scope of the destructor's class and if
found shall be accessible and unambiguous. */
- exprstmt = build_op_delete_call
- (DELETE_EXPR, current_class_ptr, virtual_size,
- /*global_p=*/false, NULL_TREE);
+ exprstmt = build_op_delete_call(DELETE_EXPR, current_class_ptr,
+ virtual_size,
+ /*global_p=*/false,
+ /*placement=*/NULL_TREE,
+ /*alloc_fn=*/NULL_TREE);
if_stmt = begin_if_stmt ();
finish_if_stmt_cond (build2 (BIT_AND_EXPR, integer_type_node,