/* Process declarations and variables for C++ compiler.
Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+ 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+ Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
any later version.
GCC is distributed in the hope that it will be useful,
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA. */
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
/* Process declarations and symbol lookup for C++ front end.
#include "debug.h"
#include "timevar.h"
#include "tree-flow.h"
+#include "pointer-set.h"
static tree grokparms (cp_parameter_declarator *, tree *);
static const char *redeclaration_error_message (tree, tree);
template <class T> void S<T>::f(int);
- The `class T' maches the `S<T>', leaving no template headers
+ The `class T' matches the `S<T>', leaving no template headers
corresponding to the `f'. */
return tsk_none;
else if (n_template_parm_scopes > n_class_scopes + 1)
location_t location;
error ("label %q+D used but not defined", label);
-#ifdef USE_MAPPED_LOCATION
location = input_location; /* FIXME want (input_filename, (line)0) */
-#else
- location.file = input_filename;
- location.line = 0;
-#endif
/* Avoid crashing later. */
define_label (location, DECL_NAME (label));
}
- else if (!TREE_USED (label))
- warning (OPT_Wunused_label, "label %q+D defined but not used", label);
+ else
+ warn_for_unused_label (label);
}
SET_IDENTIFIER_LABEL_VALUE (DECL_NAME (label), old_value);
/* In each subblock, record that this is its superior. */
if (keep >= 0)
- for (link = subblocks; link; link = TREE_CHAIN (link))
+ for (link = subblocks; link; link = BLOCK_CHAIN (link))
BLOCK_SUPERCONTEXT (link) = block;
/* We still support the old for-scope rules, whereby the variables
/* There may be OVERLOADs (wrapped in TREE_LISTs) on the BLOCK_VARs
list if a `using' declaration put them there. The debugging
- back-ends won't understand OVERLOAD, so we remove them here.
+ back ends won't understand OVERLOAD, so we remove them here.
Because the BLOCK_VARS are (temporarily) shared with
CURRENT_BINDING_LEVEL->NAMES we must do this fixup after we have
popped all the bindings. */
leave_scope ();
if (functionbody)
- DECL_INITIAL (current_function_decl) = block;
+ {
+ /* The current function is being defined, so its DECL_INITIAL
+ should be error_mark_node. */
+ gcc_assert (DECL_INITIAL (current_function_decl) == error_mark_node);
+ DECL_INITIAL (current_function_decl) = block;
+ }
else if (block)
current_binding_level->blocks
= chainon (current_binding_level->blocks, block);
itself, calling F for each. The DATA is passed to F as well. */
static int
-walk_namespaces_r (tree namespace, walk_namespaces_fn f, void* data)
+walk_namespaces_r (tree name_space, walk_namespaces_fn f, void* data)
{
int result = 0;
- tree current = NAMESPACE_LEVEL (namespace)->namespaces;
+ tree current = NAMESPACE_LEVEL (name_space)->namespaces;
- result |= (*f) (namespace, data);
+ result |= (*f) (name_space, data);
for (; current; current = TREE_CHAIN (current))
result |= walk_namespaces_r (current, f, data);
wrapup_global_declarations for this NAMESPACE. */
int
-wrapup_globals_for_namespace (tree namespace, void* data)
+wrapup_globals_for_namespace (tree name_space, void* data)
{
- struct cp_binding_level *level = NAMESPACE_LEVEL (namespace);
+ struct cp_binding_level *level = NAMESPACE_LEVEL (name_space);
VEC(tree,gc) *statics = level->static_decls;
tree *vec = VEC_address (tree, statics);
int len = VEC_length (tree, statics);
return;
name = DECL_ASSEMBLER_NAME (newdecl);
- pedwarn ("%qD was declared %<extern%> and later %<static%>", newdecl);
- pedwarn ("previous declaration of %q+D", olddecl);
+ permerror ("%qD was declared %<extern%> and later %<static%>", newdecl);
+ permerror ("previous declaration of %q+D", olddecl);
}
/* NEW_DECL is a redeclaration of OLD_DECL; both are functions or
function templates. If their exception specifications do not
- match, issue an a diagnostic. */
+ match, issue a diagnostic. */
static void
check_redeclaration_exception_specification (tree new_decl,
}
}
+#define GNU_INLINE_P(fn) (DECL_DECLARED_INLINE_P (fn) \
+ && lookup_attribute ("gnu_inline", \
+ DECL_ATTRIBUTES (fn)))
+
/* If NEWDECL is a redeclaration of OLDDECL, merge the declarations.
If the redeclaration is invalid, a diagnostic is issued, and the
error_mark_node is returned. Otherwise, OLDDECL is returned.
TREE_TYPE (newdecl) = TREE_TYPE (olddecl) = type;
}
+ /* If a function is explicitly declared "throw ()", propagate that to
+ the corresponding builtin. */
+ if (DECL_BUILT_IN_CLASS (olddecl) == BUILT_IN_NORMAL
+ && DECL_ANTICIPATED (olddecl)
+ && TREE_NOTHROW (newdecl)
+ && !TREE_NOTHROW (olddecl)
+ && built_in_decls [DECL_FUNCTION_CODE (olddecl)] != NULL_TREE
+ && built_in_decls [DECL_FUNCTION_CODE (olddecl)] != olddecl
+ && types_match)
+ TREE_NOTHROW (built_in_decls [DECL_FUNCTION_CODE (olddecl)]) = 1;
+
/* Whether or not the builtin can throw exceptions has no
bearing on this declarator. */
TREE_NOTHROW (olddecl) = 0;
}
else if (TREE_CODE (olddecl) != TREE_CODE (newdecl))
{
- if ((TREE_CODE (olddecl) == TYPE_DECL && DECL_ARTIFICIAL (olddecl)
- && TREE_CODE (newdecl) != TYPE_DECL
- && ! (TREE_CODE (newdecl) == TEMPLATE_DECL
- && TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL))
- || (TREE_CODE (newdecl) == TYPE_DECL && DECL_ARTIFICIAL (newdecl)
- && TREE_CODE (olddecl) != TYPE_DECL
- && ! (TREE_CODE (olddecl) == TEMPLATE_DECL
- && (TREE_CODE (DECL_TEMPLATE_RESULT (olddecl))
- == TYPE_DECL))))
- {
- /* We do nothing special here, because C++ does such nasty
- things with TYPE_DECLs. Instead, just let the TYPE_DECL
- get shadowed, and know that if we need to find a TYPE_DECL
- for a given name, we can look in the IDENTIFIER_TYPE_VALUE
- slot of the identifier. */
- return NULL_TREE;
+ /* C++ Standard, 3.3, clause 4:
+ "[Note: a namespace name or a class template name must be unique
+ in its declarative region (7.3.2, clause 14). ]" */
+ if (TREE_CODE (olddecl) != NAMESPACE_DECL
+ && TREE_CODE (newdecl) != NAMESPACE_DECL
+ && (TREE_CODE (olddecl) != TEMPLATE_DECL
+ || TREE_CODE (DECL_TEMPLATE_RESULT (olddecl)) != TYPE_DECL)
+ && (TREE_CODE (newdecl) != TEMPLATE_DECL
+ || TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) != TYPE_DECL))
+ {
+ if ((TREE_CODE (olddecl) == TYPE_DECL && DECL_ARTIFICIAL (olddecl)
+ && TREE_CODE (newdecl) != TYPE_DECL)
+ || (TREE_CODE (newdecl) == TYPE_DECL && DECL_ARTIFICIAL (newdecl)
+ && TREE_CODE (olddecl) != TYPE_DECL))
+ {
+ /* We do nothing special here, because C++ does such nasty
+ things with TYPE_DECLs. Instead, just let the TYPE_DECL
+ get shadowed, and know that if we need to find a TYPE_DECL
+ for a given name, we can look in the IDENTIFIER_TYPE_VALUE
+ slot of the identifier. */
+ return NULL_TREE;
+ }
+
+ if ((TREE_CODE (newdecl) == FUNCTION_DECL
+ && DECL_FUNCTION_TEMPLATE_P (olddecl))
+ || (TREE_CODE (olddecl) == FUNCTION_DECL
+ && DECL_FUNCTION_TEMPLATE_P (newdecl)))
+ return NULL_TREE;
}
- if ((TREE_CODE (newdecl) == FUNCTION_DECL
- && DECL_FUNCTION_TEMPLATE_P (olddecl))
- || (TREE_CODE (olddecl) == FUNCTION_DECL
- && DECL_FUNCTION_TEMPLATE_P (newdecl)))
- return NULL_TREE;
-
error ("%q#D redeclared as different kind of symbol", newdecl);
if (TREE_CODE (olddecl) == TREE_LIST)
olddecl = TREE_VALUE (olddecl);
if (1 == simple_cst_equal (TREE_PURPOSE (t1),
TREE_PURPOSE (t2)))
{
- pedwarn ("default argument given for parameter %d of %q#D",
- i, newdecl);
- pedwarn ("after previous specification in %q+#D", olddecl);
+ permerror ("default argument given for parameter %d of %q#D",
+ i, newdecl);
+ permerror ("after previous specification in %q+#D", olddecl);
}
else
{
olddecl);
}
}
-
- if (DECL_DECLARED_INLINE_P (newdecl)
- && ! DECL_DECLARED_INLINE_P (olddecl)
- && TREE_ADDRESSABLE (olddecl) && warn_inline)
- {
- warning (0, "%q#D was used before it was declared inline", newdecl);
- warning (0, "%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_INVALID_OVERRIDER_P (newdecl) |= DECL_INVALID_OVERRIDER_P (olddecl);
DECL_THIS_STATIC (newdecl) |= DECL_THIS_STATIC (olddecl);
if (DECL_OVERLOADED_OPERATOR_P (olddecl) != ERROR_MARK)
SET_OVERLOADED_OPERATOR_CODE
warning (OPT_Wredundant_decls, "redundant redeclaration of %qD in same scope", newdecl);
warning (OPT_Wredundant_decls, "previous declaration of %q+D", olddecl);
}
+
+ if (DECL_DELETED_FN (newdecl))
+ {
+ error ("deleted definition of %qD", newdecl);
+ error ("after previous declaration %q+D", olddecl);
+ }
}
/* Deal with C++: must preserve virtual function table size. */
= chainon (DECL_TEMPLATE_SPECIALIZATIONS (olddecl),
DECL_TEMPLATE_SPECIALIZATIONS (newdecl));
+ DECL_ATTRIBUTES (old_result)
+ = (*targetm.merge_decl_attributes) (old_result, new_result);
+
if (DECL_FUNCTION_TEMPLATE_P (newdecl))
{
- DECL_INLINE (old_result)
- |= DECL_INLINE (new_result);
- DECL_DECLARED_INLINE_P (old_result)
- |= DECL_DECLARED_INLINE_P (new_result);
- check_redeclaration_exception_specification (newdecl, olddecl);
+ if (GNU_INLINE_P (old_result) != GNU_INLINE_P (new_result)
+ && DECL_INITIAL (new_result))
+ {
+ if (DECL_INITIAL (old_result))
+ DECL_UNINLINABLE (old_result) = 1;
+ else
+ DECL_UNINLINABLE (old_result) = DECL_UNINLINABLE (new_result);
+ DECL_EXTERNAL (old_result) = DECL_EXTERNAL (new_result);
+ DECL_NOT_REALLY_EXTERN (old_result)
+ = DECL_NOT_REALLY_EXTERN (new_result);
+ DECL_INTERFACE_KNOWN (old_result)
+ = DECL_INTERFACE_KNOWN (new_result);
+ DECL_DECLARED_INLINE_P (old_result)
+ = DECL_DECLARED_INLINE_P (new_result);
+ DECL_DISREGARD_INLINE_LIMITS (old_result)
+ |= DECL_DISREGARD_INLINE_LIMITS (new_result);
+
+ }
+ else
+ {
+ DECL_DECLARED_INLINE_P (old_result)
+ |= DECL_DECLARED_INLINE_P (new_result);
+ DECL_DISREGARD_INLINE_LIMITS (old_result)
+ |= DECL_DISREGARD_INLINE_LIMITS (new_result);
+ check_redeclaration_exception_specification (newdecl, olddecl);
+ }
}
/* If the new declaration is a definition, update the file and
- line information on the declaration. */
- if (DECL_INITIAL (old_result) == NULL_TREE
- && DECL_INITIAL (new_result) != NULL_TREE)
+ line information on the declaration, and also make
+ the old declaration the same definition. */
+ if (DECL_INITIAL (new_result) != NULL_TREE)
{
DECL_SOURCE_LOCATION (olddecl)
= DECL_SOURCE_LOCATION (old_result)
= DECL_SOURCE_LOCATION (newdecl);
+ DECL_INITIAL (old_result) = DECL_INITIAL (new_result);
if (DECL_FUNCTION_TEMPLATE_P (newdecl))
DECL_ARGUMENTS (old_result)
= DECL_ARGUMENTS (new_result);
|= DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (olddecl);
DECL_NO_LIMIT_STACK (newdecl) |= DECL_NO_LIMIT_STACK (olddecl);
TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl);
- TREE_READONLY (newdecl) |= TREE_READONLY (olddecl);
TREE_NOTHROW (newdecl) |= TREE_NOTHROW (olddecl);
DECL_IS_MALLOC (newdecl) |= DECL_IS_MALLOC (olddecl);
- DECL_IS_PURE (newdecl) |= DECL_IS_PURE (olddecl);
+ DECL_IS_OPERATOR_NEW (newdecl) |= DECL_IS_OPERATOR_NEW (olddecl);
+ DECL_PURE_P (newdecl) |= DECL_PURE_P (olddecl);
+ TREE_READONLY (newdecl) |= TREE_READONLY (olddecl);
+ DECL_LOOPING_CONST_OR_PURE_P (newdecl)
+ |= DECL_LOOPING_CONST_OR_PURE_P (olddecl);
/* Keep the old RTL. */
COPY_DECL_RTL (olddecl, newdecl);
}
new_template = NULL_TREE;
if (DECL_LANG_SPECIFIC (newdecl) && DECL_LANG_SPECIFIC (olddecl))
{
- DECL_INTERFACE_KNOWN (newdecl) |= DECL_INTERFACE_KNOWN (olddecl);
- DECL_NOT_REALLY_EXTERN (newdecl) |= DECL_NOT_REALLY_EXTERN (olddecl);
- DECL_COMDAT (newdecl) |= DECL_COMDAT (olddecl);
+ bool new_redefines_gnu_inline = false;
+
+ if (new_defines_function
+ && ((DECL_INTERFACE_KNOWN (olddecl)
+ && TREE_CODE (olddecl) == FUNCTION_DECL)
+ || (TREE_CODE (olddecl) == TEMPLATE_DECL
+ && (TREE_CODE (DECL_TEMPLATE_RESULT (olddecl))
+ == FUNCTION_DECL))))
+ {
+ tree fn = olddecl;
+
+ if (TREE_CODE (fn) == TEMPLATE_DECL)
+ fn = DECL_TEMPLATE_RESULT (olddecl);
+
+ new_redefines_gnu_inline = GNU_INLINE_P (fn) && DECL_INITIAL (fn);
+ }
+
+ if (!new_redefines_gnu_inline)
+ {
+ DECL_INTERFACE_KNOWN (newdecl) |= DECL_INTERFACE_KNOWN (olddecl);
+ DECL_NOT_REALLY_EXTERN (newdecl) |= DECL_NOT_REALLY_EXTERN (olddecl);
+ DECL_COMDAT (newdecl) |= DECL_COMDAT (olddecl);
+ }
DECL_TEMPLATE_INSTANTIATED (newdecl)
|= DECL_TEMPLATE_INSTANTIATED (olddecl);
/* [temp.expl.spec/14] We don't inline explicit specialization
just because the primary template says so. */
}
+ else if (new_defines_function && DECL_INITIAL (olddecl))
+ {
+ /* Never inline re-defined extern inline functions.
+ FIXME: this could be better handled by keeping both
+ function as separate declarations. */
+ DECL_UNINLINABLE (newdecl) = 1;
+ }
else
{
if (DECL_PENDING_INLINE_INFO (newdecl) == 0)
DECL_DECLARED_INLINE_P (newdecl) |= DECL_DECLARED_INLINE_P (olddecl);
- /* If either decl says `inline', this fn is inline, unless
- its definition was passed already. */
- if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == NULL_TREE)
- DECL_INLINE (olddecl) = 1;
- DECL_INLINE (newdecl) = DECL_INLINE (olddecl);
-
DECL_UNINLINABLE (newdecl) = DECL_UNINLINABLE (olddecl)
= (DECL_UNINLINABLE (newdecl) || DECL_UNINLINABLE (olddecl));
+
+ DECL_DISREGARD_INLINE_LIMITS (newdecl)
+ = DECL_DISREGARD_INLINE_LIMITS (olddecl)
+ = (DECL_DISREGARD_INLINE_LIMITS (newdecl)
+ || DECL_DISREGARD_INLINE_LIMITS (olddecl));
}
/* Preserve abstractness on cloned [cd]tors. */
ggc_free (DECL_LANG_SPECIFIC (olddecl));
}
+ /* Merge the USED information. */
+ if (TREE_USED (olddecl))
+ TREE_USED (newdecl) = 1;
+ else if (TREE_USED (newdecl))
+ TREE_USED (olddecl) = 1;
+
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
int function_size;
{
if (DECL_NAME (olddecl) == NULL_TREE)
return "%q#D not declared in class";
- else
+ else if (!GNU_INLINE_P (olddecl)
+ || GNU_INLINE_P (newdecl))
return "redefinition of %q#D";
}
+
+ if (DECL_DECLARED_INLINE_P (olddecl) && DECL_DECLARED_INLINE_P (newdecl))
+ {
+ bool olda = GNU_INLINE_P (olddecl);
+ bool newa = GNU_INLINE_P (newdecl);
+
+ if (olda != newa)
+ {
+ if (newa)
+ return "%q+D redeclared inline with %<gnu_inline%> attribute";
+ else
+ return "%q+D redeclared inline without %<gnu_inline%> attribute";
+ }
+ }
+
return NULL;
}
else if (TREE_CODE (newdecl) == TEMPLATE_DECL)
ot = DECL_TEMPLATE_RESULT (olddecl);
if (DECL_TEMPLATE_INFO (ot))
ot = DECL_TEMPLATE_RESULT (template_for_substitution (ot));
- if (DECL_INITIAL (nt) && DECL_INITIAL (ot))
+ if (DECL_INITIAL (nt) && DECL_INITIAL (ot)
+ && (!GNU_INLINE_P (ot) || GNU_INLINE_P (nt)))
return "redefinition of %q#D";
+ if (DECL_DECLARED_INLINE_P (ot) && DECL_DECLARED_INLINE_P (nt))
+ {
+ bool olda = GNU_INLINE_P (ot);
+ bool newa = GNU_INLINE_P (nt);
+
+ if (olda != newa)
+ {
+ if (newa)
+ return "%q+D redeclared inline with %<gnu_inline%> attribute";
+ else
+ return "%q+D redeclared inline without %<gnu_inline%> attribute";
+ }
+ }
+
+ /* Core issue #226 (C++0x):
+
+ If a friend function template declaration specifies a
+ default template-argument, that declaration shall be a
+ definition and shall be the only declaration of the
+ function template in the translation unit. */
+ if ((cxx_dialect != cxx98)
+ && TREE_CODE (ot) == FUNCTION_DECL && DECL_FRIEND_P (ot)
+ && !check_default_tmpl_args (nt, DECL_TEMPLATE_PARMS (newdecl),
+ /*is_primary=*/1, /*is_partial=*/0,
+ /*is_friend_decl=*/2))
+ return "redeclaration of friend %q#D may not have default template arguments";
+
return NULL;
}
else if (TREE_CODE (newdecl) == VAR_DECL
}
else if (toplevel_bindings_p () || DECL_NAMESPACE_SCOPE_P (newdecl))
{
- /* Objects declared at top level: */
- /* If at least one is a reference, it's ok. */
+ /* The objects have been declared at namespace scope. If either
+ is a member of an anonymous union, then this is an invalid
+ redeclaration. For example:
+
+ int i;
+ union { int i; };
+
+ is invalid. */
+ if ((TREE_CODE (newdecl) == VAR_DECL && DECL_ANON_UNION_VAR_P (newdecl))
+ || (TREE_CODE (olddecl) == VAR_DECL && DECL_ANON_UNION_VAR_P (olddecl)))
+ return "redeclaration of %q#D";
+ /* If at least one declaration is a reference, there is no
+ conflict. For example:
+
+ int i = 3;
+ extern int i;
+
+ is valid. */
if (DECL_EXTERNAL (newdecl) || DECL_EXTERNAL (olddecl))
return NULL;
/* Reject two definitions. */
identify_goto (tree decl, const location_t *locus)
{
if (decl)
- pedwarn ("jump to label %qD", decl);
+ permerror ("jump to label %qD", decl);
else
- pedwarn ("jump to case label");
+ permerror ("jump to case label");
if (locus)
- pedwarn ("%H from here", locus);
+ permerror ("%H from here", locus);
}
/* Check that a single previously seen jump to a newly defined label
if (problem > 1)
error (" crosses initialization of %q+#D", new_decls);
else
- pedwarn (" enters scope of non-POD %q+#D", new_decls);
+ permerror (" enters scope of non-POD %q+#D", new_decls);
}
if (b == level)
if (ent->in_try_scope || ent->in_catch_scope
|| ent->in_omp_scope || ent->bad_decls)
{
- pedwarn ("jump to label %q+D", decl);
- pedwarn (" from here");
+ permerror ("jump to label %q+D", decl);
+ permerror (" from here");
identified = true;
}
else if (u > 1)
error (" skips initialization of %q+#D", b);
else
- pedwarn (" enters scope of non-POD %q+#D", b);
+ permerror (" enters scope of non-POD %q+#D", b);
}
if (ent->in_try_scope)
{
if (!identified)
{
- pedwarn ("jump to label %q+D", decl);
- pedwarn (" from here");
+ permerror ("jump to label %q+D", decl);
+ permerror (" from here");
identified = true;
}
error (" exits OpenMP structured block");
p->more_cleanups_ok = 0;
if (name == get_identifier ("wchar_t"))
- pedwarn ("label named wchar_t");
+ permerror ("label named wchar_t");
if (DECL_INITIAL (decl) != NULL_TREE)
{
typename_hash (const void* k)
{
hashval_t hash;
- tree t = (tree) k;
+ const_tree const t = (const_tree) k;
hash = (htab_hash_pointer (TYPE_CONTEXT (t))
^ htab_hash_pointer (DECL_NAME (TYPE_NAME (t))));
bool class_p;
} typename_info;
-/* Compare two TYPENAME_TYPEs. K1 and K2 are really of type `tree'. */
+/* Compare two TYPENAME_TYPEs. K1 is really of type `tree', K2 is
+ really of type `typename_info*' */
static int
typename_compare (const void * k1, const void * k2)
{
- tree t1;
- const typename_info *t2;
-
- t1 = (tree) k1;
- t2 = (const typename_info *) k2;
+ const_tree const t1 = (const_tree) k1;
+ const typename_info *const t2 = (const typename_info *) k2;
return (DECL_NAME (TYPE_NAME (t1)) == t2->name
&& TYPE_CONTEXT (t1) == t2->scope
else
{
/* Build the TYPENAME_TYPE. */
- t = make_aggr_type (TYPENAME_TYPE);
+ t = cxx_make_type (TYPENAME_TYPE);
TYPE_CONTEXT (t) = ti.scope;
TYPENAME_TYPE_FULLNAME (t) = ti.template_id;
TYPENAME_IS_ENUM_P (t) = ti.enum_p;
/* Store it in the hash table. */
*e = t;
+
+ /* TYPENAME_TYPEs must always be compared structurally, because
+ they may or may not resolve down to another type depending on
+ the currently open classes. */
+ SET_TYPE_STRUCTURAL_EQUALITY (t);
}
return t;
name = TREE_OPERAND (name, 0);
if (TREE_CODE (name) == TEMPLATE_DECL)
name = TREE_OPERAND (fullname, 0) = DECL_NAME (name);
+ else if (TREE_CODE (name) == OVERLOAD)
+ {
+ error ("%qD is not a type", name);
+ return error_mark_node;
+ }
}
if (TREE_CODE (name) == TEMPLATE_DECL)
{
if (dependent_type_p (context))
return build_typename_type (context, name, fullname, tag_type);
- if (!IS_AGGR_TYPE (context))
+ if (!MAYBE_CLASS_TYPE_P (context))
{
if (complain & tf_error)
error ("%q#T is not a class", context);
}
if (complain & tf_error)
- perform_or_defer_access_check (TYPE_BINFO (context), t);
+ perform_or_defer_access_check (TYPE_BINFO (context), t, t);
if (want_template)
return lookup_template_class (t, TREE_OPERAND (fullname, 1),
{
tree tmpl = NULL_TREE;
- if (IS_AGGR_TYPE (context))
+ if (MAYBE_CLASS_TYPE_P (context))
tmpl = lookup_field (context, name, 0, false);
if (!tmpl || !DECL_CLASS_TEMPLATE_P (tmpl))
}
if (complain & tf_error)
- perform_or_defer_access_check (TYPE_BINFO (context), tmpl);
+ perform_or_defer_access_check (TYPE_BINFO (context), tmpl, tmpl);
return tmpl;
}
/* Build the UNBOUND_CLASS_TEMPLATE. */
- t = make_aggr_type (UNBOUND_CLASS_TEMPLATE);
+ t = cxx_make_type (UNBOUND_CLASS_TEMPLATE);
TYPE_CONTEXT (t) = FROB_CONTEXT (context);
TREE_TYPE (t) = NULL_TREE;
+ SET_TYPE_STRUCTURAL_EQUALITY (t);
/* Build the corresponding TEMPLATE_DECL. */
d = build_decl (TEMPLATE_DECL, name, t);
return type;
}
-/* Push a type into the namespace so that the back-ends ignore it. */
+/* Push a type into the namespace so that the back ends ignore it. */
static void
record_unknown_type (tree type, const char* name)
current_lang_name = NULL_TREE;
- /* Adjust various flags based on command-line settings. */
- if (!flag_permissive)
- flag_pedantic_errors = 1;
- if (!flag_no_inline)
- {
- flag_inline_trees = 1;
- flag_no_inline = 1;
- }
- if (flag_inline_functions)
- flag_inline_trees = 2;
-
- /* Force minimum function alignment if using the least significant
- bit of function pointers to store the virtual bit. */
- if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_pfn
- && force_align_functions_log < 1)
- force_align_functions_log = 1;
+ if (flag_visibility_ms_compat)
+ default_visibility = VISIBILITY_HIDDEN;
/* Initially, C. */
current_lang_name = lang_name_c;
TYPE_POINTER_TO (unknown_type_node) = unknown_type_node;
TYPE_REFERENCE_TO (unknown_type_node) = unknown_type_node;
+ init_list_type_node = make_node (UNKNOWN_TYPE);
+ record_unknown_type (init_list_type_node, "init list");
+
{
/* Make sure we get a unique function type, so we can give
its pointer type a name. (This wins for gdb.) */
push_namespace (std_identifier);
bad_alloc_id = get_identifier ("bad_alloc");
- bad_alloc_type_node = make_aggr_type (RECORD_TYPE);
+ bad_alloc_type_node = make_class_type (RECORD_TYPE);
TYPE_CONTEXT (bad_alloc_type_node) = current_namespace;
bad_alloc_decl
= create_implicit_typedef (bad_alloc_id, bad_alloc_type_node);
tree decl = build_decl (VAR_DECL, id, type);
if (name)
- free ((char *) name);
+ free (CONST_CAST (char *, name));
/* As we're using pushdecl_with_scope, we must set the context. */
DECL_CONTEXT (decl) = current_function_decl;
anticipated but not actually declared. */
if (name[0] != '_' || name[1] != '_')
DECL_ANTICIPATED (decl) = 1;
+ else if (strncmp (name + 2, "builtin_", strlen ("builtin_")) != 0)
+ {
+ size_t len = strlen (name);
+
+ /* Treat __*_chk fortification functions as anticipated as well,
+ unless they are __builtin_*. */
+ if (len > strlen ("___chk")
+ && memcmp (name + len - strlen ("_chk"),
+ "_chk", strlen ("_chk") + 1) == 0)
+ DECL_ANTICIPATED (decl) = 1;
+ }
return decl;
}
{
tree id = DECL_NAME (decl);
const char *name = IDENTIFIER_POINTER (id);
- tree decl2 = copy_node(decl);
/* All builtins that don't begin with an '_' should additionally
go in the 'std' namespace. */
if (name[0] != '_')
{
+ tree decl2 = copy_node(decl);
push_namespace (std_identifier);
- builtin_function_1 (decl, std_node);
+ builtin_function_1 (decl2, std_node);
pop_namespace ();
}
- return builtin_function_1 (decl2, NULL_TREE);
+ return builtin_function_1 (decl, NULL_TREE);
}
/* Generate a FUNCTION_DECL with the typical flags for a runtime library
We assume that such functions never throw; if this is incorrect,
callers should unset TREE_NOTHROW. */
-tree
+static tree
build_library_fn (tree name, tree type)
{
tree fn = build_library_fn_1 (name, ERROR_MARK, type);
}
/* Like build_library_fn, but also pushes the function so that we will
- be able to find it via IDENTIFIER_GLOBAL_VALUE. */
+ be able to find it via IDENTIFIER_GLOBAL_VALUE. Also, the function
+ may throw exceptions listed in RAISES. */
tree
-push_library_fn (tree name, tree type)
+push_library_fn (tree name, tree type, tree raises)
{
- tree fn = build_library_fn (name, type);
+ tree fn;
+
+ if (raises)
+ type = build_exception_variant (type, raises);
+
+ fn = build_library_fn (name, type);
pushdecl_top_level (fn);
return fn;
}
push_void_library_fn (tree name, tree parmtypes)
{
tree type = build_function_type (void_type_node, parmtypes);
- return push_library_fn (name, type);
+ return push_library_fn (name, type, NULL_TREE);
}
/* Like push_library_fn, but also note that this function throws
tree
push_throw_library_fn (tree name, tree type)
{
- tree fn = push_library_fn (name, type);
+ tree fn = push_library_fn (name, type, NULL_TREE);
TREE_THIS_VOLATILE (fn) = 1;
TREE_NOTHROW (fn) = 0;
return fn;
tree *q;
/* Wipe out memory of synthesized methods. */
- TYPE_HAS_CONSTRUCTOR (t) = 0;
+ TYPE_HAS_USER_CONSTRUCTOR (t) = 0;
TYPE_HAS_DEFAULT_CONSTRUCTOR (t) = 0;
TYPE_HAS_INIT_REF (t) = 0;
TYPE_HAS_CONST_INIT_REF (t) = 0;
/* ISO C++ 9.5.3. Anonymous unions may not have function members. */
if (TYPE_METHODS (t))
- error ("%Jan anonymous union cannot have function members",
- TYPE_MAIN_DECL (t));
+ {
+ tree decl = TYPE_MAIN_DECL (t);
+
+ if (TREE_CODE (t) != UNION_TYPE)
+ error ("%Jan anonymous struct cannot have function members", decl);
+ else
+ error ("%Jan anonymous union cannot have function members", decl);
+ }
/* Anonymous aggregates cannot have fields with ctors, dtors or complex
assignment operators (because they cannot have these methods themselves).
else if (declspecs->redefined_builtin_type)
{
if (!in_system_header)
- pedwarn ("redeclaration of C++ built-in type %qT",
- declspecs->redefined_builtin_type);
+ permerror ("redeclaration of C++ built-in type %qT",
+ declspecs->redefined_builtin_type);
return NULL_TREE;
}
if (declspecs->type
&& TYPE_P (declspecs->type)
&& ((TREE_CODE (declspecs->type) != TYPENAME_TYPE
- && IS_AGGR_TYPE (declspecs->type))
+ && MAYBE_CLASS_TYPE_P (declspecs->type))
|| TREE_CODE (declspecs->type) == ENUMERAL_TYPE))
declared_type = declspecs->type;
else if (declspecs->type == error_mark_node)
error_p = true;
if (declared_type == NULL_TREE && ! saw_friend && !error_p)
- pedwarn ("declaration does not declare anything");
+ permerror ("declaration does not declare anything");
/* Check for an anonymous union. */
- else if (declared_type && IS_AGGR_TYPE_CODE (TREE_CODE (declared_type))
+ else if (declared_type && RECORD_OR_UNION_CODE_P (TREE_CODE (declared_type))
&& TYPE_ANONYMOUS_P (declared_type))
{
/* 7/3 In a simple-declaration, the optional init-declarator-list
/* Anonymous unions are objects, so they can have specifiers. */;
SET_ANON_AGGR_TYPE_P (declared_type);
- if (TREE_CODE (declared_type) != UNION_TYPE && pedantic
- && !in_system_header)
- pedwarn ("ISO C++ prohibits anonymous structs");
+ if (TREE_CODE (declared_type) != UNION_TYPE && !in_system_header)
+ pedwarn (OPT_pedantic, "ISO C++ prohibits anonymous structs");
}
else
|| declspecs->specs[(int)ds_thread])
error ("qualifiers can only be specified for objects "
"and functions");
+ else if (saw_typedef)
+ warning (0, "%<typedef%> was ignored in this declaration");
}
return declared_type;
attrs = type_specifiers->attributes;
type_specifiers->attributes = NULL_TREE;
type = grokdeclarator (declarator, type_specifiers, TYPENAME, 0, &attrs);
- if (attrs)
- cplus_decl_attributes (&type, attrs, 0);
+ if (attrs && type != error_mark_node)
+ {
+ if (CLASS_TYPE_P (type))
+ warning (OPT_Wattributes, "ignoring attributes applied to class type %qT "
+ "outside of definition", type);
+ else if (MAYBE_CLASS_TYPE_P (type))
+ /* A template type parameter or other dependent type. */
+ warning (OPT_Wattributes, "ignoring attributes applied to dependent "
+ "type %qT without an associated declaration", type);
+ else
+ cplus_decl_attributes (&type, attrs, 0);
+ }
return type;
}
-/* Decode a declarator in an ordinary declaration or data definition.
- This is called as soon as the type information and variable name
- have been parsed, before parsing the initializer if any.
- Here we create the ..._DECL node, fill in its type,
- and put it on the list of decls for the current context.
- The ..._DECL node is returned as the value.
-
- Exception: for arrays where the length is not specified,
- the type is left null, to be filled in by `cp_finish_decl'.
-
- Function definitions do not come here; they go to start_function
- instead. However, external and forward declarations of functions
- do go through here. Structure field declarations are done by
- grokfield and not through here. */
+/* Process a DECLARATOR for a function-scope variable declaration,
+ namespace-scope variable declaration, or function declaration.
+ (Function definitions go through start_function; class member
+ declarations appearing in the body of the class go through
+ grokfield.) The DECL corresponding to the DECLARATOR is returned.
+ If an error occurs, the error_mark_node is returned instead.
+
+ DECLSPECS are the decl-specifiers for the declaration. INITIALIZED is 1
+ if an explicit initializer is present, or 2 for an explicitly defaulted
+ function, or 3 for an explicitly deleted function, but 0 if this is a
+ variable implicitly initialized via a default constructor. ATTRIBUTES
+ and PREFIX_ATTRIBUTES are GNU attributes associated with this
+ declaration. *PUSHED_SCOPE_P is set to the scope entered in this
+ function, if any; if set, the caller is responsible for calling
+ pop_scope. */
tree
start_decl (const cp_declarator *declarator,
tree *pushed_scope_p)
{
tree decl;
- tree type, tem;
+ tree type;
tree context;
+ bool was_public;
+ int flags;
*pushed_scope_p = NULL_TREE;
switch (TREE_CODE (decl))
{
case TYPE_DECL:
- error ("typedef %qD is initialized (use __typeof__ instead)", decl);
+ error ("typedef %qD is initialized (use decltype instead)", decl);
return error_mark_node;
case FUNCTION_DECL:
- error ("function %q#D is initialized like a variable", decl);
- return error_mark_node;
+ if (initialized == 3)
+ /* We'll handle the rest of the semantics later, but we need to
+ set this now so it's visible to duplicate_decls. */
+ DECL_DELETED_FN (decl) = 1;
+ break;
default:
break;
TREE_STATIC (decl) = 1;
}
+ /* If this is a typedef that names the class for linkage purposes
+ (7.1.3p8), apply any attributes directly to the type. */
+ if (TREE_CODE (decl) == TYPE_DECL
+ && TAGGED_TYPE_P (TREE_TYPE (decl))
+ && decl == TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (decl))))
+ flags = ATTR_FLAG_TYPE_IN_PLACE;
+ else
+ flags = 0;
+
/* Set attributes here so if duplicate decl, will have proper attributes. */
- cplus_decl_attributes (&decl, attributes, 0);
+ cplus_decl_attributes (&decl, attributes, flags);
/* Dllimported symbols cannot be defined. Static data members (which
can be initialized in-class and dllimported) go through grokfield,
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%>",
- DECL_CONTEXT (field), DECL_NAME (decl),
- context, DECL_NAME (decl));
+ permerror ("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))
? current_template_parms
: NULL_TREE);
- if (field && duplicate_decls (decl, field,
- /*newdecl_is_friend=*/false))
+ if (field && field != error_mark_node
+ && duplicate_decls (decl, field,
+ /*newdecl_is_friend=*/false))
decl = field;
}
}
if (DECL_EXTERNAL (decl) && ! DECL_TEMPLATE_SPECIALIZATION (decl))
- pedwarn ("declaration of %q#D outside of class is not definition",
- decl);
+ permerror ("declaration of %q#D outside of class is not definition",
+ decl);
}
+ was_public = TREE_PUBLIC (decl);
+
/* Enter this declaration into the symbol table. */
- tem = maybe_push_decl (decl);
+ decl = maybe_push_decl (decl);
if (processing_template_decl)
- tem = push_template_decl (tem);
- if (tem == error_mark_node)
+ decl = push_template_decl (decl);
+ if (decl == error_mark_node)
return error_mark_node;
- /* Tell the back-end to use or not use .common as appropriate. If we say
+ /* Tell the back end to use or not use .common as appropriate. If we say
-fconserve-space, we want this to save .data space, at the expense of
wrong semantics. If we say -fno-conserve-space, we want this to
produce errors about redefs; to do this we force variables into the
data segment. */
if (flag_conserve_space
- && TREE_CODE (tem) == VAR_DECL
- && TREE_PUBLIC (tem)
- && !DECL_THREAD_LOCAL_P (tem)
+ && TREE_CODE (decl) == VAR_DECL
+ && TREE_PUBLIC (decl)
+ && !DECL_THREAD_LOCAL_P (decl)
&& !have_global_bss_p ())
- DECL_COMMON (tem) = 1;
+ DECL_COMMON (decl) = 1;
- if (!processing_template_decl && TREE_CODE (tem) == VAR_DECL)
- start_decl_1 (tem, initialized);
+ if (TREE_CODE (decl) == VAR_DECL
+ && DECL_NAMESPACE_SCOPE_P (decl) && !TREE_PUBLIC (decl) && !was_public
+ && !DECL_THIS_STATIC (decl) && !DECL_ARTIFICIAL (decl))
+ {
+ /* This is a const variable with implicit 'static'. Set
+ DECL_THIS_STATIC so we can tell it from variables that are
+ !TREE_PUBLIC because of the anonymous namespace. */
+ gcc_assert (cp_type_readonly (TREE_TYPE (decl)));
+ DECL_THIS_STATIC (decl) = 1;
+ }
- return tem;
+ if (!processing_template_decl && TREE_CODE (decl) == VAR_DECL)
+ start_decl_1 (decl, initialized);
+
+ return decl;
}
+/* Process the declaration of a variable DECL. INITIALIZED is true
+ iff DECL is explicitly initialized. (INITIALIZED is false if the
+ variable is initialized via an implicitly-called constructor.)
+ This function must be called for ordinary variables (including, for
+ example, implicit instantiations of templates), but must not be
+ called for template declarations. */
+
void
start_decl_1 (tree decl, bool initialized)
{
tree type;
+ bool complete_p;
+ bool aggregate_definition_p;
gcc_assert (!processing_template_decl);
return;
gcc_assert (TREE_CODE (decl) == VAR_DECL);
+
type = TREE_TYPE (decl);
+ complete_p = COMPLETE_TYPE_P (type);
+ aggregate_definition_p = MAYBE_CLASS_TYPE_P (type) && !DECL_EXTERNAL (decl);
+
+ /* If an explicit initializer is present, or if this is a definition
+ of an aggregate, then we need a complete type at this point.
+ (Scalars are always complete types, so there is nothing to
+ check.) This code just sets COMPLETE_P; errors (if necessary)
+ are issued below. */
+ if ((initialized || aggregate_definition_p)
+ && !complete_p
+ && COMPLETE_TYPE_P (complete_type (type)))
+ {
+ complete_p = true;
+ /* We will not yet have set TREE_READONLY on DECL if the type
+ was "const", but incomplete, before this point. But, now, we
+ have a complete type, so we can try again. */
+ cp_apply_type_quals_to_decl (cp_type_quals (type), decl);
+ }
if (initialized)
- /* Is it valid for this decl to have an initializer at all?
- If not, set INITIALIZED to zero, which will indirectly
- tell `cp_finish_decl' to ignore the initializer once it is parsed. */
+ /* Is it valid for this decl to have an initializer at all? */
{
/* Don't allow initializations for incomplete types except for
arrays which might be completed by the initialization. */
- if (COMPLETE_TYPE_P (complete_type (type)))
+ if (complete_p)
; /* A complete type is ok. */
else if (TREE_CODE (type) != ARRAY_TYPE)
{
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 %q#D have incomplete type", decl);
/* else we already gave an error in start_decl. */
- initialized = 0;
}
}
- else if (IS_AGGR_TYPE (type)
- && ! DECL_EXTERNAL (decl))
+ else if (aggregate_definition_p && !complete_p)
{
- if (!COMPLETE_TYPE_P (complete_type (type)))
- {
- 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)). */
- type = TREE_TYPE (decl) = error_mark_node;
- }
- else
- {
- /* If any base type in the hierarchy of TYPE needs a constructor,
- then we set initialized to 1. This way any nodes which are
- created for the purposes of initializing this aggregate
- will live as long as it does. This is necessary for global
- aggregates which do not have their initializers processed until
- the end of the file. */
- initialized = TYPE_NEEDS_CONSTRUCTING (type);
- }
+ 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)). */
+ type = TREE_TYPE (decl) = error_mark_node;
}
/* Create a new scope to hold this declaration if necessary.
return NULL_TREE;
}
+/* Subroutine of check_initializer. We're initializing a DECL of
+ std::initializer_list<T> TYPE from a braced-init-list INIT, and need to
+ extend the lifetime of the underlying array to match that of the decl,
+ just like for reference initialization. CLEANUP is as for
+ grok_reference_init. */
+
+static tree
+build_init_list_var_init (tree decl, tree type, tree init, tree *cleanup)
+{
+ tree aggr_init, array, arrtype;
+ init = perform_implicit_conversion (type, init, tf_warning_or_error);
+ aggr_init = TARGET_EXPR_INITIAL (init);
+ init = build2 (INIT_EXPR, type, decl, init);
+
+ array = AGGR_INIT_EXPR_ARG (aggr_init, 1);
+ arrtype = TREE_TYPE (array);
+ STRIP_NOPS (array);
+ gcc_assert (TREE_CODE (array) == ADDR_EXPR);
+ array = TREE_OPERAND (array, 0);
+ /* If the array is constant, finish_compound_literal already made it a
+ static variable and we don't need to do anything here. */
+ if (decl && TREE_CODE (array) == TARGET_EXPR)
+ {
+ tree subinit;
+ tree var = set_up_extended_ref_temp (decl, array, cleanup, &subinit);
+ var = build_address (var);
+ var = convert (arrtype, var);
+ AGGR_INIT_EXPR_ARG (aggr_init, 1) = var;
+ init = build2 (COMPOUND_EXPR, TREE_TYPE (init), subinit, init);
+ }
+ return init;
+}
+
+/* Designated initializers in arrays are not supported in GNU C++.
+ The parser cannot detect this error since it does not know whether
+ a given brace-enclosed initializer is for a class type or for an
+ array. This function checks that CE does not use a designated
+ initializer. If it does, an error is issued. Returns true if CE
+ is valid, i.e., does not have a designated initializer. */
+
+static bool
+check_array_designated_initializer (const constructor_elt *ce)
+{
+ /* Designated initializers for array elements are not supported. */
+ if (ce->index)
+ {
+ /* The parser only allows identifiers as designated
+ initializers. */
+ gcc_assert (TREE_CODE (ce->index) == IDENTIFIER_NODE);
+ error ("name %qD used in a GNU-style designated "
+ "initializer for an array", ce->index);
+ return false;
+ }
+
+ return true;
+}
+
/* When parsing `int a[] = {1, 2};' we don't know the size of the
array until we finish parsing the initializer. If that's the
situation we're in, update DECL accordingly. */
But let's leave it here to ease the eventual merge. */
int do_default = !DECL_EXTERNAL (decl);
tree initializer = init ? init : DECL_INITIAL (decl);
- int failure = cp_complete_array_type (&TREE_TYPE (decl), initializer,
- do_default);
+ int failure = 0;
- if (failure == 1)
+ /* Check that there are no designated initializers in INIT, as
+ those are not supported in GNU C++, and as the middle-end
+ will crash if presented with a non-numeric designated
+ initializer. */
+ if (initializer && TREE_CODE (initializer) == CONSTRUCTOR)
{
- error ("initializer fails to determine size of %qD", decl);
- TREE_TYPE (decl) = error_mark_node;
+ VEC(constructor_elt,gc) *v = CONSTRUCTOR_ELTS (initializer);
+ constructor_elt *ce;
+ HOST_WIDE_INT i;
+ for (i = 0;
+ VEC_iterate (constructor_elt, v, i, ce);
+ ++i)
+ if (!check_array_designated_initializer (ce))
+ failure = 1;
}
- else if (failure == 2)
+
+ if (!failure)
{
- if (do_default)
+ failure = cp_complete_array_type (&TREE_TYPE (decl), initializer,
+ do_default);
+ if (failure == 1)
{
- error ("array size missing in %qD", decl);
+ error ("initializer fails to determine size of %qD", decl);
+ TREE_TYPE (decl) = error_mark_node;
+ }
+ else if (failure == 2)
+ {
+ if (do_default)
+ {
+ error ("array size missing in %qD", decl);
+ TREE_TYPE (decl) = error_mark_node;
+ }
+ /* If a `static' var's size isn't known, make it extern as
+ well as static, so it does not get allocated. If it's not
+ `static', then don't mark it extern; finish_incomplete_decl
+ will give it a default size and it will get allocated. */
+ else if (!pedantic && TREE_STATIC (decl) && !TREE_PUBLIC (decl))
+ DECL_EXTERNAL (decl) = 1;
+ }
+ else if (failure == 3)
+ {
+ error ("zero-size array %qD", decl);
TREE_TYPE (decl) = error_mark_node;
}
- /* If a `static' var's size isn't known, make it extern as
- well as static, so it does not get allocated. If it's not
- `static', then don't mark it extern; finish_incomplete_decl
- will give it a default size and it will get allocated. */
- else if (!pedantic && TREE_STATIC (decl) && !TREE_PUBLIC (decl))
- DECL_EXTERNAL (decl) = 1;
- }
- else if (failure == 3)
- {
- error ("zero-size array %qD", decl);
- TREE_TYPE (decl) = error_mark_node;
}
cp_apply_type_quals_to_decl (cp_type_quals (TREE_TYPE (decl)), decl);
/* Keep this code around in case we later want to control debug info
based on whether a type is "used". (jason 1999-11-11) */
- else if (!DECL_EXTERNAL (decl) && IS_AGGR_TYPE (ttype))
+ else if (!DECL_EXTERNAL (decl) && MAYBE_CLASS_TYPE_P (ttype))
/* Let debugger know it should output info for this type. */
note_debug_info_needed (ttype);
if (TREE_CODE (DECL_SIZE (decl)) == INTEGER_CST)
constant_expression_warning (DECL_SIZE (decl));
else
- error ("storage size of %qD isn't constant", decl);
+ {
+ error ("storage size of %qD isn't constant", decl);
+ TREE_TYPE (decl) = error_mark_node;
+ }
}
}
unsigned HOST_WIDE_INT index;
/* The initializer for an array is always a CONSTRUCTOR. */
- new_init = build_constructor (NULL_TREE, NULL);
+ new_init = build_constructor (init_list_type_node, NULL);
if (sized_array_p)
{
{
tree elt_init;
- if (d->cur->index)
- {
- /* Handle array designated initializers (GNU extension). */
- if (TREE_CODE (d->cur->index) == IDENTIFIER_NODE)
- {
- error ("name %qD used in a GNU-style designated "
- "initializer for an array", d->cur->index);
- }
- else
- gcc_unreachable ();
- }
-
+ check_array_designated_initializer (d->cur);
elt_init = reshape_init_r (elt_type, d, /*first_initializer_p=*/false);
if (elt_init == error_mark_node)
return error_mark_node;
gcc_assert (CLASS_TYPE_P (type));
/* The initializer for a class is always a CONSTRUCTOR. */
- new_init = build_constructor (NULL_TREE, NULL);
+ new_init = build_constructor (init_list_type_node, NULL);
field = next_initializable_field (TYPE_FIELDS (type));
if (!field)
if (!CP_AGGREGATE_TYPE_P (type))
{
/* It is invalid to initialize a non-aggregate type with a
- brace-enclosed initializer.
+ brace-enclosed initializer before C++0x.
We need to check for BRACE_ENCLOSED_INITIALIZER_P here because
of g++.old-deja/g++.mike/p7626.C: a pointer-to-member constant is
a CONSTRUCTOR (with a record type). */
if (TREE_CODE (init) == CONSTRUCTOR
&& BRACE_ENCLOSED_INITIALIZER_P (init)) /* p7626.C */
{
- error ("braces around scalar initializer for type %qT", type);
- init = error_mark_node;
+ if (SCALAR_TYPE_P (type))
+ {
+ error ("braces around scalar initializer for type %qT", type);
+ init = error_mark_node;
+ }
+ else
+ maybe_warn_cpp0x ("extended initializer lists");
}
d->cur++;
{
if (TREE_CODE (init) == CONSTRUCTOR)
{
+ if (TREE_TYPE (init) && TYPE_PTRMEMFUNC_P (TREE_TYPE (init)))
+ /* There is no need to reshape pointer-to-member function
+ initializers, as they are always constructed correctly
+ by the front end. */
+ ;
+ else if (COMPOUND_LITERAL_P (init))
/* For a nested compound literal, there is no need to reshape since
brace elision is not allowed. Even if we decided to allow it,
we should add a call to reshape_init in finish_compound_literal,
before calling digest_init, so changing this code would still
not be necessary. */
- if (!COMPOUND_LITERAL_P (init))
+ gcc_assert (!BRACE_ENCLOSED_INITIALIZER_P (init));
+ else
{
++d->cur;
gcc_assert (BRACE_ENCLOSED_INITIALIZER_P (init));
return reshape_init (type, init);
}
- else
- gcc_assert (!BRACE_ENCLOSED_INITIALIZER_P (init));
}
warning (OPT_Wmissing_braces, "missing braces around initializer for %qT",
return new_init;
}
+/* Verify array initializer. Returns true if errors have been reported. */
+
+bool
+check_array_initializer (tree decl, tree type, tree init)
+{
+ tree element_type = TREE_TYPE (type);
+
+ /* The array type itself need not be complete, because the
+ initializer may tell us how many elements are in the array.
+ But, the elements of the array must be complete. */
+ if (!COMPLETE_TYPE_P (complete_type (element_type)))
+ {
+ if (decl)
+ error ("elements of array %q#D have incomplete type", decl);
+ else
+ error ("elements of array %q#T have incomplete type", type);
+ return true;
+ }
+ /* It is not valid to initialize a VLA. */
+ if (init
+ && ((COMPLETE_TYPE_P (type) && !TREE_CONSTANT (TYPE_SIZE (type)))
+ || !TREE_CONSTANT (TYPE_SIZE (element_type))))
+ {
+ if (decl)
+ error ("variable-sized object %qD may not be initialized", decl);
+ else
+ error ("variable-sized compound literal");
+ return true;
+ }
+ return false;
+}
+
+/* Subroutine of check_initializer; args are passed down from that function.
+ Set stmts_are_full_exprs_p to 1 across a call to build_aggr_init. */
+
+static tree
+build_aggr_init_full_exprs (tree decl, tree init, int flags)
+
+{
+ int saved_stmts_are_full_exprs_p = 0;
+ if (building_stmt_tree ())
+ {
+ saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
+ current_stmt_tree ()->stmts_are_full_exprs_p = 1;
+ }
+ init = build_aggr_init (decl, init, flags, tf_warning_or_error);
+ if (building_stmt_tree ())
+ current_stmt_tree ()->stmts_are_full_exprs_p =
+ saved_stmts_are_full_exprs_p;
+ return init;
+}
+
/* Verify INIT (the initializer for DECL), and record the
initialization in DECL_INITIAL, if appropriate. CLEANUP is as for
grok_reference_init.
if (TREE_CODE (type) == ARRAY_TYPE)
{
- tree element_type = TREE_TYPE (type);
-
- /* The array type itself need not be complete, because the
- initializer may tell us how many elements are in the array.
- But, the elements of the array must be complete. */
- if (!COMPLETE_TYPE_P (complete_type (element_type)))
- {
- error ("elements of array %q#D have incomplete type", decl);
- return NULL_TREE;
- }
- /* It is not valid to initialize an a VLA. */
- if (init
- && ((COMPLETE_TYPE_P (type) && !TREE_CONSTANT (TYPE_SIZE (type)))
- || !TREE_CONSTANT (TYPE_SIZE (element_type))))
- {
- error ("variable-sized object %qD may not be initialized", decl);
- return NULL_TREE;
- }
+ if (check_array_initializer (decl, type, init))
+ return NULL_TREE;
}
else if (!COMPLETE_TYPE_P (type))
{
else
/* There is no way to make a variable-sized class type in GNU C++. */
gcc_assert (TREE_CONSTANT (TYPE_SIZE (type)));
-
- if (!CP_AGGREGATE_TYPE_P (type)
- && init && BRACE_ENCLOSED_INITIALIZER_P (init)
- && VEC_length (constructor_elt, CONSTRUCTOR_ELTS (init)) != 1)
+
+ if (init && BRACE_ENCLOSED_INITIALIZER_P (init))
{
- error ("scalar object %qD requires one element in initializer", decl);
- TREE_TYPE (decl) = error_mark_node;
- return NULL_TREE;
+ int init_len = VEC_length (constructor_elt, CONSTRUCTOR_ELTS (init));
+ if (SCALAR_TYPE_P (type))
+ {
+ if (init_len == 0)
+ {
+ maybe_warn_cpp0x ("extended initializer lists");
+ init = build_zero_init (type, NULL_TREE, false);
+ }
+ else if (init_len != 1)
+ {
+ error ("scalar object %qD requires one element in initializer",
+ decl);
+ TREE_TYPE (decl) = error_mark_node;
+ return NULL_TREE;
+ }
+ }
}
if (TREE_CODE (decl) == CONST_DECL)
{
/* Do not reshape constructors of vectors (they don't need to be
reshaped. */
- if (TREE_CODE (init) == CONSTRUCTOR
- && !COMPOUND_LITERAL_P (init)
- && !TREE_TYPE (init)) /* ptrmemfunc */
+ if (BRACE_ENCLOSED_INITIALIZER_P (init))
{
- init = reshape_init (type, init);
-
- if ((*targetm.vector_opaque_p) (type))
+ if (is_std_init_list (type))
+ return build_init_list_var_init (decl, type, init, cleanup);
+ else if (TYPE_NON_AGGREGATE_CLASS (type))
+ {
+ /* Don't reshape if the class has constructors. */
+ if (cxx_dialect == cxx98)
+ error ("in C++98 %qD must be initialized by constructor, "
+ "not by %<{...}%>",
+ decl);
+ init = build_tree_list (NULL_TREE, init);
+ }
+ else if ((*targetm.vector_opaque_p) (type))
{
error ("opaque vector types cannot be initialized");
init = error_mark_node;
}
+ else
+ init = reshape_init (type, init);
}
/* If DECL has an array type without a specific bound, deduce the
if (type == error_mark_node)
return NULL_TREE;
- if (TYPE_HAS_CONSTRUCTOR (type) || TYPE_NEEDS_CONSTRUCTING (type))
- {
- if (TREE_CODE (type) == ARRAY_TYPE)
- goto initialize_aggr;
- else if (TREE_CODE (init) == CONSTRUCTOR)
- {
- if (TYPE_NON_AGGREGATE_CLASS (type))
- {
- error ("%qD must be initialized by constructor, "
- "not by %<{...}%>",
- decl);
- init = error_mark_node;
- }
- else
- goto dont_use_constructor;
- }
- else
- {
- int saved_stmts_are_full_exprs_p;
-
- initialize_aggr:
- saved_stmts_are_full_exprs_p = 0;
- if (building_stmt_tree ())
- {
- saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
- current_stmt_tree ()->stmts_are_full_exprs_p = 1;
- }
- init = build_aggr_init (decl, init, flags);
- if (building_stmt_tree ())
- current_stmt_tree ()->stmts_are_full_exprs_p =
- saved_stmts_are_full_exprs_p;
- return init;
- }
- }
- else
+ if (TYPE_NEEDS_CONSTRUCTING (type)
+ || (CLASS_TYPE_P (type)
+ && !BRACE_ENCLOSED_INITIALIZER_P (init)))
+ return build_aggr_init_full_exprs (decl, init, flags);
+ else if (TREE_CODE (init) != TREE_VEC)
{
- dont_use_constructor:
- 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 (0, "array %qD initialized by parenthesized string literal %qE",
- decl, DECL_INITIAL (decl));
- init = NULL;
- }
+ 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 (0, "array %qD initialized by parenthesized string literal %qE",
+ decl, DECL_INITIAL (decl));
+ init = NULL;
}
}
else if (DECL_EXTERNAL (decl))
;
else if (TYPE_P (type) && TYPE_NEEDS_CONSTRUCTING (type))
- goto initialize_aggr;
- else if (IS_AGGR_TYPE (type))
+ return build_aggr_init_full_exprs (decl, init, flags);
+ else if (MAYBE_CLASS_TYPE_P (type))
{
tree core_type = strip_array_types (type);
/* 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)
- gcc_assert (DECL_EXTERNAL (decl));
+ gcc_assert (DECL_EXTERNAL (decl) || !TREE_PUBLIC (decl));
}
/* We don't create any RTL for local variables. */
rest_of_decl_compilation (decl, toplev, at_eof);
}
+/* walk_tree helper for wrap_temporary_cleanups, below. */
+
+static tree
+wrap_cleanups_r (tree *stmt_p, int *walk_subtrees, void *data)
+{
+ if (TYPE_P (*stmt_p))
+ {
+ *walk_subtrees = 0;
+ return NULL_TREE;
+ }
+
+ if (TREE_CODE (*stmt_p) == TARGET_EXPR)
+ {
+ tree guard = (tree)data;
+ tree tcleanup = TARGET_EXPR_CLEANUP (*stmt_p);
+
+ tcleanup = build2 (TRY_CATCH_EXPR, void_type_node, tcleanup, guard);
+ /* Tell honor_protect_cleanup_actions to handle this as a separate
+ cleanup. */
+ TRY_CATCH_IS_CLEANUP (tcleanup) = 1;
+
+ TARGET_EXPR_CLEANUP (*stmt_p) = tcleanup;
+ }
+
+ return NULL_TREE;
+}
+
+/* We're initializing a local variable which has a cleanup GUARD. If there
+ are any temporaries used in the initializer INIT of this variable, we
+ need to wrap their cleanups with TRY_CATCH_EXPR (, GUARD) so that the
+ variable will be cleaned up properly if one of them throws.
+
+ Unfortunately, there's no way to express this properly in terms of
+ nesting, as the regions for the temporaries overlap the region for the
+ variable itself; if there are two temporaries, the variable needs to be
+ the first thing destroyed if either of them throws. However, we only
+ want to run the variable's cleanup if it actually got constructed. So
+ we need to guard the temporary cleanups with the variable's cleanup if
+ they are run on the normal path, but not if they are run on the
+ exceptional path. We implement this by telling
+ honor_protect_cleanup_actions to strip the variable cleanup from the
+ exceptional path. */
+
+static void
+wrap_temporary_cleanups (tree init, tree guard)
+{
+ cp_walk_tree_without_duplicates (&init, wrap_cleanups_r, (void *)guard);
+}
+
/* Generate code to initialize DECL (a local variable). */
static void
{
tree type = TREE_TYPE (decl);
tree cleanup;
+ int already_used;
gcc_assert (TREE_CODE (decl) == VAR_DECL
|| TREE_CODE (decl) == RESULT_DECL);
/* If we used it already as memory, it must stay in memory. */
DECL_INITIAL (decl) = NULL_TREE;
TREE_ADDRESSABLE (decl) = TREE_USED (decl);
+ return;
}
- if (DECL_SIZE (decl) && type != error_mark_node)
- {
- int already_used;
+ if (type == error_mark_node)
+ return;
- /* Compute and store the initial value. */
- already_used = TREE_USED (decl) || TREE_USED (type);
+ /* Compute and store the initial value. */
+ already_used = TREE_USED (decl) || TREE_USED (type);
- /* Perform the initialization. */
- if (init)
- {
- int saved_stmts_are_full_exprs_p;
+ /* Generate a cleanup, if necessary. */
+ cleanup = cxx_maybe_build_cleanup (decl);
- 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);
- current_stmt_tree ()->stmts_are_full_exprs_p =
- saved_stmts_are_full_exprs_p;
- }
+ /* Perform the initialization. */
+ if (init)
+ {
+ int saved_stmts_are_full_exprs_p;
- /* Set this to 0 so we can tell whether an aggregate which was
- initialized was ever used. Don't do this if it has a
- destructor, so we don't complain about the 'resource
- allocation is initialization' idiom. Now set
- attribute((unused)) on types so decls of that type will be
- marked used. (see TREE_USED, above.) */
- if (TYPE_NEEDS_CONSTRUCTING (type)
- && ! already_used
- && TYPE_HAS_TRIVIAL_DESTRUCTOR (type)
- && DECL_NAME (decl))
- TREE_USED (decl) = 0;
- else if (already_used)
- TREE_USED (decl) = 1;
- }
+ /* If we're only initializing a single object, guard the destructors
+ of any temporaries used in its initializer with its destructor.
+ This isn't right for arrays because each element initialization is
+ a full-expression. */
+ if (cleanup && TREE_CODE (type) != ARRAY_TYPE)
+ wrap_temporary_cleanups (init, cleanup);
- /* Generate a cleanup, if necessary. */
- cleanup = cxx_maybe_build_cleanup (decl);
- if (DECL_SIZE (decl) && cleanup)
+ 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);
+ current_stmt_tree ()->stmts_are_full_exprs_p =
+ saved_stmts_are_full_exprs_p;
+ }
+
+ /* Set this to 0 so we can tell whether an aggregate which was
+ initialized was ever used. Don't do this if it has a
+ destructor, so we don't complain about the 'resource
+ allocation is initialization' idiom. Now set
+ attribute((unused)) on types so decls of that type will be
+ marked used. (see TREE_USED, above.) */
+ if (TYPE_NEEDS_CONSTRUCTING (type)
+ && ! already_used
+ && TYPE_HAS_TRIVIAL_DESTRUCTOR (type)
+ && DECL_NAME (decl))
+ TREE_USED (decl) = 0;
+ else if (already_used)
+ TREE_USED (decl) = 1;
+
+ if (cleanup)
finish_decl_cleanup (decl, cleanup);
}
{
gcc_assert (DECL_ARTIFICIAL (decl));
if (TREE_CODE (init) == TREE_LIST)
- init = build_constructor_from_list (NULL_TREE, init);
+ init = build_constructor_from_list (TREE_TYPE (decl), init);
gcc_assert (TREE_CODE (init) == CONSTRUCTOR);
DECL_INITIAL (decl) = init;
DECL_INITIALIZED_P (decl) = 1;
make_rtl_for_nonlocal_decl (decl, init, /*asmspec=*/NULL);
}
+/* INIT is the initializer for a variable, as represented by the
+ parser. Returns true iff INIT is value-dependent. */
+
+static bool
+value_dependent_init_p (tree init)
+{
+ if (TREE_CODE (init) == TREE_LIST)
+ /* A parenthesized initializer, e.g.: int i (3, 2); ? */
+ return any_value_dependent_elements_p (init);
+ else if (TREE_CODE (init) == CONSTRUCTOR)
+ /* A brace-enclosed initializer, e.g.: int i = { 3 }; ? */
+ {
+ VEC(constructor_elt, gc) *elts;
+ size_t nelts;
+ size_t i;
+
+ elts = CONSTRUCTOR_ELTS (init);
+ nelts = VEC_length (constructor_elt, elts);
+ for (i = 0; i < nelts; ++i)
+ if (value_dependent_init_p (VEC_index (constructor_elt,
+ elts, i)->value))
+ return true;
+ }
+ else
+ /* It must be a simple expression, e.g., int i = 3; */
+ return value_dependent_expression_p (init);
+
+ return false;
+}
+
/* Finish processing of a declaration;
install its line number and initial value.
If the length of an array type is not known before,
type_dependent_p = dependent_type_p (type);
+ if (check_for_bare_parameter_packs (init))
+ {
+ init = NULL_TREE;
+ DECL_INITIAL (decl) = NULL_TREE;
+ }
+
if (init && init_const_expr_p)
{
DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = 1;
TREE_CONSTANT (decl) = 1;
}
- if (!init
- || !DECL_CLASS_SCOPE_P (decl)
- || !DECL_INTEGRAL_CONSTANT_VAR_P (decl)
- || type_dependent_p
- || value_dependent_expression_p (init))
+ /* Generally, initializers in templates are expanded when the
+ template is instantiated. But, if DECL is an integral
+ constant static data member, then it can be used in future
+ integral constant expressions, and its value must be
+ available. */
+ if (!(init
+ && DECL_CLASS_SCOPE_P (decl)
+ && DECL_INTEGRAL_CONSTANT_VAR_P (decl)
+ && !type_dependent_p
+ && !value_dependent_init_p (init)))
{
if (init)
DECL_INITIAL (decl) = init;
goto finish_end;
}
- init = fold_non_dependent_expr (init);
+ if (TREE_CODE (init) == TREE_LIST)
+ {
+ /* If the parenthesized-initializer form was used (e.g.,
+ "int A<N>::i(X)"), then INIT will be a TREE_LIST of initializer
+ arguments. (There is generally only one.) We convert them
+ individually. */
+ tree list = init;
+ for (; list; list = TREE_CHAIN (list))
+ {
+ tree elt = TREE_VALUE (list);
+ TREE_VALUE (list) = fold_non_dependent_expr (elt);
+ }
+ }
+ else
+ init = fold_non_dependent_expr (init);
processing_template_decl = 0;
}
if (TREE_CODE (decl) == TYPE_DECL)
{
if (type != error_mark_node
- && IS_AGGR_TYPE (type) && DECL_NAME (decl))
+ && MAYBE_CLASS_TYPE_P (type) && DECL_NAME (decl))
{
if (TREE_TYPE (DECL_NAME (decl)) && TREE_TYPE (decl) != type)
warning (0, "shadowing previous type declaration of %q#D", decl);
require a guard variable, and since the mangled name of the
guard variable will depend on the mangled name of this
variable. */
- if (!processing_template_decl
- && DECL_FUNCTION_SCOPE_P (decl)
+ if (DECL_FUNCTION_SCOPE_P (decl)
&& TREE_STATIC (decl)
&& !DECL_ARTIFICIAL (decl))
push_local_name (decl);
is *not* defined. */
&& (!DECL_EXTERNAL (decl) || init))
{
+ if (TYPE_FOR_JAVA (type) && MAYBE_CLASS_TYPE_P (type))
+ {
+ tree jclass
+ = IDENTIFIER_GLOBAL_VALUE (get_identifier ("jclass"));
+ /* Allow libjava/prims.cc define primitive classes. */
+ if (init != NULL_TREE
+ || jclass == NULL_TREE
+ || TREE_CODE (jclass) != TYPE_DECL
+ || !POINTER_TYPE_P (TREE_TYPE (jclass))
+ || !same_type_ignoring_top_level_qualifiers_p
+ (type, TREE_TYPE (TREE_TYPE (jclass))))
+ error ("Java object %qD not allocated with %<new%>", decl);
+ init = NULL_TREE;
+ }
if (init)
{
DECL_NONTRIVIALLY_INITIALIZED_P (decl) = 1;
else if (TREE_CODE (type) == ARRAY_TYPE)
layout_type (type);
}
+ else if (TREE_CODE (decl) == FIELD_DECL
+ && TYPE_FOR_JAVA (type) && MAYBE_CLASS_TYPE_P (type))
+ error ("non-static data member %qD has Java class type", decl);
/* Add this declaration to the statement-tree. This needs to happen
after the call to check_initializer so that the DECL_EXPR for a
{
layout_var_decl (decl);
maybe_commonize_var (decl);
- if (DECL_NAMESPACE_SCOPE_P (decl) && !TREE_PUBLIC (decl)
- && !DECL_THIS_STATIC (decl) && !DECL_ARTIFICIAL (decl))
+ }
+
+ /* This needs to happen after the linkage is set. */
+ determine_visibility (decl);
+
+ if (var_definition_p && TREE_STATIC (decl))
+ {
+ /* If a TREE_READONLY variable needs initialization
+ at runtime, it is no longer readonly and we need to
+ avoid MEM_READONLY_P being set on RTL created for it. */
+ if (init)
{
- /* This is a const variable with implicit 'static'. Set
- DECL_THIS_STATIC so we can tell it from variables that are
- !TREE_PUBLIC because of the anonymous namespace. */
- DECL_THIS_STATIC (decl) = 1;
+ if (TREE_READONLY (decl))
+ TREE_READONLY (decl) = 0;
+ was_readonly = 0;
}
+ else if (was_readonly)
+ TREE_READONLY (decl) = 1;
}
make_rtl_for_nonlocal_decl (decl, init, asmspec);
else
abstract_virtuals_error (decl, type);
- /* This needs to happen after the linkage is set. */
- determine_visibility (decl);
-
- if (TREE_CODE (decl) == FUNCTION_DECL
- || TREE_TYPE (decl) == error_mark_node)
+ if (TREE_TYPE (decl) == error_mark_node)
/* No initialization required. */
;
+ else if (TREE_CODE (decl) == FUNCTION_DECL)
+ {
+ if (init)
+ {
+ if (init == ridpointers[(int)RID_DELETE])
+ {
+ /* fixme check this is 1st decl */
+ DECL_DELETED_FN (decl) = 1;
+ DECL_DECLARED_INLINE_P (decl) = 1;
+ DECL_INITIAL (decl) = error_mark_node;
+ }
+ else if (init == ridpointers[(int)RID_DEFAULT])
+ {
+ if (!defaultable_fn_p (decl))
+ error ("%qD cannot be defaulted", decl);
+ else
+ {
+ /* An out-of-class default definition is defined at
+ the point where it is explicitly defaulted. */
+ DECL_DEFAULTED_FN (decl) = 1;
+ if (DECL_INITIAL (decl) == error_mark_node)
+ synthesize_method (decl);
+ }
+ }
+ else
+ error ("function %q#D is initialized like a variable", decl);
+ }
+ /* else no initialization required. */
+ }
else if (DECL_EXTERNAL (decl)
&& ! (DECL_LANG_SPECIFIC (decl)
&& DECL_NOT_REALLY_EXTERN (decl)))
if (init)
DECL_INITIAL (decl) = init;
}
- else
- {
- /* A variable definition. */
- if (DECL_FUNCTION_SCOPE_P (decl))
- {
- /* Initialize the local variable. */
- if (processing_template_decl)
- DECL_INITIAL (decl) = init;
- else if (!TREE_STATIC (decl))
- initialize_local_var (decl, init);
- }
+ /* A variable definition. */
+ else if (DECL_FUNCTION_SCOPE_P (decl) && !TREE_STATIC (decl))
+ /* Initialize the local variable. */
+ initialize_local_var (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 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. */
+ else 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
return decl;
}
+/* Returns the type for the argument to "__cxa_atexit" (or "atexit",
+ if "__cxa_atexit" is not being used) corresponding to the function
+ to be called when the program exits. */
+
+static tree
+get_atexit_fn_ptr_type (void)
+{
+ tree arg_types;
+ tree fn_type;
+
+ if (!atexit_fn_ptr_type_node)
+ {
+ if (flag_use_cxa_atexit
+ && !targetm.cxx.use_atexit_for_cxa_atexit ())
+ /* The parameter to "__cxa_atexit" is "void (*)(void *)". */
+ arg_types = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
+ else
+ /* The parameter to "atexit" is "void (*)(void)". */
+ arg_types = void_list_node;
+
+ fn_type = build_function_type (void_type_node, arg_types);
+ atexit_fn_ptr_type_node = build_pointer_type (fn_type);
+ }
+
+ return atexit_fn_ptr_type_node;
+}
+
/* Returns a pointer to the `atexit' function. Note that if
FLAG_USE_CXA_ATEXIT is nonzero, then this will actually be the new
`__cxa_atexit' function specified in the IA64 C++ ABI. */
use_aeabi_atexit = targetm.cxx.use_aeabi_atexit ();
/* First, build the pointer-to-function type for the first
argument. */
- arg_types = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
- fn_type = build_function_type (void_type_node, arg_types);
- fn_ptr_type = build_pointer_type (fn_type);
+ fn_ptr_type = get_atexit_fn_ptr_type ();
/* Then, build the rest of the argument types. */
arg_types = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
if (use_aeabi_atexit)
We build up the argument types and then then function type
itself. */
- fn_type = build_function_type (void_type_node, void_list_node);
- fn_ptr_type = build_pointer_type (fn_type);
+ fn_ptr_type = get_atexit_fn_ptr_type ();
arg_types = tree_cons (NULL_TREE, fn_ptr_type, void_list_node);
/* Build the final atexit type. */
fn_type = build_function_type (integer_type_node, arg_types);
start_cleanup_fn (void)
{
char name[32];
- tree parmtypes;
tree fntype;
tree fndecl;
bool use_cxa_atexit = flag_use_cxa_atexit
/* No need to mangle this. */
push_lang_context (lang_name_c);
- /* Build the parameter-types. */
- parmtypes = void_list_node;
- /* Functions passed to __cxa_atexit take an additional parameter.
- We'll just ignore it. After we implement the new calling
- convention for destructors, we can eliminate the use of
- additional cleanup functions entirely in the -fnew-abi case. */
- if (use_cxa_atexit)
- parmtypes = tree_cons (NULL_TREE, ptr_type_node, parmtypes);
- /* Build the function type itself. */
- fntype = build_function_type (void_type_node, parmtypes);
/* Build the name of the function. */
sprintf (name, "__tcf_%d", start_cleanup_cnt++);
/* Build the function declaration. */
+ fntype = TREE_TYPE (get_atexit_fn_ptr_type ());
fndecl = build_lang_decl (FUNCTION_DECL, get_identifier (name), fntype);
/* It's a function with internal linkage, generated by the
compiler. */
actually needed. It is unlikely that it will be inlined, since
it is only called via a function pointer, but we avoid unnecessary
emissions this way. */
- DECL_INLINE (fndecl) = 1;
- DECL_DECLARED_INLINE_P (fndecl) = 1;
DECL_INTERFACE_KNOWN (fndecl) = 1;
/* Build the parameter. */
if (use_cxa_atexit)
tree compound_stmt;
tree args;
tree fcall;
+ tree type;
+ bool use_dtor;
- if (TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (decl)))
+ type = TREE_TYPE (decl);
+ if (TYPE_HAS_TRIVIAL_DESTRUCTOR (type))
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,
- rather than the scope of the anonymous function. */
- build_cleanup (decl);
-
- /* Now start the function. */
- cleanup = start_cleanup_fn ();
-
- /* Now, recompute the cleanup. It may contain SAVE_EXPRs that refer
- to the original function, rather than the anonymous one. That
- will make the back-end think that nested functions are in use,
- which causes confusion. */
-
- push_deferring_access_checks (dk_no_check);
- fcall = build_cleanup (decl);
- pop_deferring_access_checks ();
+ /* If we're using "__cxa_atexit" (or "__aeabi_atexit"), and DECL is
+ a class object, we can just pass the destructor to
+ "__cxa_atexit"; we don't have to build a temporary function to do
+ the cleanup. */
+ use_dtor = (flag_use_cxa_atexit
+ && !targetm.cxx.use_atexit_for_cxa_atexit ()
+ && CLASS_TYPE_P (type));
+ if (use_dtor)
+ {
+ int idx;
- /* Create the body of the anonymous function. */
- compound_stmt = begin_compound_stmt (BCS_FN_BODY);
- finish_expr_stmt (fcall);
- finish_compound_stmt (compound_stmt);
- end_cleanup_fn ();
+ /* Find the destructor. */
+ idx = lookup_fnfields_1 (type, complete_dtor_identifier);
+ gcc_assert (idx >= 0);
+ cleanup = VEC_index (tree, CLASSTYPE_METHOD_VEC (type), idx);
+ /* Make sure it is accessible. */
+ perform_or_defer_access_check (TYPE_BINFO (type), cleanup, cleanup);
+ }
+ else
+ {
+ /* Call build_cleanup before we enter the anonymous function so
+ that any access checks will be done relative to the current
+ scope, rather than the scope of the anonymous function. */
+ build_cleanup (decl);
+
+ /* Now start the function. */
+ cleanup = start_cleanup_fn ();
+
+ /* Now, recompute the cleanup. It may contain SAVE_EXPRs that refer
+ to the original function, rather than the anonymous one. That
+ will make the back end think that nested functions are in use,
+ which causes confusion. */
+ push_deferring_access_checks (dk_no_check);
+ fcall = build_cleanup (decl);
+ pop_deferring_access_checks ();
+
+ /* Create the body of the anonymous function. */
+ compound_stmt = begin_compound_stmt (BCS_FN_BODY);
+ finish_expr_stmt (fcall);
+ finish_compound_stmt (compound_stmt);
+ end_cleanup_fn ();
+ }
/* Call atexit with the cleanup function. */
- cxx_mark_addressable (cleanup);
mark_used (cleanup);
- cleanup = build_unary_op (ADDR_EXPR, cleanup, 0);
+ cleanup = build_address (cleanup);
if (flag_use_cxa_atexit && !targetm.cxx.use_atexit_for_cxa_atexit ())
{
+ tree addr;
+
+ if (use_dtor)
+ {
+ /* We must convert CLEANUP to the type that "__cxa_atexit"
+ expects. */
+ cleanup = build_nop (get_atexit_fn_ptr_type (), cleanup);
+ /* "__cxa_atexit" will pass the address of DECL to the
+ cleanup function. */
+ mark_used (decl);
+ addr = build_address (decl);
+ /* The declared type of the parameter to "__cxa_atexit" is
+ "void *". For plain "T*", we could just let the
+ machinery in cp_build_function_call convert it -- but if the
+ type is "cv-qualified T *", then we need to convert it
+ before passing it in, to avoid spurious errors. */
+ addr = build_nop (ptr_type_node, addr);
+ }
+ else
+ /* Since the cleanup functions we build ignore the address
+ they're given, there's no reason to pass the actual address
+ in, and, in general, it's cheaper to pass NULL than any
+ other value. */
+ addr = null_pointer_node;
args = tree_cons (NULL_TREE,
- build_unary_op (ADDR_EXPR, get_dso_handle_node (), 0),
+ cp_build_unary_op (ADDR_EXPR, get_dso_handle_node (), 0,
+ tf_warning_or_error),
NULL_TREE);
if (targetm.cxx.use_aeabi_atexit ())
{
args = tree_cons (NULL_TREE, cleanup, args);
- args = tree_cons (NULL_TREE, null_pointer_node, args);
+ args = tree_cons (NULL_TREE, addr, args);
}
else
{
- args = tree_cons (NULL_TREE, null_pointer_node, args);
+ args = tree_cons (NULL_TREE, addr, args);
args = tree_cons (NULL_TREE, cleanup, args);
}
}
else
args = tree_cons (NULL_TREE, cleanup, NULL_TREE);
- return build_function_call (get_atexit_node (), args);
+ return cp_build_function_call (get_atexit_node (), args,
+ tf_warning_or_error);
}
/* DECL is a VAR_DECL with static storage duration. INIT, if present,
/* Emit code to perform this initialization but once. */
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 guard, guard_addr;
tree acquire_fn, release_fn, abort_fn;
tree flag, begin;
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");
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);
+ (acquire_fn, build_function_type (integer_type_node, argtypes),
+ NULL_TREE);
+ release_fn = push_library_fn (release_fn, vfntype, NULL_TREE);
+ abort_fn = push_library_fn (abort_fn, vfntype, NULL_TREE);
}
else
{
}
inner_if_stmt = begin_if_stmt ();
- finish_if_stmt_cond (build_call (acquire_fn, guard_addr_list),
+ finish_if_stmt_cond (build_call_n (acquire_fn, 1, guard_addr),
inner_if_stmt);
inner_then_clause = begin_compound_stmt (BCS_NO_SCOPE);
TARGET_EXPR_CLEANUP (begin)
= build3 (COND_EXPR, void_type_node, flag,
void_zero_node,
- build_call (abort_fn, guard_addr_list));
+ build_call_n (abort_fn, 1, guard_addr));
CLEANUP_EH_ONLY (begin) = 1;
/* Do the initialization itself. */
init = add_stmt_to_compound
(init, build2 (MODIFY_EXPR, void_type_node, flag, boolean_true_node));
init = add_stmt_to_compound
- (init, build_call (release_fn, guard_addr_list));
+ (init, build_call_n (release_fn, 1, guard_addr));
}
else
init = add_stmt_to_compound (init, set_guard (guard));
if (initial_value)
{
+ unsigned HOST_WIDE_INT i;
+ tree value;
+
/* An array of character type can be initialized from a
brace-enclosed string constant.
&& VEC_length (constructor_elt, v) == 1)
initial_value = value;
}
+
+ /* If any of the elements are parameter packs, we can't actually
+ complete this type now because the array size is dependent. */
+ if (TREE_CODE (initial_value) == CONSTRUCTOR)
+ {
+ FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (initial_value),
+ i, value)
+ {
+ if (PACK_EXPANSION_P (value))
+ return 0;
+ }
+ }
}
failure = complete_array_type (ptype, initial_value, do_default);
The definition for a static data member shall appear in a
namespace scope enclosing the member's class definition. */
if (!is_ancestor (current_namespace, DECL_CONTEXT (decl)))
- pedwarn ("definition of %qD is not in namespace enclosing %qT",
- decl, DECL_CONTEXT (decl));
+ permerror ("definition of %qD is not in namespace enclosing %qT",
+ decl, DECL_CONTEXT (decl));
}
/* Build a PARM_DECL for the "this" parameter. TYPE is the
if (TYPE_VOLATILE (type))
TREE_THIS_VOLATILE (decl) = 1;
+ /* Setup decl according to sfk. */
+ switch (sfk)
+ {
+ case sfk_constructor:
+ case sfk_copy_constructor:
+ DECL_CONSTRUCTOR_P (decl) = 1;
+ break;
+ case sfk_destructor:
+ DECL_DESTRUCTOR_P (decl) = 1;
+ break;
+ default:
+ break;
+ }
+
+ /* If pointers to member functions use the least significant bit to
+ indicate whether a function is virtual, ensure a pointer
+ to this function will have that bit clear. */
+ if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_pfn
+ && TREE_CODE (type) == METHOD_TYPE
+ && DECL_ALIGN (decl) < 2 * BITS_PER_UNIT)
+ DECL_ALIGN (decl) = 2 * BITS_PER_UNIT;
+
if (friendp
&& TREE_CODE (orig_declarator) == TEMPLATE_ID_EXPR)
{
error ("cannot declare %<::main%> to be inline");
if (!publicp)
error ("cannot declare %<::main%> to be static");
- if (!same_type_p (TREE_TYPE (TREE_TYPE (decl)),
- integer_type_node))
- {
- tree oldtypeargs = TYPE_ARG_TYPES (TREE_TYPE (decl));
- tree newtype;
- error ("%<::main%> must return %<int%>");
- newtype = build_function_type (integer_type_node,
- oldtypeargs);
- TREE_TYPE (decl) = newtype;
- }
- check_main_parameter_types (decl);
inlinep = 0;
publicp = 1;
}
/* Allow this; it's pretty common in C. */;
else
{
- pedwarn ("non-local function %q#D uses anonymous type",
+ permerror ("non-local function %q#D uses anonymous type",
decl);
if (DECL_ORIGINAL_TYPE (TYPE_NAME (t)))
- pedwarn ("%q+#D does not refer to the unqualified "
- "type, so it is not used for linkage",
- TYPE_NAME (t));
+ permerror ("%q+#D does not refer to the unqualified "
+ "type, so it is not used for linkage",
+ TYPE_NAME (t));
}
}
else
- pedwarn ("non-local function %q#D uses local type %qT", decl, t);
+ permerror ("non-local function %q#D uses local type %qT", decl, t);
}
}
/* If the declaration was declared inline, mark it as such. */
if (inlinep)
DECL_DECLARED_INLINE_P (decl) = 1;
- /* We inline functions that are explicitly declared inline, or, when
- the user explicitly asks us to, all functions. */
- if (DECL_DECLARED_INLINE_P (decl)
- || (flag_inline_trees == 2 && !DECL_INLINE (decl) && funcdef_flag))
- DECL_INLINE (decl) = 1;
DECL_EXTERNAL (decl) = 1;
if (quals && TREE_CODE (type) == FUNCTION_TYPE)
return decl;
if (ctype != NULL_TREE)
- {
- if (sfk == sfk_constructor)
- DECL_CONSTRUCTOR_P (decl) = 1;
-
- grokclassfn (ctype, decl, flags);
- }
+ grokclassfn (ctype, decl, flags);
decl = check_explicit_specialization (orig_declarator, decl,
template_count,
*attrlist = NULL_TREE;
}
+ /* Check main's type after attributes have been applied. */
+ if (ctype == NULL_TREE && DECL_MAIN_P (decl))
+ {
+ if (!same_type_p (TREE_TYPE (TREE_TYPE (decl)),
+ integer_type_node))
+ {
+ tree oldtypeargs = TYPE_ARG_TYPES (TREE_TYPE (decl));
+ tree newtype;
+ error ("%<::main%> must return %<int%>");
+ newtype = build_function_type (integer_type_node, oldtypeargs);
+ TREE_TYPE (decl) = newtype;
+ }
+ if (warn_main)
+ check_main_parameter_types (decl);
+ }
+
if (ctype != NULL_TREE
&& (! TYPE_FOR_JAVA (ctype) || check_java_method (decl))
&& check)
{
- tree old_decl;
+ tree old_decl = check_classfn (ctype, decl,
+ (processing_template_decl
+ > template_class_depth (ctype))
+ ? current_template_parms
+ : NULL_TREE);
+
+ if (old_decl == error_mark_node)
+ return NULL_TREE;
- old_decl = check_classfn (ctype, decl,
- (processing_template_decl
- > template_class_depth (ctype))
- ? current_template_parms
- : NULL_TREE);
if (old_decl)
{
tree ok;
XXX Isn't this done in start_function, too? */
revert_static_member_fn (decl);
if (DECL_ARTIFICIAL (old_decl))
- error ("definition of implicitly-declared %qD", old_decl);
+ {
+ error ("definition of implicitly-declared %qD", old_decl);
+ return NULL_TREE;
+ }
/* Since we've smashed OLD_DECL to its
DECL_TEMPLATE_RESULT, we must do the same to DECL. */
}
if (declspecs->specs[(int)ds_thread])
- {
- if (targetm.have_tls)
- DECL_TLS_MODEL (decl) = decl_default_tls_model (decl);
- else
- /* A mere warning is sure to result in improper semantics
- at runtime. Don't bother to allow this to compile. */
- error ("thread-local storage not supported for this target");
- }
+ DECL_TLS_MODEL (decl) = decl_default_tls_model (decl);
if (TREE_PUBLIC (decl))
{
unqualified_variant
= build_ptrmemfunc_type (TYPE_MAIN_VARIANT (type));
- t = make_aggr_type (RECORD_TYPE);
+ t = make_class_type (RECORD_TYPE);
xref_basetypes (t, NULL_TREE);
- /* Let the front-end know this is a pointer to member function... */
+ /* Let the front end know this is a pointer to member function... */
TYPE_PTRMEMFUNC_FLAG (t) = 1;
- /* ... and not really an aggregate. */
- SET_IS_AGGR_TYPE (t, 0);
+ /* ... and not really a class type. */
+ SET_CLASS_TYPE_P (t, 0);
field = build_decl (FIELD_DECL, pfn_identifier, type);
fields = field;
finish_builtin_struct (t, "__ptrmemfunc_type", fields, ptr_type_node);
- /* Zap out the name so that the back-end will give us the debugging
+ /* Zap out the name so that the back end will give us the debugging
information for this anonymous RECORD_TYPE. */
TYPE_NAME (t) = NULL_TREE;
TYPE_MAIN_VARIANT (t) = unqualified_variant;
TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (unqualified_variant);
TYPE_NEXT_VARIANT (unqualified_variant) = t;
+ TREE_TYPE (TYPE_BINFO (t)) = t;
}
/* Cache this pointer-to-member type so that we can find it again
later. */
TYPE_SET_PTRMEMFUNC_TYPE (type, t);
+ if (TYPE_STRUCTURAL_EQUALITY_P (type))
+ SET_TYPE_STRUCTURAL_EQUALITY (t);
+ else if (TYPE_CANONICAL (type) != type)
+ TYPE_CANONICAL (t) = build_ptrmemfunc_type (TYPE_CANONICAL (type));
+
return t;
}
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 "
+ else if (!INTEGRAL_TYPE_P (type))
+ pedwarn (OPT_pedantic, "ISO C++ forbids initialization of member constant "
"%qD of non-integral type %qT", decl, type);
return 0;
{
tree type;
tree itype;
+ tree abi_1_itype = NULL_TREE;
if (error_operand_p (size))
return error_mark_node;
type = TREE_TYPE (size);
}
- if (abi_version_at_least (2)
- /* We should only handle value dependent expressions specially. */
- ? value_dependent_expression_p (size)
- /* But for abi-1, we handled all instances in templates. This
- effects the manglings produced. */
- : processing_template_decl)
- return build_index_type (build_min (MINUS_EXPR, sizetype,
- size, integer_one_node));
+ if (value_dependent_expression_p (size))
+ {
+ /* We cannot do any checking for a value-dependent SIZE. Just
+ build the index type and mark that it requires structural
+ equality checks. */
+ itype = build_index_type (build_min (MINUS_EXPR, sizetype,
+ size, integer_one_node));
+ SET_TYPE_STRUCTURAL_EQUALITY (itype);
+ return itype;
+ }
+
+ if (!abi_version_at_least (2) && processing_template_decl)
+ /* For abi-1, we handled all instances in templates the same way,
+ even when they were non-dependent. This affects the manglings
+ produced. So, we do the normal checking for non-dependent
+ sizes, but at the end we'll return the same type that abi-1
+ would have, but with TYPE_CANONICAL set to the "right"
+ value that the current ABI would provide. */
+ abi_1_itype = build_index_type (build_min (MINUS_EXPR, sizetype,
+ size, integer_one_node));
/* The size might be the result of a cast. */
STRIP_TYPE_NOPS (size);
{
/* Check to see if the array bound overflowed. Make that an
error, no matter how generous we're being. */
- int old_flag_pedantic_errors = flag_pedantic_errors;
- int old_pedantic = pedantic;
- pedantic = flag_pedantic_errors = 1;
- constant_expression_warning (size);
- pedantic = old_pedantic;
- flag_pedantic_errors = old_flag_pedantic_errors;
+ constant_expression_error (size);
/* An array must have a positive number of elements. */
if (INT_CST_LT (size, integer_zero_node))
}
/* As an extension we allow zero-sized arrays. We always allow
them in system headers because glibc uses them. */
- else if (integer_zerop (size) && pedantic && !in_system_header)
+ else if (integer_zerop (size) && !in_system_header)
{
if (name)
- pedwarn ("ISO C++ forbids zero-size array %qD", name);
+ pedwarn (OPT_pedantic, "ISO C++ forbids zero-size array %qD", name);
else
- pedwarn ("ISO C++ forbids zero-size array");
+ pedwarn (OPT_pedantic, "ISO C++ forbids zero-size array");
}
}
else if (TREE_CONSTANT (size))
error ("size of array is not an integral constant-expression");
size = integer_one_node;
}
- else if (pedantic)
+ else if (pedantic && warn_vla != 0)
+ {
+ if (name)
+ pedwarn (OPT_Wvla, "ISO C++ forbids variable length array %qD", name);
+ else
+ pedwarn (OPT_Wvla, "ISO C++ forbids variable length array");
+ }
+ else if (warn_vla > 0)
{
if (name)
- pedwarn ("ISO C++ forbids variable-size array %qD", name);
+ warning (OPT_Wvla,
+ "variable length array %qD is used", name);
else
- pedwarn ("ISO C++ forbids variable-size array");
+ warning (OPT_Wvla,
+ "variable length array is used");
}
if (processing_template_decl && !TREE_CONSTANT (size))
processing_template_decl = 0;
itype = cp_build_binary_op (MINUS_EXPR,
cp_convert (ssizetype, size),
- cp_convert (ssizetype, integer_one_node));
+ cp_convert (ssizetype, integer_one_node),
+ tf_warning_or_error);
itype = fold (itype);
processing_template_decl = saved_processing_template_decl;
}
/* Create and return the appropriate index type. */
- return build_index_type (itype);
+ if (abi_1_itype)
+ {
+ tree t = build_index_type (itype);
+ TYPE_CANONICAL (abi_1_itype) = TYPE_CANONICAL (t);
+ return abi_1_itype;
+ }
+ else
+ return build_index_type (itype);
}
/* Returns the scope (if any) in which the entity declared by
break;
case sfk_conversion:
- if (type && !same_type_p (type, optype))
- error ("operator %qT declared to return %qT", optype, type);
- else if (type)
- pedwarn ("return type specified for %<operator %T%>", optype);
+ if (type)
+ error ("return type specified for %<operator %T%>", optype);
type = optype;
break;
the name and type of the object declared and construct a DECL node
for it.
- DECLSPECS is a chain of tree_list nodes whose value fields
- are the storage classes and type specifiers.
+ DECLSPECS points to the representation of declaration-specifier
+ sequence that precedes declarator.
DECL_CONTEXT says which syntactic context this declaration is in:
NORMAL for most contexts. Make a VAR_DECL or FUNCTION_DECL or TYPE_DECL.
Don't make a DECL node; just return the ..._TYPE node.
FIELD for a struct or union field; make a FIELD_DECL.
BITFIELD for a field with specified width.
- INITIALIZED is 1 if the decl has an initializer.
+ INITIALIZED is as for start_decl.
ATTRLIST is a pointer to the list of attributes, which may be NULL
if there are none; *ATTRLIST may be modified if attributes from inside
cp_storage_class storage_class;
bool unsigned_p, signed_p, short_p, long_p, thread_p;
bool type_was_error_mark_node = false;
+ bool parameter_pack_p = declarator? declarator->parameter_pack_p : false;
+ bool set_no_warning = false;
signed_p = declspecs->specs[(int)ds_signed];
unsigned_p = declspecs->specs[(int)ds_unsigned];
else if (decl_context == BITFIELD)
bitfield = 1, decl_context = FIELD;
+ if (initialized > 1)
+ funcdef_flag = true;
+
/* Look inside a declarator for the name being declared
and get it as a string, for an error message. */
for (id_declarator = declarator;
gcc_unreachable ();
}
break;
+ }
- case cdk_array:
- case cdk_pointer:
- case cdk_reference:
- case cdk_ptrmem:
- break;
+ case cdk_array:
+ case cdk_pointer:
+ case cdk_reference:
+ case cdk_ptrmem:
+ break;
- case cdk_error:
- return error_mark_node;
+ case cdk_error:
+ return error_mark_node;
- default:
- gcc_unreachable ();
- }
+ default:
+ gcc_unreachable ();
}
if (id_declarator->kind == cdk_id)
break;
return error_mark_node;
}
+ if (declspecs->conflicting_specifiers_p)
+ {
+ error ("conflicting specifiers in declaration of %qs", name);
+ return error_mark_node;
+ }
+
/* Extract the basic type from the decl-specifier-seq. */
type = declspecs->type;
if (type == error_mark_node)
{
typedef_decl = type;
type = TREE_TYPE (typedef_decl);
+ if (TREE_DEPRECATED (type)
+ && DECL_ARTIFICIAL (typedef_decl)
+ && deprecated_state != DEPRECATED_SUPPRESS)
+ warn_deprecated_use (type);
}
/* No type at all: default to `int', and set DEFAULTED_INT
because it was not a user-defined typedef. */
/* 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 %qs with no type", name);
- else if (warn_return_type)
- warning (0, "ISO C++ forbids declaration of %qs with no type", name);
+ else if (! is_main)
+ permerror ("ISO C++ forbids declaration of %qs with no type", name);
+ else if (pedantic)
+ pedwarn (OPT_pedantic,
+ "ISO C++ forbids declaration of %qs with no type", name);
+ else
+ warning (OPT_Wreturn_type,
+ "ISO C++ forbids declaration of %qs with no type", name);
type = integer_type_node;
}
error ("%<long%> or %<short%> specified with char for %qs", name);
else if (long_p && short_p)
error ("%<long%> and %<short%> specified together for %qs", name);
+ else if (type == char16_type_node || type == char32_type_node)
+ {
+ if (signed_p || unsigned_p)
+ error ("%<signed%> or %<unsigned%> invalid for %qs", name);
+ else if (short_p || long_p)
+ error ("%<short%> or %<long%> invalid for %qs", name);
+ }
else
{
ok = 1;
if (!explicit_int && !defaulted_int && !explicit_char && pedantic)
{
- pedwarn ("long, short, signed or unsigned used invalidly for %qs",
+ pedwarn (OPT_pedantic,
+ "long, short, signed or unsigned used invalidly for %qs",
name);
if (flag_pedantic_errors)
ok = 0;
else if (type == char_type_node)
type = unsigned_char_type_node;
else if (typedef_decl)
- type = c_common_unsigned_type (type);
+ type = unsigned_type_for (type);
else
type = unsigned_type_node;
}
if (pedantic)
{
tree bad_type = build_qualified_type (type, type_quals);
- pedwarn ("ignoring %qV qualifiers added to function type %qT",
+ pedwarn (OPT_pedantic,
+ "ignoring %qV qualifiers added to function type %qT",
bad_type, type);
}
type_quals = TYPE_UNQUALIFIED;
if (virtualp
&& (current_class_name == NULL_TREE || decl_context != FIELD))
{
- error ("virtual outside class declaration");
+ error ("%<virtual%> outside class declaration");
virtualp = 0;
}
/* Warn about storage classes that are invalid for certain
kinds of declarations (parameters, typenames, etc.). */
- if (declspecs->conflicting_specifiers_p)
- {
- error ("conflicting specifiers in declaration of %qs", name);
- storage_class = sc_none;
- }
- else if (thread_p
- && ((storage_class
- && storage_class != sc_extern
- && storage_class != sc_static)
- || declspecs->specs[(int)ds_typedef]))
+ 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 %qs", name);
thread_p = false;
}
- else if (decl_context != NORMAL
- && ((storage_class != sc_none
- && storage_class != sc_mutable)
- || thread_p))
+ if (decl_context != NORMAL
+ && ((storage_class != sc_none
+ && storage_class != sc_mutable)
+ || thread_p))
{
if ((decl_context == PARM || decl_context == CATCHPARM)
&& (storage_class == sc_register
storage_class = sc_none;
}
}
- else if (storage_class == sc_extern && initialized
- && !funcdef_flag)
- {
- if (toplevel_bindings_p ())
- {
- /* It's common practice (and completely valid) to have a const
- be initialized and declared extern. */
- if (!(type_quals & TYPE_QUAL_CONST))
- warning (0, "%qs initialized and declared %<extern%>", name);
- }
- else
- error ("%qs has both %<extern%> and initializer", name);
- }
else if (storage_class == sc_extern && funcdef_flag
&& ! toplevel_bindings_p ())
error ("nested function %qs declared %<extern%>", name);
}
if (storage_class && friendp)
- error ("storage class specifiers invalid in friend function declarations");
+ {
+ error ("storage class specifiers invalid in friend function declarations");
+ storage_class = sc_none;
+ staticp = 0;
+ }
if (!id_declarator)
unqualified_id = NULL_TREE;
/* Declaring a function type.
Make sure we have a valid type for the function to return. */
- /* We now know that the TYPE_QUALS don't apply to the
- decl, but to its return type. */
- type_quals = TYPE_UNQUALIFIED;
+ if (type_quals != TYPE_UNQUALIFIED)
+ {
+ if (SCALAR_TYPE_P (type) || VOID_TYPE_P (type))
+ warning (OPT_Wignored_qualifiers,
+ "type qualifiers ignored on function return type");
+ /* We now know that the TYPE_QUALS don't apply to the
+ decl, but to its return type. */
+ type_quals = TYPE_UNQUALIFIED;
+ set_no_warning = true;
+ }
- /* Warn about some types functions can't return. */
+ /* Error about some types functions can't return. */
if (TREE_CODE (type) == FUNCTION_TYPE)
{
error ("%qs declared as function returning a function", name);
- type = integer_type_node;
+ return error_mark_node;
}
if (TREE_CODE (type) == ARRAY_TYPE)
{
error ("%qs declared as function returning an array", name);
- type = integer_type_node;
+ return error_mark_node;
}
/* Pick up type qualifiers which should be applied to `this'. */
explicitp = 2;
if (virtualp)
{
- pedwarn ("constructors cannot be declared virtual");
+ permerror ("constructors cannot be declared virtual");
virtualp = 0;
}
if (decl_context == FIELD
if (TREE_CODE (type) == REFERENCE_TYPE)
{
- error (declarator->kind == cdk_reference
- ? "cannot declare reference to %q#T"
- : "cannot declare pointer to %q#T", type);
- type = TREE_TYPE (type);
+ if (declarator->kind != cdk_reference)
+ {
+ error ("cannot declare pointer to %q#T", type);
+ type = TREE_TYPE (type);
+ }
+
+ /* In C++0x, we allow reference to reference declarations
+ that occur indirectly through typedefs [7.1.3/8 dcl.typedef]
+ and template type arguments [14.3.1/4 temp.arg.type]. The
+ check for direct reference to reference declarations, which
+ are still forbidden, occurs below. Reasoning behind the change
+ can be found in DR106, DR540, and the rvalue reference
+ proposals. */
+ else if (cxx_dialect == cxx98)
+ {
+ error ("cannot declare reference to %q#T", type);
+ type = TREE_TYPE (type);
+ }
}
else if (VOID_TYPE_P (type))
{
type_quals = TYPE_UNQUALIFIED;
if (declarator->kind == cdk_ptrmem
- && (TREE_CODE (type) == FUNCTION_TYPE || memfn_quals))
+ && (TREE_CODE (type) == FUNCTION_TYPE
+ || (memfn_quals && TREE_CODE (type) == METHOD_TYPE)))
{
memfn_quals |= cp_type_quals (type);
type = build_memfn_type (type,
if (declarator->kind == cdk_reference)
{
+ /* In C++0x, the type we are creating a reference to might be
+ a typedef which is itself a reference type. In that case,
+ we follow the reference collapsing rules in
+ [7.1.3/8 dcl.typedef] to create the final reference type:
+
+ "If a typedef TD names a type that is a reference to a type
+ T, an attempt to create the type 'lvalue reference to cv TD'
+ creates the type 'lvalue reference to T,' while an attempt
+ to create the type "rvalue reference to cv TD' creates the
+ type TD."
+ */
if (!VOID_TYPE_P (type))
- type = build_reference_type (type);
+ type = cp_build_reference_type
+ ((TREE_CODE (type) == REFERENCE_TYPE
+ ? TREE_TYPE (type) : type),
+ (declarator->u.reference.rvalue_ref
+ && (TREE_CODE(type) != REFERENCE_TYPE
+ || TYPE_REF_IS_RVALUE (type))));
+
+ /* In C++0x, we need this check for direct reference to
+ reference declarations, which are forbidden by
+ [8.3.2/5 dcl.ref]. Reference to reference declarations
+ are only allowed indirectly through typedefs and template
+ type arguments. Example:
+
+ void foo(int & &); // invalid ref-to-ref decl
+
+ typedef int & int_ref;
+ void foo(int_ref &); // valid ref-to-ref decl
+ */
+ if (inner_declarator && inner_declarator->kind == cdk_reference)
+ error ("cannot declare reference to %q#T, which is not "
+ "a typedef or a template type argument", type);
}
else if (TREE_CODE (type) == METHOD_TYPE)
type = build_ptrmemfunc_type (build_pointer_type (type));
if (ctype == current_class_type)
{
if (friendp)
- pedwarn ("member functions are implicitly friends of their class");
+ {
+ permerror ("member functions are implicitly friends of their class");
+ friendp = 0;
+ }
else
- pedwarn ("extra qualification %<%T::%> on member %qs",
- ctype, name);
+ permerror_at (declarator->id_loc,
+ "extra qualification %<%T::%> on member %qs",
+ ctype, name);
}
else if (/* If the qualifying type is already complete, then we
can skip the following checks. */
attrlist = &returned_attrs;
}
+ /* Handle parameter packs. */
+ if (parameter_pack_p)
+ {
+ if (decl_context == PARM)
+ /* Turn the type into a pack expansion.*/
+ type = make_pack_expansion (type);
+ else
+ error ("non-parameter %qs cannot be a parameter pack", name);
+ }
+
/* Did array size calculations overflow? */
if (TREE_CODE (type) == ARRAY_TYPE
member function of S. We record the cv-qualification in the
function type. */
if (memfn_quals && TREE_CODE (type) == FUNCTION_TYPE)
- type = cp_build_qualified_type (type, memfn_quals);
+ {
+ type = cp_build_qualified_type (type, memfn_quals);
+
+ /* We have now dealt with these qualifiers. */
+ memfn_quals = TYPE_UNQUALIFIED;
+ }
if (decl_context == FIELD)
decl = build_lang_decl (TYPE_DECL, unqualified_id, type);
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);
+ permerror ("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.
&& TYPE_NAME (type)
&& TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
&& TYPE_ANONYMOUS_P (type)
- /* Don't do this if there are attributes. */
- && (!attrlist || !*attrlist)
&& cp_type_quals (type) == TYPE_UNQUALIFIED)
{
tree oldname = TYPE_NAME (type);
type with external linkage have external linkage. */
}
- /* Any qualifiers on a function type typedef have already been
- dealt with. */
- if (memfn_quals && !ctype && TREE_CODE (type) == FUNCTION_TYPE)
- memfn_quals = TYPE_UNQUALIFIED;
-
if (signed_p
|| (typedef_decl && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl)))
C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1;
{
/* Don't allow friend declaration without a class-key. */
if (TREE_CODE (type) == TEMPLATE_TYPE_PARM)
- pedwarn ("template parameters cannot be friends");
+ permerror ("template parameters cannot be friends");
else if (TREE_CODE (type) == TYPENAME_TYPE)
- pedwarn ("friend declaration requires class-key, "
- "i.e. %<friend class %T::%D%>",
- TYPE_CONTEXT (type), TYPENAME_TYPE_FULLNAME (type));
+ permerror ("friend declaration requires class-key, "
+ "i.e. %<friend class %T::%D%>",
+ TYPE_CONTEXT (type), TYPENAME_TYPE_FULLNAME (type));
else
- pedwarn ("friend declaration requires class-key, "
- "i.e. %<friend %#T%>",
- type);
+ permerror ("friend declaration requires class-key, "
+ "i.e. %<friend %#T%>",
+ type);
}
/* Only try to do this stuff if we didn't already give up. */
return error_mark_node;
}
}
+ else if (sfk == sfk_constructor && friendp)
+ {
+ error ("expected qualified name in friend declaration "
+ "for constructor %qD",
+ id_declarator->u.id.unqualified_name);
+ return error_mark_node;
+ }
/* Tell grokfndecl if it needs to set TREE_PUBLIC on the node. */
function_context = (ctype != NULL_TREE) ?
DECL_NONCONVERTING_P (decl) = 1;
else if (DECL_CONSTRUCTOR_P (decl))
{
- /* The constructor can be called with exactly one
- parameter if there is at least one parameter, and
- any subsequent parameters have default arguments.
+ /* A constructor with no parms is not a conversion.
Ignore any compiler-added parms. */
tree arg_types = FUNCTION_FIRST_USER_PARMTYPE (decl);
- if (arg_types == void_list_node
- || (arg_types
- && TREE_CHAIN (arg_types)
- && TREE_CHAIN (arg_types) != void_list_node
- && !TREE_PURPOSE (TREE_CHAIN (arg_types))))
+ if (arg_types == void_list_node)
DECL_NONCONVERTING_P (decl) = 1;
}
}
{
/* Friends are treated specially. */
if (ctype == current_class_type)
- ; /* We already issued a pedwarn. */
+ ; /* We already issued a permerror. */
else if (decl && DECL_NAME (decl))
{
if (template_class_depth (current_class_type) == 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 %qD",
- unqualified_id);
- pedwarn ("making %qD static", unqualified_id);
+ permerror ("ISO C++ forbids initialization of member %qD",
+ unqualified_id);
+ permerror ("making %qD static", unqualified_id);
staticp = 1;
}
DECL_EXTERNAL (decl) = 1;
if (thread_p)
- {
- if (targetm.have_tls)
- DECL_TLS_MODEL (decl) = decl_default_tls_model (decl);
- else
- /* A mere warning is sure to result in improper
- semantics at runtime. Don't bother to allow this to
- compile. */
- error ("thread-local storage not supported for this target");
- }
+ DECL_TLS_MODEL (decl) = decl_default_tls_model (decl);
}
else
{
decl = build_decl (FIELD_DECL, unqualified_id, type);
DECL_NONADDRESSABLE_P (decl) = bitfield;
+ if (bitfield && !unqualified_id)
+ TREE_NO_WARNING (decl) = 1;
+
if (storage_class == sc_mutable)
{
DECL_MUTABLE_P (decl) = 1;
&& pedantic)
{
if (storage_class == sc_static)
- pedwarn ("%<static%> specified invalid for function %qs "
+ pedwarn (OPT_pedantic,
+ "%<static%> specified invalid for function %qs "
"declared out of global scope", name);
else
- pedwarn ("%<inline%> specifier invalid for function %qs "
+ pedwarn (OPT_pedantic,
+ "%<inline%> specifier invalid for function %qs "
"declared out of global scope", name);
}
declaring main to be static. */
if (TREE_CODE (type) == METHOD_TYPE)
{
- pedwarn ("cannot declare member function %qD to have "
- "static linkage", decl);
+ permerror ("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");
+ permerror ("%<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_extern && pedantic)
{
- pedwarn ("cannot explicitly declare member %q#D to have "
- "extern linkage",
- decl);
+ pedwarn (OPT_pedantic,
+ "cannot explicitly declare member %q#D to have "
+ "extern linkage", decl);
storage_class = sc_none;
}
}
}
+ if (storage_class == sc_extern && initialized && !funcdef_flag)
+ {
+ if (toplevel_bindings_p ())
+ {
+ /* It's common practice (and completely valid) to have a const
+ be initialized and declared extern. */
+ if (!(type_quals & TYPE_QUAL_CONST))
+ warning (0, "%qs initialized and declared %<extern%>", name);
+ }
+ else
+ {
+ error ("%qs has both %<extern%> and initializer", name);
+ return error_mark_node;
+ }
+ }
+
/* Record `register' declaration for warnings on &
and in case doing stupid register allocation. */
else if (storage_class == sc_static)
DECL_THIS_STATIC (decl) = 1;
- /* Record constancy and volatility. There's no need to do this
- when processing a template; we'll do this for the instantiated
- declaration based on the type of DECL. */
+ /* Record constancy and volatility on the DECL itself . There's
+ no need to do this when processing a template; we'll do this
+ for the instantiated declaration based on the type of DECL. */
if (!processing_template_decl)
cp_apply_type_quals_to_decl (type_quals, decl);
+ if (set_no_warning)
+ TREE_NO_WARNING (decl) = 1;
+
return decl;
}
}
/* Returns nonzero if T is a local variable. */
int
-local_variable_p (tree t)
+local_variable_p (const_tree t)
{
if ((TREE_CODE (t) == VAR_DECL
/* A VAR_DECL with a context that is a _TYPE is a static data
return 0;
}
-/* Returns nonzero if T is an automatic local variable or a label.
- (These are the declarations that need to be remapped when the code
- containing them is duplicated.) */
-
-int
-nonstatic_local_decl_p (tree t)
-{
- return ((local_variable_p (t) && !TREE_STATIC (t))
- || TREE_CODE (t) == LABEL_DECL
- || TREE_CODE (t) == RESULT_DECL);
-}
-
/* Like local_variable_p, but suitable for use as a tree-walking
function. */
The keyword `this' shall not be used in a default argument of a
member function. */
- var = walk_tree_without_duplicates (&arg, local_variable_p_walkfn,
- NULL);
+ var = cp_walk_tree_without_duplicates (&arg, local_variable_p_walkfn, NULL);
if (var)
{
error ("default argument %qE uses local variable %qD", arg, var);
int ellipsis = !first_parm || first_parm->ellipsis_p;
cp_parameter_declarator *parm;
int any_error = 0;
+ struct pointer_set_t *unique_decls = pointer_set_create ();
for (parm = first_parm; parm != NULL; parm = parm->next)
{
TREE_TYPE (decl) = error_mark_node;
}
+ if (type != error_mark_node
+ && TYPE_FOR_JAVA (type)
+ && MAYBE_CLASS_TYPE_P (type))
+ {
+ error ("parameter %qD has Java class type", decl);
+ type = error_mark_node;
+ TREE_TYPE (decl) = error_mark_node;
+ init = NULL_TREE;
+ }
+
if (type != error_mark_node)
{
/* Top-level qualifiers on the parameters are
init = check_default_argument (decl, init);
}
+ if (TREE_CODE (decl) == PARM_DECL
+ && FUNCTION_PARAMETER_PACK_P (decl)
+ && parm->next)
+ error ("parameter packs must be at the end of the parameter list");
+
+ if (DECL_NAME (decl))
+ {
+ if (pointer_set_contains (unique_decls, DECL_NAME (decl)))
+ error ("multiple parameters named %qE", DECL_NAME (decl));
+ else
+ pointer_set_insert (unique_decls, DECL_NAME (decl));
+ }
+
TREE_CHAIN (decl) = decls;
decls = decl;
result = tree_cons (init, type, result);
result = chainon (result, void_list_node);
*parms = decls;
+ pointer_set_destroy (unique_decls);
return result;
}
operator. */
int
-copy_fn_p (tree d)
+copy_fn_p (const_tree d)
{
tree args;
tree arg_type;
result = -1;
}
else if (TREE_CODE (arg_type) == REFERENCE_TYPE
+ && !TYPE_REF_IS_RVALUE (arg_type)
&& TYPE_MAIN_VARIANT (TREE_TYPE (arg_type)) == DECL_CONTEXT (d))
{
if (CP_TYPE_CONST_P (TREE_TYPE (arg_type)))
return result;
}
+/* D is a constructor or overloaded `operator='.
+
+ Let T be the class in which D is declared. Then, this function
+ returns true when D is a move constructor or move assignment
+ operator, false otherwise. */
+
+bool
+move_fn_p (const_tree d)
+{
+ tree args;
+ tree arg_type;
+ bool result = false;
+
+ gcc_assert (DECL_FUNCTION_MEMBER_P (d));
+
+ if (cxx_dialect == cxx98)
+ /* There are no move constructors if we are in C++98 mode. */
+ return false;
+
+ if (TREE_CODE (d) == TEMPLATE_DECL
+ || (DECL_TEMPLATE_INFO (d)
+ && DECL_MEMBER_TEMPLATE_P (DECL_TI_TEMPLATE (d))))
+ /* Instantiations of template member functions are never copy
+ functions. Note that member functions of templated classes are
+ represented as template functions internally, and we must
+ accept those as copy functions. */
+ return 0;
+
+ args = FUNCTION_FIRST_USER_PARMTYPE (d);
+ if (!args)
+ return 0;
+
+ arg_type = TREE_VALUE (args);
+ if (arg_type == error_mark_node)
+ return 0;
+
+ if (TREE_CODE (arg_type) == REFERENCE_TYPE
+ && TYPE_REF_IS_RVALUE (arg_type)
+ && same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (arg_type)),
+ DECL_CONTEXT (d)))
+ result = true;
+
+ args = TREE_CHAIN (args);
+
+ if (args && args != void_list_node && !TREE_PURPOSE (args))
+ /* There are more non-optional args. */
+ return false;
+
+ return result;
+}
+
/* Remember any special properties of member function DECL. */
-void grok_special_member_properties (tree decl)
+void
+grok_special_member_properties (tree decl)
{
tree class_type;
{
int ctor = copy_fn_p (decl);
- TYPE_HAS_CONSTRUCTOR (class_type) = 1;
+ if (!DECL_ARTIFICIAL (decl))
+ TYPE_HAS_USER_CONSTRUCTOR (class_type) = 1;
if (ctor > 0)
{
are no other parameters or else all other parameters have
default arguments. */
TYPE_HAS_INIT_REF (class_type) = 1;
+ if (!DECL_DEFAULTED_FN (decl))
+ TYPE_HAS_COMPLEX_INIT_REF (class_type) = 1;
if (ctor > 1)
TYPE_HAS_CONST_INIT_REF (class_type) = 1;
}
else if (sufficient_parms_p (FUNCTION_FIRST_USER_PARMTYPE (decl)))
TYPE_HAS_DEFAULT_CONSTRUCTOR (class_type) = 1;
+ else if (is_list_ctor (decl))
+ TYPE_HAS_LIST_CTOR (class_type) = 1;
}
else if (DECL_OVERLOADED_OPERATOR_P (decl) == NOP_EXPR)
{
if (assop)
{
TYPE_HAS_ASSIGN_REF (class_type) = 1;
+ if (!DECL_DEFAULTED_FN (decl))
+ TYPE_HAS_COMPLEX_ASSIGN_REF (class_type) = 1;
if (assop != 1)
TYPE_HAS_CONST_ASSIGN_REF (class_type) = 1;
}
if the class has a constructor of the form X(X). */
int
-grok_ctor_properties (tree ctype, tree decl)
+grok_ctor_properties (const_tree ctype, const_tree decl)
{
int ctor_parm = copy_fn_p (decl);
gcc_unreachable ();
}
while (0);
- gcc_assert (operator_code != LAST_CPLUS_TREE_CODE);
+ gcc_assert (operator_code != MAX_TREE_CODES);
SET_OVERLOADED_OPERATOR_CODE (decl, operator_code);
if (class_type)
}
if (operator_code == NEW_EXPR || operator_code == VEC_NEW_EXPR)
- TREE_TYPE (decl) = coerce_new_type (TREE_TYPE (decl));
+ {
+ TREE_TYPE (decl) = coerce_new_type (TREE_TYPE (decl));
+ DECL_IS_OPERATOR_NEW (decl) = 1;
+ }
else if (operator_code == DELETE_EXPR || operator_code == VEC_DELETE_EXPR)
TREE_TYPE (decl) = coerce_delete_type (TREE_TYPE (decl));
else
if (arg == error_mark_node)
return false;
- /* IS_AGGR_TYPE, rather than CLASS_TYPE_P, is used
+ /* MAYBE_CLASS_TYPE_P, rather than CLASS_TYPE_P, is used
because these checks are performed even on
template functions. */
- if (IS_AGGR_TYPE (arg) || TREE_CODE (arg) == ENUMERAL_TYPE)
+ if (MAYBE_CLASS_TYPE_P (arg)
+ || TREE_CODE (arg) == ENUMERAL_TYPE)
break;
}
if (t == class_type)
what = "the same type";
/* Don't force t to be complete here. */
- else if (IS_AGGR_TYPE (t)
+ else if (MAYBE_CLASS_TYPE_P (t)
&& COMPLETE_TYPE_P (t)
&& DERIVED_FROM_P (t, class_type))
what = "a base class";
if (operator_code == POSTINCREMENT_EXPR
|| operator_code == POSTDECREMENT_EXPR)
{
- if (pedantic)
- pedwarn ("%qD cannot have default arguments", decl);
+ pedwarn (OPT_pedantic, "%qD cannot have default arguments",
+ decl);
}
else
{
| DECL_SELF_REFERENCE_P (decl));
return t;
}
+ else if (decl && TREE_CODE (decl) == TREE_LIST)
+ {
+ error ("reference to %qD is ambiguous", name);
+ print_candidates (decl);
+ return error_mark_node;
+ }
else
return NULL_TREE;
}
}
else
{
- t = make_aggr_type (code);
+ t = make_class_type (code);
TYPE_CONTEXT (t) = context;
t = pushtag (name, t, scope);
}
}
else
{
- if (template_header_p && IS_AGGR_TYPE (t))
+ if (template_header_p && MAYBE_CLASS_TYPE_P (t))
{
if (!redeclare_class_template (t, current_template_parms))
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
if (access == access_default_node)
access = default_access;
+ if (PACK_EXPANSION_P (basetype))
+ basetype = PACK_EXPANSION_PATTERN (basetype);
if (TREE_CODE (basetype) == TYPE_DECL)
basetype = TREE_TYPE (basetype);
- if (TREE_CODE (basetype) != RECORD_TYPE
- && TREE_CODE (basetype) != TYPENAME_TYPE
- && TREE_CODE (basetype) != TEMPLATE_TYPE_PARM
- && TREE_CODE (basetype) != BOUND_TEMPLATE_TEMPLATE_PARM)
+ if (!MAYBE_CLASS_TYPE_P (basetype) || TREE_CODE (basetype) == UNION_TYPE)
{
error ("base type %qT fails to be a struct or class type",
basetype);
error ("duplicate base type %qT invalid", basetype);
return false;
}
+
+ if (PACK_EXPANSION_P (TREE_VALUE (base_list)))
+ /* Regenerate the pack expansion for the bases. */
+ basetype = make_pack_expansion (basetype);
+
TYPE_MARKED_P (basetype) = 1;
base_binfo = copy_binfo (base_binfo, basetype, ref,
underlying_type = integer_types[itk_unsigned_long_long];
}
- /* Compute the minium and maximum values for the type.
+ /* Compute the minimum and maximum values for the type.
[dcl.enum]
saved_location = input_location;
input_location = DECL_SOURCE_LOCATION (decl);
value = perform_implicit_conversion (underlying_type,
- DECL_INITIAL (decl));
+ DECL_INITIAL (decl),
+ tf_warning_or_error);
input_location = saved_location;
/* Do not clobber shared ints. */
}
else
{
- error ("enumerator value for %qD not integer constant", name);
+ error ("enumerator value for %qD is not an integer constant", name);
value = NULL_TREE;
}
}
DECL_CONTEXT (decl) = FROB_CONTEXT (context);
TREE_CONSTANT (decl) = 1;
- TREE_INVARIANT (decl) = 1;
TREE_READONLY (decl) = 1;
DECL_INITIAL (decl) = value;
if (dependent_type_p (return_type))
return;
- if (!COMPLETE_OR_VOID_TYPE_P (return_type))
+ if (!COMPLETE_OR_VOID_TYPE_P (return_type)
+ || (TYPE_FOR_JAVA (return_type) && MAYBE_CLASS_TYPE_P (return_type)))
{
tree args = TYPE_ARG_TYPES (fntype);
- error ("return type %q#T is incomplete", return_type);
+ if (!COMPLETE_OR_VOID_TYPE_P (return_type))
+ error ("return type %q#T is incomplete", return_type);
+ else
+ error ("return type has Java class type %q#T", return_type);
/* Make it return void instead. */
if (TREE_CODE (fntype) == METHOD_TYPE)
For C++, we must first check whether that datum makes any sense.
For example, "class A local_a(1,2);" means that variable local_a
is an aggregate of type A, which should have a constructor
- applied to it with the argument list [1, 2]. */
+ applied to it with the argument list [1, 2].
+
+ On entry, DECL_INITIAL (decl1) should be NULL_TREE or error_mark_node,
+ or may be a BLOCK if the function has been defined previously
+ in this translation unit. On exit, DECL_INITIAL (decl1) will be
+ error_mark_node if the function has never been defined, or
+ a BLOCK if the function has been defined somewhere. */
void
start_preparsed_function (tree decl1, tree attrs, int flags)
&& lookup_attribute ("noinline", attrs))
warning (0, "inline function %q+D given attribute noinline", decl1);
+ /* Handle gnu_inline attribute. */
+ if (GNU_INLINE_P (decl1))
+ {
+ DECL_EXTERNAL (decl1) = 1;
+ DECL_NOT_REALLY_EXTERN (decl1) = 0;
+ DECL_INTERFACE_KNOWN (decl1) = 1;
+ DECL_DISREGARD_INLINE_LIMITS (decl1) = 1;
+ }
+
if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl1))
/* This is a constructor, we must ensure that any default args
introduced by this definition are propagated to the clones
/* Build the return declaration for the function. */
restype = TREE_TYPE (fntype);
- /* Promote the value to int before returning it. */
- if (c_promoting_integer_type_p (restype))
- restype = type_promotes_to (restype);
if (DECL_RESULT (decl1) == NULL_TREE)
{
tree resdecl;
cp_apply_type_quals_to_decl (cp_type_quals (restype), resdecl);
}
- /* Initialize RTL machinery. We cannot do this until
- CURRENT_FUNCTION_DECL and DECL_RESULT are set up. We do this
- even when processing a template; this is how we get
- CFUN set up, and our per-function variables initialized.
- FIXME factor out the non-RTL stuff. */
- bl = current_binding_level;
- allocate_struct_function (decl1);
- current_binding_level = bl;
-
- /* Even though we're inside a function body, we still don't want to
- call expand_expr to calculate the size of a variable-sized array.
- We haven't necessarily assigned RTL to all variables yet, so it's
- not safe to try to expand expressions involving them. */
- cfun->x_dont_save_pending_sizes_p = 1;
-
- /* Start the statement-tree, start the tree now. */
- DECL_SAVED_TREE (decl1) = push_stmt_list ();
-
/* Let the user know we're compiling this function. */
announce_function (decl1);
parsing the body of the function. */
;
else
- /* Otherwise, OLDDECL is either a previous declaration of
- the same function or DECL1 itself. */
- decl1 = olddecl;
+ {
+ /* Otherwise, OLDDECL is either a previous declaration
+ of the same function or DECL1 itself. */
+
+ if (warn_missing_declarations
+ && olddecl == decl1
+ && !DECL_MAIN_P (decl1)
+ && TREE_PUBLIC (decl1)
+ && !DECL_DECLARED_INLINE_P (decl1))
+ {
+ tree context;
+
+ /* Check whether DECL1 is in an anonymous
+ namespace. */
+ for (context = DECL_CONTEXT (decl1);
+ context;
+ context = DECL_CONTEXT (context))
+ {
+ if (TREE_CODE (context) == NAMESPACE_DECL
+ && DECL_NAME (context) == NULL_TREE)
+ break;
+ }
+
+ if (context == NULL)
+ warning (OPT_Wmissing_declarations,
+ "no previous declaration for %q+D", decl1);
+ }
+
+ decl1 = olddecl;
+ }
}
else
{
maybe_apply_pragma_weak (decl1);
}
- /* Reset these in case the call to pushdecl changed them. */
+ /* Reset this in case the call to pushdecl changed it. */
current_function_decl = decl1;
- cfun->decl = decl1;
+
+ gcc_assert (DECL_INITIAL (decl1));
+
+ /* This function may already have been parsed, in which case just
+ return; our caller will skip over the body without parsing. */
+ if (DECL_INITIAL (decl1) != error_mark_node)
+ return;
+
+ /* Initialize RTL machinery. We cannot do this until
+ CURRENT_FUNCTION_DECL and DECL_RESULT are set up. We do this
+ even when processing a template; this is how we get
+ CFUN set up, and our per-function variables initialized.
+ FIXME factor out the non-RTL stuff. */
+ bl = current_binding_level;
+ allocate_struct_function (decl1, processing_template_decl);
+
+ /* Initialize the language data structures. Whenever we start
+ a new function, we destroy temporaries in the usual way. */
+ cfun->language = GGC_CNEW (struct language_function);
+ current_stmt_tree ()->stmts_are_full_exprs_p = 1;
+ current_binding_level = bl;
+
+ /* Even though we're inside a function body, we still don't want to
+ call expand_expr to calculate the size of a variable-sized array.
+ We haven't necessarily assigned RTL to all variables yet, so it's
+ not safe to try to expand expressions involving them. */
+ cfun->dont_save_pending_sizes_p = 1;
+
+ /* Start the statement-tree, start the tree now. */
+ DECL_SAVED_TREE (decl1) = push_stmt_list ();
/* If we are (erroneously) defining a function that we have already
defined before, wipe out what we knew before. */
gcc_assert (TREE_CODE (TREE_TYPE (t)) == POINTER_TYPE);
cp_function_chain->x_current_class_ref
- = build_indirect_ref (t, NULL);
+ = cp_build_indirect_ref (t, NULL, tf_warning_or_error);
cp_function_chain->x_current_class_ptr = t;
/* Constructors and destructors need to know whether they're "in
DECL_EXTERNAL (decl1) = 0;
DECL_INTERFACE_KNOWN (decl1) = 1;
/* If this function is in an interface implemented in this file,
- make sure that the backend knows to emit this function
+ make sure that the back end knows to emit this function
here. */
if (!DECL_EXTERNAL (decl1))
mark_needed (decl1);
else
{
/* This is a definition, not a reference.
- So clear DECL_EXTERNAL. */
- DECL_EXTERNAL (decl1) = 0;
+ So clear DECL_EXTERNAL, unless this is a GNU extern inline. */
+ if (!GNU_INLINE_P (decl1))
+ DECL_EXTERNAL (decl1) = 0;
if ((DECL_DECLARED_INLINE_P (decl1)
|| DECL_TEMPLATE_INSTANTIATION (decl1))
tree val;
tree exprstmt;
- if (targetm.cxx.cdtor_returns_this ())
+ if (targetm.cxx.cdtor_returns_this ()
+ && (! TYPE_FOR_JAVA (current_class_type)))
{
/* Any return from a constructor will end up here. */
add_stmt (build_stmt (LABEL_EXPR, cdtor_label));
of curly braces, skipping the artificial block created for constructor
initializers. */
-static tree
+tree
outer_curly_brace_block (tree fndecl)
{
tree block = BLOCK_SUBBLOCKS (DECL_INITIAL (fndecl));
which then got a warning when stored in a ptr-to-function variable. */
gcc_assert (building_stmt_tree ());
+ /* The current function is being defined, so its DECL_INITIAL should
+ be set, and unless there's a multiple definition, it should be
+ error_mark_node. */
+ gcc_assert (DECL_INITIAL (fndecl) == error_mark_node);
/* For a cloned function, we've already got all the code we need;
there's no need to add any extra bits. */
/* Hack. We don't want the middle-end to warn that this
return is unreachable, so put the statement on the
special line 0. */
-#ifdef USE_MAPPED_LOCATION
- SET_EXPR_LOCATION (stmt, UNKNOWN_LOCATION);
-#else
- annotate_with_file_line (stmt, input_filename, 0);
-#endif
+ {
+ location_t linezero = linemap_line_start (line_table, 0, 1);
+ SET_EXPR_LOCATION (stmt, linezero);
+ }
}
if (use_eh_spec_block (current_function_decl))
if (!processing_template_decl
&& !cp_function_chain->can_throw
&& !flag_non_call_exceptions
- && targetm.binds_local_p (fndecl))
+ && !DECL_REPLACEABLE_P (fndecl))
TREE_NOTHROW (fndecl) = 1;
/* This must come after expand_function_end because cleanups might
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. */
+ variables are selected in check_return_expr. */
if (current_function_return_value)
{
tree r = current_function_return_value;
/* Don't complain if we abort or throw. */
&& !current_function_returns_abnormally
&& !DECL_NAME (DECL_RESULT (fndecl))
- /* Normally, with -Wreturn-type, flow will complain. Unless we're an
- inline function, as we might never be compiled separately. */
- && (DECL_INLINE (fndecl) || processing_template_decl)
+ && !TREE_NO_WARNING (fndecl)
/* Structor return values (if any) are set by the compiler. */
&& !DECL_CONSTRUCTOR_P (fndecl)
&& !DECL_DESTRUCTOR_P (fndecl))
- warning (OPT_Wreturn_type, "no return statement in function returning non-void");
+ {
+ warning (OPT_Wreturn_type,
+ "no return statement in function returning non-void");
+ TREE_NO_WARNING (fndecl) = 1;
+ }
/* Store the end of the function, so that we get good line number
info for the epilogue. */
f->extern_decl_map = NULL;
/* Handle attribute((warn_unused_result)). Relies on gimple input. */
- c_warn_unused_result (&DECL_SAVED_TREE (fndecl));
+ c_warn_unused_result (gimple_body (fndecl));
}
/* Clear out the bits we don't need. */
local_names = 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. */
- cfun = NULL;
+ set_cfun (NULL);
current_function_decl = NULL;
/* If this is an in-class inline definition, we may have to pop the
check_template_shadow (fndecl);
DECL_DECLARED_INLINE_P (fndecl) = 1;
- if (flag_default_inline)
- DECL_INLINE (fndecl) = 1;
/* We process method specializations in finish_struct_1. */
if (processing_template_decl && !DECL_TEMPLATE_SPECIALIZATION (fndecl))
}
/* Called when a class type (given by TYPE) is defined. If there are
- any existing VAR_DECLs whose type hsa been completed by this
+ any existing VAR_DECLs whose type has been completed by this
declaration, update them now. */
void
complete_type_check_abstract (type);
}
-/* If DECL is of a type which needs a cleanup, build that cleanup
- here. */
+/* If DECL is of a type which needs a cleanup, build and return an
+ expression to perform that cleanup here. Return NULL_TREE if no
+ cleanup need be done. */
tree
cxx_maybe_build_cleanup (tree decl)
{
- tree type = TREE_TYPE (decl);
+ tree type;
+ tree attr;
+ tree cleanup;
+
+ /* Assume no cleanup is required. */
+ cleanup = NULL_TREE;
- if (type != error_mark_node && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
+ if (error_operand_p (decl))
+ return cleanup;
+
+ /* Handle "__attribute__((cleanup))". We run the cleanup function
+ before the destructor since the destructor is what actually
+ terminates the lifetime of the object. */
+ attr = lookup_attribute ("cleanup", DECL_ATTRIBUTES (decl));
+ if (attr)
+ {
+ tree id;
+ tree fn;
+ tree arg;
+
+ /* Get the name specified by the user for the cleanup function. */
+ id = TREE_VALUE (TREE_VALUE (attr));
+ /* Look up the name to find the cleanup function to call. It is
+ important to use lookup_name here because that is what is
+ used in c-common.c:handle_cleanup_attribute when performing
+ initial checks on the attribute. Note that those checks
+ include ensuring that the function found is not an overloaded
+ function, or an object with an overloaded call operator,
+ etc.; we can rely on the fact that the function found is an
+ ordinary FUNCTION_DECL. */
+ fn = lookup_name (id);
+ arg = build_address (decl);
+ mark_used (decl);
+ cleanup = cp_build_function_call (fn, build_tree_list (NULL_TREE,
+ arg),
+ tf_warning_or_error);
+ }
+ /* Handle ordinary C++ destructors. */
+ type = TREE_TYPE (decl);
+ if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
{
int flags = LOOKUP_NORMAL|LOOKUP_DESTRUCTOR;
- tree rval;
bool has_vbases = (TREE_CODE (type) == RECORD_TYPE
&& CLASSTYPE_VBASECLASSES (type));
+ tree addr;
+ tree call;
if (TREE_CODE (type) == ARRAY_TYPE)
- rval = decl;
+ addr = decl;
else
- {
- cxx_mark_addressable (decl);
- rval = build_unary_op (ADDR_EXPR, decl, 0);
- }
+ addr = build_address (decl);
/* Optimize for space over speed here. */
if (!has_vbases || flag_expensive_optimizations)
flags |= LOOKUP_NONVIRTUAL;
- rval = build_delete (TREE_TYPE (rval), rval,
+ call = build_delete (TREE_TYPE (addr), addr,
sfk_complete_destructor, flags, 0);
-
- return rval;
+ if (cleanup)
+ cleanup = build_compound_expr (cleanup, call);
+ else
+ cleanup = call;
}
- return NULL_TREE;
+
+ return cleanup;
}
\f
/* When a stmt has been parsed, this function is called. */
DECL_STATIC_FUNCTION_P (decl) = 1;
}
-/* Initialize the variables used during compilation of a C++
- function. */
-
-void
-cxx_push_function_context (struct function * f)
-{
- struct language_function *p = GGC_CNEW (struct language_function);
- f->language = p;
-
- /* Whenever we start a new function, we destroy temporaries in the
- usual way. */
- current_stmt_tree ()->stmts_are_full_exprs_p = 1;
-
- if (f->decl)
- {
- tree fn = f->decl;
-
- if (DECL_SAVED_FUNCTION_DATA (fn))
- {
- /* If we already parsed this function, and we're just expanding it
- now, restore saved state. */
- *cp_function_chain = *DECL_SAVED_FUNCTION_DATA (fn);
-
- /* We don't need the saved data anymore. Unless this is an inline
- function; we need the named return value info for
- declare_return_variable. */
- if (! DECL_INLINE (fn))
- DECL_SAVED_FUNCTION_DATA (fn) = NULL;
- }
- }
-}
-
-/* Free the language-specific parts of F, now that we've finished
- compiling the function. */
-
-void
-cxx_pop_function_context (struct function * f)
-{
- f->language = 0;
-}
-
/* Return which tree structure is used by T, or TS_CP_GENERIC if T is
one of the language-independent trees. */
case IDENTIFIER_NODE: return TS_CP_IDENTIFIER;
case OVERLOAD: return TS_CP_OVERLOAD;
case TEMPLATE_PARM_INDEX: return TS_CP_TPI;
- case TINST_LEVEL: return TS_CP_TINST_LEVEL;
case PTRMEM_CST: return TS_CP_PTRMEM;
case BASELINK: return TS_CP_BASELINK;
+ case STATIC_ASSERT: return TS_CP_STATIC_ASSERT;
+ case ARGUMENT_PACK_SELECT: return TS_CP_ARGUMENT_PACK_SELECT;
+ case TRAIT_EXPR: return TS_CP_TRAIT_EXPR;
default: return TS_CP_GENERIC;
}
}