if (last_time)
{
check_global_declarations (vec, len);
+ emit_debug_global_declarations (vec, len);
return 0;
}
error_mark_node is returned. Otherwise, OLDDECL is returned.
If NEWDECL is not a redeclaration of OLDDECL, NULL_TREE is
- returned. */
+ returned.
+
+ NEWDECL_IS_FRIEND is true if NEWDECL was declared as a friend. */
tree
-duplicate_decls (tree newdecl, tree olddecl)
+duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
{
unsigned olddecl_uid = DECL_UID (olddecl);
- int olddecl_friend = 0, types_match = 0;
+ int olddecl_friend = 0, types_match = 0, hidden_friend = 0;
int new_defines_function = 0;
if (newdecl == olddecl)
if (TREE_CODE (olddecl) == FUNCTION_DECL
&& DECL_ARTIFICIAL (olddecl))
{
+ gcc_assert (!DECL_HIDDEN_FRIEND_P (olddecl));
if (TREE_CODE (newdecl) != FUNCTION_DECL)
{
- /* Avoid warnings redeclaring anticipated built-ins. */
+ /* Avoid warnings redeclaring built-ins which have not been
+ explicitly declared. */
if (DECL_ANTICIPATED (olddecl))
return NULL_TREE;
}
else if (!types_match)
{
- /* Avoid warnings redeclaring anticipated built-ins. */
+ /* Avoid warnings redeclaring built-ins which have not been
+ explicitly declared. */
if (DECL_ANTICIPATED (olddecl))
{
/* Deal with fileptr_type_node. FILE type is not known
= TYPE_ARG_TYPES (TREE_TYPE (newdecl));
types_match = decls_match (newdecl, olddecl);
if (types_match)
- return duplicate_decls (newdecl, olddecl);
+ return duplicate_decls (newdecl, olddecl,
+ newdecl_is_friend);
TYPE_ARG_TYPES (TREE_TYPE (olddecl)) = oldargs;
}
}
/* Replace the old RTL to avoid problems with inlining. */
COPY_DECL_RTL (newdecl, olddecl);
}
- /* Even if the types match, prefer the new declarations type
- for anticipated built-ins, for exception lists, etc... */
+ /* Even if the types match, prefer the new declarations type for
+ built-ins which have not been explicitly declared, for
+ exception lists, etc... */
else if (DECL_ANTICIPATED (olddecl))
{
tree type = TREE_TYPE (newdecl);
/* Don't warn about extern decl followed by definition. */
&& !(DECL_EXTERNAL (olddecl) && ! DECL_EXTERNAL (newdecl))
/* Don't warn about friends, let add_friend take care of it. */
- && ! (DECL_FRIEND_P (newdecl) || DECL_FRIEND_P (olddecl)))
+ && ! (newdecl_is_friend || DECL_FRIEND_P (olddecl)))
{
warning (0, "redundant redeclaration of %qD in same scope", newdecl);
warning (0, "previous declaration of %q+D", olddecl);
{
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 (olddecl);
DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (newdecl)
|= DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (olddecl);
}
DECL_INITIALIZED_IN_CLASS_P (newdecl)
|= DECL_INITIALIZED_IN_CLASS_P (olddecl);
olddecl_friend = DECL_FRIEND_P (olddecl);
+ hidden_friend = (DECL_ANTICIPATED (olddecl)
+ && DECL_HIDDEN_FRIEND_P (olddecl)
+ && newdecl_is_friend);
/* Only functions have DECL_BEFRIENDING_CLASSES. */
if (TREE_CODE (newdecl) == FUNCTION_DECL
DECL_UID (olddecl) = olddecl_uid;
if (olddecl_friend)
DECL_FRIEND_P (olddecl) = 1;
+ if (hidden_friend)
+ {
+ DECL_ANTICIPATED (olddecl) = 1;
+ DECL_HIDDEN_FRIEND_P (olddecl) = 1;
+ }
/* NEWDECL contains the merged attribute lists.
Update OLDDECL to be the same. */
if (TREE_CODE (decl) != VAR_DECL || TREE_STATIC (decl))
return 0;
- if (DECL_INITIAL (decl) == NULL_TREE
- && pod_type_p (TREE_TYPE (decl)))
+ if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))
+ || DECL_NONTRIVIALLY_INITIALIZED_P (decl))
+ return 2;
+
+ if (pod_type_p (TREE_TYPE (decl)))
return 0;
- /* This is really only important if we're crossing an initialization.
- The POD stuff is just pedantry; why should it matter if the class
+ /* The POD stuff is just pedantry; why should it matter if the class
contains a field of pointer to member type? */
- if (DECL_INITIAL (decl)
- || (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))))
- return 2;
return 1;
}
switch_location = EXPR_LOCATION (cs->switch_stmt);
else
switch_location = input_location;
- c_do_switch_warnings (cs->cases, switch_location,
- SWITCH_STMT_TYPE (cs->switch_stmt),
- SWITCH_STMT_COND (cs->switch_stmt));
+ if (!processing_template_decl)
+ c_do_switch_warnings (cs->cases, switch_location,
+ SWITCH_STMT_TYPE (cs->switch_stmt),
+ SWITCH_STMT_COND (cs->switch_stmt));
splay_tree_delete (cs->cases);
switch_stack = switch_stack->next;
struct cp_binding_level *b = current_binding_level;
while (b->level_chain->kind != sk_function_parms)
b = b->level_chain;
- pushdecl_with_scope (decl, b);
+ pushdecl_with_scope (decl, b, /*is_friend=*/false);
cp_finish_decl (decl, init, NULL_TREE, LOOKUP_ONLYCONVERTING);
}
else
if (libname)
SET_DECL_ASSEMBLER_NAME (decl, get_identifier (libname));
- /* Warn if a function in the namespace for users
- is used without an occasion to consider it declared. */
+ /* A function in the user's namespace should have an explicit
+ declaration before it is used. Mark the built-in function as
+ anticipated but not actually declared. */
if (name[0] != '_' || name[1] != '_')
DECL_ANTICIPATED (decl) = 1;
deprecated_state = DEPRECATED_NORMAL;
- if (decl == NULL_TREE || TREE_CODE (decl) == VOID_TYPE)
+ if (decl == NULL_TREE || TREE_CODE (decl) == VOID_TYPE
+ || decl == error_mark_node)
return error_mark_node;
type = TREE_TYPE (decl);
- if (type == error_mark_node)
- return error_mark_node;
-
context = DECL_CONTEXT (decl);
if (context)
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_INITIAL (field))
+ if (DECL_INITIAL (decl)
+ && DECL_INITIALIZED_IN_CLASS_P (field))
error ("duplicate initialization of %qD", decl);
- if (duplicate_decls (decl, field))
+ if (duplicate_decls (decl, field, /*newdecl_is_friend=*/false))
decl = field;
}
}
> template_class_depth (context))
? current_template_parms
: NULL_TREE);
- if (field && duplicate_decls (decl, field))
+ if (field && duplicate_decls (decl, field,
+ /*newdecl_is_friend=*/false))
decl = field;
}
initializer is considered for the initialization of the first
member of the subaggregate. */
if (TREE_CODE (init) != CONSTRUCTOR
- && can_convert_arg (type, TREE_TYPE (init), init))
+ && can_convert_arg (type, TREE_TYPE (init), init, LOOKUP_NORMAL))
{
d->cur++;
return init;
placed in a particular register. */
if (TREE_CODE (decl) == VAR_DECL && DECL_REGISTER (decl))
{
- change_decl_assembler_name (decl, get_identifier (asmspec));
+ set_user_assembler_name (decl, asmspec);
DECL_HARD_REGISTER (decl) = 1;
}
else
is *not* defined. */
&& (!DECL_EXTERNAL (decl) || init))
{
+ if (init)
+ DECL_NONTRIVIALLY_INITIALIZED_P (decl) = 1;
init = check_initializer (decl, init, flags, &cleanup);
/* Thread-local storage cannot be dynamically initialized. */
if (DECL_THREAD_LOCAL_P (decl) && init)
"initialized", decl);
init = NULL_TREE;
}
+
+ /* Check that the initializer for a static data member was a
+ constant. Although we check in the parser that the
+ initializer is an integral constant expression, we do not
+ simplify division-by-zero at the point at which it
+ 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 (DECL_EXTERNAL (decl) && init)
{
- /* The static data member cannot be initialized by a
- non-constant when being declared. */
error ("%qD cannot be initialized by a non-constant expression"
" when being declared", decl);
DECL_INITIALIZED_IN_CLASS_P (decl) = 0;
error ("%q+D declared with an exception specification", object);
}
+/* DECL is a member function or static data member and is presently
+ being defined. Check that the definition is taking place in a
+ valid namespace. */
+
+static void
+check_class_member_definition_namespace (tree decl)
+{
+ /* These checks only apply to member functions and static data
+ members. */
+ gcc_assert (TREE_CODE (decl) == FUNCTION_DECL
+ || TREE_CODE (decl) == VAR_DECL);
+ /* We check for problems with specializations in pt.c in
+ check_specialization_namespace, where we can issue better
+ diagnostics. */
+ if (processing_specialization)
+ return;
+ /* There are no restrictions on the placement of
+ explicit instantiations. */
+ if (processing_explicit_instantiation)
+ return;
+ /* [class.mfct]
+
+ A member function definition that appears outside of the
+ class definition shall appear in a namespace scope enclosing
+ the class definition.
+
+ [class.static.data]
+
+ The definition for a static data member shall appear in a
+ namespace scope enclosing the member's class definition. */
+ if (!is_ancestor (current_namespace, DECL_CONTEXT (decl)))
+ pedwarn ("definition of %qD is not in namespace enclosing %qT",
+ decl, DECL_CONTEXT (decl));
+}
+
/* CTYPE is class type, or null if non-class.
TYPE is type this FUNCTION_DECL should have, either FUNCTION_TYPE
or METHOD_TYPE.
}
if (ctype)
- DECL_CONTEXT (decl) = ctype;
+ {
+ DECL_CONTEXT (decl) = ctype;
+ if (funcdef_flag)
+ check_class_member_definition_namespace (decl);
+ }
if (ctype == NULL_TREE && DECL_MAIN_P (decl))
{
if (!same_type_p (TREE_TYPE (TREE_TYPE (decl)),
integer_type_node))
{
+ tree oldtypeargs = TYPE_ARG_TYPES (TREE_TYPE (decl));
+ tree newtype;
error ("%<::main%> must return %<int%>");
- TREE_TYPE (TREE_TYPE (decl)) = integer_type_node;
+ newtype = build_function_type (integer_type_node,
+ oldtypeargs);
+ TREE_TYPE (decl) = newtype;
}
inlinep = 0;
publicp = 1;
/* Attempt to merge the declarations. This can fail, in
the case of some invalid specialization declarations. */
pushed_scope = push_scope (ctype);
- ok = duplicate_decls (decl, old_decl);
+ ok = duplicate_decls (decl, old_decl, friendp);
if (pushed_scope)
pop_scope (pushed_scope);
if (!ok)
set_linkage_for_static_data_member (decl);
/* This function is only called with out-of-class definitions. */
DECL_EXTERNAL (decl) = 0;
+ check_class_member_definition_namespace (decl);
}
/* At top level, either `static' or no s.c. makes a definition
(perhaps tentative), and absence of `static' makes it public. */
unqualified_id = dname;
}
- /* If DECLARATOR is non-NULL, we know it is a cdk_id declarator;
- otherwise, we would not have exited the loop above. */
+ /* If TYPE is a FUNCTION_TYPE, but the function name was explicitly
+ qualified with a class-name, turn it into a METHOD_TYPE, unless
+ we know that the function is static. We take advantage of this
+ opportunity to do other processing that pertains to entities
+ explicitly declared to be class members. Note that if DECLARATOR
+ is non-NULL, we know it is a cdk_id declarator; otherwise, we
+ would not have exited the loop above. */
if (declarator
&& declarator->u.id.qualifying_scope
&& TYPE_P (declarator->u.id.qualifying_scope))
is correct; there shouldn't be a `template <>' for the
definition of `S<int>::f'. */
- if (CLASSTYPE_TEMPLATE_INFO (t)
- && (CLASSTYPE_TEMPLATE_INSTANTIATION (t)
- || uses_template_parms (CLASSTYPE_TI_ARGS (t)))
+ if (CLASSTYPE_TEMPLATE_SPECIALIZATION (t)
+ && !any_dependent_template_arguments_p (CLASSTYPE_TI_ARGS (t)))
+ /* T is an explicit (not partial) specialization. All
+ containing classes must therefore also be explicitly
+ specialized. */
+ break;
+ if ((CLASSTYPE_USE_TEMPLATE (t) || CLASSTYPE_IS_TEMPLATE (t))
&& PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (t)))
template_count += 1;
}
if (ctype == current_class_type)
- {
- /* class A {
- void A::f ();
- };
-
- Is this ill-formed? */
-
- if (pedantic)
- pedwarn ("extra qualification %<%T::%> on member %qs ignored",
- ctype, name);
- }
+ pedwarn ("extra qualification %<%T::%> on member %qs",
+ ctype, name);
else if (TREE_CODE (type) == FUNCTION_TYPE)
{
tree sname = declarator->u.id.unqualified_name;
}
}
+ /* Now TYPE has the actual type. */
+
if (returned_attrs)
{
if (attrlist)
attrlist = &returned_attrs;
}
- /* Now TYPE has the actual type. */
-
/* Did array size calculations overflow? */
if (TREE_CODE (type) == ARRAY_TYPE
&& COMPLETE_TYPE_P (type)
- && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
- && TREE_OVERFLOW (TYPE_SIZE (type)))
+ && TREE_CODE (TYPE_SIZE_UNIT (type)) == INTEGER_CST
+ && TREE_OVERFLOW (TYPE_SIZE_UNIT (type)))
{
error ("size of array %qs is too large", name);
/* If we proceed with the array type as it is, we'll eventually
}
/* 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))
+ if (sfk == sfk_destructor)
{
- error ("declaration of %qD as member of %qT",
- id_declarator->u.id.unqualified_name,
- ctype);
- return error_mark_node;
+ if (!ctype)
+ {
+ gcc_assert (friendp);
+ error ("expected qualified name in friend declaration "
+ "for destructor %qD",
+ id_declarator->u.id.unqualified_name);
+ return error_mark_node;
+ }
+
+ if (!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. */
{
if (dependent_type_p (TREE_TYPE (parms)))
continue;
- if (VOID_TYPE_P (TREE_TYPE (parms)))
- /* grokparms will have already issued an error. */
- TREE_TYPE (parms) = error_mark_node;
- else if (complete_type_or_else (TREE_TYPE (parms), parms))
+ if (!VOID_TYPE_P (TREE_TYPE (parms))
+ && complete_type_or_else (TREE_TYPE (parms), parms))
{
relayout_decl (parms);
DECL_ARG_TYPE (parms) = type_passed_as (TREE_TYPE (parms));
}
+ else
+ /* grokparms or complete_type_or_else will have already issued
+ an error. */
+ TREE_TYPE (parms) = error_mark_node;
}
}
deal with it after the class is complete. */
return arg;
- if (processing_template_decl || uses_template_parms (arg))
- /* We don't do anything checking until instantiation-time. Note
- that there may be uninstantiated arguments even for an
- instantiated function, since default arguments are not
- instantiated until they are needed. */
- return arg;
-
if (TYPE_P (decl))
{
decl_type = decl;
A default argument expression is implicitly converted to the
parameter type. */
if (!TREE_TYPE (arg)
- || !can_convert_arg (decl_type, TREE_TYPE (arg), arg))
+ || !can_convert_arg (decl_type, TREE_TYPE (arg), arg, LOOKUP_NORMAL))
{
if (decl)
error ("default argument for %q#D has type %qT",
decl, ptr ? "pointer" : "reference", t);
}
- if (!any_error && init)
- init = check_default_argument (decl, init);
- else
+ if (any_error)
init = NULL_TREE;
+ else if (init && !processing_template_decl)
+ init = check_default_argument (decl, init);
}
TREE_CHAIN (decl) = decls;
return error_mark_node;
}
else if (TREE_CODE (type) != ENUMERAL_TYPE
- && tag_code == enum_type
- && tag_code != typename_type)
+ && tag_code == enum_type)
{
error ("%qT referred to as enum", type);
error ("%q+T has a previous declaration here", type);
/* Update the minimum and maximum values, if appropriate. */
value = DECL_INITIAL (decl);
+ if (value == error_mark_node)
+ value = integer_zero_node;
/* Figure out what the minimum and maximum values of the
enumerators are. */
if (!minnode)
type of the enumeration. */
for (values = TYPE_VALUES (enumtype); values; values = TREE_CHAIN (values))
{
+ location_t saved_location;
+
decl = TREE_VALUE (values);
+ saved_location = input_location;
+ input_location = DECL_SOURCE_LOCATION (decl);
value = perform_implicit_conversion (underlying_type,
DECL_INITIAL (decl));
+ input_location = saved_location;
/* Do not clobber shared ints. */
value = copy_node (value);
overflowed |= !int_fits_type_p (value, TREE_TYPE (prev_value));
if (overflowed)
- error ("overflow in enumeration values at %qD", name);
+ {
+ error ("overflow in enumeration values at %qD", name);
+ value = error_mark_node;
+ }
}
else
value = integer_zero_node;
return;
if (!COMPLETE_OR_VOID_TYPE_P (return_type))
{
- error ("return type %q#T is incomplete", TREE_TYPE (fntype));
+ tree args = TYPE_ARG_TYPES (fntype);
+
+ error ("return type %q#T is incomplete", return_type);
- /* Make it return void instead, but don't change the
- type of the DECL_RESULT, in case we have a named return value. */
+ /* Make it return void instead. */
if (TREE_CODE (fntype) == METHOD_TYPE)
- {
- tree ctype = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (fntype)));
- TREE_TYPE (decl)
- = build_method_type_directly (ctype,
- void_type_node,
- FUNCTION_ARG_CHAIN (decl));
- }
+ fntype = build_method_type_directly (TREE_TYPE (TREE_VALUE (args)),
+ void_type_node,
+ TREE_CHAIN (args));
else
- TREE_TYPE (decl)
- = build_function_type (void_type_node,
- TYPE_ARG_TYPES (TREE_TYPE (decl)));
+ fntype = build_function_type (void_type_node, args);
TREE_TYPE (decl)
= build_exception_variant (fntype,
- TYPE_RAISES_EXCEPTIONS (fntype));
+ TYPE_RAISES_EXCEPTIONS (TREE_TYPE (decl)));
}
else
abstract_virtuals_error (decl, TREE_TYPE (fntype));
tree current_function_parms;
struct c_fileinfo *finfo
= get_fileinfo (lbasename (LOCATION_FILE (DECL_SOURCE_LOCATION (decl1))));
+ bool honor_interface;
/* Sanity check. */
gcc_assert (TREE_CODE (TREE_VALUE (void_list_node)) == VOID_TYPE);
}
}
+ honor_interface = (!DECL_TEMPLATE_INSTANTIATION (decl1)
+ /* Implicitly-defined methods (like the
+ destructor for a class in which no destructor
+ is explicitly declared) must not be defined
+ until their definition is needed. So, we
+ ignore interface specifications for
+ compiler-generated functions. */
+ && !DECL_ARTIFICIAL (decl1));
+
if (DECL_INTERFACE_KNOWN (decl1))
{
tree ctx = decl_function_context (decl1);
/* If this function belongs to an interface, it is public.
If it belongs to someone else's interface, it is also external.
This only affects inlines and template instantiations. */
- else if (finfo->interface_unknown == 0
- && ! DECL_TEMPLATE_INSTANTIATION (decl1))
+ else if (!finfo->interface_unknown && honor_interface)
{
if (DECL_DECLARED_INLINE_P (decl1)
|| DECL_TEMPLATE_INSTANTIATION (decl1)
}
else
DECL_EXTERNAL (decl1) = 0;
- DECL_NOT_REALLY_EXTERN (decl1) = 0;
DECL_INTERFACE_KNOWN (decl1) = 1;
/* If this function is in an interface implemented in this file,
make sure that the backend knows to emit this function
mark_needed (decl1);
}
else if (finfo->interface_unknown && finfo->interface_only
- && ! DECL_TEMPLATE_INSTANTIATION (decl1))
+ && honor_interface)
{
/* If MULTIPLE_SYMBOL_SPACES is defined and we saw a #pragma
interface, we will have both finfo->interface_unknown and
/* Do the necessary processing for the beginning of a function body, which
in this case includes member-initializers, but not the catch clauses of
a function-try-block. Currently, this means opening a binding level
- for the member-initializers (in a ctor) and member cleanups (in a dtor).
- In other functions, this isn't necessary, but it doesn't hurt. */
+ for the member-initializers (in a ctor) and member cleanups (in a dtor). */
tree
begin_function_body (void)
{
tree stmt;
+ if (! FUNCTION_NEEDS_BODY_BLOCK (current_function_decl))
+ return NULL_TREE;
+
if (processing_template_decl)
/* Do nothing now. */;
else
void
finish_function_body (tree compstmt)
{
+ if (compstmt == NULL_TREE)
+ return;
+
/* Close the block. */
finish_compound_stmt (compstmt);
finish_destructor_body ();
}
+/* Given a function, returns the BLOCK corresponding to the outermost level
+ of curly braces, skipping the artificial block created for constructor
+ initializers. */
+
+static tree
+outer_curly_brace_block (tree fndecl)
+{
+ tree block = BLOCK_SUBBLOCKS (DECL_INITIAL (fndecl));
+ if (FUNCTION_NEEDS_BODY_BLOCK (current_function_decl))
+ /* Skip the artificial function body block. */
+ block = BLOCK_SUBBLOCKS (block);
+ return block;
+}
+
/* Finish up a function declaration and compile that function
all the way to assembler language output. The free the storage
for the function definition.
the function so we know that their lifetime always ends with a
return; see g++.dg/opt/nrv6.C. We could be more flexible if
we were to do this optimization in tree-ssa. */
- && (outer = BLOCK_SUBBLOCKS (DECL_INITIAL (fndecl)))
- /* Skip the artificial function body block. */
- && (outer = BLOCK_SUBBLOCKS (outer))
+ && (outer = outer_curly_brace_block (fndecl))
&& chain_member (r, BLOCK_VARS (outer)))
finalize_nrv (&DECL_SAVED_TREE (fndecl), r, DECL_RESULT (fndecl));
&& TREE_CODE( DECL_CONTEXT (fndecl)) != NAMESPACE_DECL)
error ("%qD is already defined in class %qT", fndecl,
DECL_CONTEXT (fndecl));
- return void_type_node;
+ return error_mark_node;
}
check_template_shadow (fndecl);