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;
}
/* Returns true iff ATTR is an attribute which needs to be applied at
instantiation time rather than template definition time. */
-bool
-is_late_template_attribute (tree attr)
+static bool
+is_late_template_attribute (tree attr, tree decl)
{
tree name = TREE_PURPOSE (attr);
- if (is_attribute_p ("aligned", name))
+ tree args = TREE_VALUE (attr);
+ const struct attribute_spec *spec = lookup_attribute_spec (name);
+
+ if (!spec)
+ /* Unknown attribute. */
+ return false;
+
+ if (is_attribute_p ("aligned", name)
+ && args
+ && value_dependent_expression_p (TREE_VALUE (args)))
+ /* Can't apply this until we know the desired alignment. */
return true;
+ else if (TREE_CODE (decl) == TYPE_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;
+ 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. */
+ 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)
+splice_template_attributes (tree *attr_p, tree decl)
{
tree *p = attr_p;
tree late_attrs = NULL_TREE;
for (; *p; )
{
- if (is_late_template_attribute (*p))
+ if (is_late_template_attribute (*p, decl))
{
+ ATTR_IS_DEPENDENT (*p) = 1;
*q = *p;
*p = TREE_CHAIN (*p);
q = &TREE_CHAIN (*q);
static void
save_template_attributes (tree *attr_p, tree *decl_p)
{
- tree late_attrs = splice_template_attributes (attr_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
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)
{
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;
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;
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);