Used by RTTI
tree type_info_type_node, tinfo_decl_id, tinfo_decl_type;
- tree tinfo_var_id;
-
-*/
+ tree tinfo_var_id; */
tree cp_global_trees[CPTI_MAX];
This is initially set to the binding level in which the label
is defined, but is modified as scopes are closed. */
struct cp_binding_level *binding_level;
- /* The head of the names list that was current when the label was
+ /* The head of the names list that was current when the label was
defined, or the inner scope popped. These are the decls that will
be skipped when jumping to the label. */
tree names_in_scope;
/* The following bits are set after the label is defined, and are
updated as scopes are popped. They indicate that a backward jump
- to the label will illegally enter a scope of the given flavour. */
+ to the label will illegally enter a scope of the given flavor. */
bool in_try_scope;
bool in_catch_scope;
bool in_omp_scope;
static enum deprecated_states deprecated_state = DEPRECATED_NORMAL;
-/* True if a declaration with an `extern' linkage specifier is being
- processed. */
-bool have_extern_spec;
-
\f
/* A TREE_LIST of VAR_DECLs. The TREE_PURPOSE is a RECORD_TYPE or
UNION_TYPE; the TREE_VALUE is a VAR_DECL with that type. At the
/* Need to check scope for variable declaration (VAR_DECL).
For typedef (TYPE_DECL), scope is ignored. */
if (TREE_CODE (newdecl) == VAR_DECL
- && CP_DECL_CONTEXT (newdecl) != CP_DECL_CONTEXT (olddecl))
+ && CP_DECL_CONTEXT (newdecl) != CP_DECL_CONTEXT (olddecl)
+ /* [dcl.link]
+ Two declarations for an object with C language linkage
+ with the same name (ignoring the namespace that qualify
+ it) that appear in different namespace scopes refer to
+ the same object. */
+ && !(DECL_EXTERN_C_P (olddecl) && DECL_EXTERN_C_P (newdecl)))
return 0;
if (TREE_TYPE (newdecl) == error_mark_node)
if ((pedantic || ! DECL_IN_SYSTEM_HEADER (old_decl))
&& ! DECL_IS_BUILTIN (old_decl)
&& flag_exceptions
- && !comp_except_specs (new_exceptions, old_exceptions,
+ && !comp_except_specs (new_exceptions, old_exceptions,
/*exact=*/true))
{
error ("declaration of %qF throws different exceptions", new_decl);
warning (0, "prototype for %q+#D", newdecl);
warning (0, "%Jfollows non-prototype definition here", olddecl);
}
- else if (TREE_CODE (olddecl) == FUNCTION_DECL
+ else if ((TREE_CODE (olddecl) == FUNCTION_DECL
+ || TREE_CODE (olddecl) == VAR_DECL)
&& DECL_LANGUAGE (newdecl) != DECL_LANGUAGE (olddecl))
{
- /* extern "C" int foo ();
- int foo () { bar (); }
- is OK. */
+ /* [dcl.link]
+ If two declarations of the same function or object
+ specify different linkage-specifications ..., the program
+ is ill-formed.... Except for functions with C++ linkage,
+ a function declaration without a linkage specification
+ shall not precede the first linkage specification for
+ that function. A function can be declared without a
+ linkage specification after an explicit linkage
+ specification has been seen; the linkage explicitly
+ specified in the earlier declaration is not affected by
+ such a function declaration.
+
+ DR 563 raises the question why the restrictions on
+ functions should not also apply to objects. Older
+ versions of G++ silently ignore the linkage-specification
+ for this example:
+
+ namespace N {
+ extern int i;
+ extern "C" int i;
+ }
+
+ which is clearly wrong. Therefore, we now treat objects
+ like functions. */
if (current_lang_depth () == 0)
- SET_DECL_LANGUAGE (newdecl, DECL_LANGUAGE (olddecl));
+ {
+ /* There is no explicit linkage-specification, so we use
+ the linkage from the previous declaration. */
+ if (!DECL_LANG_SPECIFIC (newdecl))
+ retrofit_lang_decl (newdecl);
+ SET_DECL_LANGUAGE (newdecl, DECL_LANGUAGE (olddecl));
+ }
else
{
error ("previous declaration of %q+#D with %qL linkage",
{
DECL_THIS_EXTERN (newdecl) |= DECL_THIS_EXTERN (olddecl);
DECL_INITIALIZED_P (newdecl) |= DECL_INITIALIZED_P (olddecl);
- DECL_NONTRIVIALLY_INITIALIZED_P (newdecl)
+ DECL_NONTRIVIALLY_INITIALIZED_P (newdecl)
|= DECL_NONTRIVIALLY_INITIALIZED_P (olddecl);
DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (newdecl)
|= DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (olddecl);
DECL_VISIBILITY (newdecl) = DECL_VISIBILITY (olddecl);
DECL_VISIBILITY_SPECIFIED (newdecl) = 1;
}
- /* Init priority used to be merged from newdecl to olddecl by the memcpy,
+ /* Init priority used to be merged from newdecl to olddecl by the memcpy,
so keep this behavior. */
if (TREE_CODE (newdecl) == VAR_DECL && DECL_HAS_INIT_PRIORITY_P (newdecl))
{
memcpy ((char *) olddecl + sizeof (struct tree_common),
(char *) newdecl + sizeof (struct tree_common),
sizeof (struct tree_decl_common) - sizeof (struct tree_common));
- switch (TREE_CODE (olddecl))
+ switch (TREE_CODE (olddecl))
{
case LABEL_DECL:
case VAR_DECL:
/* Check that a single previously seen jump to a newly defined label
is OK. DECL is the LABEL_DECL or 0; LEVEL is the binding_level for
the jump context; NAMES are the names in scope in LEVEL at the jump
- context; LOCUS is the source position of the jump or 0. Returns
+ context; LOCUS is the source position of the jump or 0. Returns
true if all is well. */
static bool
TREE_STATIC (decl) = 1;
TREE_READONLY (decl) = 1;
DECL_ARTIFICIAL (decl) = 1;
- DECL_INITIAL (decl) = init;
TREE_USED (decl) = 1;
while (b->level_chain->kind != sk_function_parms)
b = b->level_chain;
pushdecl_with_scope (decl, b, /*is_friend=*/false);
- cp_finish_decl (decl, init, /*init_const_expr_p=*/false, NULL_TREE,
+ cp_finish_decl (decl, init, /*init_const_expr_p=*/false, NULL_TREE,
LOOKUP_ONLYCONVERTING);
}
else
*pushed_scope_p = NULL_TREE;
- /* This should only be done once on the top most decl. */
- if (have_extern_spec)
- {
- declspecs->storage_class = sc_extern;
- have_extern_spec = false;
- }
-
/* An object declared as __attribute__((deprecated)) suppresses
warnings of uses of other deprecated items. */
if (lookup_attribute ("deprecated", attributes))
DECL_EXTERNAL (decl) = 0;
if (toplevel_bindings_p ())
TREE_STATIC (decl) = 1;
-
- /* Tell `pushdecl' this is an initialized decl
- even though we don't yet have the initializer expression.
- Also tell `cp_finish_decl' it may store the real initializer. */
- DECL_INITIAL (decl) = error_mark_node;
}
/* Set attributes here so if duplicate decl, will have proper attributes. */
cplus_decl_attributes (&decl, attributes, 0);
+ /* Dllimported symbols cannot be defined. Static data members (which
+ can be initialized in-class and dllimported) go through grokfield,
+ not here, so we don't need to exclude those decls when checking for
+ a definition. */
+ if (initialized && DECL_DLLIMPORT_P (decl))
+ {
+ error ("definition of %q#D is marked %<dllimport%>", decl);
+ DECL_DLLIMPORT_P (decl) = 0;
+ }
+
/* If #pragma weak was used, mark the decl weak now. */
maybe_apply_pragma_weak (decl);
declaration will have DECL_EXTERNAL set, but will have an
initialization. Thus, duplicate_decls won't warn
about this situation, and so we check here. */
- if (DECL_INITIAL (decl)
- && DECL_INITIALIZED_IN_CLASS_P (field))
+ if (initialized && DECL_INITIALIZED_IN_CLASS_P (field))
error ("duplicate initialization of %qD", decl);
if (duplicate_decls (decl, field, /*newdecl_is_friend=*/false))
decl = field;
We check for processing_specialization so this only applies
to the new specialization syntax. */
- if (!DECL_INITIAL (decl)
- && processing_specialization)
+ if (!initialized && processing_specialization)
DECL_EXTERNAL (decl) = 1;
}
&& !have_global_bss_p ())
DECL_COMMON (tem) = 1;
- if (! processing_template_decl)
- start_decl_1 (tem);
+ if (!processing_template_decl && TREE_CODE (tem) == VAR_DECL)
+ start_decl_1 (tem, initialized);
return tem;
}
void
-start_decl_1 (tree decl)
+start_decl_1 (tree decl, bool initialized)
{
- tree type = TREE_TYPE (decl);
- int initialized = (DECL_INITIAL (decl) != NULL_TREE);
+ tree type;
- if (type == error_mark_node)
+ gcc_assert (!processing_template_decl);
+
+ if (error_operand_p (decl))
return;
+ gcc_assert (TREE_CODE (decl) == VAR_DECL);
+ type = TREE_TYPE (decl);
+
if (initialized)
/* Is it valid for this decl to have an initializer at all?
If not, set INITIALIZED to zero, which will indirectly
initialized = 0;
}
}
-
- if (!initialized
- && TREE_CODE (decl) != TYPE_DECL
- && TREE_CODE (decl) != TEMPLATE_DECL
- && type != error_mark_node
- && IS_AGGR_TYPE (type)
- && ! DECL_EXTERNAL (decl))
+ else if (IS_AGGR_TYPE (type)
+ && ! DECL_EXTERNAL (decl))
{
- if ((! processing_template_decl || ! uses_template_parms (type))
- && !COMPLETE_TYPE_P (complete_type (type)))
+ if (!COMPLETE_TYPE_P (complete_type (type)))
{
error ("aggregate %q#D has incomplete type and cannot be defined",
decl);
}
}
- if (! initialized)
- DECL_INITIAL (decl) = NULL_TREE;
-
/* Create a new scope to hold this declaration if necessary.
Whether or not a new scope is necessary cannot be determined
until after the type has been completed; if the type is a
do_default);
if (failure == 1)
- error ("initializer fails to determine size of %qD", decl);
-
- if (failure == 2)
+ {
+ error ("initializer fails to determine size of %qD", decl);
+ TREE_TYPE (decl) = error_mark_node;
+ }
+ else if (failure == 2)
{
if (do_default)
- error ("array size missing in %qD", decl);
+ {
+ error ("array size missing in %qD", decl);
+ TREE_TYPE (decl) = error_mark_node;
+ }
/* If a `static' var's size isn't known, make it extern as
well as static, so it does not get allocated. If it's not
`static', then don't mark it extern; finish_incomplete_decl
else if (!pedantic && TREE_STATIC (decl) && !TREE_PUBLIC (decl))
DECL_EXTERNAL (decl) = 1;
}
-
- if (failure == 3)
- error ("zero-size array %qD", decl);
+ else if (failure == 3)
+ {
+ error ("zero-size array %qD", decl);
+ TREE_TYPE (decl) = error_mark_node;
+ }
cp_apply_type_quals_to_decl (cp_type_quals (TREE_TYPE (decl)), decl);
static void
layout_var_decl (tree decl)
{
- tree type = TREE_TYPE (decl);
+ tree type;
+
+ if (TREE_STATIC (decl)
+ && !DECL_ARTIFICIAL (decl)
+ && current_function_decl
+ && DECL_CONTEXT (decl) == current_function_decl)
+ push_local_name (decl);
+
+ type = TREE_TYPE (decl);
+ if (type == error_mark_node)
+ return;
/* If we haven't already layed out this declaration, do so now.
Note that we must not call complete type for an external object
else
error ("storage size of %qD isn't constant", decl);
}
-
- if (TREE_STATIC (decl)
- && !DECL_ARTIFICIAL (decl)
- && current_function_decl
- && DECL_CONTEXT (decl) == current_function_decl)
- push_local_name (decl);
}
/* If a local static variable is declared in an inline function, or if
}
elt_init = reshape_init_r (elt_type, d, /*first_initializer_p=*/false);
+ if (elt_init == error_mark_node)
+ return error_mark_node;
CONSTRUCTOR_APPEND_ELT (CONSTRUCTOR_ELTS (new_init), NULL_TREE, elt_init);
}
{
error ("invalid type %qT as initializer for a vector of type %qT",
TREE_TYPE (d->cur->value), type);
- value = error_mark_node;
+ value = error_mark_node;
}
++d->cur;
return value;
{
if (pedantic)
pedwarn ("ISO C++ does not allow designated initializers");
-
+
field = lookup_field_1 (type, d->cur->index, /*want_type=*/false);
if (!field || TREE_CODE (field) != FIELD_DECL)
error ("braces around scalar initializer for type %qT", type);
init = error_mark_node;
}
-
+
d->cur++;
return init;
}
tree str_init = init;
/* Strip one level of braces if and only if they enclose a single
- element (as allowed by [dcl.init.string]). */
+ element (as allowed by [dcl.init.string]). */
if (!first_initializer_p
&& TREE_CODE (str_init) == CONSTRUCTOR
&& VEC_length (constructor_elt, CONSTRUCTOR_ELTS (str_init)) == 1)
str_init = VEC_index (constructor_elt,
CONSTRUCTOR_ELTS (str_init), 0)->value;
}
-
+
/* If it's a string literal, then it's the initializer for the array
- as a whole. Otherwise, continue with normal initialization for
+ as a whole. Otherwise, continue with normal initialization for
array types (one value per array element). */
if (TREE_CODE (str_init) == STRING_CST)
{
d.end = d.cur + VEC_length (constructor_elt, v);
new_init = reshape_init_r (type, &d, true);
+ if (new_init == error_mark_node)
+ return error_mark_node;
/* Make sure all the element of the constructor were used. Otherwise,
issue an error about exceeding initializers. */
tree type = TREE_TYPE (decl);
tree init_code = NULL;
- /* If `start_decl' didn't like having an initialization, ignore it now. */
- if (init != NULL_TREE && DECL_INITIAL (decl) == NULL_TREE)
- init = NULL_TREE;
-
- /* If an initializer is present, DECL_INITIAL has been
- error_mark_node, to indicate that an as-of-yet unevaluated
- initialization will occur. From now on, DECL_INITIAL reflects
- the static initialization -- if any -- of DECL. */
- DECL_INITIAL (decl) = NULL_TREE;
-
/* Things that are going to be initialized need to have complete
type. */
TREE_TYPE (decl) = type = complete_type (TREE_TYPE (decl));
else if (init)
{
/* Do not reshape constructors of vectors (they don't need to be
- reshaped. */
+ reshaped. */
if (TREE_CODE (init) == CONSTRUCTOR
&& !COMPOUND_LITERAL_P (init)
&& !TREE_TYPE (init)) /* ptrmemfunc */
array size from the initializer. */
maybe_deduce_size_from_array_init (decl, init);
type = TREE_TYPE (decl);
+ if (type == error_mark_node)
+ return NULL_TREE;
if (TYPE_HAS_CONSTRUCTOR (type) || TYPE_NEEDS_CONSTRUCTING (type))
{
if the (init) syntax was used. */
void
-cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
+cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
tree asmspec_tree, int flags)
{
tree type;
const char *asmspec = NULL;
int was_readonly = 0;
bool var_definition_p = false;
+ int saved_processing_template_decl;
if (decl == error_mark_node)
return;
}
gcc_assert (TREE_CODE (decl) != RESULT_DECL);
+ /* Parameters are handled by store_parm_decls, not cp_finish_decl. */
+ gcc_assert (TREE_CODE (decl) != PARM_DECL);
+
+ type = TREE_TYPE (decl);
+ if (type == error_mark_node)
+ return;
/* Assume no cleanup is required. */
cleanup = NULL_TREE;
+ saved_processing_template_decl = processing_template_decl;
/* If a name was specified, get the string. */
if (global_scope_p (current_binding_level))
if (asmspec_tree)
asmspec = TREE_STRING_POINTER (asmspec_tree);
- if (init && TREE_CODE (init) == NAMESPACE_DECL)
- {
- error ("cannot initialize %qD to namespace %qD", decl, init);
- init = NULL_TREE;
- }
-
if (current_class_type
&& CP_DECL_CONTEXT (decl) == current_class_type
&& TYPE_BEING_DEFINED (current_class_type)
&& (DECL_INITIAL (decl) || init))
DECL_INITIALIZED_IN_CLASS_P (decl) = 1;
- type = TREE_TYPE (decl);
-
- if (type == error_mark_node)
- goto finish_end;
-
if (processing_template_decl)
{
+ bool type_dependent_p;
+
/* Add this declaration to the statement-tree. */
if (at_function_scope_p ())
add_decl_expr (decl);
- if (init && DECL_INITIAL (decl))
+ type_dependent_p = dependent_type_p (type);
+
+ if (init && init_const_expr_p)
{
- DECL_INITIAL (decl) = init;
- if (init_const_expr_p)
- {
- DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = 1;
- if (DECL_INTEGRAL_CONSTANT_VAR_P (decl))
- TREE_CONSTANT (decl) = 1;
- }
+ DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = 1;
+ if (DECL_INTEGRAL_CONSTANT_VAR_P (decl))
+ TREE_CONSTANT (decl) = 1;
}
- if (TREE_CODE (decl) == VAR_DECL
- && !DECL_PRETTY_FUNCTION_P (decl)
- && !dependent_type_p (TREE_TYPE (decl)))
- maybe_deduce_size_from_array_init (decl, init);
+ if (!init
+ || !DECL_CLASS_SCOPE_P (decl)
+ || !DECL_INTEGRAL_CONSTANT_VAR_P (decl)
+ || type_dependent_p
+ || value_dependent_expression_p (init))
+ {
+ if (init)
+ DECL_INITIAL (decl) = init;
+ if (TREE_CODE (decl) == VAR_DECL
+ && !DECL_PRETTY_FUNCTION_P (decl)
+ && !type_dependent_p)
+ maybe_deduce_size_from_array_init (decl, init);
+ goto finish_end;
+ }
- goto finish_end;
+ init = fold_non_dependent_expr (init);
+ processing_template_decl = 0;
}
- /* Parameters are handled by store_parm_decls, not cp_finish_decl. */
- gcc_assert (TREE_CODE (decl) != PARM_DECL);
-
/* Take care of TYPE_DECLs up front. */
if (TREE_CODE (decl) == TYPE_DECL)
{
occurs. Therefore, in:
struct S { static const int i = 7 / 0; };
-
+
we issue an error at this point. It would
probably be better to forbid division by zero in
integral constant expressions. */
if (at_function_scope_p ())
add_decl_expr (decl);
- if (TREE_CODE (decl) == VAR_DECL)
- layout_var_decl (decl);
-
- /* Output the assembler code and/or RTL code for variables and functions,
- unless the type is an undefined structure or union.
- If not, it will get done when the type is completed. */
- if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL)
+ /* Let the middle end know about variables and functions -- but not
+ static data members in uninstantiated class templates. */
+ if (!saved_processing_template_decl
+ && (TREE_CODE (decl) == VAR_DECL
+ || TREE_CODE (decl) == FUNCTION_DECL))
{
if (TREE_CODE (decl) == VAR_DECL)
- maybe_commonize_var (decl);
+ {
+ layout_var_decl (decl);
+ maybe_commonize_var (decl);
+ }
make_rtl_for_nonlocal_decl (decl, init, asmspec);
{
/* Initialize the local variable. */
if (processing_template_decl)
- {
- if (init || DECL_INITIAL (decl) == error_mark_node)
- DECL_INITIAL (decl) = init;
- }
+ DECL_INITIAL (decl) = init;
else if (!TREE_STATIC (decl))
initialize_local_var (decl, init);
}
push_cleanup (decl, cleanup, false);
finish_end:
+ processing_template_decl = saved_processing_template_decl;
if (was_readonly)
TREE_READONLY (decl) = 1;
/* 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)
{
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
tree newtype;
error ("%<::main%> must return %<int%>");
newtype = build_function_type (integer_type_node,
- oldtypeargs);
+ oldtypeargs);
TREE_TYPE (decl) = newtype;
}
inlinep = 0;
}
/* [dcl.fct.edf]
-
+
The declarator in a function-definition shall have the form
D1 ( parameter-declaration-clause) ... */
if (funcdef_flag && innermost_code != cdk_function)
if (dependent_name && !friendp)
{
error ("%<%T::%D%> is not a valid declarator", ctype, dependent_name);
- return void_type_node;
+ return error_mark_node;
}
/* Issue errors about use of storage classes for parameters. */
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. */
-
+
/* 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)
+ if (staticp == 2)
error ((flags == DTOR_FLAG)
? "destructor cannot be static member function"
: "constructor cannot be static member function");
&& !member_function_or_else (ctype,
current_class_type,
flags))
- return void_type_node;
+ return error_mark_node;
if (flags != DTOR_FLAG)
{
pedwarn ("constructors cannot be declared virtual");
virtualp = 0;
}
- if (decl_context == FIELD)
- {
- TYPE_HAS_CONSTRUCTOR (ctype) = 1;
- if (sfk != sfk_constructor)
- return NULL_TREE;
- }
+ if (decl_context == FIELD
+ && sfk != sfk_constructor)
+ return error_mark_node;
}
if (decl_context == FIELD)
staticp = 0;
&& (TREE_CODE (type) == FUNCTION_TYPE || memfn_quals))
{
memfn_quals |= cp_type_quals (type);
- type = build_memfn_type (type,
+ type = build_memfn_type (type,
declarator->u.pointer.class_type,
memfn_quals);
memfn_quals = TYPE_UNQUALIFIED;
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
+ && (/* If the function is being defined, then
+ qualifying type must certainly be complete. */
+ funcdef_flag
+ /* A friend declaration of "T::f" is OK, even if
+ "T" is a template parameter. But, if this
+ function is not a friend, the qualifying type
+ must be a class. */
+ || (!friendp && !CLASS_TYPE_P (ctype))
+ /* For a declaration, the type need not be
+ complete, if either it is dependent (since there
+ is no meaningful definition of complete in that
+ case) or the qualifying class is currently being
+ defined. */
|| !(dependent_type_p (ctype)
|| currently_open_class (ctype)))
/* Check that the qualifying type is complete. */
in typenames, fields or parameters. */
if (current_lang_name == lang_name_java)
TYPE_FOR_JAVA (type) = 1;
-
+
/* This declaration:
- typedef void f(int) const;
+ typedef void f(int) const;
- declares a function type which is not a member of any
+ 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
+ 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)
|| (typedef_decl && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl)))
C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1;
- bad_specifiers (decl, "type", virtualp,
+ bad_specifiers (decl, "type", virtualp,
memfn_quals != TYPE_UNQUALIFIED,
inlinep, friendp, raises != NULL_TREE);
{
decl = cp_build_parm_decl (unqualified_id, type);
- bad_specifiers (decl, "parameter", virtualp,
+ bad_specifiers (decl, "parameter", virtualp,
memfn_quals != TYPE_UNQUALIFIED,
inlinep, friendp, raises != NULL_TREE);
}
{
/* Something like struct S { int N::j; }; */
error ("invalid use of %<::%>");
- decl = NULL_TREE;
+ return error_mark_node;
}
else if (TREE_CODE (type) == FUNCTION_TYPE)
{
{
error ("can't make %qD into a method -- not in a class",
unqualified_id);
- return void_type_node;
+ return error_mark_node;
}
/* ``A union may [ ... ] not [ have ] virtual functions.''
{
error ("function %qD declared virtual inside a union",
unqualified_id);
- return void_type_node;
+ return error_mark_node;
}
if (NEW_DELETE_OPNAME_P (unqualified_id))
sfk,
funcdef_flag, template_count, in_namespace, attrlist);
if (decl == NULL_TREE)
- return decl;
+ return error_mark_node;
#if 0
/* This clobbers the attrs stored in `decl' from `attrlist'. */
/* The decl and setting of decl_attr is also turned off. */
funcdef_flag, template_count, in_namespace,
attrlist);
if (decl == NULL_TREE)
- return NULL_TREE;
+ return error_mark_node;
}
else if (!staticp && !dependent_type_p (type)
&& !COMPLETE_TYPE_P (complete_type (type))
}
decl = do_friend (ctype, unqualified_id, decl,
- *attrlist, flags,
+ *attrlist, flags,
funcdef_flag);
return decl;
}
else
- return void_type_node;
+ return error_mark_node;
}
/* Structure field. It may not be a function, except for C++. */
void_type_node, as if this was a friend
declaration, to cause callers to completely
ignore this declaration. */
- return void_type_node;
+ return error_mark_node;
}
if (staticp)
}
}
- bad_specifiers (decl, "field", virtualp,
+ bad_specifiers (decl, "field", virtualp,
memfn_quals != TYPE_UNQUALIFIED,
inlinep, friendp, raises != NULL_TREE);
}
int publicp = 0;
if (!unqualified_id)
- return NULL_TREE;
+ return error_mark_node;
if (TREE_CODE (unqualified_id) == TEMPLATE_ID_EXPR)
original_name = dname;
publicp, inlinep, sfk, funcdef_flag,
template_count, in_namespace, attrlist);
if (decl == NULL_TREE)
- return NULL_TREE;
+ return error_mark_node;
if (staticp == 1)
{
initialized,
(type_quals & TYPE_QUAL_CONST) != 0,
ctype ? ctype : in_namespace);
- bad_specifiers (decl, "variable", virtualp,
+ bad_specifiers (decl, "variable", virtualp,
memfn_quals != TYPE_UNQUALIFIED,
inlinep, friendp, raises != NULL_TREE);
tree arg_type;
int result = 1;
- gcc_assert (DECL_FUNCTION_MEMBER_P (d));
+ if (!DECL_FUNCTION_MEMBER_P (d))
+ /* Non-members are invalid. We complained, but kept the declaration. */
+ return 0;
- if (DECL_TEMPLATE_INFO (d)
- && DECL_MEMBER_TEMPLATE_P (DECL_TI_TEMPLATE (d)))
+ if (TREE_CODE (d) == TEMPLATE_DECL
+ || (DECL_TEMPLATE_INFO (d)
+ && DECL_MEMBER_TEMPLATE_P (DECL_TI_TEMPLATE (d))))
/* Instantiations of template member functions are never copy
functions. Note that member functions of templated classes are
represented as template functions internally, and we must
void grok_special_member_properties (tree decl)
{
+ tree class_type;
+
if (!DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
- ; /* Not special. */
- else if (DECL_CONSTRUCTOR_P (decl))
+ return;
+
+ class_type = DECL_CONTEXT (decl);
+ if (DECL_CONSTRUCTOR_P (decl))
{
int ctor = copy_fn_p (decl);
+ TYPE_HAS_CONSTRUCTOR (class_type) = 1;
+
if (ctor > 0)
{
/* [class.copy]
X&, volatile X& or const volatile X&, and either there
are no other parameters or else all other parameters have
default arguments. */
- TYPE_HAS_INIT_REF (DECL_CONTEXT (decl)) = 1;
+ TYPE_HAS_INIT_REF (class_type) = 1;
if (ctor > 1)
- TYPE_HAS_CONST_INIT_REF (DECL_CONTEXT (decl)) = 1;
+ TYPE_HAS_CONST_INIT_REF (class_type) = 1;
}
else if (sufficient_parms_p (FUNCTION_FIRST_USER_PARMTYPE (decl)))
- TYPE_HAS_DEFAULT_CONSTRUCTOR (DECL_CONTEXT (decl)) = 1;
+ TYPE_HAS_DEFAULT_CONSTRUCTOR (class_type) = 1;
}
else if (DECL_OVERLOADED_OPERATOR_P (decl) == NOP_EXPR)
{
if (assop)
{
- TYPE_HAS_ASSIGN_REF (DECL_CONTEXT (decl)) = 1;
+ TYPE_HAS_ASSIGN_REF (class_type) = 1;
if (assop != 1)
- TYPE_HAS_CONST_ASSIGN_REF (DECL_CONTEXT (decl)) = 1;
+ TYPE_HAS_CONST_ASSIGN_REF (class_type) = 1;
}
}
}
for (p = argtypes; p && p != void_list_node; p = TREE_CHAIN (p))
{
tree arg = non_reference (TREE_VALUE (p));
+ if (arg == error_mark_node)
+ return;
+
/* IS_AGGR_TYPE, rather than CLASS_TYPE_P, is used
because these checks are performed even on
template functions. */
if (!COMPLETE_OR_VOID_TYPE_P (return_type))
{
tree args = TYPE_ARG_TYPES (fntype);
-
+
error ("return type %q#T is incomplete", return_type);
/* Make it return void instead. */
ignore interface specifications for
compiler-generated functions. */
&& !DECL_ARTIFICIAL (decl1));
-
+
if (DECL_INTERFACE_KNOWN (decl1))
{
tree ctx = decl_function_context (decl1);
{
tree decl1;
- if (have_extern_spec)
- {
- declspecs->storage_class = sc_extern;
- /* This should only be done once on the outermost decl. */
- have_extern_spec = false;
- }
-
decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1, &attrs);
/* If the declarator is not suitable for a function definition,
cause a syntax error. */
tables. */
initialize_vtbl_ptrs (current_class_ptr);
finish_compound_stmt (compound_stmt);
-
+
/* And insert cleanups for our bases and members so that they
will be properly destroyed if we throw. */
push_base_cleanups ();
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,
+ exprstmt = build_op_delete_call(DELETE_EXPR, current_class_ptr,
virtual_size,
- /*global_p=*/false,
- /*placement=*/NULL_TREE,
+ /*global_p=*/false,
+ /*placement=*/NULL_TREE,
/*alloc_fn=*/NULL_TREE);
if_stmt = begin_if_stmt ();
{
if (compstmt == NULL_TREE)
return;
-
+
/* Close the block. */
finish_compound_stmt (compstmt);
f->x_vtt_parm = NULL;
f->x_return_value = NULL;
f->bindings = NULL;
+ f->extern_decl_map = NULL;
/* Handle attribute((warn_unused_result)). Relies on gimple input. */
c_warn_unused_result (&DECL_SAVED_TREE (fndecl));
fndecl = copy_node (fndecl);
TREE_CHAIN (fndecl) = NULL_TREE;
}
- grok_special_member_properties (fndecl);
}
finish_decl (fndecl, NULL_TREE, NULL_TREE);