/* Process declarations and variables for C++ compiler.
Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
This file is part of GCC.
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);
static tree grokvardecl (tree, tree, const cp_decl_specifier_seq *,
int, int, tree);
static void record_unknown_type (tree, const char *);
static int typename_compare (const void *, const void *);
static tree local_variable_p_walkfn (tree *, int *, void *);
static tree record_builtin_java_type (const char *, int);
-static const char *tag_name (enum tag_types code);
+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,
static void expand_static_init (tree, tree);
static tree next_initializable_field (tree);
static tree reshape_init (tree, tree *);
-static tree build_typename_type (tree, tree, tree);
/* Erroneous argument lists can use this *IFF* they do not modify it. */
tree error_mark_list;
{
location_t location;
- cp_error_at ("label `%D' used but not defined", label);
+ cp_error_at ("label %qD used but not defined", label);
#ifdef USE_MAPPED_LOCATION
location = input_location; /* FIXME want (input_filename, (line)0) */
#else
define_label (location, DECL_NAME (label));
}
else if (warn_unused_label && !TREE_USED (label))
- cp_warning_at ("label `%D' defined but not used", label);
+ cp_warning_at ("label %qD defined but not used", label);
}
SET_IDENTIFIER_LABEL_VALUE (DECL_NAME (label), old_value);
named_labels = NULL;
}
+/* The following two routines are used to interface to Objective-C++.
+ The binding level is purposely treated as an opaque type. */
+
+void *
+objc_get_current_scope (void)
+{
+ return current_binding_level;
+}
+
+/* The following routine is used by the NeXT-style SJLJ exceptions;
+ variables get marked 'volatile' so as to not be clobbered by
+ _setjmp()/_longjmp() calls. All variables in the current scope,
+ as well as parent scopes up to (but not including) ENCLOSING_BLK
+ shall be thusly marked. */
+
+void
+objc_mark_locals_volatile (void *enclosing_blk)
+{
+ struct cp_binding_level *scope;
+
+ for (scope = current_binding_level;
+ scope && scope != enclosing_blk && scope->kind == sk_block;
+ scope = scope->level_chain)
+ {
+ tree decl;
+
+ for (decl = scope->names; decl; decl = TREE_CHAIN (decl))
+ {
+ if (TREE_CODE (decl) == VAR_DECL)
+ {
+ DECL_REGISTER (decl) = 0;
+ TREE_THIS_VOLATILE (decl) = 1;
+ }
+ }
+ }
+}
+
/* Exit a binding level.
Pop the level off, and restore the state of the identifier-decl mappings
that were in effect when this level was entered.
block = NULL_TREE;
- my_friendly_assert (current_binding_level->kind != sk_class, 19990916);
+ gcc_assert (current_binding_level->kind != sk_class);
real_functionbody = (current_binding_level->kind == sk_cleanup
? ((functionbody = 0), tmp) : functionbody);
subblocks = functionbody >= 0 ? current_binding_level->blocks : 0;
- my_friendly_assert (VEC_length(cp_class_binding,
- current_binding_level->class_shadowed) == 0,
- 19990414);
+ gcc_assert (!VEC_length(cp_class_binding,
+ current_binding_level->class_shadowed));
/* We used to use KEEP == 2 to indicate that the new block should go
at the beginning of the list of blocks at this binding level,
rather than the end. This hack is no longer used. */
- my_friendly_assert (keep == 0 || keep == 1, 0);
+ gcc_assert (keep == 0 || keep == 1);
if (current_binding_level->keep)
keep = 1;
&& ! TREE_USED (decl)
&& ! DECL_IN_SYSTEM_HEADER (decl)
&& DECL_NAME (decl) && ! DECL_ARTIFICIAL (decl))
- warning ("%Junused variable '%D'", decl, decl);
+ warning ("%Junused variable %qD", decl, decl);
/* Remove declarations for all the DECLs in this level. */
for (link = decls; link; link = TREE_CHAIN (link))
}
else
{
+ tree name;
+
/* Remove the binding. */
decl = link;
if (TREE_CODE (decl) == TREE_LIST)
decl = TREE_VALUE (decl);
+ name = decl;
+
+ if (TREE_CODE (name) == OVERLOAD)
+ name = OVL_FUNCTION (name);
- if (DECL_P (decl))
- pop_binding (DECL_NAME (decl), decl);
- else if (TREE_CODE (decl) == OVERLOAD)
- pop_binding (DECL_NAME (OVL_FUNCTION (decl)), decl);
- else
- abort ();
+ gcc_assert (DECL_P (name));
+ pop_binding (DECL_NAME (name), decl);
}
}
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. */
return;
name = DECL_ASSEMBLER_NAME (newdecl);
- pedwarn ("`%D' was declared `extern' and later `static'", newdecl);
- cp_pedwarn_at ("previous declaration of `%D'", olddecl);
+ pedwarn ("%qD was declared %<extern%> and later %<static%>", newdecl);
+ cp_pedwarn_at ("previous declaration of %qD", olddecl);
}
/* If NEWDECL is a redeclaration of OLDDECL, merge the declarations.
&& DECL_UNINLINABLE (olddecl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
{
- warning ("%Jfunction '%D' redeclared as inline", newdecl, newdecl);
- warning ("%Jprevious declaration of '%D' with attribute noinline",
+ warning ("%Jfunction %qD redeclared as inline", newdecl, newdecl);
+ warning ("%Jprevious declaration of %qD with attribute noinline",
olddecl, olddecl);
}
else if (DECL_DECLARED_INLINE_P (olddecl)
&& DECL_UNINLINABLE (newdecl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl)))
{
- warning ("%Jfunction '%D' redeclared with attribute noinline",
+ warning ("%Jfunction %qD redeclared with attribute noinline",
newdecl, newdecl);
- warning ("%Jprevious declaration of '%D' was inline",
+ warning ("%Jprevious declaration of %qD was inline",
olddecl, olddecl);
}
}
if (! TREE_PUBLIC (newdecl))
{
if (warn_shadow)
- warning ("shadowing %s function `%#D'",
- DECL_BUILT_IN (olddecl) ? "built-in" : "library",
- olddecl);
+ warning ("shadowing %s function %q#D",
+ DECL_BUILT_IN (olddecl) ? "built-in" : "library",
+ olddecl);
/* Discard the old built-in function. */
return NULL_TREE;
}
/* If the built-in is not ansi, then programs can override
it even globally without an error. */
else if (! DECL_BUILT_IN (olddecl))
- warning ("library function `%#D' redeclared as non-function `%#D'",
- olddecl, newdecl);
+ warning ("library function %q#D redeclared as non-function %q#D",
+ olddecl, newdecl);
else
{
- error ("declaration of `%#D'", newdecl);
- error ("conflicts with built-in declaration `%#D'",
- olddecl);
+ error ("declaration of %q#D", newdecl);
+ error ("conflicts with built-in declaration %q#D",
+ olddecl);
}
return NULL_TREE;
}
if (TREE_PUBLIC (newdecl))
{
- warning ("new declaration `%#D'", newdecl);
- warning ("ambiguates built-in declaration `%#D'",
- olddecl);
+ warning ("new declaration %q#D", newdecl);
+ warning ("ambiguates built-in declaration %q#D",
+ olddecl);
}
else if (warn_shadow)
- warning ("shadowing %s function `%#D'",
- DECL_BUILT_IN (olddecl) ? "built-in" : "library",
- olddecl);
+ warning ("shadowing %s function %q#D",
+ DECL_BUILT_IN (olddecl) ? "built-in" : "library",
+ olddecl);
}
else
/* Discard the old built-in function. */
&& DECL_FUNCTION_TEMPLATE_P (newdecl)))
return NULL_TREE;
- error ("`%#D' redeclared as different kind of symbol", newdecl);
+ error ("%q#D redeclared as different kind of symbol", newdecl);
if (TREE_CODE (olddecl) == TREE_LIST)
olddecl = TREE_VALUE (olddecl);
- cp_error_at ("previous declaration of `%#D'", olddecl);
+ cp_error_at ("previous declaration of %q#D", olddecl);
return error_mark_node;
}
if (TREE_CODE (DECL_TEMPLATE_RESULT (olddecl)) == TYPE_DECL
|| TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL)
{
- error ("declaration of template `%#D'", newdecl);
- cp_error_at ("conflicts with previous declaration `%#D'",
+ error ("declaration of template %q#D", newdecl);
+ cp_error_at ("conflicts with previous declaration %q#D",
olddecl);
}
else if (TREE_CODE (DECL_TEMPLATE_RESULT (olddecl)) == FUNCTION_DECL
&& same_type_p (TREE_TYPE (TREE_TYPE (newdecl)),
TREE_TYPE (TREE_TYPE (olddecl))))
{
- error ("new declaration `%#D'", newdecl);
- cp_error_at ("ambiguates old declaration `%#D'", olddecl);
+ error ("new declaration %q#D", newdecl);
+ cp_error_at ("ambiguates old declaration %q#D", olddecl);
}
return NULL_TREE;
}
{
if (DECL_EXTERN_C_P (newdecl) && DECL_EXTERN_C_P (olddecl))
{
- error ("declaration of C function `%#D' conflicts with",
- newdecl);
- cp_error_at ("previous declaration `%#D' here", olddecl);
+ error ("declaration of C function %q#D conflicts with",
+ newdecl);
+ cp_error_at ("previous declaration %q#D here", olddecl);
}
else if (compparms (TYPE_ARG_TYPES (TREE_TYPE (newdecl)),
TYPE_ARG_TYPES (TREE_TYPE (olddecl))))
{
- error ("new declaration `%#D'", newdecl);
- cp_error_at ("ambiguates old declaration `%#D'", olddecl);
+ error ("new declaration %q#D", newdecl);
+ cp_error_at ("ambiguates old declaration %q#D", olddecl);
}
else
return NULL_TREE;
}
else
{
- error ("conflicting declaration '%#D'", newdecl);
- cp_error_at ("'%D' has a previous declaration as `%#D'",
+ error ("conflicting declaration %q#D", newdecl);
+ cp_error_at ("%qD has a previous declaration as %q#D",
olddecl, olddecl);
- return NULL_TREE;
+ return error_mark_node;
}
}
else if (TREE_CODE (newdecl) == FUNCTION_DECL
A namespace-name or namespace-alias shall not be declared as
the name of any other entity in the same declarative region.
A namespace-name defined at global scope shall not be
- declared as the name of any other entity in any glogal scope
+ declared as the name of any other entity in any global scope
of the program. */
- error ("declaration of `namespace %D' conflicts with", newdecl);
- cp_error_at ("previous declaration of `namespace %D' here", olddecl);
+ error ("declaration of namespace %qD conflicts with", newdecl);
+ cp_error_at ("previous declaration of namespace %qD here", olddecl);
return error_mark_node;
}
else
if (DECL_NAME (olddecl) != NULL_TREE)
cp_error_at ((DECL_INITIAL (olddecl)
&& namespace_bindings_p ())
- ? "`%#D' previously defined here"
- : "`%#D' previously declared here", olddecl);
+ ? "%q#D previously defined here"
+ : "%q#D previously declared here", olddecl);
return error_mark_node;
}
else if (TREE_CODE (olddecl) == FUNCTION_DECL
&& TYPE_ARG_TYPES (TREE_TYPE (newdecl)) != NULL_TREE)
{
/* Prototype decl follows defn w/o prototype. */
- cp_warning_at ("prototype for `%#D'", newdecl);
+ cp_warning_at ("prototype for %q#D", newdecl);
warning ("%Jfollows non-prototype definition here", olddecl);
}
else if (TREE_CODE (olddecl) == FUNCTION_DECL
SET_DECL_LANGUAGE (newdecl, DECL_LANGUAGE (olddecl));
else
{
- cp_error_at ("previous declaration of `%#D' with %L linkage",
+ cp_error_at ("previous declaration of %q#D with %qL linkage",
olddecl, DECL_LANGUAGE (olddecl));
- error ("conflicts with new declaration with %L linkage",
- DECL_LANGUAGE (newdecl));
+ error ("conflicts with new declaration with %qL linkage",
+ DECL_LANGUAGE (newdecl));
}
}
if (1 == simple_cst_equal (TREE_PURPOSE (t1),
TREE_PURPOSE (t2)))
{
- pedwarn ("default argument given for parameter %d of `%#D'",
+ pedwarn ("default argument given for parameter %d of %q#D",
i, newdecl);
- cp_pedwarn_at ("after previous specification in `%#D'",
+ cp_pedwarn_at ("after previous specification in %q#D",
olddecl);
}
else
{
- error ("default argument given for parameter %d of `%#D'",
- i, newdecl);
- cp_error_at ("after previous specification in `%#D'",
+ error ("default argument given for parameter %d of %q#D",
+ i, newdecl);
+ cp_error_at ("after previous specification in %q#D",
olddecl);
}
}
&& ! DECL_DECLARED_INLINE_P (olddecl)
&& TREE_ADDRESSABLE (olddecl) && warn_inline)
{
- warning ("`%#D' was used before it was declared inline", newdecl);
+ warning ("%q#D was used before it was declared inline", newdecl);
warning ("%Jprevious non-inline declaration here", olddecl);
}
}
DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl);
DECL_PURE_VIRTUAL_P (newdecl) |= DECL_PURE_VIRTUAL_P (olddecl);
DECL_VIRTUAL_P (newdecl) |= DECL_VIRTUAL_P (olddecl);
- DECL_NEEDS_FINAL_OVERRIDER_P (newdecl) |= DECL_NEEDS_FINAL_OVERRIDER_P (olddecl);
DECL_THIS_STATIC (newdecl) |= DECL_THIS_STATIC (olddecl);
if (DECL_OVERLOADED_OPERATOR_P (olddecl) != ERROR_MARK)
SET_OVERLOADED_OPERATOR_CODE
/* Don't warn about friends, let add_friend take care of it. */
&& ! (DECL_FRIEND_P (newdecl) || DECL_FRIEND_P (olddecl)))
{
- warning ("redundant redeclaration of `%D' in same scope", newdecl);
- cp_warning_at ("previous declaration of `%D'", olddecl);
+ warning ("redundant redeclaration of %qD in same scope", newdecl);
+ cp_warning_at ("previous declaration of %qD", olddecl);
}
}
&& !comp_except_specs (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (newdecl)),
TYPE_RAISES_EXCEPTIONS (TREE_TYPE (olddecl)), 1))
{
- error ("declaration of `%F' throws different exceptions",
- newdecl);
- cp_error_at ("than previous declaration `%F'", olddecl);
+ error ("declaration of %qF throws different exceptions",
+ newdecl);
+ cp_error_at ("than previous declaration %qF", olddecl);
}
}
TREE_TYPE (newdecl) = TREE_TYPE (olddecl) = newtype;
TREE_READONLY (olddecl) = 1;
if (TREE_THIS_VOLATILE (newdecl))
TREE_THIS_VOLATILE (olddecl) = 1;
+ if (TREE_NOTHROW (newdecl))
+ TREE_NOTHROW (olddecl) = 1;
+
+ /* Merge deprecatedness. */
+ if (TREE_DEPRECATED (newdecl))
+ TREE_DEPRECATED (olddecl) = 1;
/* Merge the initialization information. */
if (DECL_INITIAL (newdecl) == NULL_TREE
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 newdecl is not a specialization, then it is not a
template-related function at all. And that means that we
should have exited above, returning 0. */
- my_friendly_assert (DECL_TEMPLATE_SPECIALIZATION (newdecl),
- 0);
+ gcc_assert (DECL_TEMPLATE_SPECIALIZATION (newdecl));
if (TREE_USED (olddecl))
/* From [temp.expl.spec]:
that specialization that would cause an implicit
instantiation to take place, in every translation unit in
which such a use occurs. */
- error ("explicit specialization of %D after first use",
+ error ("explicit specialization of %qD after first use",
olddecl);
SET_DECL_TEMPLATE_SPECIALIZATION (olddecl);
&& DECL_VISIBILITY_SPECIFIED (newdecl)
&& DECL_VISIBILITY (newdecl) != DECL_VISIBILITY (olddecl))
{
- warning ("%J'%D': visibility attribute ignored because it",
+ warning ("%J%qD: visibility attribute ignored because it",
newdecl, newdecl);
warning ("%Jconflicts with previous declaration here", olddecl);
}
DECL_VISIBILITY_SPECIFIED (newdecl) = 1;
}
+ /* The DECL_LANG_SPECIFIC information in OLDDECL will be replaced
+ with that from NEWDECL below. */
+ if (DECL_LANG_SPECIFIC (olddecl))
+ {
+ gcc_assert (DECL_LANG_SPECIFIC (olddecl)
+ != DECL_LANG_SPECIFIC (newdecl));
+ ggc_free (DECL_LANG_SPECIFIC (olddecl));
+ }
+
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
int function_size;
&& TREE_STATIC (olddecl))))
make_decl_rtl (olddecl);
+ /* The NEWDECL will no longer be needed. Because every out-of-class
+ declaration of a member results in a call to duplicate_decls,
+ freeing these nodes represents in a significant savings. */
+ ggc_free (newdecl);
+
return olddecl;
}
\f
if (same_type_p (TREE_TYPE (newdecl), TREE_TYPE (olddecl)))
return 0;
else
- return "redefinition of `%#D'";
+ return "redefinition of %q#D";
}
else if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
/* 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
a redeclaration - this is a conflict with a used function. */
if (DECL_NAMESPACE_SCOPE_P (olddecl)
&& DECL_CONTEXT (olddecl) != DECL_CONTEXT (newdecl))
- return "`%D' conflicts with used function";
+ return "%qD conflicts with used function";
/* We'll complain about linkage mismatches in
warn_extern_redeclared_static. */
&& DECL_INITIAL (newdecl) != NULL_TREE)
{
if (DECL_NAME (olddecl) == NULL_TREE)
- return "`%#D' not declared in class";
+ return "%q#D not declared in class";
else
- return "redefinition of `%#D'";
+ return "redefinition of %q#D";
}
return 0;
}
{
if (COMPLETE_TYPE_P (TREE_TYPE (newdecl))
&& COMPLETE_TYPE_P (TREE_TYPE (olddecl)))
- return "redefinition of `%#D'";
+ return "redefinition of %q#D";
return NULL;
}
if (DECL_TEMPLATE_INFO (ot))
ot = DECL_TEMPLATE_RESULT (template_for_substitution (ot));
if (DECL_INITIAL (nt) && DECL_INITIAL (ot))
- return "redefinition of `%#D'";
+ return "redefinition of %q#D";
return NULL;
}
if (DECL_EXTERNAL (newdecl) || DECL_EXTERNAL (olddecl))
return 0;
/* Reject two definitions. */
- return "redefinition of `%#D'";
+ return "redefinition of %q#D";
}
else
{
/* Reject two definitions, and reject a definition
together with an external reference. */
if (!(DECL_EXTERNAL (newdecl) && DECL_EXTERNAL (olddecl)))
- return "redeclaration of `%#D'";
+ return "redeclaration of %q#D";
return 0;
}
}
/* You can't use labels at global scope. */
if (current_function_decl == NULL_TREE)
{
- error ("label `%E' referenced outside of any function", id);
+ error ("label %qE referenced outside of any function", id);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
}
if (! identified)
{
if (decl)
- pedwarn ("jump to label `%D'", decl);
+ pedwarn ("jump to label %qD", decl);
else
pedwarn ("jump to case label");
}
if (problem > 1)
- cp_error_at (" crosses initialization of `%#D'",
+ cp_error_at (" crosses initialization of %q#D",
new_decls);
else
- cp_pedwarn_at (" enters scope of non-POD `%#D'",
+ cp_pedwarn_at (" enters scope of non-POD %q#D",
new_decls);
}
if (! identified)
{
if (decl)
- pedwarn ("jump to label `%D'", decl);
+ pedwarn ("jump to label %qD", decl);
else
pedwarn ("jump to case label");
if ((lab->in_try_scope || lab->in_catch_scope || lab->bad_decls)
&& !identified)
{
- cp_pedwarn_at ("jump to label `%D'", decl);
+ cp_pedwarn_at ("jump to label %qD", decl);
pedwarn (" from here");
identified = 1;
}
/* Can't skip init of __exception_info. */
error ("%J enters catch block", b);
else if (u > 1)
- cp_error_at (" skips initialization of `%#D'", b);
+ cp_error_at (" skips initialization of %q#D", b);
else
- cp_pedwarn_at (" enters scope of non-POD `%#D'", b);
+ cp_pedwarn_at (" enters scope of non-POD %q#D", b);
}
if (lab->in_try_scope)
pedwarn ("label named wchar_t");
if (DECL_INITIAL (decl) != NULL_TREE)
- error ("duplicate label `%D'", decl);
+ error ("duplicate label %qD", decl);
else
{
/* Mark label as having been defined. */
check_previous_gotos (decl);
}
- timevar_pop (TV_NAME_LOOKUP);
- return decl;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
}
struct cp_switch
}
/* 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);
return hash;
}
+typedef struct typename_info {
+ tree scope;
+ tree name;
+ tree template_id;
+ bool enum_p;
+ bool class_p;
+} typename_info;
+
/* Compare two TYPENAME_TYPEs. K1 and K2 are really of type `tree'. */
static int
typename_compare (const void * k1, const void * k2)
{
tree t1;
- tree t2;
- tree d1;
- tree d2;
+ const typename_info *t2;
t1 = (tree) k1;
- t2 = (tree) k2;
- d1 = TYPE_NAME (t1);
- d2 = TYPE_NAME (t2);
+ t2 = (const typename_info *) k2;
- return (DECL_NAME (d1) == DECL_NAME (d2)
- && TYPE_CONTEXT (t1) == TYPE_CONTEXT (t2)
- && ((TREE_TYPE (t1) != NULL_TREE)
- == (TREE_TYPE (t2) != NULL_TREE))
- && same_type_p (TREE_TYPE (t1), TREE_TYPE (t2))
- && TYPENAME_TYPE_FULLNAME (t1) == TYPENAME_TYPE_FULLNAME (t2));
+ return (DECL_NAME (TYPE_NAME (t1)) == t2->name
+ && TYPE_CONTEXT (t1) == t2->scope
+ && TYPENAME_TYPE_FULLNAME (t1) == t2->template_id
+ && TYPENAME_IS_ENUM_P (t1) == t2->enum_p
+ && TYPENAME_IS_CLASS_P (t1) == t2->class_p);
}
/* Build a TYPENAME_TYPE. If the type is `typename T::t', CONTEXT is
- the type of `T', NAME is the IDENTIFIER_NODE for `t'. If BASE_TYPE
- is non-NULL, this type is being created by the implicit typename
- extension, and BASE_TYPE is a type named `t' in some base class of
- `T' which depends on template parameters.
-
+ the type of `T', NAME is the IDENTIFIER_NODE for `t'.
+
Returns the new TYPENAME_TYPE. */
static GTY ((param_is (union tree_node))) htab_t typename_htab;
static tree
-build_typename_type (tree context, tree name, tree fullname)
+build_typename_type (tree context, tree name, tree fullname,
+ enum tag_types tag_type)
{
tree t;
tree d;
+ typename_info ti;
void **e;
+ hashval_t hash;
if (typename_htab == NULL)
- {
- typename_htab = htab_create_ggc (61, &typename_hash,
- &typename_compare, NULL);
- }
-
- /* Build the TYPENAME_TYPE. */
- t = make_aggr_type (TYPENAME_TYPE);
- TYPE_CONTEXT (t) = FROB_CONTEXT (context);
- TYPENAME_TYPE_FULLNAME (t) = fullname;
-
- /* Build the corresponding TYPE_DECL. */
- d = build_decl (TYPE_DECL, name, t);
- TYPE_NAME (TREE_TYPE (d)) = d;
- TYPE_STUB_DECL (TREE_TYPE (d)) = d;
- DECL_CONTEXT (d) = FROB_CONTEXT (context);
- DECL_ARTIFICIAL (d) = 1;
+ typename_htab = htab_create_ggc (61, &typename_hash,
+ &typename_compare, NULL);
+
+ ti.scope = FROB_CONTEXT (context);
+ ti.name = name;
+ ti.template_id = fullname;
+ ti.enum_p = tag_type == enum_type;
+ ti.class_p = (tag_type == class_type
+ || tag_type == record_type
+ || tag_type == union_type);
+ hash = (htab_hash_pointer (ti.scope)
+ ^ htab_hash_pointer (ti.name));
/* See if we already have this type. */
- e = htab_find_slot (typename_htab, t, INSERT);
+ e = htab_find_slot_with_hash (typename_htab, &ti, hash, INSERT);
if (*e)
t = (tree) *e;
else
- *e = t;
-
+ {
+ /* Build the TYPENAME_TYPE. */
+ t = make_aggr_type (TYPENAME_TYPE);
+ TYPE_CONTEXT (t) = ti.scope;
+ TYPENAME_TYPE_FULLNAME (t) = ti.template_id;
+ TYPENAME_IS_ENUM_P (t) = ti.enum_p;
+ TYPENAME_IS_CLASS_P (t) = ti.class_p;
+
+ /* Build the corresponding TYPE_DECL. */
+ d = build_decl (TYPE_DECL, name, t);
+ TYPE_NAME (TREE_TYPE (d)) = d;
+ TYPE_STUB_DECL (TREE_TYPE (d)) = d;
+ DECL_CONTEXT (d) = FROB_CONTEXT (context);
+ DECL_ARTIFICIAL (d) = 1;
+
+ /* Store it in the hash table. */
+ *e = t;
+ }
+
return t;
}
-/* Resolve `typename CONTEXT::NAME'. Returns an appropriate type,
- unless an error occurs, in which case error_mark_node is returned.
- If we locate a non-artificial TYPE_DECL and TF_KEEP_TYPE_DECL is
- set, we return that, rather than the _TYPE it corresponds to, in
- other cases we look through the type decl. If TF_ERROR is set,
- complain about errors, otherwise be quiet. */
+/* Resolve `typename CONTEXT::NAME'. TAG_TYPE indicates the tag
+ provided to name the type. Returns an appropriate type, unless an
+ error occurs, in which case error_mark_node is returned. If we
+ locate a non-artificial TYPE_DECL and TF_KEEP_TYPE_DECL is set, we
+ return that, rather than the _TYPE it corresponds to, in other
+ cases we look through the type decl. If TF_ERROR is set, complain
+ about errors, otherwise be quiet. */
tree
-make_typename_type (tree context, tree name, tsubst_flags_t complain)
+make_typename_type (tree context, tree name, enum tag_types tag_type,
+ tsubst_flags_t complain)
{
tree fullname;
}
if (TREE_CODE (name) == TEMPLATE_DECL)
{
- error ("`%D' used without template parameters", name);
- return error_mark_node;
- }
- my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 20030802);
-
- if (TREE_CODE (context) == NAMESPACE_DECL)
- {
- /* We can get here from typename_sub0 in the explicit_template_type
- expansion. Just fail. */
- if (complain & tf_error)
- error ("no class template named `%#T' in `%#T'",
- name, context);
+ error ("%qD used without template parameters", name);
return error_mark_node;
}
+ gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
+ gcc_assert (TYPE_P (context));
if (!dependent_type_p (context)
|| currently_open_class (context))
if (!tmpl || !DECL_CLASS_TEMPLATE_P (tmpl))
{
if (complain & tf_error)
- error ("no class template named `%#T' in `%#T'",
- name, context);
+ error ("no class template named %q#T in %q#T",
+ name, context);
return error_mark_node;
}
if (!IS_AGGR_TYPE (context))
{
if (complain & tf_error)
- error ("no type named `%#T' in `%#T'", name, context);
+ error ("no type named %q#T in %q#T", name, context);
return error_mark_node;
}
if (TREE_CODE (t) != TYPE_DECL)
{
if (complain & tf_error)
- error ("no type named `%#T' in `%#T'", name, context);
+ error ("no type named %q#T in %q#T", name, context);
return error_mark_node;
}
if (!dependent_type_p (context))
{
if (complain & tf_error)
- error ("no type named `%#T' in `%#T'", name, context);
+ error ("no type named %q#T in %q#T", name, context);
return error_mark_node;
}
- return build_typename_type (context, name, fullname);
+ return build_typename_type (context, name, fullname, tag_type);
}
-/* Resolve `CONTEXT::template NAME'. Returns an appropriate type,
- unless an error occurs, in which case error_mark_node is returned.
- If we locate a TYPE_DECL, we return that, rather than the _TYPE it
- corresponds to. If COMPLAIN zero, don't complain about any errors
- that occur. */
+/* Resolve `CONTEXT::template NAME'. Returns a TEMPLATE_DECL if the name
+ can be resolved or an UNBOUND_CLASS_TEMPLATE, unless an error occurs,
+ in which case error_mark_node is returned.
+
+ If PARM_LIST is non-NULL, also make sure that the template parameter
+ list of TEMPLATE_DECL matches.
+
+ If COMPLAIN zero, don't complain about any errors that occur. */
tree
-make_unbound_class_template (tree context, tree name, tsubst_flags_t complain)
+make_unbound_class_template (tree context, tree name, tree parm_list,
+ tsubst_flags_t complain)
{
tree t;
tree d;
name = TYPE_IDENTIFIER (name);
else if (DECL_P (name))
name = DECL_NAME (name);
- if (TREE_CODE (name) != IDENTIFIER_NODE)
- abort ();
+ gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
if (!dependent_type_p (context)
|| currently_open_class (context))
if (!tmpl || !DECL_CLASS_TEMPLATE_P (tmpl))
{
if (complain & tf_error)
- error ("no class template named `%#T' in `%#T'", name, context);
+ error ("no class template named %q#T in %q#T", name, context);
+ return error_mark_node;
+ }
+
+ if (parm_list
+ && !comp_template_parms (DECL_TEMPLATE_PARMS (tmpl), parm_list))
+ {
+ if (complain & tf_error)
+ {
+ error ("template parameters do not match template");
+ cp_error_at ("%qD declared here", tmpl);
+ }
return error_mark_node;
}
TYPE_STUB_DECL (TREE_TYPE (d)) = d;
DECL_CONTEXT (d) = FROB_CONTEXT (context);
DECL_ARTIFICIAL (d) = 1;
+ DECL_TEMPLATE_PARMS (d) = parm_list;
return t;
}
{ "C++", &lang_name_cplusplus, 0 },
{ "C", &lang_name_c, 0 },
{ "Java", &lang_name_java, 0 },
- { CTOR_NAME, &ctor_identifier, 1 },
- { "__base_ctor", &base_ctor_identifier, 1 },
- { "__comp_ctor", &complete_ctor_identifier, 1 },
- { DTOR_NAME, &dtor_identifier, 1 },
- { "__comp_dtor", &complete_dtor_identifier, 1 },
- { "__base_dtor", &base_dtor_identifier, 1 },
- { "__deleting_dtor", &deleting_dtor_identifier, 1 },
+ /* Some of these names have a trailing space so that it is
+ impossible for them to conflict with names written by users. */
+ { "__ct ", &ctor_identifier, 1 },
+ { "__base_ctor ", &base_ctor_identifier, 1 },
+ { "__comp_ctor ", &complete_ctor_identifier, 1 },
+ { "__dt ", &dtor_identifier, 1 },
+ { "__comp_dtor ", &complete_dtor_identifier, 1 },
+ { "__base_dtor ", &base_dtor_identifier, 1 },
+ { "__deleting_dtor ", &deleting_dtor_identifier, 1 },
{ IN_CHARGE_NAME, &in_charge_identifier, 0 },
{ "nelts", &nelts_identifier, 0 },
{ THIS_NAME, &this_identifier, 0 },
tree void_ftype;
tree void_ftype_ptr;
- build_common_tree_nodes (flag_signed_char);
+ build_common_tree_nodes (flag_signed_char, false);
/* Create all the identifiers we need. */
initialize_predefined_identifiers ();
current_function_decl = NULL_TREE;
current_binding_level = NULL;
/* Enter the global namespace. */
- my_friendly_assert (global_namespace == NULL_TREE, 375);
+ gcc_assert (global_namespace == NULL_TREE);
global_namespace = build_lang_decl (NAMESPACE_DECL, global_scope_name,
void_type_node);
begin_scope (sk_namespace, global_namespace);
flag_no_inline = 1;
}
if (flag_inline_functions)
- {
- flag_inline_trees = 2;
- flag_inline_functions = 0;
- }
+ flag_inline_trees = 2;
/* Force minimum function alignment if using the least significant
bit of function pointers to store the virtual bit. */
java_char_type_node = record_builtin_java_type ("__java_char", -16);
java_boolean_type_node = record_builtin_java_type ("__java_boolean", -1);
- integer_two_node = build_int_cst (NULL_TREE, 2, 0);
- integer_three_node = build_int_cst (NULL_TREE, 3, 0);
+ integer_two_node = build_int_cst (NULL_TREE, 2);
+ integer_three_node = build_int_cst (NULL_TREE, 3);
record_builtin_type (RID_BOOL, "bool", boolean_type_node);
truthvalue_type_node = boolean_type_node;
if (CLASS_TYPE_P (type))
{
if (TYPE_NEEDS_CONSTRUCTING (type))
- cp_error_at ("member %#D' with constructor not allowed in anonymous aggregate",
+ cp_error_at ("member %q#D with constructor not allowed "
+ "in anonymous aggregate",
field);
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
- cp_error_at ("member %#D' with destructor not allowed in anonymous aggregate",
+ cp_error_at ("member %q#D with destructor not allowed "
+ "in anonymous aggregate",
field);
if (TYPE_HAS_COMPLEX_ASSIGN_REF (type))
- cp_error_at ("member %#D' with copy assignment operator not allowed in anonymous aggregate",
+ cp_error_at ("member %q#D with copy assignment operator "
+ "not allowed in anonymous aggregate",
field);
}
}
return NULL_TREE;
}
- if (TYPE_P (declspecs->type)
+ if (declspecs->type
+ && TYPE_P (declspecs->type)
&& ((TREE_CODE (declspecs->type) != TYPENAME_TYPE
&& IS_AGGR_TYPE (declspecs->type))
|| TREE_CODE (declspecs->type) == ENUMERAL_TYPE))
{
if (declspecs->specs[(int)ds_inline]
|| declspecs->specs[(int)ds_virtual])
- error ("`%s' can only be specified for functions",
+ error ("%qs can only be specified for functions",
declspecs->specs[(int)ds_inline]
? "inline" : "virtual");
else if (saw_friend
&& (!current_class_type
|| current_scope () != current_class_type))
- error ("`friend' can only be specified inside a class");
+ error ("%<friend%> can only be specified inside a class");
else if (declspecs->specs[(int)ds_explicit])
- error ("`explicit' can only be specified for constructors");
+ error ("%<explicit%> can only be specified for constructors");
else if (declspecs->storage_class)
error ("a storage class can only be specified for objects "
"and functions");
if (!t)
return NULL_TREE;
+ if (declspecs->attributes)
+ {
+ cp_warning_at ("attribute ignored in declaration of %q#T", t);
+ cp_warning_at ("attribute for %q#T must follow the %qs keyword",
+ t,
+ class_key_or_enum_as_string (t));
+
+ }
+
maybe_process_partial_specialization (t);
/* This is where the variables in an anonymous union are
int initialized,
tree attributes,
tree prefix_attributes,
- bool *pop_scope_p)
+ tree *pushed_scope_p)
{
tree decl;
tree type, tem;
tree context;
+ *pushed_scope_p = NULL_TREE;
+
/* This should only be done once on the top most decl. */
if (have_extern_spec)
{
deprecated_state = DEPRECATED_NORMAL;
if (decl == NULL_TREE || TREE_CODE (decl) == VOID_TYPE)
- return NULL_TREE;
+ return error_mark_node;
type = TREE_TYPE (decl);
if (type == error_mark_node)
- return NULL_TREE;
+ return error_mark_node;
context = DECL_CONTEXT (decl);
if (context)
- *pop_scope_p = push_scope (context);
- else
- *pop_scope_p = false;
+ {
+ *pushed_scope_p = push_scope (context);
- /* We are only interested in class contexts, later. */
- if (context && TREE_CODE (context) == NAMESPACE_DECL)
- context = NULL_TREE;
+ /* We are only interested in class contexts, later. */
+ if (TREE_CODE (context) == NAMESPACE_DECL)
+ context = NULL_TREE;
+ }
if (initialized)
/* Is it valid for this decl to have an initializer at all?
switch (TREE_CODE (decl))
{
case TYPE_DECL:
- error ("typedef `%D' is initialized (use __typeof__ instead)", decl);
+ error ("typedef %qD is initialized (use __typeof__ instead)", decl);
initialized = 0;
break;
case FUNCTION_DECL:
- error ("function `%#D' is initialized like a variable", decl);
+ error ("function %q#D is initialized like a variable", decl);
initialized = 0;
break;
{
if (! toplevel_bindings_p ()
&& DECL_EXTERNAL (decl))
- warning ("declaration of `%#D' has `extern' and is initialized",
- decl);
+ warning ("declaration of %q#D has %<extern%> and is initialized",
+ decl);
DECL_EXTERNAL (decl) = 0;
if (toplevel_bindings_p ())
TREE_STATIC (decl) = 1;
&& DECL_DECLARED_INLINE_P (decl)
&& DECL_UNINLINABLE (decl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (decl)))
- warning ("%Jinline function '%D' given attribute noinline", decl, decl);
+ warning ("%Jinline function %qD given attribute noinline", decl, decl);
if (context && COMPLETE_TYPE_P (complete_type (context)))
{
{
tree field = lookup_field (context, DECL_NAME (decl), 0, false);
if (field == NULL_TREE || TREE_CODE (field) != VAR_DECL)
- error ("`%#D' is not a static member of `%#T'", decl, context);
+ error ("%q#D is not a static member of %q#T", decl, context);
else
{
if (DECL_CONTEXT (field) != context)
{
if (!same_type_p (DECL_CONTEXT (field), context))
- pedwarn ("ISO C++ does not permit `%T::%D' to be defined as `%T::%D'",
+ pedwarn ("ISO C++ does not permit %<%T::%D%> "
+ "to be defined as %<%T::%D%>",
DECL_CONTEXT (field), DECL_NAME (decl),
context, DECL_NAME (decl));
DECL_CONTEXT (decl) = DECL_CONTEXT (field);
}
+ if (processing_specialization
+ && template_class_depth (context) == 0
+ && CLASSTYPE_TEMPLATE_SPECIALIZATION (context))
+ error ("template header not allowed in member definition "
+ "of explicitly specialized class");
/* Static data member are tricky; an in-class initialization
still doesn't provide a definition, so the in-class
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))
- error ("duplicate initialization of %D", decl);
+ error ("duplicate initialization of %qD", decl);
if (duplicate_decls (decl, field))
decl = field;
}
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.
}
if (DECL_EXTERNAL (decl) && ! DECL_TEMPLATE_SPECIALIZATION (decl))
- pedwarn ("declaration of `%#D' outside of class is not definition",
- decl);
+ pedwarn ("declaration of %q#D outside of class is not definition",
+ decl);
}
/* Enter this declaration into the symbol table. */
; /* A complete type is ok. */
else if (TREE_CODE (type) != ARRAY_TYPE)
{
- error ("variable `%#D' has initializer but incomplete type",
- decl);
+ error ("variable %q#D has initializer but incomplete type", decl);
initialized = 0;
type = TREE_TYPE (decl) = error_mark_node;
}
else if (!COMPLETE_TYPE_P (complete_type (TREE_TYPE (type))))
{
if (DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl))
- error ("elements of array `%#D' have incomplete type", decl);
+ error ("elements of array %q#D have incomplete type", decl);
/* else we already gave an error in start_decl. */
initialized = 0;
}
if ((! processing_template_decl || ! uses_template_parms (type))
&& !COMPLETE_TYPE_P (complete_type (type)))
{
- error ("aggregate `%#D' has incomplete type and cannot be defined",
+ error ("aggregate %q#D has incomplete type and cannot be defined",
decl);
/* Change the type so that assemble_variable will give
DECL an rtl we can live with: (mem (const_int 0)). */
if ((DECL_LANG_SPECIFIC (decl) == 0
|| DECL_IN_AGGR_P (decl) == 0)
&& ! DECL_THIS_EXTERN (decl))
- error ("`%D' declared as reference but not initialized", decl);
+ error ("%qD declared as reference but not initialized", decl);
return NULL_TREE;
}
if (TREE_CODE (init) == CONSTRUCTOR)
{
- error ("ISO C++ forbids use of initializer list to initialize reference `%D'", decl);
+ error ("ISO C++ forbids use of initializer list to "
+ "initialize reference %qD", decl);
return NULL_TREE;
}
if (TREE_CODE (init) == TREE_LIST)
init = build_x_compound_expr_from_list (init, "initializer");
- if (TREE_CODE (TREE_TYPE (init)) == REFERENCE_TYPE)
- init = convert_from_reference (init);
-
if (TREE_CODE (TREE_TYPE (type)) != ARRAY_TYPE
&& TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE)
/* Note: default conversion is only called in very special cases. */
return NULL_TREE;
else if (tmp == NULL_TREE)
{
- error ("cannot initialize `%T' from `%T'", type, TREE_TYPE (init));
+ error ("cannot initialize %qT from %qT", type, TREE_TYPE (init));
return NULL_TREE;
}
int failure = complete_array_type (type, initializer, do_default);
if (failure == 1)
- error ("initializer fails to determine size of `%D'", decl);
+ error ("initializer fails to determine size of %qD", decl);
if (failure == 2)
{
if (do_default)
- error ("array size missing in `%D'", decl);
+ error ("array size missing in %qD", decl);
/* 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
if (pedantic && TYPE_DOMAIN (type) != NULL_TREE
&& tree_int_cst_lt (TYPE_MAX_VALUE (TYPE_DOMAIN (type)),
integer_zero_node))
- error ("zero-size array `%D'", decl);
+ error ("zero-size array %qD", decl);
layout_decl (decl, 0);
}
/* An automatic variable with an incomplete type: that is an error.
Don't talk about array types here, since we took care of that
message in grokdeclarator. */
- error ("storage size of `%D' isn't known", decl);
+ error ("storage size of %qD isn't known", decl);
TREE_TYPE (decl) = error_mark_node;
}
#if 0
if (TREE_CODE (DECL_SIZE (decl)) == INTEGER_CST)
constant_expression_warning (DECL_SIZE (decl));
else
- error ("storage size of `%D' isn't constant", decl);
+ error ("storage size of %qD isn't constant", decl);
}
if (TREE_STATIC (decl)
be merged. */
TREE_PUBLIC (decl) = 0;
DECL_COMMON (decl) = 0;
- cp_warning_at ("sorry: semantics of inline function static data `%#D' are wrong (you'll wind up with multiple copies)", decl);
- warning ("%J you can work around this by removing the initializer",
+ cp_warning_at ("sorry: semantics of inline function static "
+ "data %q#D are wrong (you'll wind up "
+ "with multiple copies)", decl);
+ warning ("%J you can work around this by removing "
+ "the initializer",
decl);
}
}
&& CP_TYPE_CONST_P (type)
&& !TYPE_NEEDS_CONSTRUCTING (type)
&& !DECL_INITIAL (decl))
- error ("uninitialized const `%D'", decl);
+ error ("uninitialized const %qD", decl);
}
/* FIELD is a FIELD_DECL or NULL. In the former case, the value
return field;
}
+/* Subroutine of reshape_init. Reshape the constructor for an array. INITP
+ is the pointer to the old constructor list (to the CONSTRUCTOR_ELTS of
+ the CONSTRUCTOR we are processing), while NEW_INIT is the CONSTRUCTOR we
+ are building.
+ ELT_TYPE is the element type of the array. MAX_INDEX is an INTEGER_CST
+ representing the size of the array minus one (the maximum index), or
+ NULL_TREE if the array was declared without specifying the size. */
+
+static bool
+reshape_init_array (tree elt_type, tree max_index,
+ tree *initp, tree new_init)
+{
+ bool sized_array_p = (max_index != NULL_TREE);
+ HOST_WIDE_INT max_index_cst = 0;
+ HOST_WIDE_INT index;
+
+ if (sized_array_p)
+ /* HWI is either 32bit or 64bit, so it must be enough to represent the
+ array size. */
+ max_index_cst = tree_low_cst (max_index, 1);
+
+ /* Loop until there are no more initializers. */
+ for (index = 0;
+ *initp && (!sized_array_p || index <= max_index_cst);
+ ++index)
+ {
+ tree element_init;
+ tree designated_index;
+
+ element_init = reshape_init (elt_type, initp);
+ if (element_init == error_mark_node)
+ return false;
+ TREE_CHAIN (element_init) = CONSTRUCTOR_ELTS (new_init);
+ CONSTRUCTOR_ELTS (new_init) = element_init;
+ designated_index = TREE_PURPOSE (element_init);
+ if (designated_index)
+ {
+ /* Handle array designated initializers (GNU extension). */
+ if (TREE_CODE (designated_index) == IDENTIFIER_NODE)
+ {
+ error ("name %qD used in a GNU-style designated "
+ "initializer for an array", designated_index);
+ TREE_PURPOSE (element_init) = NULL_TREE;
+ }
+ else
+ {
+ gcc_assert (TREE_CODE (designated_index) == INTEGER_CST);
+ if (sized_array_p
+ && tree_int_cst_lt (max_index, designated_index))
+ {
+ error ("Designated initializer %qE larger than array "
+ "size", designated_index);
+ TREE_PURPOSE (element_init) = NULL_TREE;
+ }
+ else
+ index = tree_low_cst (designated_index, 1);
+ }
+ }
+ }
+
+ return true;
+}
+
/* Undo the brace-elision allowed by [dcl.init.aggr] in a
brace-enclosed aggregate initializer.
old_init_value = (TREE_CODE (*initp) == TREE_LIST
? TREE_VALUE (*initp) : old_init);
- my_friendly_assert (old_init_value, 20030723);
+ gcc_assert (old_init_value);
/* If the initializer is brace-enclosed, pull initializers from the
enclosed elements. Advance past the brace-enclosed initializer
brace-enclosed initializer. */
if (brace_enclosed_p)
{
- error ("brace-enclosed initializer used to initialize `%T'",
+ error ("brace-enclosed initializer used to initialize %qT",
type);
if (TREE_CODE (old_init) == TREE_LIST)
TREE_VALUE (old_init) = error_mark_node;
initializer-list {}. */
if (!brace_enclosed_p)
{
- error ("initializer for `%T' must be brace-enclosed",
- type);
+ error ("initializer for %qT must be brace-enclosed", type);
return error_mark_node;
}
}
field = lookup_field_1 (type, TREE_PURPOSE (*initp),
/*want_type=*/false);
if (!field || TREE_CODE (field) != FIELD_DECL)
- error ("`%T' has no non-static data member named `%D'",
+ error ("%qT has no non-static data member named %qD",
type, TREE_PURPOSE (*initp));
}
if (!field)
else if (TREE_CODE (type) == ARRAY_TYPE
|| TREE_CODE (type) == VECTOR_TYPE)
{
- tree index;
- tree max_index;
-
- /* If the bound of the array is known, take no more initializers
- than are allowed. */
- max_index = NULL_TREE;
- if (TREE_CODE (type) == ARRAY_TYPE)
- {
- if (TYPE_DOMAIN (type))
- max_index = array_type_nelts (type);
- }
- else
- {
- /* For a vector, the representation type is a struct
- containing a single member which is an array of the
- appropriate size. */
- tree rtype = TYPE_DEBUG_REPRESENTATION_TYPE (type);
- if (rtype && TYPE_DOMAIN (TREE_TYPE (TYPE_FIELDS (rtype))))
- max_index = array_type_nelts (TREE_TYPE (TYPE_FIELDS (rtype)));
- }
-
- /* Loop through the array elements, gathering initializers. */
- for (index = size_zero_node;
- *initp && (!max_index || !tree_int_cst_lt (max_index, index));
- index = size_binop (PLUS_EXPR, index, size_one_node))
- {
- tree element_init;
+ /* If the bound of the array is known, take no more initializers
+ than are allowed. */
+ tree max_index = NULL_TREE;
+ if (TREE_CODE (type) == ARRAY_TYPE)
+ {
+ if (TYPE_DOMAIN (type))
+ max_index = array_type_nelts (type);
+ }
+ else
+ {
+ /* For a vector, the representation type is a struct
+ containing a single member which is an array of the
+ appropriate size. */
+ tree rtype = TYPE_DEBUG_REPRESENTATION_TYPE (type);
+ if (rtype && TYPE_DOMAIN (TREE_TYPE (TYPE_FIELDS (rtype))))
+ max_index = array_type_nelts (TREE_TYPE (TYPE_FIELDS
+ (rtype)));
+ }
- element_init = reshape_init (TREE_TYPE (type), initp);
- if (element_init == error_mark_node)
- return error_mark_node;
- TREE_CHAIN (element_init) = CONSTRUCTOR_ELTS (new_init);
- CONSTRUCTOR_ELTS (new_init) = element_init;
- if (TREE_PURPOSE (element_init))
- {
- tree next_index = TREE_PURPOSE (element_init);
- if (TREE_CODE (next_index) == IDENTIFIER_NODE)
- {
- error ("name `%D' used in a GNU-style designated "
- "initializer for an array", next_index);
- TREE_PURPOSE (element_init) = NULL_TREE;
- }
- else
- index = next_index;
- }
- }
+ if (!reshape_init_array (TREE_TYPE (type), max_index,
+ initp, new_init))
+ return error_mark_node;
}
else
- abort ();
+ gcc_unreachable ();
/* The initializers were placed in reverse order in the
CONSTRUCTOR. */
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 `%T'", 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;
}
else if (init && COMPLETE_TYPE_P (type)
&& !TREE_CONSTANT (TYPE_SIZE (type)))
{
- error ("variable-sized object `%D' may not be initialized", decl);
+ error ("variable-sized object %qD may not be initialized", decl);
init = NULL_TREE;
}
else if (TREE_CODE (type) == ARRAY_TYPE
&& !COMPLETE_TYPE_P (complete_type (TREE_TYPE (type))))
{
- error ("elements of array `%#D' have incomplete type", decl);
+ error ("elements of array %q#D have incomplete type", decl);
init = NULL_TREE;
}
else if (TREE_CODE (type) != ARRAY_TYPE && !COMPLETE_TYPE_P (type))
{
- error ("`%D' has incomplete type", decl);
+ error ("%qD has incomplete type", decl);
TREE_TYPE (decl) = error_mark_node;
init = NULL_TREE;
}
if (TREE_CODE (decl) == CONST_DECL)
{
- my_friendly_assert (TREE_CODE (decl) != REFERENCE_TYPE, 148);
+ gcc_assert (TREE_CODE (decl) != REFERENCE_TYPE);
DECL_INITIAL (decl) = init;
- my_friendly_assert (init != NULL_TREE, 149);
+ gcc_assert (init != NULL_TREE);
init = NULL_TREE;
}
else if (!DECL_EXTERNAL (decl) && TREE_CODE (type) == REFERENCE_TYPE)
{
if (TYPE_NON_AGGREGATE_CLASS (type))
{
- error ("`%D' must be initialized by constructor, not by `{...}'",
+ error ("%qD must be initialized by constructor, "
+ "not by %<{...}%>",
decl);
init = error_mark_node;
}
if (TREE_CODE (init) != TREE_VEC)
{
init_code = store_init_value (decl, init);
+ if (pedantic && TREE_CODE (type) == ARRAY_TYPE
+ && DECL_INITIAL (decl)
+ && TREE_CODE (DECL_INITIAL (decl)) == STRING_CST
+ && PAREN_STRING_LITERAL_P (DECL_INITIAL (decl)))
+ warning ("array %qD initialized by parenthesized string literal %qE",
+ decl, DECL_INITIAL (decl));
init = NULL;
}
}
tree core_type = strip_array_types (type);
if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (core_type))
- error ("structure `%D' with uninitialized const members", decl);
+ error ("structure %qD with uninitialized const members", decl);
if (CLASSTYPE_REF_FIELDS_NEED_INIT (core_type))
- error ("structure `%D' with uninitialized reference members",
- decl);
+ error ("structure %qD with uninitialized reference members", decl);
check_for_uninitialized_const_var (decl);
}
DECL_HARD_REGISTER (decl) = 1;
}
else
- set_user_assembler_name (decl, asmspec);
+ {
+ if (TREE_CODE (decl) == FUNCTION_DECL
+ && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL)
+ set_builtin_user_assembler_name (decl, asmspec);
+ set_user_assembler_name (decl, asmspec);
+ }
}
/* Handle non-variables up front. */
member. */
if (DECL_LANG_SPECIFIC (decl) && DECL_IN_AGGR_P (decl))
{
- my_friendly_assert (TREE_STATIC (decl), 19990828);
+ gcc_assert (TREE_STATIC (decl));
/* An in-class declaration of a static data member should be
external; it is only a declaration, and not a definition. */
if (init == NULL_TREE)
- my_friendly_assert (DECL_EXTERNAL (decl), 20000723);
+ gcc_assert (DECL_EXTERNAL (decl));
}
/* We don't create any RTL for local variables. */
{
/* Fool with the linkage of static consts according to #pragma
interface. */
- if (!interface_unknown && !TREE_PUBLIC (decl))
+ struct c_fileinfo *finfo = get_fileinfo (lbasename (input_filename));
+ if (!finfo->interface_unknown && !TREE_PUBLIC (decl))
{
TREE_PUBLIC (decl) = 1;
- DECL_EXTERNAL (decl) = interface_only;
+ DECL_EXTERNAL (decl) = finfo->interface_only;
}
defer_p = 1;
tree type = TREE_TYPE (decl);
tree cleanup;
- my_friendly_assert (TREE_CODE (decl) == VAR_DECL
- || TREE_CODE (decl) == RESULT_DECL,
- 20021010);
- my_friendly_assert (!TREE_STATIC (decl), 20021010);
+ gcc_assert (TREE_CODE (decl) == VAR_DECL
+ || TREE_CODE (decl) == RESULT_DECL);
+ gcc_assert (!TREE_STATIC (decl));
if (DECL_SIZE (decl) == NULL_TREE)
{
{
int saved_stmts_are_full_exprs_p;
- my_friendly_assert (building_stmt_tree (), 20000906);
+ gcc_assert (building_stmt_tree ());
saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
current_stmt_tree ()->stmts_are_full_exprs_p = 1;
finish_expr_stmt (init);
finish_decl_cleanup (decl, cleanup);
}
+/* DECL is a VAR_DECL for a compiler-generated variable with static
+ storage duration (like a virtual table) whose initializer is a
+ compile-time constant. Initialize the variable and provide it to
+ the back end. */
+
+void
+initialize_artificial_var (tree decl, tree init)
+{
+ DECL_INITIAL (decl) = build_constructor (NULL_TREE, init);
+ DECL_INITIALIZED_P (decl) = 1;
+ determine_visibility (decl);
+ layout_var_decl (decl);
+ maybe_commonize_var (decl);
+ make_rtl_for_nonlocal_decl (decl, init, /*asmspec=*/NULL);
+}
+
/* Finish processing of a declaration;
install its line number and initial value.
If the length of an array type is not known before,
tree cleanup;
const char *asmspec = NULL;
int was_readonly = 0;
+ bool var_definition_p = false;
if (decl == error_mark_node)
return;
return;
}
- my_friendly_assert (TREE_CODE (decl) != RESULT_DECL, 20030619);
+ gcc_assert (TREE_CODE (decl) != RESULT_DECL);
/* Assume no cleanup is required. */
cleanup = NULL_TREE;
if (init && TREE_CODE (init) == NAMESPACE_DECL)
{
- error ("cannot initialize `%D' to namespace `%D'",
- decl, init);
+ error ("cannot initialize %qD to namespace %qD", decl, init);
init = NULL_TREE;
}
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. */
&& !DECL_PRETTY_FUNCTION_P (decl)
&& !dependent_type_p (TREE_TYPE (decl)))
maybe_deduce_size_from_array_init (decl, init);
+
goto finish_end;
}
/* Parameters are handled by store_parm_decls, not cp_finish_decl. */
- my_friendly_assert (TREE_CODE (decl) != PARM_DECL, 19990828);
+ gcc_assert (TREE_CODE (decl) != PARM_DECL);
/* Take care of TYPE_DECLs up front. */
if (TREE_CODE (decl) == TYPE_DECL)
&& IS_AGGR_TYPE (type) && DECL_NAME (decl))
{
if (TREE_TYPE (DECL_NAME (decl)) && TREE_TYPE (decl) != type)
- warning ("shadowing previous type declaration of `%#D'", decl);
+ warning ("shadowing previous type declaration of %q#D", decl);
set_identifier_type_value (DECL_NAME (decl), decl);
}
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)
/* Only PODs can have thread-local storage. Other types may require
various kinds of non-trivial initialization. */
if (DECL_THREAD_LOCAL (decl) && !pod_type_p (TREE_TYPE (decl)))
- error ("`%D' cannot be thread-local because it has non-POD type `%T'",
+ error ("%qD cannot be thread-local because it has non-POD type %qT",
decl, TREE_TYPE (decl));
/* Convert the initializer to the type of DECL, if we have not
already initialized DECL. */
/* Thread-local storage cannot be dynamically initialized. */
if (DECL_THREAD_LOCAL (decl) && init)
{
- error ("`%D' is thread-local and so cannot be dynamically "
+ error ("%qD is thread-local and so cannot be dynamically "
"initialized", decl);
init = NULL_TREE;
}
/* Remember that the initialization for this variable has
taken place. */
DECL_INITIALIZED_P (decl) = 1;
+ /* This declaration is the definition of this variable,
+ unless we are initializing a static data member within
+ the class specifier. */
+ if (!DECL_EXTERNAL (decl))
+ var_definition_p = true;
/* The variable is being defined, so determine its
visibility. */
determine_visibility (decl);
else if (!TREE_STATIC (decl))
initialize_local_var (decl, init);
}
-
- if (TREE_STATIC (decl))
- expand_static_init (decl, init);
- }
+
+ /* If a variable is defined, and then a subsequent
+ definition with external linkage is encountered, we will
+ get here twice for the same variable. We want to avoid
+ calling expand_static_init more than once. For variables
+ that are not static data members, we can call
+ expand_static_init only when we actually process the
+ initializer. It is not legal to redeclare a static data
+ member, so this issue does not arise in that case. */
+ if (var_definition_p && TREE_STATIC (decl))
+ expand_static_init (decl, init);
+ }
}
/* If a CLEANUP_STMT was created to destroy a temporary bound to a
TREE_PUBLIC (decl) = 1;
DECL_EXTERNAL (decl) = 1;
DECL_ARTIFICIAL (decl) = 1;
- pushdecl (decl);
+ /* If the user has explicitly declared this variable (perhaps
+ because the code we are compiling is part of a low-level runtime
+ library), then it is possible that our declaration will be merged
+ with theirs by pushdecl. */
+ decl = pushdecl (decl);
cp_finish_decl (decl, NULL_TREE, NULL_TREE, 0);
pop_from_top_level ();
static tree
start_cleanup_fn (void)
{
- int old_interface_only = interface_only;
- int old_interface_unknown = interface_unknown;
char name[32];
tree parmtypes;
tree fntype;
/* No need to mangle this. */
push_lang_context (lang_name_c);
- interface_only = 0;
- interface_unknown = 1;
-
/* Build the parameter-types. */
parmtypes = void_list_node;
/* Functions passed to __cxa_atexit take an additional parameter.
pushdecl (fndecl);
start_preparsed_function (fndecl, NULL_TREE, SF_PRE_PARSED);
- interface_unknown = old_interface_unknown;
- interface_only = old_interface_only;
-
pop_lang_context ();
return current_function_decl;
/* Generate code to handle the destruction of DECL, an object with
static storage duration. */
-void
+tree
register_dtor_fn (tree decl)
{
tree cleanup;
tree fcall;
if (TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (decl)))
- return;
+ return void_zero_node;
/* Call build_cleanup before we enter the anonymous function so that
any access checks will be done relative to the current scope,
}
else
args = tree_cons (NULL_TREE, cleanup, NULL_TREE);
- finish_expr_stmt (build_function_call (get_atexit_node (), args));
+ return build_function_call (get_atexit_node (), args);
}
/* DECL is a VAR_DECL with static storage duration. INIT, if present,
static void
expand_static_init (tree decl, tree init)
{
- my_friendly_assert (TREE_CODE (decl) == VAR_DECL, 20021010);
- my_friendly_assert (TREE_STATIC (decl), 20021010);
+ gcc_assert (TREE_CODE (decl) == VAR_DECL);
+ gcc_assert (TREE_STATIC (decl));
/* Some variables require no initialization. */
if (!init
&& TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (decl)))
return;
- if (! toplevel_bindings_p ())
+ if (DECL_FUNCTION_SCOPE_P (decl))
{
/* Emit code to perform this initialization but once. */
- tree if_stmt;
- tree then_clause;
- tree assignment;
- tree guard;
- tree guard_init;
+ tree if_stmt = NULL_TREE, inner_if_stmt = NULL_TREE;
+ tree then_clause = NULL_TREE, inner_then_clause = NULL_TREE;
+ tree guard, guard_addr, guard_addr_list;
+ tree acquire_fn, release_fn, abort_fn;
+ tree flag, begin;
/* Emit code to perform this initialization but once. This code
looks like:
- static int guard = 0;
- if (!guard) {
- // Do initialization.
- guard = 1;
- // Register variable for destruction at end of program.
+ static <type> guard;
+ if (!guard.first_byte) {
+ if (__cxa_guard_acquire (&guard)) {
+ bool flag = false;
+ try {
+ // Do initialization.
+ flag = true; __cxa_guard_release (&guard);
+ // Register variable for destruction at end of program.
+ } catch {
+ if (!flag) __cxa_guard_abort (&guard);
+ }
}
- Note that the `temp' variable is only set to 1 *after* the
+ Note that the `flag' variable is only set to 1 *after* the
initialization is complete. This ensures that an exception,
thrown during the construction, will cause the variable to
reinitialized when we pass through this code again, as per:
[stmt.dcl]
- If the initialization exits by throwing an exception, the
+ If the initialization exits by throwing an exception, the
initialization is not complete, so it will be tried again
the next time control enters the declaration.
- In theory, this process should be thread-safe, too; multiple
- threads should not be able to initialize the variable more
- than once. We don't yet attempt to ensure thread-safety. */
+ This process should be thread-safe, too; multiple threads
+ should not be able to initialize the variable more than
+ once. */
/* Create the guard variable. */
guard = get_guard (decl);
- /* Begin the conditional initialization. */
- if_stmt = begin_if_stmt ();
- finish_if_stmt_cond (get_guard_cond (guard), if_stmt);
- then_clause = begin_compound_stmt (0);
-
- /* Do the initialization itself. */
- assignment = init ? init : NULL_TREE;
-
- /* Once the assignment is complete, set TEMP to 1. Since the
- construction of the static object is complete at this point,
- we want to make sure TEMP is set to 1 even if a temporary
- constructed during the initialization throws an exception
- when it is destroyed. So, we combine the initialization and
- the assignment to TEMP into a single expression, ensuring
- that when we call finish_expr_stmt the cleanups will not be
- run until after TEMP is set to 1. */
- guard_init = set_guard (guard);
- if (assignment)
- assignment = build_compound_expr (assignment, guard_init);
+ /* This optimization isn't safe on targets with relaxed memory
+ consistency. On such targets we force synchronization in
+ __cxa_guard_acquire. */
+ if (!targetm.relaxed_ordering || !flag_threadsafe_statics)
+ {
+ /* Begin the conditional initialization. */
+ if_stmt = begin_if_stmt ();
+ finish_if_stmt_cond (get_guard_cond (guard), if_stmt);
+ then_clause = begin_compound_stmt (BCS_NO_SCOPE);
+ }
+
+ if (flag_threadsafe_statics)
+ {
+ guard_addr = build_address (guard);
+ guard_addr_list = build_tree_list (NULL_TREE, guard_addr);
+
+ acquire_fn = get_identifier ("__cxa_guard_acquire");
+ release_fn = get_identifier ("__cxa_guard_release");
+ abort_fn = get_identifier ("__cxa_guard_abort");
+ if (!get_global_value_if_present (acquire_fn, &acquire_fn))
+ {
+ tree argtypes = tree_cons (NULL_TREE, TREE_TYPE (guard_addr),
+ void_list_node);
+ tree vfntype = build_function_type (void_type_node, argtypes);
+ acquire_fn = push_library_fn
+ (acquire_fn, build_function_type (integer_type_node, argtypes));
+ release_fn = push_library_fn (release_fn, vfntype);
+ abort_fn = push_library_fn (abort_fn, vfntype);
+ }
+ else
+ {
+ release_fn = identifier_global_value (release_fn);
+ abort_fn = identifier_global_value (abort_fn);
+ }
+
+ inner_if_stmt = begin_if_stmt ();
+ finish_if_stmt_cond (build_call (acquire_fn, guard_addr_list),
+ inner_if_stmt);
+
+ inner_then_clause = begin_compound_stmt (BCS_NO_SCOPE);
+ begin = get_target_expr (boolean_false_node);
+ flag = TARGET_EXPR_SLOT (begin);
+
+ TARGET_EXPR_CLEANUP (begin)
+ = build (COND_EXPR, void_type_node, flag,
+ void_zero_node,
+ build_call (abort_fn, guard_addr_list));
+ CLEANUP_EH_ONLY (begin) = 1;
+
+ /* Do the initialization itself. */
+ init = add_stmt_to_compound (begin, init);
+ init = add_stmt_to_compound
+ (init, build (MODIFY_EXPR, void_type_node, flag, boolean_true_node));
+ init = add_stmt_to_compound
+ (init, build_call (release_fn, guard_addr_list));
+ }
else
- assignment = guard_init;
- finish_expr_stmt (assignment);
+ init = add_stmt_to_compound (init, set_guard (guard));
/* Use atexit to register a function for destroying this static
variable. */
- register_dtor_fn (decl);
+ init = add_stmt_to_compound (init, register_dtor_fn (decl));
- finish_compound_stmt (then_clause);
- finish_then_clause (if_stmt);
- finish_if_stmt (if_stmt);
+ finish_expr_stmt (init);
+
+ if (flag_threadsafe_statics)
+ {
+ finish_compound_stmt (inner_then_clause);
+ finish_then_clause (inner_if_stmt);
+ finish_if_stmt (inner_if_stmt);
+ }
+
+ if (!targetm.relaxed_ordering || !flag_threadsafe_statics)
+ {
+ finish_compound_stmt (then_clause);
+ finish_then_clause (if_stmt);
+ finish_if_stmt (if_stmt);
+ }
}
else
static_aggregates = tree_cons (init, decl, static_aggregates);
= int_size_in_bytes (TREE_TYPE (TREE_TYPE (initial_value)));
maxindex = build_int_cst (NULL_TREE,
(TREE_STRING_LENGTH (initial_value)
- / eltsize) - 1, 0);
+ / eltsize) - 1);
}
else if (TREE_CODE (initial_value) == CONSTRUCTOR)
{
initial_value = NULL_TREE;
/* Prevent further error messages. */
- maxindex = build_int_cst (NULL_TREE, 0, 0);
+ maxindex = build_int_cst (NULL_TREE, 0);
}
}
if (!maxindex)
{
if (do_default)
- maxindex = build_int_cst (NULL_TREE, 0, 0);
+ maxindex = build_int_cst (NULL_TREE, 0);
value = 2;
}
if (ctype && ctype != cur_type)
{
if (flags == DTOR_FLAG)
- error ("destructor for alien class `%T' cannot be a member",
- ctype);
+ error ("destructor for alien class %qT cannot be a member", ctype);
else
- error ("constructor for alien class `%T' cannot be a member",
- ctype);
+ error ("constructor for alien class %qT cannot be a member", ctype);
return 0;
}
return 1;
int raises)
{
if (virtualp)
- error ("`%D' declared as a `virtual' %s", object, type);
+ error ("%qD declared as a %<virtual%> %s", object, type);
if (inlinep)
- error ("`%D' declared as an `inline' %s", object, type);
+ error ("%qD declared as an %<inline%> %s", object, type);
if (quals)
- error ("`const' and `volatile' function specifiers on `%D' invalid in %s declaration",
- object, type);
+ error ("%<const%> and %<volatile%> function specifiers on "
+ "%qD invalid in %s declaration",
+ object, type);
if (friendp)
- cp_error_at ("`%D' declared as a friend", object);
+ cp_error_at ("%qD declared as a friend", object);
if (raises
&& (TREE_CODE (object) == TYPE_DECL
|| (!TYPE_PTRFN_P (TREE_TYPE (object))
&& !TYPE_REFFN_P (TREE_TYPE (object))
&& !TYPE_PTRMEMFUNC_P (TREE_TYPE (object)))))
- cp_error_at ("`%D' declared with an exception specification", object);
+ cp_error_at ("%qD declared with an exception specification", object);
}
/* CTYPE is class type, or null if non-class.
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)
+ tree in_namespace,
+ tree* attrlist)
{
tree decl;
int staticp = ctype && TREE_CODE (type) == FUNCTION_TYPE;
if (ctype == NULL_TREE && DECL_MAIN_P (decl))
{
if (processing_template_decl)
- error ("cannot declare `::main' to be a template");
+ error ("cannot declare %<::main%> to be a template");
if (inlinep)
- error ("cannot declare `::main' to be inline");
+ error ("cannot declare %<::main%> to be inline");
if (!publicp)
- error ("cannot declare `::main' to be static");
+ error ("cannot declare %<::main%> to be static");
if (!same_type_p (TREE_TYPE (TREE_TYPE (decl)),
integer_type_node))
- error ("`main' must return `int'");
+ {
+ error ("%<::main%> must return %<int%>");
+ TREE_TYPE (TREE_TYPE (decl)) = integer_type_node;
+ }
inlinep = 0;
publicp = 1;
}
/* Allow this; it's pretty common in C. */;
else
{
- pedwarn ("non-local function `%#D' uses anonymous type",
+ pedwarn ("non-local function %q#D uses anonymous type",
decl);
if (DECL_ORIGINAL_TYPE (TYPE_NAME (t)))
- cp_pedwarn_at ("\
-`%#D' does not refer to the unqualified type, so it is not used for linkage",
- TYPE_NAME (t));
+ cp_pedwarn_at ("%q#D does not refer to the unqualified "
+ "type, so it is not used for linkage",
+ TYPE_NAME (t));
}
}
else
- pedwarn ("non-local function `%#D' uses local type `%T'",
- decl, t);
+ pedwarn ("non-local function %q#D uses local type %qT", decl, t);
}
}
DECL_EXTERNAL (decl) = 1;
if (quals && TREE_CODE (type) == FUNCTION_TYPE)
{
- error ("%smember function `%D' cannot have cv-qualifier",
+ error ("%smember function %qD cannot have cv-qualifier",
(ctype ? "static " : "non-"), decl);
quals = TYPE_UNQUALIFIED;
}
{
if (funcdef_flag)
error
- ("defining explicit specialization `%D' in friend declaration",
+ ("defining explicit specialization %qD in friend declaration",
orig_declarator);
else
{
if (PROCESSING_REAL_TEMPLATE_DECL_P ())
{
/* Something like `template <class T> friend void f<T>()'. */
- error ("invalid use of template-id `%D' in declaration of primary template",
- orig_declarator);
+ error ("invalid use of template-id %qD in declaration "
+ "of primary template",
+ orig_declarator);
return NULL_TREE;
}
(see template_id in parse.y). If the current class contains
such a name, we'll get a COMPONENT_REF here. Undo that. */
- my_friendly_assert (TREE_TYPE (TREE_OPERAND (fns, 0))
- == current_class_type, 20001120);
+ gcc_assert (TREE_TYPE (TREE_OPERAND (fns, 0))
+ == current_class_type);
fns = TREE_OPERAND (fns, 1);
}
- my_friendly_assert (TREE_CODE (fns) == IDENTIFIER_NODE
- || TREE_CODE (fns) == OVERLOAD, 20001120);
+ gcc_assert (TREE_CODE (fns) == IDENTIFIER_NODE
+ || TREE_CODE (fns) == OVERLOAD);
DECL_TEMPLATE_INFO (decl) = tree_cons (fns, args, NULL_TREE);
if (has_default_arg)
{
- error ("default arguments are not allowed in declaration of friend template specialization `%D'",
- decl);
+ error ("default arguments are not allowed in declaration "
+ "of friend template specialization %qD",
+ decl);
return NULL_TREE;
}
if (inlinep)
{
- error ("`inline' is not allowed in declaration of friend template specialization `%D'",
- decl);
+ error ("%<inline%> is not allowed in declaration of friend "
+ "template specialization %qD",
+ decl);
return NULL_TREE;
}
}
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,
if (decl == error_mark_node)
return NULL_TREE;
+ if (attrlist)
+ {
+ cplus_decl_attributes (&decl, *attrlist, 0);
+ *attrlist = NULL_TREE;
+ }
+
if (ctype != NULL_TREE
&& (! TYPE_FOR_JAVA (ctype) || check_java_method (decl))
&& check)
(processing_template_decl
> template_class_depth (ctype))
? current_template_parms
- : NULL_TREE);
+ : NULL_TREE);
if (old_decl && TREE_CODE (old_decl) == TEMPLATE_DECL)
/* Because grokfndecl is always supposed to return a
XXX Isn't this done in start_function, too? */
revert_static_member_fn (decl);
if (old_decl && DECL_ARTIFICIAL (old_decl))
- error ("definition of implicitly-declared `%D'", old_decl);
+ error ("definition of implicitly-declared %qD", old_decl);
if (old_decl)
{
tree ok;
- bool pop_p;
+ tree pushed_scope;
/* Since we've smashed OLD_DECL to its
DECL_TEMPLATE_RESULT, we must do the same to DECL. */
/* Attempt to merge the declarations. This can fail, in
the case of some invalid specialization declarations. */
- pop_p = push_scope (ctype);
+ pushed_scope = push_scope (ctype);
ok = duplicate_decls (decl, old_decl);
- if (pop_p)
- pop_scope (ctype);
+ if (pushed_scope)
+ pop_scope (pushed_scope);
if (!ok)
{
- error ("no `%#D' member function declared in class `%T'",
+ error ("no %q#D member function declared in class %qT",
decl, ctype);
return NULL_TREE;
}
TREE_STATIC (decl) = 1;
/* For non-template classes, static data members are always put
out in exactly those files where they are defined, just as
- with ordinarly namespace-scope variables. */
+ with ordinary namespace-scope variables. */
if (!processing_template_decl)
DECL_INTERFACE_KNOWN (decl) = 1;
}
tree scope)
{
tree decl;
+ tree explicit_scope;
- my_friendly_assert (!name || TREE_CODE (name) == IDENTIFIER_NODE,
- 20020808);
+ gcc_assert (!name || TREE_CODE (name) == IDENTIFIER_NODE);
- /* Compute the scope in which to place the variable. */
+ /* Compute the scope in which to place the variable, but remember
+ whether or not that scope was explicitly specified by the user. */
+ explicit_scope = scope;
if (!scope)
{
/* An explicit "extern" specifier indicates a namespace-scope
if (declspecs->storage_class == sc_extern)
scope = current_namespace;
else if (!at_function_scope_p ())
- {
- scope = current_scope ();
- if (!scope)
- scope = current_namespace;
- }
+ scope = current_scope ();
}
if (scope
else
decl = build_decl (VAR_DECL, name, type);
- if (scope && TREE_CODE (scope) == NAMESPACE_DECL)
- set_decl_namespace (decl, scope, 0);
+ if (explicit_scope && TREE_CODE (explicit_scope) == NAMESPACE_DECL)
+ set_decl_namespace (decl, explicit_scope, 0);
else
DECL_CONTEXT (decl) = scope;
declare an entity with linkage.
Only check this for public decls for now. */
- tree t = no_linkage_check (TREE_TYPE (decl),
- /*relaxed_p=*/false);
+ tree t = no_linkage_check (TREE_TYPE (decl), /*relaxed_p=*/false);
if (t)
{
if (TYPE_ANONYMOUS_P (t))
{
if (DECL_EXTERN_C_P (decl))
- /* Allow this; it's pretty common in C. */;
+ /* Allow this; it's pretty common in C. */
+ ;
else
{
- pedwarn ("non-local variable `%#D' uses anonymous type",
+ /* DRs 132, 319 and 389 seem to indicate types with
+ no linkage can only be used to declare extern "C"
+ entities. Since it's not always an error in the
+ ISO C++ 90 Standard, we only issue a warning. */
+ warning ("non-local variable %q#D uses anonymous type",
decl);
if (DECL_ORIGINAL_TYPE (TYPE_NAME (t)))
- cp_pedwarn_at ("\
-`%#D' does not refer to the unqualified type, so it is not used for linkage",
+ cp_warning_at ("%q#D does not refer to the unqualified "
+ "type, so it is not used for linkage",
TYPE_NAME (t));
}
}
else
- pedwarn ("non-local variable `%#D' uses local type `%T'",
- decl, t);
+ warning ("non-local variable %q#D uses local type %qT", decl, t);
}
}
+ else
+ DECL_INTERFACE_KNOWN (decl) = 1;
return decl;
}
}
else
{
- my_friendly_assert (TREE_CODE (member_type) != FUNCTION_TYPE,
- 20030716);
+ gcc_assert (TREE_CODE (member_type) != FUNCTION_TYPE);
return build_offset_type (class_type, member_type);
}
}
required. */
if (!ARITHMETIC_TYPE_P (type) && TREE_CODE (type) != ENUMERAL_TYPE)
{
- error ("invalid in-class initialization of static data member of non-integral type `%T'",
+ error ("invalid in-class initialization of static data member "
+ "of non-integral type %qT",
type);
/* If we just return the declaration, crashes will sometimes
occur. We therefore return void_type_node, as if this were a
return 1;
}
else if (!CP_TYPE_CONST_P (type))
- error ("ISO C++ forbids in-class initialization of non-const static member `%D'",
- decl);
+ error ("ISO C++ forbids in-class initialization of non-const "
+ "static member %qD",
+ decl);
else if (pedantic && !INTEGRAL_TYPE_P (type))
- pedwarn ("ISO C++ forbids initialization of member constant `%D' of non-integral type `%T'", decl, type);
+ pedwarn ("ISO C++ forbids initialization of member constant "
+ "%qD of non-integral type %qT", decl, type);
return 0;
}
if (!dependent_type_p (type) && !INTEGRAL_TYPE_P (type))
{
if (name)
- error ("size of array `%D' has non-integral type `%T'", name, type);
+ error ("size of array %qD has non-integral type %qT", name, type);
else
- error ("size of array has non-integral type `%T'", type);
+ error ("size of array has non-integral type %qT", type);
size = integer_one_node;
type = TREE_TYPE (size);
}
STRIP_TYPE_NOPS (size);
/* It might be a const variable or enumeration constant. */
- size = decl_constant_value (size);
+ size = integral_constant_value (size);
/* Normally, the array-bound will be a constant. */
if (TREE_CODE (size) == INTEGER_CST)
if (INT_CST_LT (size, integer_zero_node))
{
if (name)
- error ("size of array `%D' is negative", name);
+ error ("size of array %qD is negative", name);
else
error ("size of array is negative");
size = integer_one_node;
else if (integer_zerop (size) && pedantic && !in_system_header)
{
if (name)
- pedwarn ("ISO C++ forbids zero-size array `%D'", name);
+ pedwarn ("ISO C++ forbids zero-size array %qD", name);
else
pedwarn ("ISO C++ forbids zero-size array");
}
{
/* `(int) &fn' is not a valid array bound. */
if (name)
- error ("size of array `%D' is not an integral constant-expression",
- name);
+ error ("size of array %qD is not an integral constant-expression",
+ name);
else
error ("size of array is not an integral constant-expression");
}
else if (pedantic)
{
if (name)
- pedwarn ("ISO C++ forbids variable-size array `%D'", name);
+ pedwarn ("ISO C++ forbids variable-size array %qD", name);
else
pedwarn ("ISO C++ forbids variable-size array");
}
itype = build_min (MINUS_EXPR, sizetype, size, integer_one_node);
else
{
+ HOST_WIDE_INT saved_processing_template_decl;
+
/* Compute the index of the largest element in the array. It is
- one less than the number of elements in the array. */
- itype
- = fold (cp_build_binary_op (MINUS_EXPR,
- cp_convert (ssizetype, size),
- cp_convert (ssizetype, integer_one_node)));
+ one less than the number of elements in the array. We save
+ and restore PROCESSING_TEMPLATE_DECL so that computations in
+ cp_build_binary_op will be appropriately folded. */
+ saved_processing_template_decl = processing_template_decl;
+ processing_template_decl = 0;
+ itype = cp_build_binary_op (MINUS_EXPR,
+ cp_convert (ssizetype, size),
+ cp_convert (ssizetype, integer_one_node));
+ itype = fold (itype);
+ processing_template_decl = saved_processing_template_decl;
+
if (!TREE_CONSTANT (itype))
/* A variable sized array. */
itype = variable_size (itype);
/* If the declarator-id is a SCOPE_REF, the scope in which the
declaration occurs is the first operand. */
if (declarator
- && declarator->u.id.name
- && TREE_CODE (declarator->u.id.name) == SCOPE_REF)
- return TREE_OPERAND (declarator->u.id.name, 0);
+ && declarator->u.id.qualifying_scope)
+ return declarator->u.id.qualifying_scope;
- /* Otherwise, the declarator is not a quablified name; the entity will
+ /* Otherwise, the declarator is not a qualified name; the entity will
be declared in the current scope. */
return NULL_TREE;
}
if (error_msg)
{
if (name)
- error ("declaration of `%D' as %s", name, error_msg);
+ error ("declaration of %qD as %s", name, error_msg);
else
error ("creating %s", error_msg);
if (TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type))
{
if (name)
- error ("declaration of `%D' as multidimensional array must have bounds for all dimensions except the first",
- name);
+ error ("declaration of %qD as multidimensional array must "
+ "have bounds for all dimensions except the first",
+ name);
else
- error ("multidimensional array must have bounds for all dimensions except the first");
+ error ("multidimensional array must have bounds for all "
+ "dimensions except the first");
return error_mark_node;
}
if (type)
error ("return type specification for destructor invalid");
/* We can't use the proper return type here because we run into
- problems with abiguous bases and covariant returns.
+ problems with ambiguous bases and covariant returns.
Java classes are left unchanged because (void *) isn't a valid
Java type, and we don't want to change the Java ABI. */
if (targetm.cxx.cdtor_returns_this () && !TYPE_FOR_JAVA (optype))
case sfk_conversion:
if (type && !same_type_p (type, optype))
- error ("operator `%T' declared to return `%T'", optype, type);
+ error ("operator %qT declared to return %qT", optype, type);
else if (type)
- pedwarn ("return type specified for `operator %T'", optype);
+ pedwarn ("return type specified for %<operator %T%>", optype);
type = optype;
break;
default:
- abort ();
- break;
+ gcc_unreachable ();
}
return type;
}
+/* A variable or data member (whose unqualified name is IDENTIFIER)
+ has been declared with the indicated TYPE. If the TYPE is not
+ acceptable, issue an error message and return a type to use for
+ error-recovery purposes. */
+
+tree
+check_var_type (tree identifier, tree type)
+{
+ if (VOID_TYPE_P (type))
+ {
+ if (!identifier)
+ error ("unnamed variable or field declared void");
+ else if (TREE_CODE (identifier) == IDENTIFIER_NODE)
+ {
+ gcc_assert (!IDENTIFIER_OPNAME_P (identifier));
+ error ("variable or field %qE declared void", identifier);
+ }
+ else
+ error ("variable or field declared void");
+ type = integer_type_node;
+ }
+
+ return type;
+}
+
/* Given declspecs and a declarator (abstract or otherwise), determine
the name and type of the object declared and construct a DECL node
for it.
cp_decl_spec ds;
cp_storage_class storage_class;
bool unsigned_p, signed_p, short_p, long_p, thread_p;
+ bool type_was_error_mark_node = false;
signed_p = declspecs->specs[(int)ds_signed];
unsigned_p = declspecs->specs[(int)ds_unsigned];
case cdk_id:
{
- tree decl = id_declarator->u.id.name;
+ tree qualifying_scope = id_declarator->u.id.qualifying_scope;
+ tree decl = id_declarator->u.id.unqualified_name;
if (!decl)
break;
- if (TREE_CODE (decl) == SCOPE_REF)
+ if (qualifying_scope)
{
- tree qualifying_scope = TREE_OPERAND (decl, 0);
-;
- /* It is valid to write:
-
- class C { void f(); };
- typedef C D;
- void D::f();
-
- The standard is not clear about whether `typedef const C D' is
- legal; as of 2002-09-15 the committee is considering
- that question. EDG 3.0 allows that syntax.
- Therefore, we do as well. */
- if (qualifying_scope && TYPE_P (qualifying_scope))
+ if (TYPE_P (qualifying_scope))
{
- ctype = TYPE_MAIN_VARIANT (qualifying_scope);
+ ctype = qualifying_scope;
if (innermost_code != cdk_function
&& current_class_type
&& !UNIQUELY_DERIVED_FROM_P (ctype,
current_class_type))
{
- error ("type `%T' is not derived from type `%T'",
+ error ("type %qT is not derived from type %qT",
ctype, current_class_type);
- ctype = NULL_TREE;
+ return error_mark_node;
}
- TREE_OPERAND (decl, 0) = ctype;
}
else if (TREE_CODE (qualifying_scope) == NAMESPACE_DECL)
in_namespace = qualifying_scope;
- decl = TREE_OPERAND (decl, 1);
}
if (TREE_CODE (decl) == BASELINK)
decl = BASELINK_FUNCTIONS (decl);
{
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;
dname = TREE_OPERAND (dname, 1);
if (TREE_CODE (dname) != IDENTIFIER_NODE)
{
- my_friendly_assert (is_overloaded_fn (dname),
- 19990331);
+ gcc_assert (is_overloaded_fn (dname));
dname = DECL_NAME (get_first_fn (dname));
}
}
if (C_IS_RESERVED_WORD (dname))
{
- error ("declarator-id missing; using reserved word `%D'",
+ error ("declarator-id missing; using reserved word %qD",
dname);
name = IDENTIFIER_POINTER (dname);
}
name = IDENTIFIER_POINTER (dname);
else
{
- my_friendly_assert (flags == NO_SPECIAL, 154);
+ gcc_assert (flags == NO_SPECIAL);
flags = TYPENAME_FLAG;
ctor_return_type = TREE_TYPE (dname);
sfk = sfk_conversion;
break;
default:
- abort ();
+ gcc_unreachable ();
}
break;
break;
default:
- abort ();
+ gcc_unreachable ();
}
}
if (id_declarator->kind == cdk_id)
&& innermost_code != cdk_function
&& ! (ctype && !declspecs->any_specifiers_p))
{
- error ("declaration of `%D' as non-function", dname);
- return void_type_node;
+ error ("declaration of %qD as non-function", dname);
+ return error_mark_node;
}
/* Anything declared one level down from the top level
/* If there were multiple types specified in the decl-specifier-seq,
issue an error message. */
if (declspecs->multiple_types_p)
- error ("two or more data types in declaration of `%s'", name);
+ error ("two or more data types in declaration of %qs", name);
/* Extract the basic type from the decl-specifier-seq. */
type = declspecs->type;
if (type == error_mark_node)
- type = NULL_TREE;
+ {
+ type = NULL_TREE;
+ type_was_error_mark_node = true;
+ }
/* If the entire declaration is itself tagged as deprecated then
suppress reports of deprecated items. */
if (type && TREE_DEPRECATED (type)
if (ds == ds_long)
{
if (count > 2)
- error ("`long long long' is too long for GCC");
+ error ("%<long long long%> is too long for GCC");
else if (pedantic && !in_system_header && warn_long_long)
- pedwarn ("ISO C++ does not support `long long'");
+ pedwarn ("ISO C++ does not support %<long long%>");
else
longlong = 1;
}
"__complex",
"__thread"
};
- error ("duplicate `%s'", decl_spec_names[(int)ds]);
+ error ("duplicate %qs", decl_spec_names[(int)ds]);
}
}
&& in_namespace == NULL_TREE
&& current_namespace == global_namespace);
- if (in_system_header || flag_ms_extensions)
+ if (type_was_error_mark_node)
+ /* We've already issued an error, don't complain more. */;
+ else if (in_system_header || flag_ms_extensions)
/* Allow it, sigh. */;
else if (pedantic || ! is_main)
- pedwarn ("ISO C++ forbids declaration of `%s' with no type",
- name);
+ pedwarn ("ISO C++ forbids declaration of %qs with no type", name);
else if (warn_return_type)
- warning ("ISO C++ forbids declaration of `%s' with no type",
- name);
+ warning ("ISO C++ forbids declaration of %qs with no type", name);
type = integer_type_node;
}
int ok = 0;
if (TREE_CODE (type) == REAL_TYPE)
- error ("short, signed or unsigned invalid for `%s'", name);
+ error ("short, signed or unsigned invalid for %qs", name);
else if (TREE_CODE (type) != INTEGER_TYPE)
- error ("long, short, signed or unsigned invalid for `%s'", name);
+ error ("long, short, signed or unsigned invalid for %qs", name);
else if (long_p && short_p)
- error ("long and short specified together for `%s'", name);
+ error ("long and short specified together for %qs", name);
else if ((long_p || short_p) && explicit_char)
- error ("long or short specified with char for `%s'", name);
+ error ("long or short specified with char for %qs", name);
else if ((long_p|| short_p) && TREE_CODE (type) == REAL_TYPE)
- error ("long or short specified with floating type for `%s'", name);
+ error ("long or short specified with floating type for %qs", name);
else if (signed_p && unsigned_p)
- error ("signed and unsigned given together for `%s'", name);
+ error ("signed and unsigned given together for %qs", name);
else
{
ok = 1;
if (!explicit_int && !defaulted_int && !explicit_char && pedantic)
{
- pedwarn ("long, short, signed or unsigned used invalidly for `%s'",
+ pedwarn ("long, short, signed or unsigned used invalidly for %qs",
name);
if (flag_pedantic_errors)
ok = 0;
if (declspecs->specs[(int)ds_complex])
{
if (TREE_CODE (type) != INTEGER_TYPE && TREE_CODE (type) != REAL_TYPE)
- error ("complex invalid for `%s'", name);
+ error ("complex invalid for %qs", 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
if (declspecs->specs[(int)ds_restrict])
type_quals |= TYPE_QUAL_RESTRICT;
if (sfk == sfk_conversion && type_quals != TYPE_UNQUALIFIED)
- error ("qualifiers are not allowed on declaration of `operator %T'",
- ctor_return_type);
+ 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)
if (virtualp && staticp == 2)
{
- error ("member `%D' cannot be declared both virtual and static",
- dname);
+ error ("member %qD cannot be declared both virtual and static", dname);
staticp = 0;
}
friendp = !! declspecs->specs[(int)ds_friend];
if (dependant_name && !friendp)
{
- error ("`%T::%D' is not a valid declarator", ctype, dependant_name);
+ error ("%<%T::%D%> is not a valid declarator", ctype, dependant_name);
return void_type_node;
}
/* 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);
+ error ("multiple storage classes in declaration of %qs", 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);
+ error ("multiple storage classes in declaration of %qs", name);
thread_p = false;
}
else if (decl_context != NORMAL
{
/* Avoid trying to get an operand off an identifier node. */
if (declarator->kind != cdk_id)
- tmp = declarator->declarator->u.id.name;
+ tmp = declarator->declarator->u.id.unqualified_name;
else
- tmp = declarator->u.id.name;
+ tmp = declarator->u.id.unqualified_name;
op = IDENTIFIER_OPNAME_P (tmp);
if (IDENTIFIER_TYPENAME_P (tmp))
{
name = "<invalid operator>";
}
}
- error ("storage class specified for %s `%s'",
+ error ("storage class specified for %s %qs",
op ? "member operator" : "field",
name);
}
else
{
if (decl_context == PARM || decl_context == CATCHPARM)
- error ("storage class specified for parameter `%s'", name);
+ error ("storage class specified for parameter %qs", name);
else
error ("storage class specified for typename");
}
/* It's common practice (and completely valid) to have a const
be initialized and declared extern. */
if (!(type_quals & TYPE_QUAL_CONST))
- warning ("`%s' initialized and declared `extern'", name);
+ warning ("%qs initialized and declared %<extern%>", name);
}
else
- error ("`%s' has both `extern' and initializer", name);
+ error ("%qs has both %<extern%> and initializer", name);
}
else if (storage_class == sc_extern && funcdef_flag
&& ! toplevel_bindings_p ())
- error ("nested function `%s' declared `extern'", name);
+ error ("nested function %qs declared %<extern%>", name);
else if (toplevel_bindings_p ())
{
if (storage_class == sc_auto)
- error ("top-level declaration of `%s' specifies `auto'", name);
+ error ("top-level declaration of %qs specifies %<auto%>", name);
}
else if (thread_p
&& storage_class != sc_extern
&& storage_class != sc_static)
{
- error ("function-scope `%s' implicitly auto and declared `__thread'",
+ error ("function-scope %qs implicitly auto and declared %<__thread%>",
name);
thread_p = false;
}
unqualified_id = NULL_TREE;
else
{
- unqualified_id = id_declarator->u.id.name;
- if (TREE_CODE (unqualified_id) == SCOPE_REF)
- unqualified_id = TREE_OPERAND (unqualified_id, 1);
+ unqualified_id = id_declarator->u.id.unqualified_name;
if (TREE_CODE (unqualified_id) == BASELINK)
unqualified_id = BASELINK_FUNCTIONS (unqualified_id);
switch (TREE_CODE (unqualified_id))
break;
default:
- abort ();
+ gcc_unreachable ();
}
}
case cdk_array:
type = create_array_type_for_decl (dname, type,
declarator->u.array.bounds);
- if (inner_declarator
- && (inner_declarator->kind == cdk_pointer
- || inner_declarator->kind == cdk_reference
- || inner_declarator->kind == cdk_ptrmem))
- /* We can never complete an array type which is the
- target of a pointer, so go ahead and lay it out. */
- layout_type (type);
break;
case cdk_function:
if (TREE_CODE (type) == FUNCTION_TYPE)
{
- error ("`%s' declared as function returning a function", name);
+ error ("%qs declared as function returning a function", name);
type = integer_type_node;
}
if (TREE_CODE (type) == ARRAY_TYPE)
{
- error ("`%s' declared as function returning an array", name);
+ error ("%qs declared as function returning an array", name);
type = integer_type_node;
}
else if (friendp)
{
if (initialized)
- error ("can't initialize friend function `%s'", name);
+ error ("can't initialize friend function %qs", name);
if (virtualp)
{
/* Cannot be both friend and virtual. */
if (decl_context == NORMAL)
error ("friend declaration not in class definition");
if (current_function_decl && funcdef_flag)
- error ("can't define friend function `%s' in a local class definition",
- name);
+ error ("can't define friend function %qs in a local "
+ "class definition",
+ name);
}
arg_types = grokparms (declarator->u.function.parameters,
}
type = build_function_type (type, arg_types);
+ type = cp_build_qualified_type (type, quals);
}
break;
if (TREE_CODE (type) == REFERENCE_TYPE)
{
error (declarator->kind == cdk_reference
- ? "cannot declare reference to `%#T'"
- : "cannot declare pointer to `%#T'", type);
+ ? "cannot declare reference to %q#T"
+ : "cannot declare pointer to %q#T", type);
type = TREE_TYPE (type);
}
else if (VOID_TYPE_P (type))
{
if (declarator->kind == cdk_reference)
- error ("cannot declare reference to `%#T'", type);
+ error ("cannot declare reference to %q#T", type);
else if (declarator->kind == cdk_ptrmem)
- error ("cannot declare pointer to `%#T' member", type);
+ error ("cannot declare pointer to %q#T member", type);
}
/* We now know that the TYPE_QUALS don't apply to the decl,
&& (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);
else if (TREE_CODE (type) == METHOD_TYPE)
type = build_ptrmemfunc_type (build_pointer_type (type));
else if (declarator->kind == cdk_ptrmem)
- type = build_ptrmem_type (declarator->u.pointer.class_type,
- type);
+ {
+ /* 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)
+ /* We will already have complained. */
+ type = error_mark_node;
+ else
+ type = build_ptrmem_type (declarator->u.pointer.class_type,
+ type);
+ }
else
type = build_pointer_type (type);
break;
default:
- abort ();
+ gcc_unreachable ();
}
}
&& TREE_CODE (type) != FUNCTION_TYPE
&& TREE_CODE (type) != METHOD_TYPE)
{
- error ("template-id `%D' used as a declarator",
+ error ("template-id %qD used as a declarator",
unqualified_id);
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 (declarator
- && TREE_CODE (declarator->u.id.name) == SCOPE_REF
- /* If the qualifying scope was invalid, it will have been set to
- NULL_TREE above. */
- && TREE_OPERAND (declarator->u.id.name, 0)
- && TYPE_P (TREE_OPERAND (declarator->u.id.name, 0)))
+ && declarator->u.id.qualifying_scope
+ && TYPE_P (declarator->u.id.qualifying_scope))
{
tree t;
- ctype = TREE_OPERAND (declarator->u.id.name, 0);
- if (TYPE_P (ctype))
- ctype = TYPE_MAIN_VARIANT (ctype);
+ ctype = declarator->u.id.qualifying_scope;
+ ctype = TYPE_MAIN_VARIANT (ctype);
t = ctype;
while (t != NULL_TREE && CLASS_TYPE_P (t))
{
Is this ill-formed? */
if (pedantic)
- pedwarn ("extra qualification `%T::' on member `%s' ignored",
+ pedwarn ("extra qualification %<%T::%> on member %qs ignored",
ctype, name);
}
else if (TREE_CODE (type) == FUNCTION_TYPE)
{
- tree sname = TREE_OPERAND (declarator->u.id.name, 1);
+ tree sname = declarator->u.id.unqualified_name;
if (TREE_CODE (sname) == IDENTIFIER_NODE
&& NEW_DELETE_OPNAME_P (sname))
TYPE_ARG_TYPES (type));
else
{
- error ("cannot declare member function `%T::%s' within `%T'",
+ error ("cannot declare member function %<%T::%s%> within %<%T%>",
ctype, name, current_class_type);
return error_mark_node;
}
if (current_class_type)
{
- error ("cannot declare member `%T::%s' within `%T'",
+ error ("cannot declare member %<%T::%s%> within %qT",
ctype, name, current_class_type);
return void_type_node;
}
&& COMPLETE_TYPE_P (type)
&& TREE_OVERFLOW (TYPE_SIZE (type)))
{
- error ("size of array `%s' is too large", name);
+ error ("size of array %qs is too large", name);
/* If we proceed with the array type as it is, we'll eventually
crash in tree_low_cst(). */
type = error_mark_node;
&& variably_modified_type_p (type, NULL_TREE))
{
if (decl_context == FIELD)
- error ("data member may not have variably modified type `%T'", type);
+ error ("data member may not have variably modified type %qT", type);
else
- error ("parameter may not have variably modified type `%T'", type);
+ error ("parameter may not have variably modified type %qT", type);
type = error_mark_node;
}
{
/* [dcl.fct.spec] The explicit specifier shall only be used in
declarations of constructors within a class definition. */
- error ("only declarations of constructors can be `explicit'");
+ error ("only declarations of constructors can be %<explicit%>");
explicitp = 0;
}
{
if (decl_context != FIELD || friendp)
{
- error ("non-member `%s' cannot be declared `mutable'", name);
+ error ("non-member %qs 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);
+ error ("non-object member %qs 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);
+ error ("function %qs cannot be declared %<mutable%>", name);
storage_class = sc_none;
}
else if (staticp)
{
- error ("static `%s' cannot be declared `mutable'", name);
+ error ("static %qs cannot be declared %<mutable%>", name);
storage_class = sc_none;
}
else if (type_quals & TYPE_QUAL_CONST)
{
- error ("const `%s' cannot be declared `mutable'", name);
+ error ("const %qs cannot be declared %<mutable%>", name);
storage_class = sc_none;
}
}
TYPE_FOR_JAVA (type) = 1;
if (decl_context == FIELD)
- {
- if (constructor_name_p (unqualified_id, current_class_type))
- pedwarn ("ISO C++ forbids nested type `%D' 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)
+ || (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P
+ (current_function_decl)))
+ /* The TYPE_DECL is "abstract" because there will be
+ clones of this constructor/destructor, and there will
+ be copies of this TYPE_DECL generated in those
+ 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.
tree t;
/* Replace the anonymous name with the real name everywhere. */
- lookup_tag_reverse (type, unqualified_id);
for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
if (TYPE_NAME (t) == oldname)
TYPE_NAME (t) = decl;
{
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),
}
if (inlinep)
{
- error ("`inline' specified for friend class declaration");
+ error ("%<inline%> specified for friend class declaration");
inlinep = 0;
}
pedwarn ("template parameters cannot be friends");
else if (TREE_CODE (type) == TYPENAME_TYPE)
pedwarn ("friend declaration requires class-key, "
- "i.e. `friend class %T::%D'",
+ "i.e. %<friend class %T::%D%>",
TYPE_CONTEXT (type), TYPENAME_TYPE_FULLNAME (type));
else
pedwarn ("friend declaration requires class-key, "
- "i.e. `friend %#T'",
+ "i.e. %<friend %#T%>",
type);
}
make_friend_class (current_class_type, TYPE_MAIN_VARIANT (type),
/*complain=*/true);
else
- error ("trying to make class `%T' a friend of global scope",
- type);
+ error ("trying to make class %qT a friend of global scope",
+ type);
type = void_type_node;
}
&& TREE_CODE (type) != UNION_TYPE
&& ! bitfield)
{
- error ("abstract declarator `%T' used as declaration", type);
- unqualified_id = make_anon_name ();
+ error ("abstract declarator %qT used as declaration", type);
+ return error_mark_node;
}
- /* `void' at top level (not within pointer)
- is allowed only in typedefs or type names.
- We don't complain about parms either, but that is because
- a better error message can be made later. */
-
- if (TREE_CODE (type) == VOID_TYPE && decl_context != PARM)
+ /* Only functions may be declared using an operator-function-id. */
+ if (unqualified_id
+ && IDENTIFIER_OPNAME_P (unqualified_id)
+ && TREE_CODE (type) != FUNCTION_TYPE
+ && TREE_CODE (type) != METHOD_TYPE)
{
- if (! unqualified_id)
- error ("unnamed variable or field declared void");
- else if (TREE_CODE (unqualified_id) == IDENTIFIER_NODE)
- {
- if (IDENTIFIER_OPNAME_P (unqualified_id))
- abort ();
- else
- error ("variable or field `%s' declared void", name);
- }
- else
- error ("variable or field declared void");
- type = integer_type_node;
+ error ("declaration of %qD as non-function", unqualified_id);
+ return error_mark_node;
}
+ /* We don't check parameter types here because we can emit a better
+ error message later. */
+ if (decl_context != PARM)
+ type = check_var_type (unqualified_id, type);
+
/* Now create the decl, which may be a VAR_DECL, a PARM_DECL
or a FUNCTION_DECL, depending on DECL_CONTEXT and TYPE. */
if (decl_context == PARM || decl_context == CATCHPARM)
{
if (ctype || in_namespace)
- error ("cannot use `::' in parameter declaration");
+ error ("cannot use %<::%> in parameter declaration");
/* A parameter declared as an array of T is really a pointer to T.
One declared as a function is really a pointer to a function.
else if (in_namespace && !friendp)
{
/* Something like struct S { int N::j; }; */
- error ("invalid use of `::'");
+ error ("invalid use of %<::%>");
decl = NULL_TREE;
}
else if (TREE_CODE (type) == FUNCTION_TYPE)
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 `%D' cannot be declared friend",
- unqualified_id);
- friendp = 0;
- }
-
if (friendp == 0)
{
if (ctype == NULL_TREE)
if (ctype == NULL_TREE)
{
- error ("can't make `%D' into a method -- not in a class",
+ error ("can't make %qD into a method -- not in a class",
unqualified_id);
return void_type_node;
}
ARM 9.5 */
if (virtualp && TREE_CODE (ctype) == UNION_TYPE)
{
- error ("function `%D' declared virtual inside a union",
+ error ("function %qD declared virtual inside a union",
unqualified_id);
return void_type_node;
}
{
if (virtualp)
{
- error ("`%D' cannot be declared virtual, since it is always static",
+ error ("%qD cannot be declared virtual, since it "
+ "is always static",
unqualified_id);
virtualp = 0;
}
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,
- funcdef_flag, template_count, in_namespace);
+ sfk,
+ funcdef_flag, template_count, in_namespace, attrlist);
if (decl == NULL_TREE)
return decl;
#if 0
parms,
unqualified_id,
virtualp, flags, quals, raises,
- friendp ? -1 : 0, friendp, 1, 0, funcdef_flag,
- template_count, in_namespace);
+ friendp ? -1 : 0, friendp, 1, 0, sfk,
+ funcdef_flag, template_count, in_namespace,
+ attrlist);
if (decl == NULL_TREE)
return NULL_TREE;
}
&& (TREE_CODE (type) != ARRAY_TYPE || initialized == 0))
{
if (unqualified_id)
- error ("field `%D' has incomplete type", unqualified_id);
+ error ("field %qD has incomplete type", unqualified_id);
else
- error ("name `%T' has incomplete type", type);
+ error ("name %qT has incomplete type", type);
/* If we're instantiating a template, tell them which
instantiation made the field's type be incomplete. */
&& IDENTIFIER_TEMPLATE (TYPE_IDENTIFIER (current_class_type))
&& declspecs->type
&& declspecs->type == type)
- error (" in instantiation of template `%T'",
- current_class_type);
+ error (" in instantiation of template %qT",
+ current_class_type);
type = error_mark_node;
decl = NULL_TREE;
{
if (friendp)
{
- error ("`%E' is neither function nor member function; "
+ error ("%qE is neither function nor member function; "
"cannot be declared friend", unqualified_id);
friendp = 0;
}
the rest of the compiler does not correctly
handle the initialization unless the member is
static so we make it static below. */
- pedwarn ("ISO C++ forbids initialization of member `%D'",
+ pedwarn ("ISO C++ forbids initialization of member %qD",
unqualified_id);
- pedwarn ("making `%D' static", unqualified_id);
+ pedwarn ("making %qD static", unqualified_id);
staticp = 1;
}
original_name = unqualified_id;
if (storage_class == sc_auto)
- error ("storage class `auto' invalid for function `%s'", name);
+ error ("storage class %<auto%> invalid for function %qs", name);
else if (storage_class == sc_register)
- error ("storage class `register' invalid for function `%s'", name);
+ error ("storage class %<register%> invalid for function %qs", name);
else if (thread_p)
- error ("storage class `__thread' invalid for function `%s'", name);
+ error ("storage class %<__thread%> invalid for function %qs", name);
/* Function declaration not at top level.
Storage classes other than `extern' are not allowed
&& pedantic)
{
if (storage_class == sc_static)
- pedwarn ("`static' specified invalid for function `%s' declared out of global scope", name);
+ pedwarn ("%<static%> specified invalid for function %qs "
+ "declared out of global scope", name);
else
- pedwarn ("`inline' specifier invalid for function `%s' declared out of global scope", name);
+ pedwarn ("%<inline%> specifier invalid for function %qs "
+ "declared out of global scope", name);
}
if (ctype == NULL_TREE)
{
if (virtualp)
{
- error ("virtual non-class function `%s'", name);
+ error ("virtual non-class function %qs", name);
virtualp = 0;
}
}
decl = grokfndecl (ctype, type, original_name, parms, unqualified_id,
virtualp, flags, quals, raises,
1, friendp,
- publicp, inlinep, funcdef_flag,
- template_count, in_namespace);
+ publicp, inlinep, sfk, funcdef_flag,
+ template_count, in_namespace, attrlist);
if (decl == NULL_TREE)
return NULL_TREE;
declaring main to be static. */
if (TREE_CODE (type) == METHOD_TYPE)
{
- pedwarn ("cannot declare member function `%D' to have static linkage", decl);
+ pedwarn ("cannot declare member function %qD to have "
+ "static linkage", decl);
invalid_static = 1;
}
else if (current_function_decl)
DECL_CONTEXT (decl) = ctype;
if (staticp == 1)
{
- pedwarn ("`static' may not be used when defining (as opposed to declaring) a static data member");
+ 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);
+ error ("static member %qD declared %<register%>", decl);
storage_class = sc_none;
}
if (storage_class == sc_extern && pedantic)
{
- pedwarn ("cannot explicitly declare member `%#D' to have extern linkage",
- decl);
+ pedwarn ("cannot explicitly declare member %q#D to have "
+ "extern linkage",
+ decl);
storage_class = sc_none;
}
}
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;
}
{
for (; parms; parms = TREE_CHAIN (parms))
{
+ 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;
|| !can_convert_arg (decl_type, TREE_TYPE (arg), arg))
{
if (decl)
- error ("default argument for `%#D' has type `%T'",
- decl, TREE_TYPE (arg));
+ error ("default argument for %q#D has type %qT",
+ decl, TREE_TYPE (arg));
else
- error ("default argument for parameter of type `%T' has type `%T'",
- decl_type, TREE_TYPE (arg));
+ error ("default argument for parameter of type %qT has type %qT",
+ decl_type, TREE_TYPE (arg));
return error_mark_node;
}
NULL);
if (var)
{
- error ("default argument `%E' uses local variable `%D'",
- arg, var);
+ error ("default argument %qE uses local variable %qD", arg, var);
return error_mark_node;
}
type = cp_build_qualified_type (type, 0);
if (TREE_CODE (type) == METHOD_TYPE)
{
- error ("parameter `%D' invalidly declared method type", decl);
+ error ("parameter %qD invalidly declared method type", decl);
type = build_pointer_type (type);
TREE_TYPE (decl) = type;
}
t = TREE_TYPE (t);
}
if (TREE_CODE (t) == ARRAY_TYPE)
- error ("parameter `%D' includes %s to array of unknown bound `%T'",
- decl, ptr ? "pointer" : "reference", t);
+ error ("parameter %qD includes %s to array of unknown "
+ "bound %qT",
+ decl, ptr ? "pointer" : "reference", t);
}
if (!any_error && init)
tree arg_type;
int result = 1;
- my_friendly_assert (DECL_FUNCTION_MEMBER_P (d), 20011208);
+ gcc_assert (DECL_FUNCTION_MEMBER_P (d));
- if (DECL_TEMPLATE_INFO (d) && is_member_template (DECL_TI_TEMPLATE (d)))
+ if (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
or implicitly defined), there's no need to worry about their
existence. Theoretically, they should never even be
instantiated, but that's hard to forestall. */
- error ("invalid constructor; you probably meant `%T (const %T&)'",
+ error ("invalid constructor; you probably meant %<%T (const %T&)%>",
ctype, ctype);
return 0;
}
#include "operators.def"
#undef DEF_OPERATOR
- abort ();
+ gcc_unreachable ();
}
while (0);
- my_friendly_assert (operator_code != LAST_CPLUS_TREE_CODE, 20000526);
+ gcc_assert (operator_code != LAST_CPLUS_TREE_CODE);
SET_OVERLOADED_OPERATOR_CODE (decl, operator_code);
if (! friendp)
if (DECL_NAMESPACE_SCOPE_P (decl))
{
if (CP_DECL_CONTEXT (decl) != global_namespace)
- error ("`%D' may not be declared within a namespace", decl);
+ error ("%qD may not be declared within a namespace", decl);
else if (!TREE_PUBLIC (decl))
- error ("`%D' may not be declared as static", decl);
+ error ("%qD may not be declared as static", decl);
}
}
|| operator_code == COMPONENT_REF
|| operator_code == ARRAY_REF
|| operator_code == NOP_EXPR)
- error ("`%D' must be a nonstatic member function", decl);
+ error ("%qD must be a nonstatic member function", decl);
else
{
tree p;
if (DECL_STATIC_FUNCTION_P (decl))
- error ("`%D' must be either a non-static member function or a non-member function", decl);
+ error ("%qD must be either a non-static member "
+ "function or a non-member function", decl);
for (p = argtypes; p && p != void_list_node; p = TREE_CHAIN (p))
{
if (!complain)
return false;
- error ("`%D' must have an argument of class or "
+ error ("%qD must have an argument of class or "
"enumerated type",
decl);
ok = false;
what = "a base class";
if (what && warn_conversion)
- warning ("conversion to %s%s will never use a type conversion operator",
+ warning ("conversion to %s%s will never use a type "
+ "conversion operator",
ref ? "a reference to " : "", what);
}
}
break;
default:
- abort ();
+ gcc_unreachable ();
}
SET_OVERLOADED_OPERATOR_CODE (decl, operator_code);
&& ! same_type_p (TREE_VALUE (TREE_CHAIN (argtypes)), integer_type_node))
{
if (methodp)
- error ("postfix `%D' must take `int' as its argument",
+ error ("postfix %qD must take %<int%> as its argument",
decl);
else
error
- ("postfix `%D' must take `int' as its second argument",
+ ("postfix %qD must take %<int%> as its second argument",
decl);
}
}
else
{
if (methodp)
- error ("`%D' must take either zero or one argument", decl);
+ error ("%qD must take either zero or one argument", decl);
else
- error ("`%D' must take either one or two arguments", decl);
+ error ("%qD must take either one or two arguments", decl);
}
/* More Effective C++ rule 6. */
if (TREE_CODE (ret) != REFERENCE_TYPE
|| !same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (ret)),
arg))
- warning ("prefix `%D' should return `%T'", decl,
- build_reference_type (arg));
+ warning ("prefix %qD should return %qT", decl,
+ build_reference_type (arg));
}
else
{
if (!same_type_p (TYPE_MAIN_VARIANT (ret), arg))
- warning ("postfix `%D' should return `%T'", decl, arg);
+ warning ("postfix %qD should return %qT", decl, arg);
}
}
}
if (arity != 1)
{
if (methodp)
- error ("`%D' must take `void'", decl);
+ error ("%qD must take %<void%>", decl);
else
- error ("`%D' must take exactly one argument", decl);
+ error ("%qD must take exactly one argument", decl);
}
}
else /* if (binary_op_p (operator_code)) */
if (arity != 2)
{
if (methodp)
- error ("`%D' must take exactly one argument", decl);
+ error ("%qD must take exactly one argument", decl);
else
- error ("`%D' must take exactly two arguments", decl);
+ error ("%qD must take exactly two arguments", decl);
}
/* More Effective C++ rule 7. */
&& (operator_code == TRUTH_ANDIF_EXPR
|| operator_code == TRUTH_ORIF_EXPR
|| operator_code == COMPOUND_EXPR))
- warning ("user-defined `%D' always evaluates both arguments",
- decl);
+ warning ("user-defined %qD always evaluates both arguments",
+ decl);
}
/* Effective C++ rule 23. */
|| operator_code == MULT_EXPR
|| operator_code == TRUNC_MOD_EXPR)
&& TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) == REFERENCE_TYPE)
- warning ("`%D' should return by value", decl);
+ warning ("%qD should return by value", decl);
/* [over.oper]/8 */
for (; argtypes && argtypes != void_list_node;
|| operator_code == POSTDECREMENT_EXPR)
{
if (pedantic)
- pedwarn ("`%D' cannot have default arguments", decl);
+ pedwarn ("%qD cannot have default arguments", decl);
}
else
- error ("`%D' cannot have default arguments", decl);
+ error ("%qD cannot have default arguments", decl);
}
}
return ok;
}
\f
+/* Return a string giving the keyword associate with CODE. */
+
static const char *
tag_name (enum tag_types code)
{
case class_type:
return "class";
case union_type:
- return "union ";
+ return "union";
case enum_type:
return "enum";
+ case typename_type:
+ return "typename";
default:
- abort ();
+ gcc_unreachable ();
}
}
type = TREE_TYPE (decl);
+ /* Check TEMPLATE_TYPE_PARM first because DECL_IMPLICIT_TYPEDEF_P
+ is false for this case as well. */
+ if (TREE_CODE (type) == TEMPLATE_TYPE_PARM)
+ {
+ error ("using template type parameter %qT after %qs",
+ type, tag_name (tag_code));
+ return error_mark_node;
+ }
/* [dcl.type.elab]
If the identifier resolves to a typedef-name or a template
In other words, the only legitimate declaration to use in the
elaborated type specifier is the implicit typedef created when
the type is declared. */
- if (!DECL_IMPLICIT_TYPEDEF_P (decl))
- {
- error ("using typedef-name `%D' after `%s'", decl, tag_name (tag_code));
- return IS_AGGR_TYPE (type) ? type : error_mark_node;
- }
-
- if (TREE_CODE (type) == TEMPLATE_TYPE_PARM)
+ else if (!DECL_IMPLICIT_TYPEDEF_P (decl)
+ && tag_code != typename_type)
{
- error ("using template type parameter `%T' after `%s'",
- type, tag_name (tag_code));
+ error ("using typedef-name %qD after %qs", decl, tag_name (tag_code));
+ cp_error_at ("%qD has a previous declaration here", decl);
return error_mark_node;
}
else if (TREE_CODE (type) != RECORD_TYPE
&& TREE_CODE (type) != UNION_TYPE
- && tag_code != enum_type)
+ && tag_code != enum_type
+ && tag_code != typename_type)
{
- error ("`%T' referred to as `%s'", type, tag_name (tag_code));
+ error ("%qT referred to as %qs", type, tag_name (tag_code));
+ cp_error_at ("%qT has a previous declaration here", type);
return error_mark_node;
}
else if (TREE_CODE (type) != ENUMERAL_TYPE
- && tag_code == enum_type)
+ && tag_code == enum_type
+ && tag_code != typename_type)
{
- error ("`%T' referred to as enum", type);
+ error ("%qT referred to as enum", type);
+ cp_error_at ("%qT has a previous declaration here", type);
return error_mark_node;
}
else if (!allow_template_p
then the required template argument is missing. */
- error ("template argument required for `%s %T'",
+ error ("template argument required for %<%s %T%>",
tag_name (tag_code),
DECL_NAME (CLASSTYPE_TI_TEMPLATE (type)));
return error_mark_node;
return type;
}
+/* Lookup NAME in elaborate type specifier in scope according to
+ SCOPE and issue diagnostics if necessary.
+ Return *_TYPE node upon success, NULL_TREE when the NAME is not
+ found, and ERROR_MARK_NODE for type error. */
+
+static tree
+lookup_and_check_tag (enum tag_types tag_code, tree name,
+ tag_scope scope, bool template_header_p)
+{
+ tree t;
+ tree decl;
+ if (scope == ts_global)
+ decl = lookup_name (name, 2);
+ else
+ decl = lookup_type_scope (name, scope);
+
+ if (decl && DECL_CLASS_TEMPLATE_P (decl))
+ decl = DECL_TEMPLATE_RESULT (decl);
+
+ if (decl && TREE_CODE (decl) == TYPE_DECL)
+ {
+ /* Look for invalid nested type:
+ class C {
+ class C {};
+ }; */
+ if (scope == ts_current && DECL_SELF_REFERENCE_P (decl))
+ {
+ error ("%qD has the same name as the class in which it is "
+ "declared",
+ decl);
+ return error_mark_node;
+ }
+
+ /* Two cases we need to consider when deciding if a class
+ template is allowed as an elaborated type specifier:
+ 1. It is a self reference to its own class.
+ 2. It comes with a template header.
+
+ For example:
+
+ template <class T> class C {
+ class C *c1; // DECL_SELF_REFERENCE_P is true
+ class D;
+ };
+ template <class U> class C; // template_header_p is true
+ template <class T> class C<T>::D {
+ class C *c2; // DECL_SELF_REFERENCE_P is true
+ }; */
+
+ t = check_elaborated_type_specifier (tag_code,
+ decl,
+ template_header_p
+ | DECL_SELF_REFERENCE_P (decl));
+ return t;
+ }
+ else
+ return NULL_TREE;
+}
+
/* Get the struct, enum or union (TAG_CODE says which) with tag NAME.
Define the tag as a forward-reference if it is not defined.
If a declaration is given, process it here, and report an error if
multiple declarations are not identical.
- GLOBALIZE is false when this is also a definition. Only look in
+ SCOPE is TS_CURRENT when this is also a definition. Only look in
the current frame for the name (since C++ allows new names in any
- scope.)
+ scope.) It is TS_WITHIN_ENCLOSING_NON_CLASS if this is a friend
+ declaration. Only look beginning from the current scope outward up
+ till the nearest non-class scope. Otherwise it is TS_GLOBAL.
TEMPLATE_HEADER_P is true when this declaration is preceded by
a set of template parameters. */
tree
xref_tag (enum tag_types tag_code, tree name,
- bool globalize, bool template_header_p)
+ tag_scope scope, bool template_header_p)
{
enum tree_code code;
tree t;
- struct cp_binding_level *b = current_binding_level;
tree context = NULL_TREE;
timevar_push (TV_NAME_LOOKUP);
- my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 0);
+ gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
switch (tag_code)
{
code = ENUMERAL_TYPE;
break;
default:
- abort ();
+ gcc_unreachable ();
}
- if (! globalize)
- {
- /* If we know we are defining this tag, only look it up in
- this scope and don't try to find it as a type. */
- t = lookup_tag (code, name, b, 1);
- }
+ /* In case of anonymous name, xref_tag is only called to
+ make type node and push name. Name lookup is not required. */
+ if (ANON_AGGRNAME_P (name))
+ t = NULL_TREE;
else
- {
- tree decl = lookup_name (name, 2);
-
- if (decl && DECL_CLASS_TEMPLATE_P (decl))
- decl = DECL_TEMPLATE_RESULT (decl);
-
- if (decl && TREE_CODE (decl) == TYPE_DECL)
- {
- /* Two cases we need to consider when deciding if a class
- template is allowed as an elaborated type specifier:
- 1. It is a self reference to its own class.
- 2. It comes with a template header.
-
- For example:
+ t = lookup_and_check_tag (tag_code, name,
+ scope, template_header_p);
- template <class T> class C {
- class C *c1; // DECL_SELF_REFERENCE_P is true
- class D;
- };
- template <class U> class C; // template_header_p is true
- template <class T> class C<T>::D {
- class C *c2; // DECL_SELF_REFERENCE_P is true
- }; */
+ if (t == error_mark_node)
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
- t = check_elaborated_type_specifier (tag_code,
- decl,
- template_header_p
- | DECL_SELF_REFERENCE_P (decl));
- if (t == error_mark_node)
- POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
- }
- else
- t = NULL_TREE;
-
- if (t && current_class_type
- && template_class_depth (current_class_type)
- && template_header_p)
- {
- /* Since GLOBALIZE is nonzero, we are not looking at a
- definition of this tag. Since, in addition, we are currently
- processing a (member) template declaration of a template
- class, we must be very careful; consider:
+ if (scope != ts_current && t && current_class_type
+ && template_class_depth (current_class_type)
+ && template_header_p)
+ {
+ /* Since SCOPE is not TS_CURRENT, we are not looking at a
+ definition of this tag. Since, in addition, we are currently
+ processing a (member) template declaration of a template
+ class, we must be very careful; consider:
- template <class X>
- struct S1
+ template <class X>
+ struct S1
- template <class U>
- struct S2
- { template <class V>
- friend struct S1; };
+ template <class U>
+ struct S2
+ { template <class V>
+ friend struct S1; };
- Here, the S2::S1 declaration should not be confused with the
- outer declaration. In particular, the inner version should
- have a template parameter of level 2, not level 1. This
- would be particularly important if the member declaration
- were instead:
+ Here, the S2::S1 declaration should not be confused with the
+ outer declaration. In particular, the inner version should
+ have a template parameter of level 2, not level 1. This
+ would be particularly important if the member declaration
+ were instead:
- template <class V = U> friend struct S1;
+ template <class V = U> friend struct S1;
- say, when we should tsubst into `U' when instantiating
- S2. On the other hand, when presented with:
+ say, when we should tsubst into `U' when instantiating
+ S2. On the other hand, when presented with:
- template <class T>
- struct S1 {
- template <class U>
- struct S2 {};
- template <class U>
- friend struct S2;
- };
+ template <class T>
+ struct S1 {
+ template <class U>
+ struct S2 {};
+ template <class U>
+ friend struct S2;
+ };
- we must find the inner binding eventually. We
- accomplish this by making sure that the new type we
- create to represent this declaration has the right
- TYPE_CONTEXT. */
- context = TYPE_CONTEXT (t);
- t = NULL_TREE;
- }
+ we must find the inner binding eventually. We
+ accomplish this by making sure that the new type we
+ create to represent this declaration has the right
+ TYPE_CONTEXT. */
+ context = TYPE_CONTEXT (t);
+ t = NULL_TREE;
}
if (! t)
the forward-reference will be altered into a real type. */
if (code == ENUMERAL_TYPE)
{
- error ("use of enum `%#D' without previous declaration", name);
+ error ("use of enum %q#D without previous declaration", name);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
}
else
{
t = make_aggr_type (code);
TYPE_CONTEXT (t) = context;
- pushtag (name, t, globalize);
+ /* pushtag only cares whether SCOPE is zero or not. */
+ t = pushtag (name, t, scope != ts_current);
}
}
else
{
- if (!globalize && processing_template_decl && IS_AGGR_TYPE (t))
+ if (template_header_p && IS_AGGR_TYPE (t))
redeclare_class_template (t, current_template_parms);
else if (!processing_template_decl
&& CLASS_TYPE_P (t)
&& CLASSTYPE_IS_TEMPLATE (t))
{
- error ("redeclaration of `%T' as a non-template", t);
+ error ("redeclaration of %qT as a non-template", t);
t = error_mark_node;
}
}
}
tree
-xref_tag_from_type (tree old, tree id, int globalize)
+xref_tag_from_type (tree old, tree id, tag_scope scope)
{
enum tag_types tag_kind;
if (id == NULL_TREE)
id = TYPE_IDENTIFIER (old);
- return xref_tag (tag_kind, id, globalize, false);
+ return xref_tag (tag_kind, id, scope, false);
}
/* Create the binfo hierarchy for REF with (possibly NULL) base list
{
tree *basep;
tree binfo, base_binfo;
- unsigned max_vbases = 0; /* Maxium direct & indirect virtual bases. */
- unsigned max_bases = 0; /* Maxium direct bases. */
+ unsigned max_vbases = 0; /* Maximum direct & indirect virtual bases. */
+ unsigned max_bases = 0; /* Maximum direct bases. */
int i;
tree default_access;
tree igo_prev; /* Track Inheritance Graph Order. */
}
}
- SET_CLASSTYPE_MARKED (ref);
+ TYPE_MARKED_P (ref) = 1;
/* The binfo slot should be empty, unless this is an (ill-formed)
redefinition. */
- my_friendly_assert (!TYPE_BINFO (ref) || TYPE_SIZE (ref), 20040706);
- my_friendly_assert (TYPE_MAIN_VARIANT (ref) == ref, 20040712);
+ gcc_assert (!TYPE_BINFO (ref) || TYPE_SIZE (ref));
+ gcc_assert (TYPE_MAIN_VARIANT (ref) == ref);
binfo = make_tree_binfo (max_bases);
CLASSTYPE_NON_AGGREGATE (ref) = 1;
if (TREE_CODE (ref) == UNION_TYPE)
- error ("derived union `%T' invalid", ref);
+ error ("derived union %qT invalid", ref);
}
if (max_bases > 1)
{
- TYPE_USES_MULTIPLE_INHERITANCE (ref) = 1;
- /* If there is more than one non-empty they cannot be at the
- same address. */
- TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (ref) = 1;
-
if (TYPE_FOR_JAVA (ref))
- error ("Java class '%T' cannot have multiple bases", ref);
+ error ("Java class %qT cannot have multiple bases", ref);
}
if (max_vbases)
{
CLASSTYPE_VBASECLASSES (ref) = VEC_alloc (tree, max_vbases);
- TYPE_USES_VIRTUAL_BASECLASSES (ref) = 1;
- /* Converting to a virtual base class requires looking up the
- offset of the virtual base. */
- TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (ref) = 1;
if (TYPE_FOR_JAVA (ref))
- error ("Java class '%T' cannot have virtual bases", ref);
+ error ("Java class %qT cannot have virtual bases", ref);
}
for (igo_prev = binfo; base_list; base_list = TREE_CHAIN (base_list))
&& TREE_CODE (basetype) != TEMPLATE_TYPE_PARM
&& TREE_CODE (basetype) != BOUND_TEMPLATE_TEMPLATE_PARM)
{
- error ("base type `%T' fails to be a struct or class type",
+ error ("base type %qT fails to be a struct or class type",
basetype);
continue;
}
- if (CLASSTYPE_MARKED (basetype))
- {
- if (basetype == ref)
- error ("recursive type `%T' undefined", basetype);
- else
- error ("duplicate base type `%T' invalid", basetype);
- continue;
- }
- SET_CLASSTYPE_MARKED (basetype);
-
if (TYPE_FOR_JAVA (basetype) && (current_lang_depth () == 0))
TYPE_FOR_JAVA (ref) = 1;
if (CLASS_TYPE_P (basetype) && !dependent_type_p (basetype))
{
base_binfo = TYPE_BINFO (basetype);
- /* The orignal basetype could have been a typedef'd type. */
+ /* The original basetype could have been a typedef'd type. */
basetype = BINFO_TYPE (base_binfo);
/* Inherit flags from the base. */
TYPE_HAS_ARRAY_NEW_OPERATOR (ref)
|= TYPE_HAS_ARRAY_NEW_OPERATOR (basetype);
TYPE_GETS_DELETE (ref) |= TYPE_GETS_DELETE (basetype);
- TYPE_USES_MULTIPLE_INHERITANCE (ref)
- |= TYPE_USES_MULTIPLE_INHERITANCE (basetype);
- TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (ref)
- |= TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (basetype);
TYPE_HAS_CONVERSION (ref) |= TYPE_HAS_CONVERSION (basetype);
+ CLASSTYPE_DIAMOND_SHAPED_P (ref)
+ |= CLASSTYPE_DIAMOND_SHAPED_P (basetype);
+ CLASSTYPE_REPEATED_BASE_P (ref)
+ |= CLASSTYPE_REPEATED_BASE_P (basetype);
+ }
+
+ /* We must do this test after we've seen through a typedef
+ type. */
+ if (TYPE_MARKED_P (basetype))
+ {
+ if (basetype == ref)
+ error ("recursive type %qT undefined", basetype);
+ else
+ error ("duplicate base type %qT invalid", basetype);
+ continue;
}
+ TYPE_MARKED_P (basetype) = 1;
base_binfo = copy_binfo (base_binfo, basetype, ref,
&igo_prev, via_virtual);
BINFO_BASE_ACCESS_APPEND (binfo, access);
}
+ if (VEC_space (tree, CLASSTYPE_VBASECLASSES (ref), 1))
+ /* If we have space in the vbase vector, we must have shared at
+ least one of them, and are therefore diamond shaped. */
+ CLASSTYPE_DIAMOND_SHAPED_P (ref) = 1;
+
/* Unmark all the types. */
for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
- CLEAR_CLASSTYPE_MARKED (BINFO_TYPE (base_binfo));
- CLEAR_CLASSTYPE_MARKED (ref);
+ TYPE_MARKED_P (BINFO_TYPE (base_binfo)) = 0;
+ TYPE_MARKED_P (ref) = 0;
+
+ /* Now see if we have a repeated base type. */
+ if (!CLASSTYPE_REPEATED_BASE_P (ref))
+ {
+ for (base_binfo = binfo; base_binfo;
+ base_binfo = TREE_CHAIN (base_binfo))
+ {
+ if (TYPE_MARKED_P (BINFO_TYPE (base_binfo)))
+ {
+ CLASSTYPE_REPEATED_BASE_P (ref) = 1;
+ break;
+ }
+ TYPE_MARKED_P (BINFO_TYPE (base_binfo)) = 1;
+ }
+ for (base_binfo = binfo; base_binfo;
+ base_binfo = TREE_CHAIN (base_binfo))
+ if (TYPE_MARKED_P (BINFO_TYPE (base_binfo)))
+ TYPE_MARKED_P (BINFO_TYPE (base_binfo)) = 0;
+ else
+ break;
+ }
}
\f
/* Begin compiling the definition of an enumeration type.
- NAME is its name (or null if anonymous).
+ NAME is its name.
Returns the type object, as yet incomplete.
Also records info about it so that build_enumerator
may be used to declare the individual values as they are read. */
tree
start_enum (tree name)
{
- tree enumtype = NULL_TREE;
- struct cp_binding_level *b = current_binding_level;
+ tree enumtype;
+
+ gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
/* If this is the real definition for a previous forward reference,
fill in the contents in the same object that used to be the
forward reference. */
- if (name != NULL_TREE)
- enumtype = lookup_tag (ENUMERAL_TYPE, name, b, 1);
+ enumtype = lookup_and_check_tag (enum_type, name,
+ /*tag_scope=*/ts_current,
+ /*template_header_p=*/false);
if (enumtype != NULL_TREE && TREE_CODE (enumtype) == ENUMERAL_TYPE)
{
- error ("multiple definition of `%#T'", enumtype);
+ error ("multiple definition of %q#T", enumtype);
error ("%Jprevious definition here", TYPE_MAIN_DECL (enumtype));
/* Clear out TYPE_VALUES, and start again. */
TYPE_VALUES (enumtype) = NULL_TREE;
}
else
{
+ /* In case of error, make a dummy enum to allow parsing to
+ continue. */
+ if (enumtype == error_mark_node)
+ name = make_anon_name ();
+
enumtype = make_node (ENUMERAL_TYPE);
- pushtag (name, enumtype, 0);
+ enumtype = pushtag (name, enumtype, 0);
}
return enumtype;
tree maxnode;
tree t;
bool unsignedp;
+ bool use_short_enum;
int lowprec;
int highprec;
int precision;
maxnode = value;
else if (tree_int_cst_lt (value, minnode))
minnode = value;
-
- /* Set the TREE_TYPE for the values as well. That's so that when
- we call decl_constant_value we get an entity of the right type
- (but with the constant value). But first make a copy so we
- don't clobber shared INTEGER_CSTs. */
- if (TREE_TYPE (value) != enumtype)
- {
- value = DECL_INITIAL (decl) = copy_node (value);
- TREE_TYPE (value) = enumtype;
- }
}
}
else
We use "int" or an "unsigned int" as the underlying type, even if
a smaller integral type would work, unless the user has
- explicitly requested that we use the smallest possible type. */
- for (itk = (flag_short_enums ? itk_char : itk_int);
+ explicitly requested that we use the smallest possible type. The
+ user can request that for all enumerations with a command line
+ flag, or for just one enumeration with an attribute. */
+
+ use_short_enum = flag_short_enums
+ || lookup_attribute ("packed", TYPE_ATTRIBUTES (enumtype));
+
+ for (itk = (use_short_enum ? itk_char : itk_int);
itk != itk_none;
itk++)
{
IF no integral type can represent all the enumerator values, the
enumeration is ill-formed. */
error ("no integral type can represent all of the enumerator values "
- "for `%T'", enumtype);
+ "for %qT", enumtype);
precision = TYPE_PRECISION (long_long_integer_type_node);
underlying_type = integer_types[itk_unsigned_long_long];
}
underlying type in the range bmin to bmax, where bmin and bmax are,
respectively, the smallest and largest values of the smallest bit-
field that can store emin and emax. */
- TYPE_PRECISION (enumtype) = precision;
+
+ /* The middle-end currently assumes that types with TYPE_PRECISION
+ narrower than their underlying type are suitably zero or sign
+ extended to fill their mode. g++ doesn't make these guarantees.
+ Until the middle-end can represent such paradoxical types, we
+ set the TYPE_PRECISION to the width of the underlying type. */
+ TYPE_PRECISION (enumtype) = TYPE_PRECISION (underlying_type);
+
set_min_and_max_values_for_integral_type (enumtype, precision, unsignedp);
/* [dcl.enum]
decl = TREE_VALUE (values);
value = perform_implicit_conversion (underlying_type,
DECL_INITIAL (decl));
+
+ /* Do not clobber shared ints. */
+ value = copy_node (value);
+
TREE_TYPE (value) = enumtype;
DECL_INITIAL (decl) = value;
TREE_VALUE (values) = value;
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);
/* Validate and default VALUE. */
if (value != NULL_TREE)
{
- value = decl_constant_value (value);
+ value = integral_constant_value (value);
if (TREE_CODE (value) == INTEGER_CST)
{
}
else
{
- error ("enumerator value for `%D' not integer constant", name);
+ error ("enumerator value for %qD not integer constant", name);
value = NULL_TREE;
}
}
/* Default based on previous value. */
if (value == NULL_TREE)
{
- tree prev_value;
-
if (TYPE_VALUES (enumtype))
{
- /* The next value is the previous value ... */
+ HOST_WIDE_INT hi;
+ unsigned HOST_WIDE_INT lo;
+ tree prev_value;
+ bool overflowed;
+
+ /* The next value is the previous value plus one. We can
+ safely assume that the previous value is an INTEGER_CST.
+ add_double doesn't know the type of the target expression,
+ so we must check with int_fits_type_p as well. */
prev_value = DECL_INITIAL (TREE_VALUE (TYPE_VALUES (enumtype)));
- /* ... plus one. */
- value = cp_build_binary_op (PLUS_EXPR,
- prev_value,
- integer_one_node);
-
- if (tree_int_cst_lt (value, prev_value))
- error ("overflow in enumeration values at `%D'", name);
+ overflowed = add_double (TREE_INT_CST_LOW (prev_value),
+ TREE_INT_CST_HIGH (prev_value),
+ 1, 0, &lo, &hi);
+ value = build_int_cst_wide (TREE_TYPE (prev_value), lo, hi);
+ overflowed |= !int_fits_type_p (value, TREE_TYPE (prev_value));
+
+ if (overflowed)
+ error ("overflow in enumeration values at %qD", name);
}
else
value = integer_zero_node;
/* C++ associates enums with global, function, or class declarations. */
context = current_scope ();
- if (!context)
- context = current_namespace;
/* Build the actual enumeration constant. Note that the enumeration
constants have the type of their initializers until the
/* In a function definition, arg types must be complete. */
require_complete_types_for_parms (current_function_parms);
+ if (dependent_type_p (return_type))
+ return;
if (!COMPLETE_OR_VOID_TYPE_P (return_type))
{
- error ("return type `%#T' is incomplete", TREE_TYPE (fntype));
+ error ("return type %q#T is incomplete", TREE_TYPE (fntype));
/* Make it return void instead, but don't change the
type of the DECL_RESULT, in case we have a named return value. */
int doing_friend = 0;
struct cp_binding_level *bl;
tree current_function_parms;
+ struct c_fileinfo *finfo = get_fileinfo (lbasename (input_filename));
/* Sanity check. */
- my_friendly_assert (TREE_CODE (TREE_VALUE (void_list_node)) == VOID_TYPE, 160);
- my_friendly_assert (TREE_CHAIN (void_list_node) == NULL_TREE, 161);
+ gcc_assert (TREE_CODE (TREE_VALUE (void_list_node)) == VOID_TYPE);
+ gcc_assert (TREE_CHAIN (void_list_node) == NULL_TREE);
fntype = TREE_TYPE (decl1);
if (TREE_CODE (fntype) == METHOD_TYPE)
if (DECL_DECLARED_INLINE_P (decl1)
&& lookup_attribute ("noinline", attrs))
- warning ("%Jinline function '%D' given attribute noinline", decl1, decl1);
+ warning ("%Jinline function %qD given attribute noinline", decl1, decl1);
if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl1))
/* This is a constructor, we must ensure that any default args
if (warn_ecpp
&& DECL_OVERLOADED_OPERATOR_P (decl1) == NOP_EXPR
&& TREE_CODE (TREE_TYPE (fntype)) == VOID_TYPE)
- warning ("`operator=' should return a reference to `*this'");
+ warning ("%<operator=%> should return a reference to %<*this%>");
/* Make the init_value nonzero so pushdecl knows this is not tentative.
error_mark_node is replaced below (in poplevel) with the BLOCK. */
/* Make sure the parameter and return types are reasonable. When
you declare a function, these types can be incomplete, but they
must be complete when you define the function. */
- if (! processing_template_decl)
- check_function_type (decl1, current_function_parms);
+ check_function_type (decl1, current_function_parms);
/* Build the return declaration for the function. */
restype = TREE_TYPE (fntype);
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
between `current_class_type' and `current_class_ptr'. */
tree t = DECL_ARGUMENTS (decl1);
- my_friendly_assert (t != NULL_TREE && TREE_CODE (t) == PARM_DECL,
- 162);
- my_friendly_assert (TREE_CODE (TREE_TYPE (t)) == POINTER_TYPE,
- 19990811);
+ gcc_assert (t != NULL_TREE && TREE_CODE (t) == PARM_DECL);
+ gcc_assert (TREE_CODE (TREE_TYPE (t)) == POINTER_TYPE);
cp_function_chain->x_current_class_ref
= build_indirect_ref (t, NULL);
}
if (DECL_HAS_VTT_PARM_P (decl1))
{
- if (DECL_NAME (t) != vtt_parm_identifier)
- abort ();
+ gcc_assert (DECL_NAME (t) == vtt_parm_identifier);
current_vtt_parm = t;
}
}
/* 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 (interface_unknown == 0
+ else if (finfo->interface_unknown == 0
&& ! DECL_TEMPLATE_INSTANTIATION (decl1))
{
if (DECL_DECLARED_INLINE_P (decl1)
|| processing_template_decl)
{
DECL_EXTERNAL (decl1)
- = (interface_only
+ = (finfo->interface_only
|| (DECL_DECLARED_INLINE_P (decl1)
&& ! flag_implement_inlines
&& !DECL_VINDEX (decl1)));
if (!DECL_EXTERNAL (decl1))
mark_needed (decl1);
}
- else if (interface_unknown && interface_only
+ else if (finfo->interface_unknown && finfo->interface_only
&& ! DECL_TEMPLATE_INSTANTIATION (decl1))
{
/* If MULTIPLE_SYMBOL_SPACES is defined and we saw a #pragma
- interface, we will have interface_only set but not
- interface_known. In that case, we don't want to use the normal
- heuristics because someone will supply a #pragma implementation
- elsewhere, and deducing it here would produce a conflict. */
+ interface, we will have both finfo->interface_unknown and
+ finfo->interface_only set. In that case, we don't want to
+ use the normal heuristics because someone will supply a
+ #pragma implementation elsewhere, and deducing it here would
+ produce a conflict. */
comdat_linkage (decl1);
DECL_EXTERNAL (decl1) = 0;
DECL_INTERFACE_KNOWN (decl1) = 1;
if (decl1 == NULL_TREE || TREE_CODE (decl1) != FUNCTION_DECL)
return 0;
- cplus_decl_attributes (&decl1, attrs, 0);
-
/* If #pragma weak was used, mark the decl weak now. */
if (global_scope_p (current_binding_level))
maybe_apply_pragma_weak (decl1);
if (DECL_MAIN_P (decl1))
- {
- /* If this doesn't return integer_type, or a typedef to
- integer_type, complain. */
- if (!same_type_p (TREE_TYPE (TREE_TYPE (decl1)), integer_type_node))
- {
- if (pedantic || warn_return_type)
- pedwarn ("return type for `main' changed to `int'");
- TREE_TYPE (decl1) = default_function_type;
- }
- }
+ /* main must return int. grokfndecl should have corrected it
+ (and issued a diagnostic) if the user got it wrong. */
+ gcc_assert (same_type_p (TREE_TYPE (TREE_TYPE (decl1)),
+ integer_type_node));
start_preparsed_function (decl1, attrs, /*flags=*/SF_DEFAULT);
|| TREE_CODE (parm) != VOID_TYPE)
pushdecl (parm);
else
- error ("parameter `%D' declared void", parm);
+ error ("parameter %qD declared void", parm);
}
else
{
/* Save the language-specific per-function data so that we can
get it back when we really expand this function. */
- my_friendly_assert (!DECL_PENDING_INLINE_P (decl),
- 19990908);
+ gcc_assert (!DECL_PENDING_INLINE_P (decl));
/* Make a copy. */
f = GGC_NEW (struct language_function);
This caused &foo to be of type ptr-to-const-function
which then got a warning when stored in a ptr-to-function variable. */
- my_friendly_assert (building_stmt_tree (), 20000911);
+ gcc_assert (building_stmt_tree ());
/* For a cloned function, we've already got all the code we need;
there's no need to add any extra bits. */
{
if (DECL_MAIN_P (current_function_decl))
{
- /* Make it so that `main' always returns 0 by default. */
+ tree stmt;
+
+ /* Make it so that `main' always returns 0 by default (or
+ 1 for VMS). */
#if VMS_TARGET
- finish_return_stmt (integer_one_node);
+ stmt = finish_return_stmt (integer_one_node);
#else
- finish_return_stmt (integer_zero_node);
+ stmt = finish_return_stmt (integer_zero_node);
#endif
+ /* Hack. We don't want the middle-end to warn that this
+ return is unreachable, so put the statement on the
+ special line 0. */
+ annotate_with_file_line (stmt, input_filename, 0);
}
/* Finish dealing with exception specifiers. */
if (current_binding_level->kind != sk_function_parms)
{
/* Make sure we have already experienced errors. */
- if (errorcount == 0)
- abort ();
+ gcc_assert (errorcount);
/* Throw away the broken statement tree and extra binding
levels. */
/* Statements should always be full-expressions at the outermost set
of curly braces for a function. */
- my_friendly_assert (stmts_are_full_exprs_p (), 19990831);
+ gcc_assert (stmts_are_full_exprs_p ());
/* Set up the named return value optimization, if we can. Candidate
variables are selected in check_return_value. */
/* Genericize before inlining. */
if (!processing_template_decl)
{
+ struct language_function *f = DECL_SAVED_FUNCTION_DATA (fndecl);
cp_genericize (fndecl);
+ /* Clear out the bits we don't need. */
+ f->x_current_class_ptr = NULL;
+ f->x_current_class_ref = NULL;
+ f->x_eh_spec_block = NULL;
+ f->x_in_charge_parm = NULL;
+ f->x_vtt_parm = NULL;
+ f->x_return_value = NULL;
+ f->bindings = NULL;
/* Handle attribute((warn_unused_result)). Relies on gimple input. */
c_warn_unused_result (&DECL_SAVED_TREE (fndecl));
}
+ /* Clear out the bits we don't need. */
+ local_names = NULL;
+ named_label_uses = NULL;
/* We're leaving the context of this function, so zap cfun. It's still in
DECL_STRUCT_FUNCTION, and we'll restore it in tree_rest_of_compilation. */
{
if (DECL_CONTEXT (fndecl)
&& TREE_CODE( DECL_CONTEXT (fndecl)) != NAMESPACE_DECL)
- error ("`%D' is already defined in class `%T'", fndecl,
+ error ("%qD is already defined in class %qT", fndecl,
DECL_CONTEXT (fndecl));
return void_type_node;
}
{
if (DECL_NAME (link) != NULL_TREE)
pop_binding (DECL_NAME (link), link);
- my_friendly_assert (TREE_CODE (link) != FUNCTION_DECL, 163);
+ gcc_assert (TREE_CODE (link) != FUNCTION_DECL);
DECL_CONTEXT (link) = NULL_TREE;
}
for String.cc in libg++. */
if (DECL_FRIEND_P (fndecl))
{
- CLASSTYPE_INLINE_FRIENDS (current_class_type)
- = tree_cons (NULL_TREE, fndecl, CLASSTYPE_INLINE_FRIENDS (current_class_type));
+ VEC_safe_push (tree, CLASSTYPE_INLINE_FRIENDS (current_class_type),
+ fndecl);
decl = void_type_node;
}
void
maybe_register_incomplete_var (tree var)
{
- my_friendly_assert (TREE_CODE (var) == VAR_DECL, 20020406);
+ gcc_assert (TREE_CODE (var) == VAR_DECL);
/* Keep track of variables with incomplete types. */
if (!processing_template_decl && TREE_TYPE (var) != error_mark_node
{
tree *list = &incomplete_vars;
- my_friendly_assert (CLASS_TYPE_P (type), 20020406);
+ gcc_assert (CLASS_TYPE_P (type));
while (*list)
{
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);
}
{
int flags = LOOKUP_NORMAL|LOOKUP_DESTRUCTOR;
tree rval;
+ bool has_vbases = (TREE_CODE (type) == RECORD_TYPE
+ && CLASSTYPE_VBASECLASSES (type));
if (TREE_CODE (type) == ARRAY_TYPE)
rval = decl;
}
/* Optimize for space over speed here. */
- if (! TYPE_USES_VIRTUAL_BASECLASSES (type)
- || flag_expensive_optimizations)
+ if (!has_vbases || flag_expensive_optimizations)
flags |= LOOKUP_NONVIRTUAL;
rval = build_delete (TREE_TYPE (rval), rval,
sfk_complete_destructor, flags, 0);
- if (TYPE_USES_VIRTUAL_BASECLASSES (type)
- && ! TYPE_HAS_DESTRUCTOR (type))
- rval = build_compound_expr (rval, build_vbase_delete (type, decl));
-
return rval;
}
return NULL_TREE;
if (cp_type_quals (TREE_TYPE (TREE_VALUE (args)))
!= TYPE_UNQUALIFIED)
- error ("static member function `%#D' declared with type qualifiers",
- decl);
+ error ("static member function %q#D declared with type qualifiers", decl);
args = TREE_CHAIN (args);
tmp = build_function_type (TREE_TYPE (function), args);
return DECL_MAIN_P (decl);
}
+/* Return the COMDAT group into which DECL should be placed. */
+
+const char *
+cxx_comdat_group (tree decl)
+{
+ tree name;
+
+ /* Virtual tables, construction virtual tables, and virtual table
+ tables all go in a single COMDAT group, named after the primary
+ virtual table. */
+ if (TREE_CODE (decl) == VAR_DECL && DECL_VTABLE_OR_VTT_P (decl))
+ name = DECL_ASSEMBLER_NAME (CLASSTYPE_VTABLES (DECL_CONTEXT (decl)));
+ /* For all other DECLs, the COMDAT group is the mangled name of the
+ declaration itself. */
+ else
+ name = DECL_ASSEMBLER_NAME (decl);
+
+ return IDENTIFIER_POINTER (name);
+}
+
#include "gt-cp-decl.h"
-#include "gtype-cp.h"