/* Process declarations and variables for C++ compiler.
Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
Hacked 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.
int at_eof;
-/* Functions called along with real static constructors and destructors. */
-
-tree static_ctors;
-tree static_dtors;
-
\f
/* Return a member function type (a METHOD_TYPE), given FNTYPE (a
sees templates. */
if (!processing_template_decl)
DECL_ARG_TYPE (parm) = type_passed_as (type);
+
+ /* If the type is a pack expansion, then we have a function
+ parameter pack. */
+ if (type && TREE_CODE (type) == TYPE_PACK_EXPANSION)
+ FUNCTION_PARAMETER_PACK_P (parm) = 1;
+
return parm;
}
TEMPLATE_DECL, it can be NULL since the parameters can be extracted
from the declaration. If the function is not a function template, it
must be NULL.
- It returns the original declaration for the function, or NULL_TREE
- if no declaration was found (and an error was emitted). */
+ It returns the original declaration for the function, NULL_TREE if
+ no declaration was found, error_mark_node if an error was emitted. */
tree
check_classfn (tree ctype, tree function, tree template_parms)
error ("no %q#D member function declared in class %qT",
function, ctype);
- /* If we did not find the method in the class, add it to avoid
- spurious errors (unless the CTYPE is not yet defined, in which
- case we'll only confuse ourselves when the function is declared
- properly within the class. */
- if (COMPLETE_TYPE_P (ctype))
- add_method (ctype, function, NULL_TREE);
-
if (pushed_scope)
pop_scope (pushed_scope);
- return NULL_TREE;
+ return error_mark_node;
}
/* DECL is a function with vague linkage. Remember it so that at the
value = push_template_decl (value);
if (attrlist)
- {
- /* Avoid storing attributes in template parameters:
- tsubst is not ready to handle them. */
- tree type = TREE_TYPE (value);
- if (TREE_CODE (type) == TEMPLATE_TYPE_PARM
- || TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM)
- sorry ("applying attributes to template parameters is not implemented");
- else
- cplus_decl_attributes (&value, attrlist, 0);
- }
+ cplus_decl_attributes (&value, attrlist, 0);
return value;
}
}
\f
+/* Returns true iff ATTR is an attribute which needs to be applied at
+ instantiation time rather than template definition time. */
+
+static bool
+is_late_template_attribute (tree attr, tree decl)
+{
+ tree name = TREE_PURPOSE (attr);
+ tree args = TREE_VALUE (attr);
+ const struct attribute_spec *spec = lookup_attribute_spec (name);
+ tree arg;
+
+ if (!spec)
+ /* Unknown attribute. */
+ return false;
+
+ /* If any of the arguments are dependent expressions, we can't evaluate
+ the attribute until instantiation time. */
+ for (arg = args; arg; arg = TREE_CHAIN (arg))
+ {
+ tree t = TREE_VALUE (arg);
+ if (value_dependent_expression_p (t)
+ || type_dependent_expression_p (t))
+ return true;
+ }
+
+ if (TREE_CODE (decl) == TYPE_DECL
+ || TYPE_P (decl)
+ || spec->type_required)
+ {
+ tree type = TYPE_P (decl) ? decl : TREE_TYPE (decl);
+
+ /* We can't apply any attributes to a completely unknown type until
+ instantiation time. */
+ enum tree_code code = TREE_CODE (type);
+ if (code == TEMPLATE_TYPE_PARM
+ || code == BOUND_TEMPLATE_TEMPLATE_PARM
+ || code == TYPENAME_TYPE)
+ return true;
+ /* Also defer most attributes on dependent types. This is not
+ necessary in all cases, but is the better default. */
+ else if (dependent_type_p (type)
+ /* But attribute visibility specifically works on
+ templates. */
+ && !is_attribute_p ("visibility", name))
+ return true;
+ else
+ return false;
+ }
+ else
+ return false;
+}
+
+/* ATTR_P is a list of attributes. Remove any attributes which need to be
+ applied at instantiation time and return them. If IS_DEPENDENT is true,
+ the declaration itself is dependent, so all attributes should be applied
+ at instantiation time. */
+
+static tree
+splice_template_attributes (tree *attr_p, tree decl)
+{
+ tree *p = attr_p;
+ tree late_attrs = NULL_TREE;
+ tree *q = &late_attrs;
+
+ if (!p)
+ return NULL_TREE;
+
+ for (; *p; )
+ {
+ if (is_late_template_attribute (*p, decl))
+ {
+ ATTR_IS_DEPENDENT (*p) = 1;
+ *q = *p;
+ *p = TREE_CHAIN (*p);
+ q = &TREE_CHAIN (*q);
+ *q = NULL_TREE;
+ }
+ else
+ p = &TREE_CHAIN (*p);
+ }
+
+ return late_attrs;
+}
+
+/* Remove any late attributes from the list in ATTR_P and attach them to
+ DECL_P. */
+
+static void
+save_template_attributes (tree *attr_p, tree *decl_p)
+{
+ tree late_attrs = splice_template_attributes (attr_p, *decl_p);
+ tree *q;
+
+ if (!late_attrs)
+ return;
+
+ /* Give this type a name so we know to look it up again at instantiation
+ time. */
+ if (TREE_CODE (*decl_p) == TYPE_DECL
+ && DECL_ORIGINAL_TYPE (*decl_p) == NULL_TREE)
+ {
+ tree oldt = TREE_TYPE (*decl_p);
+ tree newt = build_variant_type_copy (oldt);
+ DECL_ORIGINAL_TYPE (*decl_p) = oldt;
+ TREE_TYPE (*decl_p) = newt;
+ TYPE_NAME (newt) = *decl_p;
+ TREE_USED (newt) = TREE_USED (*decl_p);
+ }
+
+ if (DECL_P (*decl_p))
+ q = &DECL_ATTRIBUTES (*decl_p);
+ else
+ q = &TYPE_ATTRIBUTES (*decl_p);
+
+ if (*q)
+ q = &TREE_CHAIN (tree_last (*q));
+ *q = late_attrs;
+}
+
+/* Like decl_attributes, but handle C++ complexity. */
+
void
cplus_decl_attributes (tree *decl, tree attributes, int flags)
{
if (*decl == NULL_TREE || *decl == void_type_node
- || *decl == error_mark_node)
+ || *decl == error_mark_node
+ || attributes == NULL_TREE)
return;
+ if (processing_template_decl)
+ {
+ save_template_attributes (&attributes, decl);
+ if (attributes == NULL_TREE)
+ return;
+ }
+
if (TREE_CODE (*decl) == TEMPLATE_DECL)
decl = &DECL_TEMPLATE_RESULT (*decl);
tree base;
decl = build_decl (VAR_DECL, DECL_NAME (field), TREE_TYPE (field));
+ DECL_ANON_UNION_VAR_P (decl) = 1;
base = get_base_address (object);
TREE_PUBLIC (decl) = TREE_PUBLIC (base);
error ("%<operator new%> must return type %qT", ptr_type_node);
}
- if (!args || args == void_list_node
- || !same_type_p (TREE_VALUE (args), size_type_node))
+ if (args && args != void_list_node)
{
- e = 2;
- if (args && args != void_list_node)
- args = TREE_CHAIN (args);
- pedwarn ("%<operator new%> takes type %<size_t%> (%qT) "
- "as first parameter", size_type_node);
+ if (TREE_PURPOSE (args))
+ {
+ /* [basic.stc.dynamic.allocation]
+
+ The first parameter shall not have an associated default
+ argument. */
+ error ("the first parameter of %<operator new%> cannot "
+ "have a default argument");
+ /* Throw away the default argument. */
+ TREE_PURPOSE (args) = NULL_TREE;
+ }
+
+ if (!same_type_p (TREE_VALUE (args), size_type_node))
+ {
+ e = 2;
+ args = TREE_CHAIN (args);
+ }
}
+ else
+ e = 2;
+
+ if (e == 2)
+ pedwarn ("%<operator new%> takes type %<size_t%> (%qT) "
+ "as first parameter", size_type_node);
+
switch (e)
{
case 2:
return type;
}
\f
+/* DECL is a VAR_DECL for a vtable: walk through the entries in the vtable
+ and mark them as needed. */
+
static void
mark_vtable_entries (tree decl)
{
type_visibility (tree type)
{
int vis = VISIBILITY_DEFAULT;
- walk_tree_without_duplicates (&type, min_vis_r, &vis);
+ cp_walk_tree_without_duplicates (&type, min_vis_r, &vis);
return vis;
}
if (!DECL_EXTERN_C_P (decl))
{
TREE_PUBLIC (decl) = 0;
+ DECL_ONE_ONLY (decl) = 0;
DECL_INTERFACE_KNOWN (decl) = 1;
if (DECL_LANG_SPECIFIC (decl))
DECL_NOT_REALLY_EXTERN (decl) = 1;
else
use_template = 0;
- /* Anything that is exported must have default visibility. */
- if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
- && lookup_attribute ("dllexport",
- TREE_CODE (decl) == TYPE_DECL
- ? TYPE_ATTRIBUTES (TREE_TYPE (decl))
- : DECL_ATTRIBUTES (decl)))
- {
- DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
- DECL_VISIBILITY_SPECIFIED (decl) = 1;
- }
-
/* If DECL is a member of a class, visibility specifiers on the
class can influence the visibility of the DECL. */
if (DECL_CLASS_SCOPE_P (decl))
class_type = DECL_CONTEXT (decl);
- else if (TREE_CODE (decl) == VAR_DECL
- && DECL_TINFO_P (decl)
- && CLASS_TYPE_P (TREE_TYPE (DECL_NAME (decl))))
- class_type = TREE_TYPE (DECL_NAME (decl));
else
{
/* Not a class member. */
but have no TEMPLATE_INFO, so don't try to check it. */
use_template = 0;
}
+ else if (TREE_CODE (decl) == VAR_DECL && DECL_TINFO_P (decl)
+ && flag_visibility_ms_compat)
+ {
+ /* Under -fvisibility-ms-compat, types are visible by default,
+ even though their contents aren't. */
+ tree underlying_type = TREE_TYPE (DECL_NAME (decl));
+ int underlying_vis = type_visibility (underlying_type);
+ if (underlying_vis == VISIBILITY_ANON
+ || CLASSTYPE_VISIBILITY_SPECIFIED (underlying_type))
+ constrain_visibility (decl, underlying_vis);
+ else
+ DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
+ }
else if (TREE_CODE (decl) == VAR_DECL && DECL_TINFO_P (decl))
{
/* tinfo visibility is based on the type it's for. */
{
/* Propagate anonymity from type to decl. */
int tvis = type_visibility (TREE_TYPE (decl));
- if (tvis == VISIBILITY_ANON)
+ if (tvis == VISIBILITY_ANON
+ || ! DECL_VISIBILITY_SPECIFIED (decl))
constrain_visibility (decl, tvis);
}
}
static void
determine_visibility_from_class (tree decl, tree class_type)
{
+ if (DECL_VISIBILITY_SPECIFIED (decl))
+ return;
+
if (visibility_options.inlines_hidden
/* Don't do this for inline templates; specializations might not be
inline, and we don't want them to inherit the hidden
visibility. We'll set it here for all inline instantiations. */
&& !processing_template_decl
- && ! DECL_VISIBILITY_SPECIFIED (decl)
&& TREE_CODE (decl) == FUNCTION_DECL
&& DECL_DECLARED_INLINE_P (decl)
&& (! DECL_LANG_SPECIFIC (decl)
|| ! DECL_EXPLICIT_INSTANTIATION (decl)))
DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
- else if (!DECL_VISIBILITY_SPECIFIED (decl))
+ else
{
/* Default to the class visibility. */
DECL_VISIBILITY (decl) = CLASSTYPE_VISIBILITY (class_type);
&& !DECL_CONSTRUCTION_VTABLE_P (decl)))
&& TREE_PUBLIC (decl)
&& !DECL_REALLY_EXTERN (decl)
- && !DECL_VISIBILITY_SPECIFIED (decl)
&& !CLASSTYPE_VISIBILITY_SPECIFIED (class_type))
targetm.cxx.determine_class_data_visibility (decl);
}
for (t = TYPE_FIELDS (type); t; t = TREE_CHAIN (t))
if (TREE_CODE (t) == FIELD_DECL && TREE_TYPE (t) != error_mark_node)
{
- tree ftype = strip_array_types (TREE_TYPE (t));
+ tree ftype = strip_pointer_or_array_types (TREE_TYPE (t));
int subvis = type_visibility (ftype);
if (subvis == VISIBILITY_ANON)
- warning (0, "\
+ {
+ if (!in_main_input_context ())
+ warning (0, "\
%qT has a field %qD whose type uses the anonymous namespace",
- type, t);
+ type, t);
+ }
else if (IS_AGGR_TYPE (ftype)
&& vis < VISIBILITY_HIDDEN
&& subvis >= VISIBILITY_HIDDEN)
int subvis = type_visibility (TREE_TYPE (t));
if (subvis == VISIBILITY_ANON)
- warning (0, "\
+ {
+ if (!in_main_input_context())
+ warning (0, "\
%qT has a base %qT whose type uses the anonymous namespace",
- type, TREE_TYPE (t));
+ type, TREE_TYPE (t));
+ }
else if (vis < VISIBILITY_HIDDEN
&& subvis >= VISIBILITY_HIDDEN)
warning (OPT_Wattributes, "\
{
/* DECL is an implicit instantiation of a function or static
data member. */
- if (flag_implicit_templates
+ if ((flag_implicit_templates
+ && !flag_use_repository)
|| (flag_implicit_inline_templates
&& TREE_CODE (decl) == FUNCTION_DECL
&& DECL_DECLARED_INLINE_P (decl)))
if (TREE_CODE (type) == ARRAY_TYPE)
temp = decl;
else
- {
- cxx_mark_addressable (decl);
- temp = build1 (ADDR_EXPR, build_pointer_type (type), decl);
- }
+ temp = build_address (decl);
temp = build_delete (TREE_TYPE (temp), temp,
sfk_complete_destructor,
LOOKUP_NORMAL|LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0);
DECL_ONE_ONLY (guard) = DECL_ONE_ONLY (decl);
if (TREE_PUBLIC (decl))
DECL_WEAK (guard) = DECL_WEAK (decl);
+ DECL_VISIBILITY (guard) = DECL_VISIBILITY (decl);
+ DECL_VISIBILITY_SPECIFIED (guard) = DECL_VISIBILITY_SPECIFIED (decl);
DECL_ARTIFICIAL (guard) = 1;
DECL_IGNORED_P (guard) = 1;
void_list_node));
start_preparsed_function (fndecl, /*attrs=*/NULL_TREE, SF_PRE_PARSED);
- /* It can be a static function as long as collect2 does not have
- to scan the object file to find its ctor/dtor routine. */
- TREE_PUBLIC (current_function_decl) = ! targetm.have_ctors_dtors;
+ TREE_PUBLIC (current_function_decl) = 0;
+
+ /* Mark as artificial because it's not explicitly in the user's
+ source code. */
+ DECL_ARTIFICIAL (current_function_decl) = 1;
/* Mark this declaration as used to avoid spurious warnings. */
TREE_USED (current_function_decl) = 1;
/* Finish up. */
finish_compound_stmt (body);
fn = finish_function (0);
- expand_or_defer_fn (fn);
- /* When only doing semantic analysis, and no RTL generation, we
- can't call functions that directly emit assembly code; there is
- no assembly file in which to put the code. */
- if (flag_syntax_only)
- return;
-
- if (targetm.have_ctors_dtors)
+ if (method_type == 'I')
{
- rtx fnsym = XEXP (DECL_RTL (fn), 0);
- cgraph_mark_needed_node (cgraph_node (fn));
- if (method_type == 'I')
- (* targetm.asm_out.constructor) (fnsym, initp);
- else
- (* targetm.asm_out.destructor) (fnsym, initp);
+ DECL_STATIC_CONSTRUCTOR (fn) = 1;
+ decl_init_priority_insert (fn, initp);
+ }
+ else
+ {
+ DECL_STATIC_DESTRUCTOR (fn) = 1;
+ decl_fini_priority_insert (fn, initp);
}
+
+ expand_or_defer_fn (fn);
}
/* The names of the parameters to the function created to handle
&& constructor_p && objc_static_init_needed_p ())
{
body = start_objects (function_key, priority);
- static_ctors = objc_generate_static_init_call (static_ctors);
+ objc_generate_static_init_call (NULL_TREE);
}
/* Call the static storage duration function with appropriate
}
}
- /* If we're generating code for the DEFAULT_INIT_PRIORITY, throw in
- calls to any functions marked with attributes indicating that
- they should be called at initialization- or destruction-time. */
- if (priority == DEFAULT_INIT_PRIORITY)
- {
- tree fns;
-
- for (fns = constructor_p ? static_ctors : static_dtors;
- fns;
- fns = TREE_CHAIN (fns))
- {
- fndecl = TREE_VALUE (fns);
-
- /* Calls to pure/const functions will expand to nothing. */
- if (! (flags_from_decl_or_type (fndecl) & (ECF_CONST | ECF_PURE)))
- {
- if (! body)
- body = start_objects (function_key, priority);
- finish_expr_stmt (build_function_call (fndecl, NULL_TREE));
- }
- }
- }
-
/* Close out the function. */
if (body)
finish_objects (function_key, priority, body);
/* Generate the functions themselves, but only if they are really
needed. */
- if (pi->initializations_p
- || (priority == DEFAULT_INIT_PRIORITY && static_ctors))
+ if (pi->initializations_p)
generate_ctor_or_dtor_function (/*constructor_p=*/true, priority, locus);
- if (pi->destructions_p
- || (priority == DEFAULT_INIT_PRIORITY && static_dtors))
+ if (pi->destructions_p)
generate_ctor_or_dtor_function (/*constructor_p=*/false, priority, locus);
/* Keep iterating. */
Here we must deal with member pointers. */
tree
-cxx_callgraph_analyze_expr (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
- tree from ATTRIBUTE_UNUSED)
+cxx_callgraph_analyze_expr (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED)
{
tree t = *tp;
splay_tree_foreach (priority_info_map,
generate_ctor_and_dtor_functions_for_priority,
/*data=*/&locus);
- else
- {
- /* If we have a ctor or this is obj-c++ and we need a static init,
- call generate_ctor_or_dtor_function. */
- if (static_ctors || (c_dialect_objc () && objc_static_init_needed_p ()))
- generate_ctor_or_dtor_function (/*constructor_p=*/true,
- DEFAULT_INIT_PRIORITY, &locus);
- if (static_dtors)
- generate_ctor_or_dtor_function (/*constructor_p=*/false,
- DEFAULT_INIT_PRIORITY, &locus);
- }
+ else if (c_dialect_objc () && objc_static_init_needed_p ())
+ /* If this is obj-c++ and we need a static init, call
+ generate_ctor_or_dtor_function. */
+ generate_ctor_or_dtor_function (/*constructor_p=*/true,
+ DEFAULT_INIT_PRIORITY, &locus);
/* We're done with the splay-tree now. */
if (priority_info_map)
parameter. That must be done before the FN is transformed
because we depend on the form of FN. */
args = build_non_dependent_args (args);
+ object = build_non_dependent_expr (object);
if (TREE_CODE (fn) == DOTSTAR_EXPR)
object = build_unary_op (ADDR_EXPR, object, 0);
- object = build_non_dependent_expr (object);
args = tree_cons (NULL_TREE, object, args);
/* Now that the arguments are done, transform FN. */
fn = build_non_dependent_expr (fn);