static int unary_op_p (enum tree_code);
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,
- tree *);
static tree grokvardecl (tree, tree, const cp_decl_specifier_seq *,
int, int, tree);
static void record_unknown_type (tree, const char *);
static const char *tag_name (enum tag_types);
static tree lookup_and_check_tag (enum tag_types, tree, tag_scope, bool);
static int walk_namespaces_r (tree, walk_namespaces_fn, void *);
-static int walk_globals_r (tree, void*);
-static int walk_vtables_r (tree, void*);
static tree make_label_decl (tree, int);
static void use_label (tree);
static void check_previous_goto_1 (tree, struct cp_binding_level *, tree,
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, block);
}
-/* Delete the node BLOCK from the current binding level.
- This is used for the block inside a stmt expr ({...})
- so that the block can be reinserted where appropriate. */
-
-void
-delete_block (tree block)
-{
- tree t;
- if (current_binding_level->blocks == block)
- current_binding_level->blocks = TREE_CHAIN (block);
- for (t = current_binding_level->blocks; t;)
- {
- if (TREE_CHAIN (t) == block)
- TREE_CHAIN (t) = TREE_CHAIN (block);
- else
- t = TREE_CHAIN (t);
- }
- TREE_CHAIN (block) = NULL_TREE;
- /* Clear TREE_USED which is always set by poplevel.
- The flag is set again if insert_block is called. */
- TREE_USED (block) = 0;
-}
-
/* Insert BLOCK at the end of the list of subblocks of the
current binding level. This is used when a BIND_EXPR is expanded,
to handle the BLOCK node inside the BIND_EXPR. */
= chainon (current_binding_level->blocks, block);
}
-/* Returns nonzero if T is a virtual function table. */
-
-int
-vtable_decl_p (tree t, void* data ATTRIBUTE_UNUSED )
-{
- return (TREE_CODE (t) == VAR_DECL && DECL_VIRTUAL_P (t));
-}
-
-/* Returns nonzero if T is a TYPE_DECL for a type with virtual
- functions. */
-
-int
-vtype_decl_p (tree t, void *data ATTRIBUTE_UNUSED )
-{
- return (TREE_CODE (t) == TYPE_DECL
- && TREE_CODE (TREE_TYPE (t)) == RECORD_TYPE
- && TYPE_POLYMORPHIC_P (TREE_TYPE (t)));
-}
-
-struct walk_globals_data {
- walk_globals_pred p;
- walk_globals_fn f;
- void *data;
-};
-
-/* Walk the vtable declarations in NAMESPACE. Whenever one is found
- for which P returns nonzero, call F with its address. If any call
- to F returns a nonzero value, return a nonzero value. */
-
-static int
-walk_vtables_r (tree namespace, void* data)
-{
- struct walk_globals_data* wgd = (struct walk_globals_data *) data;
- walk_globals_fn f = wgd->f;
- void *d = wgd->data;
- tree decl = NAMESPACE_LEVEL (namespace)->vtables;
- int result = 0;
-
- for (; decl ; decl = TREE_CHAIN (decl))
- result |= (*f) (&decl, d);
-
- return result;
-}
-
-/* Walk the vtable declarations. Whenever one is found for which P
- returns nonzero, call F with its address. If any call to F
- returns a nonzero value, return a nonzero value. */
-bool
-walk_vtables (walk_globals_pred p, walk_globals_fn f, void *data)
-{
- struct walk_globals_data wgd;
- wgd.p = p;
- wgd.f = f;
- wgd.data = data;
-
- return walk_namespaces (walk_vtables_r, &wgd);
-}
-
/* Walk all the namespaces contained NAMESPACE, including NAMESPACE
itself, calling F for each. The DATA is passed to F as well. */
return walk_namespaces_r (global_namespace, f, data);
}
-/* Walk the global declarations in NAMESPACE. Whenever one is found
- for which P returns nonzero, call F with its address. If any call
- to F returns a nonzero value, return a nonzero value. */
-
-static int
-walk_globals_r (tree namespace, void* data)
-{
- struct walk_globals_data* wgd = (struct walk_globals_data *) data;
- walk_globals_pred p = wgd->p;
- walk_globals_fn f = wgd->f;
- void *d = wgd->data;
- tree *t;
- int result = 0;
-
- t = &NAMESPACE_LEVEL (namespace)->names;
-
- while (*t)
- {
- tree glbl = *t;
-
- if ((*p) (glbl, d))
- result |= (*f) (t, d);
-
- /* If F changed *T, then *T still points at the next item to
- examine. */
- if (*t == glbl)
- t = &TREE_CHAIN (*t);
- }
-
- return result;
-}
-
-/* Walk the global declarations. Whenever one is found for which P
- returns true, call F with its address. If any call to F
- returns true, return true. */
-
-bool
-walk_globals (walk_globals_pred p, walk_globals_fn f, void *data)
-{
- struct walk_globals_data wgd;
- wgd.p = p;
- wgd.f = f;
- wgd.data = data;
-
- return walk_namespaces (walk_globals_r, &wgd);
-}
-
/* Call wrapup_globals_declarations for the globals in NAMESPACE. If
DATA is non-NULL, this is the last time we will call
wrapup_global_declarations for this NAMESPACE. */
DECL_COMDAT (newdecl) |= DECL_COMDAT (olddecl);
DECL_TEMPLATE_INSTANTIATED (newdecl)
|= DECL_TEMPLATE_INSTANTIATED (olddecl);
+ /* If the OLDDECL is an implicit instantiation, then the NEWDECL
+ must be too. But, it may not yet be marked as such if the
+ caller has created NEWDECL, but has not yet figured out that
+ it is a redeclaration. */
+ if (DECL_IMPLICIT_INSTANTIATION (olddecl)
+ && !DECL_USE_TEMPLATE (newdecl))
+ SET_DECL_IMPLICIT_INSTANTIATION (newdecl);
/* Don't really know how much of the language-specific
values we should copy from old to new. */
DECL_IN_AGGR_P (newdecl) = DECL_IN_AGGR_P (olddecl);
/* If this is a pure function, its olddecl will actually be
the original initialization to `0' (which we force to call
abort()). Don't complain about redefinition in this case. */
- if (DECL_LANG_SPECIFIC (olddecl) && DECL_PURE_VIRTUAL_P (olddecl))
+ if (DECL_LANG_SPECIFIC (olddecl) && DECL_PURE_VIRTUAL_P (olddecl)
+ && DECL_INITIAL (olddecl) == NULL_TREE)
return 0;
/* If both functions come from different namespaces, this is not
}
/* Find the condition on which this switch statement depends. */
- cond = SWITCH_COND (switch_stack->switch_stmt);
+ cond = SWITCH_STMT_COND (switch_stack->switch_stmt);
if (cond && TREE_CODE (cond) == TREE_LIST)
cond = TREE_VALUE (cond);
if ((DECL_LANG_SPECIFIC (decl) && DECL_USE_TEMPLATE (decl))
|| CLASSTYPE_TEMPLATE_INSTANTIATION (context))
{
- SET_DECL_TEMPLATE_SPECIALIZATION (decl);
+ /* Do not mark DECL as an explicit specialization if it was
+ not already marked as an instantiation; a declaration
+ should never be marked as a specialization unless we know
+ what template is being specialized. */
+ if (DECL_LANG_SPECIFIC (decl) && DECL_USE_TEMPLATE (decl))
+ SET_DECL_TEMPLATE_SPECIALIZATION (decl);
/* [temp.expl.spec] An explicit specialization of a static data
member of a template is a definition if the declaration
includes an initializer; otherwise, it is a declaration.
new_init = build_tree_list (TREE_PURPOSE (old_init), new_init);
}
- /* If this was a brace-enclosed initializer and all of the
- initializers were not used up, there is a problem. */
- if (brace_enclosed_p && *initp)
- error ("too many initializers for %qT", type);
+ /* If there are more initializers than necessary, issue a
+ diagnostic. */
+ if (*initp)
+ {
+ if (brace_enclosed_p)
+ error ("too many initializers for %qT", type);
+ else if (warn_missing_braces)
+ warning ("missing braces around initializer");
+ }
return new_init;
}
if (type == error_mark_node)
goto finish_end;
- if (TYPE_HAS_MUTABLE_P (type))
- TREE_READONLY (decl) = 0;
-
if (processing_template_decl)
{
/* Add this declaration to the statement-tree. */
ttype = target_type (type);
- /* Currently, GNU C++ puts constants in text space, making them
- impossible to initialize. In the future, one would hope for
- an operating system which understood the difference between
- initialization and the running of a program. */
- if (! DECL_EXTERNAL (decl) && TREE_READONLY (decl))
+ /* A reference will be modified here, as it is initialized. */
+ if (! DECL_EXTERNAL (decl)
+ && TREE_READONLY (decl)
+ && TREE_CODE (type) == REFERENCE_TYPE)
{
was_readonly = 1;
- if (TYPE_NEEDS_CONSTRUCTING (type)
- || TREE_CODE (type) == REFERENCE_TYPE)
- TREE_READONLY (decl) = 0;
+ TREE_READONLY (decl) = 0;
}
if (TREE_CODE (decl) == VAR_DECL)
CHECK is 1 if we must find this method in CTYPE, 0 if we should
not look, and -1 if we should not call `grokclassfn' at all.
+ SFK is the kind of special function (if any) for the new function.
+
Returns `NULL_TREE' if something goes wrong, after issuing
applicable error messages. */
int friendp,
int publicp,
int inlinep,
+ special_function_kind sfk,
int funcdef_flag,
int template_count,
tree in_namespace,
if (check < 0)
return decl;
- if (flags == NO_SPECIAL && ctype && constructor_name_p (declarator, ctype))
- DECL_CONSTRUCTOR_P (decl) = 1;
-
- /* Function gets the ugly name, field gets the nice one. This call
- may change the type of the function (because of default
- parameters)! */
if (ctype != NULL_TREE)
- grokclassfn (ctype, decl, flags, quals);
+ {
+ if (sfk == sfk_constructor)
+ DECL_CONSTRUCTOR_P (decl) = 1;
+
+ grokclassfn (ctype, decl, flags, quals);
+ }
decl = check_explicit_specialization (orig_declarator, decl,
template_count,
{
case BIT_NOT_EXPR:
{
- tree type = TREE_OPERAND (decl, 0);
- type = constructor_name (type);
- name = IDENTIFIER_POINTER (type);
+ tree type;
+
+ if (innermost_code != cdk_function)
+ {
+ error ("declaration of %qD as non-function", decl);
+ return error_mark_node;
+ }
+ else if (!qualifying_scope
+ && !(current_class_type && at_class_scope_p ()))
+ {
+ error ("declaration of %qD as non-member", decl);
+ return error_mark_node;
+ }
+
+ type = TREE_OPERAND (decl, 0);
+ name = IDENTIFIER_POINTER (constructor_name (type));
}
break;
error ("qualifiers are not allowed on declaration of %<operator %T%>",
ctor_return_type);
+ if (TREE_CODE (type) == FUNCTION_TYPE
+ && type_quals != TYPE_UNQUALIFIED)
+ {
+ /* This was an error in C++98 (cv-qualifiers cannot be added to
+ a function type), but DR 295 makes the code well-formed by
+ dropping the extra qualifiers. */
+ if (pedantic)
+ {
+ tree bad_type = build_qualified_type (type, type_quals);
+ pedwarn ("ignoring %qV qualifiers added to function type %qT",
+ bad_type, type);
+ }
+ type_quals = TYPE_UNQUALIFIED;
+ }
type_quals |= cp_type_quals (type);
type = cp_build_qualified_type_real
(type, type_quals, ((typedef_decl && !DECL_ARTIFICIAL (typedef_decl)
}
type = build_function_type (type, arg_types);
+ type = cp_build_qualified_type (type, quals);
}
break;
&& (TREE_CODE (type) == FUNCTION_TYPE
|| (quals && TREE_CODE (type) == METHOD_TYPE)))
{
- tree dummy = build_decl (TYPE_DECL, NULL_TREE, type);
+ 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);
declarator->u.pointer.class_type);
type = build_pointer_type (type);
}
+ else if (declarator->u.pointer.class_type == error_mark_node)
+ /* We will already have complained. */
+ type = error_mark_node;
else
type = build_ptrmem_type (declarator->u.pointer.class_type,
type);
TYPE_FOR_JAVA (type) = 1;
if (decl_context == FIELD)
- {
- if (constructor_name_p (unqualified_id, current_class_type))
- pedwarn ("ISO C++ forbids nested type %qD with same name "
- "as enclosing class",
- unqualified_id);
- decl = build_lang_decl (TYPE_DECL, unqualified_id, type);
- }
+ decl = build_lang_decl (TYPE_DECL, unqualified_id, type);
else
+ decl = build_decl (TYPE_DECL, unqualified_id, type);
+ if (id_declarator && declarator->u.id.qualifying_scope)
+ error ("%Jtypedef name may not be a nested-name-specifier", decl);
+
+ if (decl_context != FIELD)
{
- decl = build_decl (TYPE_DECL, unqualified_id, type);
- if (in_namespace || ctype)
- error ("%Jtypedef name may not be a nested-name-specifier", decl);
if (!current_function_decl)
DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace);
else if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (current_function_decl)
clones. */
DECL_ABSTRACT (decl) = 1;
}
+ else if (constructor_name_p (unqualified_id, current_class_type))
+ pedwarn ("ISO C++ forbids nested type %qD with same name "
+ "as enclosing class",
+ unqualified_id);
/* If the user declares "typedef struct {...} foo" then the
struct will have an anonymous name. Fill that name in now.
{
if (ctype == NULL_TREE)
{
- if (TREE_CODE (type) != METHOD_TYPE)
- error ("%Jinvalid type qualifier for non-member function type",
- decl);
- else
+ 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);
}
parms = nreverse (decls);
+
+ if (decl_context != TYPENAME)
+ {
+ /* A cv-qualifier-seq shall only be part of the function type
+ for a non-static member function. [8.3.5/4 dcl.fct] */
+ if (cp_type_quals (type) != TYPE_UNQUALIFIED
+ && (current_class_type == NULL_TREE || staticp) )
+ {
+ error ("qualified function types cannot be used to declare %s functions",
+ (staticp? "static member" : "free"));
+ type = TYPE_MAIN_VARIANT (type);
+ }
+
+ /* The qualifiers on the function type become the qualifiers on
+ the non-static member function. */
+ quals |= cp_type_quals (type);
+ }
}
/* If this is a type name (such as, in a cast or sizeof),
int publicp = 0;
tree function_context;
- /* We catch the others as conflicts with the builtin
- typedefs. */
- if (friendp && unqualified_id == ridpointers[(int) RID_SIGNED])
- {
- error ("function %qD cannot be declared friend",
- unqualified_id);
- friendp = 0;
- }
-
if (friendp == 0)
{
if (ctype == NULL_TREE)
TYPE_ARG_TYPES (type));
}
+ /* Check that the name used for a destructor makes sense. */
+ if (sfk == sfk_destructor
+ && !same_type_p (TREE_OPERAND
+ (id_declarator->u.id.unqualified_name, 0),
+ ctype))
+ {
+ error ("declaration of %qD as member of %qT",
+ id_declarator->u.id.unqualified_name,
+ ctype);
+ return error_mark_node;
+ }
+
/* Tell grokfndecl if it needs to set TREE_PUBLIC on the node. */
function_context = (ctype != NULL_TREE) ?
decl_function_context (TYPE_MAIN_DECL (ctype)) : NULL_TREE;
unqualified_id,
virtualp, flags, quals, raises,
friendp ? -1 : 0, friendp, publicp, inlinep,
+ sfk,
funcdef_flag, template_count, in_namespace, attrlist);
if (decl == NULL_TREE)
return decl;
parms,
unqualified_id,
virtualp, flags, quals, raises,
- friendp ? -1 : 0, friendp, 1, 0, funcdef_flag,
- template_count, in_namespace, attrlist);
+ friendp ? -1 : 0, friendp, 1, 0, sfk,
+ funcdef_flag, template_count, in_namespace,
+ attrlist);
if (decl == NULL_TREE)
return NULL_TREE;
}
decl = grokfndecl (ctype, type, original_name, parms, unqualified_id,
virtualp, flags, quals, raises,
1, friendp,
- publicp, inlinep, funcdef_flag,
+ publicp, inlinep, sfk, funcdef_flag,
template_count, in_namespace, attrlist);
if (decl == NULL_TREE)
return NULL_TREE;
when processing a template; we'll do this for the instantiated
declaration based on the type of DECL. */
if (!processing_template_decl)
- c_apply_type_quals_to_decl (type_quals, decl);
+ cp_apply_type_quals_to_decl (type_quals, decl);
return decl;
}
tree context;
tree type;
+ /* If the VALUE was erroneous, pretend it wasn't there; that will
+ result in the enum being assigned the next value in sequence. */
+ if (value == error_mark_node)
+ value = NULL_TREE;
+
/* Remove no-op casts from the value. */
if (value)
STRIP_TYPE_NOPS (value);
DECL_IGNORED_P (resdecl) = 1;
DECL_RESULT (decl1) = resdecl;
- c_apply_type_quals_to_decl (cp_type_quals (restype), resdecl);
+ cp_apply_type_quals_to_decl (cp_type_quals (restype), resdecl);
}
/* Initialize RTL machinery. We cannot do this until
if (same_type_p (type, TREE_PURPOSE (*list)))
{
tree var = TREE_VALUE (*list);
+ tree type = TREE_TYPE (var);
/* Complete the type of the variable. The VAR_DECL itself
will be laid out in expand_expr. */
- complete_type (TREE_TYPE (var));
+ complete_type (type);
+ cp_apply_type_quals_to_decl (cp_type_quals (type), var);
/* Remove this entry from the list. */
*list = TREE_CHAIN (*list);
}
rval = build_delete (TREE_TYPE (rval), rval,
sfk_complete_destructor, flags, 0);
- if (has_vbases && !TYPE_HAS_DESTRUCTOR (type))
- rval = build_compound_expr (rval, build_vbase_delete (type, decl));
-
return rval;
}
return NULL_TREE;