/* Process declarations and variables for C++ compiler.
Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010
- Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010,
+ 2011, 2012 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GCC.
#include "flags.h"
#include "cp-tree.h"
#include "decl.h"
-#include "output.h"
-#include "except.h"
#include "toplev.h"
#include "timevar.h"
#include "cpplib.h"
#include "target.h"
#include "c-family/c-common.h"
-#include "tree-mudflap.h"
+#include "c-family/c-objc.h"
#include "cgraph.h"
#include "tree-inline.h"
#include "c-family/c-pragma.h"
-#include "tree-dump.h"
+#include "dumpfile.h"
#include "intl.h"
#include "gimple.h"
#include "pointer-set.h"
static void import_export_class (tree);
static tree get_guard_bits (tree);
static void determine_visibility_from_class (tree, tree);
+static bool determine_hidden_inline (tree);
static bool decl_defined_p (tree);
/* A list of static class variables. This is needed, because a
tree raises = TYPE_RAISES_EXCEPTIONS (fntype);
tree attrs = TYPE_ATTRIBUTES (fntype);
+ if (new_ret == error_mark_node)
+ return fntype;
+
if (same_type_p (new_ret, TREE_TYPE (fntype)))
return fntype;
}
else
newtype = build_method_type_directly
- (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (fntype))),
- new_ret, TREE_CHAIN (args));
+ (class_of_this_parm (fntype), new_ret, TREE_CHAIN (args));
if (raises)
newtype = build_exception_variant (newtype, raises);
if (attrs)
basetype = TREE_TYPE (TREE_VALUE (arg_types));
arg_types = TREE_CHAIN (arg_types);
- parms = TREE_CHAIN (DECL_ARGUMENTS (fn));
+ parms = DECL_CHAIN (DECL_ARGUMENTS (fn));
/* If this is a subobject constructor or destructor, our caller will
pass us a pointer to our VTT. */
parm = build_artificial_parm (vtt_parm_identifier, vtt_parm_type);
/* First add it to DECL_ARGUMENTS between 'this' and the real args... */
- TREE_CHAIN (parm) = parms;
+ DECL_CHAIN (parm) = parms;
parms = parm;
/* ...and then to TYPE_ARG_TYPES. */
/* Then add the in-charge parm (before the VTT parm). */
parm = build_artificial_parm (in_charge_identifier, integer_type_node);
- TREE_CHAIN (parm) = parms;
+ DECL_CHAIN (parm) = parms;
parms = parm;
arg_types = hash_tree_chain (integer_type_node, arg_types);
/* Insert our new parameter(s) into the list. */
- TREE_CHAIN (DECL_ARGUMENTS (fn)) = parms;
+ DECL_CHAIN (DECL_ARGUMENTS (fn)) = parms;
/* And rebuild the function type. */
fntype = build_method_type_directly (basetype, TREE_TYPE (TREE_TYPE (fn)),
along the way. */
tree
-grok_array_decl (tree array_expr, tree index_exp)
+grok_array_decl (location_t loc, tree array_expr, tree index_exp)
{
tree type;
tree expr;
{
if (type_dependent_expression_p (array_expr)
|| type_dependent_expression_p (index_exp))
- return build_min_nt (ARRAY_REF, array_expr, index_exp,
- NULL_TREE, NULL_TREE);
+ return build_min_nt_loc (loc, ARRAY_REF, array_expr, index_exp,
+ NULL_TREE, NULL_TREE);
array_expr = build_non_dependent_expr (array_expr);
index_exp = build_non_dependent_expr (index_exp);
}
/* If they have an `operator[]', use that. */
if (MAYBE_CLASS_TYPE_P (type) || MAYBE_CLASS_TYPE_P (TREE_TYPE (index_exp)))
- expr = build_new_op (ARRAY_REF, LOOKUP_NORMAL,
- array_expr, index_exp, NULL_TREE,
- /*overloaded_p=*/NULL, tf_warning_or_error);
+ expr = build_new_op (loc, ARRAY_REF, LOOKUP_NORMAL, array_expr, index_exp,
+ NULL_TREE, /*overload=*/NULL, tf_warning_or_error);
else
{
tree p1, p2, i1, i2;
It is a little-known fact that, if `a' is an array and `i' is
an int, you can write `i[a]', which means the same thing as
`a[i]'. */
- if (TREE_CODE (type) == ARRAY_TYPE)
+ if (TREE_CODE (type) == ARRAY_TYPE || TREE_CODE (type) == VECTOR_TYPE)
p1 = array_expr;
else
p1 = build_expr_type_conversion (WANT_POINTER, array_expr, false);
Implements ARM $5.3.4. This is called from the parser. */
tree
-delete_sanity (tree exp, tree size, bool doing_vec, int use_global_delete)
+delete_sanity (tree exp, tree size, bool doing_vec, int use_global_delete,
+ tsubst_flags_t complain)
{
tree t, type;
}
/* An array can't have been allocated by new, so complain. */
- if (TREE_CODE (exp) == VAR_DECL
- && TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE)
- warning (0, "deleting array %q#D", exp);
+ if (TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE)
+ warning (0, "deleting array %q#E", exp);
t = build_expr_type_conversion (WANT_POINTER, exp, true);
if (doing_vec)
return build_vec_delete (t, /*maxindex=*/NULL_TREE,
sfk_deleting_destructor,
- use_global_delete);
+ use_global_delete, complain);
else
return build_delete (type, t, sfk_deleting_destructor,
- LOOKUP_NORMAL, use_global_delete);
+ LOOKUP_NORMAL, use_global_delete,
+ complain);
}
/* Report an error if the indicated template declaration is not the
decl = DECL_TEMPLATE_RESULT (tmpl);
if (TREE_CODE (decl) == FUNCTION_DECL
+ || DECL_ALIAS_TEMPLATE_P (tmpl)
|| (TREE_CODE (decl) == TYPE_DECL
&& MAYBE_CLASS_TYPE_P (TREE_TYPE (decl))))
{
&& !comp_template_parms (template_parms,
DECL_TEMPLATE_PARMS (function)))
{
- error ("template parameter lists provided don't match the "
+ error ("template parameter lists provided don%'t match the "
"template parameters of %qD", function);
return error_mark_node;
}
if (! processing_template_decl)
VEC_safe_push (tree, gc, pending_statics, decl);
- if (LOCAL_CLASS_P (current_class_type))
+ if (LOCAL_CLASS_P (current_class_type)
+ /* We already complained about the template definition. */
+ && !DECL_TEMPLATE_INSTANTIATION (decl))
permerror (input_location, "local class %q#T shall not have static data member %q#D",
current_class_type, decl);
- /* Static consts need not be initialized in the class definition. */
- if (init != NULL_TREE && TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
- {
- static int explained = 0;
-
- error ("initializer invalid for static member with constructor");
- if (!explained)
- {
- error ("(an out of class initialization is required)");
- explained = 1;
- }
- init = NULL_TREE;
- }
-
- DECL_INITIAL (decl) = init;
DECL_IN_AGGR_P (decl) = 1;
if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
{
tree value;
const char *asmspec = 0;
- int flags = LOOKUP_ONLYCONVERTING;
+ int flags;
tree name;
if (init
DECL_NONLOCAL (value) = 1;
DECL_CONTEXT (value) = current_class_type;
- if (processing_template_decl)
- value = push_template_decl (value);
-
if (attrlist)
{
int attrflags = 0;
cplus_decl_attributes (&value, attrlist, attrflags);
}
- if (declspecs->specs[(int)ds_typedef]
+ if (decl_spec_seq_has_spec_p (declspecs, ds_typedef)
&& TREE_TYPE (value) != error_mark_node
&& TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (value))) != value)
- cp_set_underlying_type (value);
+ set_underlying_type (value);
+ /* It's important that push_template_decl below follows
+ set_underlying_type above so that the created template
+ carries the properly set type of VALUE. */
+ if (processing_template_decl)
+ value = push_template_decl (value);
+
+ record_locally_defined_typedef (value);
return value;
}
DECL_DECLARED_INLINE_P (value) = 1;
}
}
+ else if (TREE_CODE (init) == DEFAULT_ARG)
+ error ("invalid initializer for member function %qD", value);
else if (TREE_CODE (TREE_TYPE (value)) == METHOD_TYPE)
{
if (integer_zerop (init))
value);
}
}
- else if (pedantic && TREE_CODE (value) != VAR_DECL)
- /* Already complained in grokdeclarator. */
- init = NULL_TREE;
+ else if (TREE_CODE (value) == FIELD_DECL)
+ /* C++11 NSDMI, keep going. */;
+ else if (TREE_CODE (value) != VAR_DECL)
+ gcc_unreachable ();
else if (!processing_template_decl)
{
if (TREE_CODE (init) == CONSTRUCTOR)
- init = digest_init (TREE_TYPE (value), init);
- else
- init = integral_constant_value (init);
+ init = digest_init (TREE_TYPE (value), init, tf_warning_or_error);
+ init = maybe_constant_init (init);
if (init != error_mark_node && !TREE_CONSTANT (init))
{
if (attrlist)
cplus_decl_attributes (&value, attrlist, 0);
+ if (init && BRACE_ENCLOSED_INITIALIZER_P (init)
+ && CONSTRUCTOR_IS_DIRECT_INIT (init))
+ flags = LOOKUP_NORMAL;
+ else
+ flags = LOOKUP_IMPLICIT;
+
switch (TREE_CODE (value))
{
case VAR_DECL:
init = error_mark_node;
cp_finish_decl (value, init, /*init_const_expr_p=*/false,
NULL_TREE, flags);
- DECL_INITIAL (value) = init;
DECL_IN_AGGR_P (value) = 1;
return value;
if (width != error_mark_node)
{
- constant_expression_warning (width);
+ /* The width must be an integer type. */
+ if (!type_dependent_expression_p (width)
+ && !INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (TREE_TYPE (width)))
+ error ("width of bit-field %qD has non-integral type %qT", value,
+ TREE_TYPE (width));
DECL_INITIAL (value) = width;
SET_DECL_C_BIT_FIELD (value);
}
if (is_attribute_p ("weak", name))
return true;
+ /* Attribute unused is applied directly, as it appertains to
+ decls. */
+ if (is_attribute_p ("unused", name))
+ 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))
old_attrs = *q;
- /* Place the late attributes at the beginning of the attribute
+ /* Merge the late attributes at the beginning with the attribute
list. */
- TREE_CHAIN (tree_last (late_attrs)) = *q;
+ late_attrs = merge_attributes (late_attrs, *q);
*q = late_attrs;
if (!DECL_P (*decl_p) && *decl_p == TYPE_MAIN_VARIANT (*decl_p))
so we must compensate by getting rid of it. */
outer
= build_method_type_directly
- (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (type))),
- inner,
+ (class_of_this_parm (type), inner,
TREE_CHAIN (TYPE_ARG_TYPES (type)));
}
else if (TREE_CODE (type) == OFFSET_TYPE)
return cp_build_qualified_type (outer, cp_type_quals (type));
}
+/* Replaces any constexpr expression that may be into the attributes
+ arguments with their reduced value. */
+
+static void
+cp_check_const_attributes (tree attributes)
+{
+ tree attr;
+ for (attr = attributes; attr; attr = TREE_CHAIN (attr))
+ {
+ tree arg;
+ for (arg = TREE_VALUE (attr); arg; arg = TREE_CHAIN (arg))
+ {
+ tree expr = TREE_VALUE (arg);
+ if (EXPR_P (expr))
+ TREE_VALUE (arg) = maybe_constant_value (expr);
+ }
+ }
+}
+
/* Like decl_attributes, but handle C++ complexity. */
void
return;
}
+ cp_check_const_attributes (attributes);
+
if (TREE_CODE (*decl) == TEMPLATE_DECL)
decl = &DECL_TEMPLATE_RESULT (*decl);
/* Rather than write the code to handle the non-union case,
just give an error. */
if (TREE_CODE (type) != UNION_TYPE)
- error ("anonymous struct not inside named type");
+ {
+ error ("anonymous struct not inside named type");
+ return error_mark_node;
+ }
for (field = TYPE_FIELDS (type);
field != NULL_TREE;
- field = TREE_CHAIN (field))
+ field = DECL_CHAIN (field))
{
tree decl;
tree ref;
permerror (input_location, "protected member %q+#D in anonymous union", field);
if (processing_template_decl)
- ref = build_min_nt (COMPONENT_REF, object,
- DECL_NAME (field), NULL_TREE);
+ ref = build_min_nt_loc (UNKNOWN_LOCATION, COMPONENT_REF, object,
+ DECL_NAME (field), NULL_TREE);
else
ref = build_class_member_access_expr (object, field, NULL_TREE,
false, tf_warning_or_error);
/* Use main_decl to set the mangled name. */
DECL_NAME (anon_union_decl) = DECL_NAME (main_decl);
maybe_commonize_var (anon_union_decl);
- mangle_decl (anon_union_decl);
+ if (TREE_STATIC (anon_union_decl) || DECL_EXTERNAL (anon_union_decl))
+ mangle_decl (anon_union_decl);
DECL_NAME (anon_union_decl) = NULL_TREE;
}
pushdecl (anon_union_decl);
- if (building_stmt_tree ()
- && at_function_scope_p ())
- add_decl_expr (anon_union_decl);
- else if (!processing_template_decl)
- rest_of_decl_compilation (anon_union_decl,
- toplevel_bindings_p (), at_eof);
+ cp_finish_decl (anon_union_decl, NULL_TREE, false, NULL_TREE, 0);
}
\f
/* Auxiliary functions to make type signatures for
DECL_COMDAT (decl) = 1;
/* Mark it needed so we don't forget to emit it. */
mark_decl_referenced (decl);
+ TREE_USED (decl) = 1;
}
}
}
void
mark_needed (tree decl)
{
- /* It's possible that we no longer need to set
- TREE_SYMBOL_REFERENCED here directly, but doing so is
- harmless. */
- TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)) = 1;
+ TREE_USED (decl) = 1;
mark_decl_referenced (decl);
}
return true;
/* If this entity was used, let the back end see it; it will decide
whether or not to emit it into the object file. */
- if (TREE_USED (decl)
- || (DECL_ASSEMBLER_NAME_SET_P (decl)
- && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))))
+ if (TREE_USED (decl))
return true;
/* Functions marked "dllexport" must be emitted so that they are
visible to other DLLs. */
- if (lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl)))
+ if (flag_keep_inline_dllexport
+ && lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl)))
return true;
/* Otherwise, DECL does not need to be emitted -- yet. A subsequent
reference to DECL might cause it to be emitted later. */
tree vtbl;
tree primary_vtbl;
int needed = 0;
- struct varpool_node *current = NULL, *last = NULL, *first = NULL;
+ struct varpool_node *current = NULL, *last = NULL;
/* If the vtables for this class have already been emitted there is
nothing more to do. */
determine_key_method (ctype);
/* See if any of the vtables are needed. */
- for (vtbl = CLASSTYPE_VTABLES (ctype); vtbl; vtbl = TREE_CHAIN (vtbl))
+ for (vtbl = CLASSTYPE_VTABLES (ctype); vtbl; vtbl = DECL_CHAIN (vtbl))
{
import_export_decl (vtbl);
if (DECL_NOT_REALLY_EXTERN (vtbl) && decl_needed_p (vtbl))
/* The ABI requires that we emit all of the vtables if we emit any
of them. */
- for (vtbl = CLASSTYPE_VTABLES (ctype); vtbl; vtbl = TREE_CHAIN (vtbl))
+ for (vtbl = CLASSTYPE_VTABLES (ctype); vtbl; vtbl = DECL_CHAIN (vtbl))
{
/* Mark entities references from the virtual table as used. */
mark_vtable_entries (vtbl);
if (TREE_TYPE (DECL_INITIAL (vtbl)) == 0)
{
- tree expr = store_init_value (vtbl, DECL_INITIAL (vtbl), LOOKUP_NORMAL);
+ VEC(tree,gc)* cleanups = NULL;
+ tree expr = store_init_value (vtbl, DECL_INITIAL (vtbl), &cleanups,
+ LOOKUP_NORMAL);
/* It had better be all done at compile-time. */
- gcc_assert (!expr);
+ gcc_assert (!expr && !cleanups);
}
/* Write it out. */
actually marking the variable as written. */
if (flag_syntax_only)
TREE_ASM_WRITTEN (vtbl) = 1;
- else if (DECL_COMDAT (vtbl))
+ else if (DECL_ONE_ONLY (vtbl))
{
current = varpool_node (vtbl);
if (last)
- last->same_comdat_group = current;
+ symtab_add_to_same_comdat_group ((symtab_node) current, (symtab_node) last);
last = current;
- if (!first)
- first = current;
}
}
- if (first != last)
- last->same_comdat_group = first;
-
/* Since we're writing out the vtable here, also write the debug
info. */
note_debug_info_needed (ctype);
}
/* Limit the visibility of DECL to VISIBILITY, if not explicitly
- specified (or if VISIBILITY is static). */
+ specified (or if VISIBILITY is static). If TMPL is true, this
+ constraint is for a template argument, and takes precedence
+ over explicitly-specified visibility on the template. */
-static bool
-constrain_visibility (tree decl, int visibility)
+static void
+constrain_visibility (tree decl, int visibility, bool tmpl)
{
if (visibility == VISIBILITY_ANON)
{
}
}
else if (visibility > DECL_VISIBILITY (decl)
- && !DECL_VISIBILITY_SPECIFIED (decl))
+ && (tmpl || !DECL_VISIBILITY_SPECIFIED (decl)))
{
DECL_VISIBILITY (decl) = (enum symbol_visibility) visibility;
- return true;
+ /* This visibility was not specified. */
+ DECL_VISIBILITY_SPECIFIED (decl) = false;
}
- return false;
}
/* Constrain the visibility of DECL based on the visibility of its template
}
}
if (vis)
- constrain_visibility (decl, vis);
+ constrain_visibility (decl, vis, true);
}
}
containing function by default, except that
-fvisibility-inlines-hidden doesn't affect them. */
tree fn = DECL_CONTEXT (decl);
- if (DECL_VISIBILITY_SPECIFIED (fn) || ! DECL_CLASS_SCOPE_P (fn))
+ if (DECL_VISIBILITY_SPECIFIED (fn))
{
DECL_VISIBILITY (decl) = DECL_VISIBILITY (fn);
DECL_VISIBILITY_SPECIFIED (decl) =
DECL_VISIBILITY_SPECIFIED (fn);
}
else
- determine_visibility_from_class (decl, DECL_CONTEXT (fn));
+ {
+ if (DECL_CLASS_SCOPE_P (fn))
+ determine_visibility_from_class (decl, DECL_CONTEXT (fn));
+ else if (determine_hidden_inline (fn))
+ {
+ DECL_VISIBILITY (decl) = default_visibility;
+ DECL_VISIBILITY_SPECIFIED (decl) =
+ visibility_options.inpragma;
+ }
+ else
+ {
+ DECL_VISIBILITY (decl) = DECL_VISIBILITY (fn);
+ DECL_VISIBILITY_SPECIFIED (decl) =
+ DECL_VISIBILITY_SPECIFIED (fn);
+ }
+ }
/* Local classes in templates have CLASSTYPE_USE_TEMPLATE set,
but have no TEMPLATE_INFO, so don't try to check it. */
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);
+ || (CLASS_TYPE_P (underlying_type)
+ && CLASSTYPE_VISIBILITY_SPECIFIED (underlying_type)))
+ constrain_visibility (decl, underlying_vis, false);
else
DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
}
{
/* tinfo visibility is based on the type it's for. */
constrain_visibility
- (decl, type_visibility (TREE_TYPE (DECL_NAME (decl))));
+ (decl, type_visibility (TREE_TYPE (DECL_NAME (decl))), false);
/* Give the target a chance to override the visibility associated
with DECL. */
on their template unless they override it with an attribute. */;
else if (! DECL_VISIBILITY_SPECIFIED (decl))
{
- /* Set default visibility to whatever the user supplied with
- #pragma GCC visibility or a namespace visibility attribute. */
- DECL_VISIBILITY (decl) = default_visibility;
- DECL_VISIBILITY_SPECIFIED (decl) = visibility_options.inpragma;
+ if (determine_hidden_inline (decl))
+ DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
+ else
+ {
+ /* Set default visibility to whatever the user supplied with
+ #pragma GCC visibility or a namespace visibility attribute. */
+ DECL_VISIBILITY (decl) = default_visibility;
+ DECL_VISIBILITY_SPECIFIED (decl) = visibility_options.inpragma;
+ }
}
}
? TYPE_TEMPLATE_INFO (TREE_TYPE (decl))
: DECL_TEMPLATE_INFO (decl));
tree args = TI_ARGS (tinfo);
+ tree attribs = (TREE_CODE (decl) == TYPE_DECL
+ ? TYPE_ATTRIBUTES (TREE_TYPE (decl))
+ : DECL_ATTRIBUTES (decl));
if (args != error_mark_node)
{
- int depth = TMPL_ARGS_DEPTH (args);
tree pattern = DECL_TEMPLATE_RESULT (TI_TEMPLATE (tinfo));
if (!DECL_VISIBILITY_SPECIFIED (decl))
{
- DECL_VISIBILITY (decl) = DECL_VISIBILITY (pattern);
- DECL_VISIBILITY_SPECIFIED (decl)
- = DECL_VISIBILITY_SPECIFIED (pattern);
+ if (!DECL_VISIBILITY_SPECIFIED (pattern)
+ && determine_hidden_inline (decl))
+ DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
+ else
+ {
+ DECL_VISIBILITY (decl) = DECL_VISIBILITY (pattern);
+ DECL_VISIBILITY_SPECIFIED (decl)
+ = DECL_VISIBILITY_SPECIFIED (pattern);
+ }
}
- /* FIXME should TMPL_ARGS_DEPTH really return 1 for null input? */
- if (args && depth > template_class_depth (class_type))
- /* Limit visibility based on its template arguments. */
- constrain_visibility_for_template (decl, args);
+ if (args
+ /* Template argument visibility outweighs #pragma or namespace
+ visibility, but not an explicit attribute. */
+ && !lookup_attribute ("visibility", attribs))
+ {
+ int depth = TMPL_ARGS_DEPTH (args);
+ int class_depth = 0;
+ if (class_type && CLASSTYPE_TEMPLATE_INFO (class_type))
+ class_depth = TMPL_ARGS_DEPTH (CLASSTYPE_TI_ARGS (class_type));
+ if (DECL_VISIBILITY_SPECIFIED (decl))
+ {
+ /* A class template member with explicit visibility
+ overrides the class visibility, so we need to apply
+ all the levels of template args directly. */
+ int i;
+ for (i = 1; i <= depth; ++i)
+ {
+ tree lev = TMPL_ARGS_LEVEL (args, i);
+ constrain_visibility_for_template (decl, lev);
+ }
+ }
+ else if (depth > class_depth)
+ /* Limit visibility based on its template arguments. */
+ constrain_visibility_for_template (decl, args);
+ }
}
}
if (decl_anon_ns_mem_p (decl))
/* Names in an anonymous namespace get internal linkage.
This might change once we implement export. */
- constrain_visibility (decl, VISIBILITY_ANON);
+ constrain_visibility (decl, VISIBILITY_ANON, false);
else if (TREE_CODE (decl) != TYPE_DECL)
{
/* Propagate anonymity from type to decl. */
int tvis = type_visibility (TREE_TYPE (decl));
if (tvis == VISIBILITY_ANON
|| ! DECL_VISIBILITY_SPECIFIED (decl))
- constrain_visibility (decl, tvis);
+ constrain_visibility (decl, tvis, false);
}
else if (no_linkage_check (TREE_TYPE (decl), /*relaxed_p=*/true))
/* DR 757: A type without linkage shall not be used as the type of a
Since non-extern "C" decls need to be defined in the same
translation unit, we can make the type internal. */
- constrain_visibility (decl, VISIBILITY_ANON);
+ constrain_visibility (decl, VISIBILITY_ANON, false);
/* If visibility changed and DECL already has DECL_RTL, ensure
symbol flags are updated. */
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
- && TREE_CODE (decl) == FUNCTION_DECL
- && DECL_DECLARED_INLINE_P (decl)
- && (! DECL_LANG_SPECIFIC (decl)
- || ! DECL_EXPLICIT_INSTANTIATION (decl)))
+ if (determine_hidden_inline (decl))
DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
else
{
targetm.cxx.determine_class_data_visibility (decl);
}
+/* Returns true iff DECL is an inline that should get hidden visibility
+ because of -fvisibility-inlines-hidden. */
+
+static bool
+determine_hidden_inline (tree decl)
+{
+ return (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
+ && TREE_CODE (decl) == FUNCTION_DECL
+ && DECL_DECLARED_INLINE_P (decl)
+ && (! DECL_LANG_SPECIFIC (decl)
+ || ! DECL_EXPLICIT_INSTANTIATION (decl)));
+}
+
/* Constrain the visibility of a class TYPE based on the visibility of its
field types. Warn if any fields require lesser visibility. */
if (CLASSTYPE_VISIBILITY_SPECIFIED (type))
vis = VISIBILITY_INTERNAL;
- for (t = TYPE_FIELDS (type); t; t = TREE_CHAIN (t))
+ for (t = TYPE_FIELDS (type); t; t = DECL_CHAIN (t))
if (TREE_CODE (t) == FIELD_DECL && TREE_TYPE (t) != error_mark_node)
{
tree ftype = strip_pointer_or_array_types (TREE_TYPE (t));
temp = build_address (decl);
temp = build_delete (TREE_TYPE (temp), temp,
sfk_complete_destructor,
- LOOKUP_NORMAL|LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0);
+ LOOKUP_NORMAL|LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0,
+ tf_warning_or_error);
return temp;
}
{
tree body;
tree fndecl;
- char type[10];
+ char type[14];
/* Make ctor or dtor function. METHOD_TYPE may be 'I' or 'D'. */
joiner = '_';
#endif
- sprintf (type, "%c%c%.5u", method_type, joiner, initp);
+ sprintf (type, "sub_%c%c%.5u", method_type, joiner, initp);
}
else
- sprintf (type, "%c", method_type);
+ sprintf (type, "sub_%c", method_type);
fndecl = build_lang_decl (FUNCTION_DECL,
get_file_function_name (type),
DECL_CONTEXT (priority_decl) = ssdf_decl;
TREE_USED (priority_decl) = 1;
- TREE_CHAIN (initialize_p_decl) = priority_decl;
+ DECL_CHAIN (initialize_p_decl) = priority_decl;
DECL_ARGUMENTS (ssdf_decl) = initialize_p_decl;
/* Put the function in the global scope. */
it's DECL_CONTECT() properly set. */
static tree
fix_temporary_vars_context_r (tree *node,
- int *unused ATTRIBUTE_UNUSED,
- void *unused1 ATTRIBUTE_UNUSED)
+ int * /*unused*/,
+ void * /*unused1*/)
{
gcc_assert (current_function_decl);
{
tree var;
- for (var = BIND_EXPR_VARS (*node); var; var = TREE_CHAIN (var))
+ for (var = BIND_EXPR_VARS (*node); var; var = DECL_CHAIN (var))
if (TREE_CODE (var) == VAR_DECL
&& !DECL_NAME (var)
&& DECL_ARTIFICIAL (var)
/* Call the static storage duration function with appropriate
arguments. */
- for (i = 0; VEC_iterate (tree, ssdf_decls, i, fndecl); ++i)
+ FOR_EACH_VEC_ELT (tree, ssdf_decls, i, fndecl)
{
/* Calls to pure or const functions will expand to nothing. */
if (! (flags_from_decl_or_type (fndecl) & (ECF_CONST | ECF_PURE)))
return 0;
}
-/* Called via LANGHOOK_CALLGRAPH_ANALYZE_EXPR. It is supposed to mark
- decls referenced from front-end specific constructs; it will be called
- only for language-specific tree nodes.
-
- Here we must deal with member pointers. */
-
-tree
-cxx_callgraph_analyze_expr (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED)
-{
- tree t = *tp;
-
- switch (TREE_CODE (t))
- {
- case PTRMEM_CST:
- if (TYPE_PTRMEMFUNC_P (TREE_TYPE (t)))
- cgraph_mark_address_taken_node (cgraph_node (PTRMEM_CST_MEMBER (t)));
- break;
- case BASELINK:
- if (TREE_CODE (BASELINK_FUNCTIONS (t)) == FUNCTION_DECL)
- cgraph_mark_address_taken_node (cgraph_node (BASELINK_FUNCTIONS (t)));
- break;
- case VAR_DECL:
- if (DECL_CONTEXT (t)
- && flag_use_repository
- && TREE_CODE (DECL_CONTEXT (t)) == FUNCTION_DECL)
- /* If we need a static variable in a function, then we
- need the containing function. */
- mark_decl_referenced (DECL_CONTEXT (t));
- break;
- default:
- break;
- }
-
- return NULL;
-}
-
/* Java requires that we be able to reference a local address for a
method, and not be confused by PLT entries. If hidden aliases are
supported, collect and return all the functions for which we should
return candidates;
#endif
- for (node = cgraph_nodes; node ; node = node->next)
+ FOR_EACH_FUNCTION (node)
{
- tree fndecl = node->decl;
+ tree fndecl = node->symbol.decl;
if (DECL_CONTEXT (fndecl)
&& TYPE_P (DECL_CONTEXT (fndecl))
return;
#endif
- for (node = cgraph_nodes; node ; node = node->next)
+ FOR_EACH_FUNCTION (node)
{
- tree fndecl = node->decl;
+ tree fndecl = node->symbol.decl;
if (TREE_ASM_WRITTEN (fndecl)
&& pointer_set_contains (candidates, fndecl))
}
}
+/* Nonzero for a VAR_DECL whose value can be used in a constant expression.
+
+ [expr.const]
+
+ An integral constant-expression can only involve ... const
+ variables of integral or enumeration types initialized with
+ constant expressions ...
+
+ C++0x also allows constexpr variables and temporaries initialized
+ with constant expressions. We handle the former here, but the latter
+ are just folded away in cxx_eval_constant_expression.
+
+ The standard does not require that the expression be non-volatile.
+ G++ implements the proposed correction in DR 457. */
+
+bool
+decl_constant_var_p (tree decl)
+{
+ if (!decl_maybe_constant_var_p (decl))
+ return false;
+
+ /* We don't know if a template static data member is initialized with
+ a constant expression until we instantiate its initializer. Even
+ in the case of a constexpr variable, we can't treat it as a
+ constant until its initializer is complete in case it's used in
+ its own initializer. */
+ mark_used (decl);
+ return DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl);
+}
+
+/* Returns true if DECL could be a symbolic constant variable, depending on
+ its initializer. */
+
+bool
+decl_maybe_constant_var_p (tree decl)
+{
+ tree type = TREE_TYPE (decl);
+ if (TREE_CODE (decl) != VAR_DECL)
+ return false;
+ if (DECL_DECLARED_CONSTEXPR_P (decl))
+ return true;
+ return (CP_TYPE_CONST_NON_VOLATILE_P (type)
+ && INTEGRAL_OR_ENUMERATION_TYPE_P (type));
+}
+
/* Complain that DECL uses a type with no linkage but is never defined. */
static void
collect_ada_namespace (global_namespace, source_file);
}
+/* Clear DECL_EXTERNAL for NODE. */
+
+static bool
+clear_decl_external (struct cgraph_node *node, void * /*data*/)
+{
+ DECL_EXTERNAL (node->symbol.decl) = 0;
+ return false;
+}
+
/* This routine is called at the end of compilation.
Its job is to create all the code needed to initialize and
destroy the global aggregates. We do the destruction
at_eof = 1;
/* Bad parse errors. Just forget about it. */
- if (! global_bindings_p () || current_class_type || decl_namespace_list)
+ if (! global_bindings_p () || current_class_type
+ || !VEC_empty (tree,decl_namespace_list))
return;
if (pch_file)
c_common_write_pch ();
+ cgraph_process_same_body_aliases ();
+
/* Handle -fdump-ada-spec[-slim] */
if (dump_enabled_p (TDI_ada))
{
/* FIXME - huh? was input_line -= 1;*/
+ timevar_start (TV_PHASE_DEFERRED);
+
/* We now have to write out all the stuff we put off writing out.
These include:
generating the initializer for an object may cause templates to be
instantiated, etc., etc. */
- timevar_push (TV_VARCONST);
-
emit_support_tinfos ();
do
/* Go through the set of inline functions whose bodies have not
been emitted yet. If out-of-line copies of these functions
are required, emit them. */
- for (i = 0; VEC_iterate (tree, deferred_fns, i, decl); ++i)
+ FOR_EACH_VEC_ELT (tree, deferred_fns, i, decl)
{
/* Does it need synthesizing? */
if (DECL_DEFAULTED_FN (decl) && ! DECL_INITIAL (decl)
&& DECL_INITIAL (decl)
&& decl_needed_p (decl))
{
- struct cgraph_node *node = cgraph_get_node (decl), *alias, *next;
+ struct cgraph_node *node, *next;
- DECL_EXTERNAL (decl) = 0;
- /* If we mark !DECL_EXTERNAL one of the same body aliases,
- we need to mark all of them that way. */
- if (node && node->same_body)
- {
- DECL_EXTERNAL (node->decl) = 0;
- for (alias = node->same_body; alias; alias = alias->next)
- DECL_EXTERNAL (alias->decl) = 0;
- }
+ node = cgraph_get_node (decl);
+ if (node->same_body_alias)
+ node = cgraph_alias_aliased_node (node);
+
+ cgraph_for_node_and_aliases (node, clear_decl_external,
+ NULL, true);
/* If we mark !DECL_EXTERNAL one of the symbols in some comdat
group, we need to mark all symbols in the same comdat group
that way. */
- if (node->same_comdat_group)
- for (next = node->same_comdat_group;
+ if (node->symbol.same_comdat_group)
+ for (next = cgraph (node->symbol.same_comdat_group);
next != node;
- next = next->same_comdat_group)
- {
- DECL_EXTERNAL (next->decl) = 0;
- if (next->same_body)
- {
- for (alias = next->same_body;
- alias;
- alias = alias->next)
- DECL_EXTERNAL (alias->decl) = 0;
- }
- }
+ next = cgraph (next->symbol.same_comdat_group))
+ cgraph_for_node_and_aliases (next, clear_decl_external,
+ NULL, true);
}
/* If we're going to need to write this function out, and
if (!DECL_EXTERNAL (decl)
&& decl_needed_p (decl)
&& !TREE_ASM_WRITTEN (decl)
- && !cgraph_node (decl)->local.finalized)
+ && !cgraph_get_node (decl)->local.finalized)
{
/* We will output the function; no longer consider it in this
loop. */
reconsider = true;
/* Static data members are just like namespace-scope globals. */
- for (i = 0; VEC_iterate (tree, pending_statics, i, decl); ++i)
+ FOR_EACH_VEC_ELT (tree, pending_statics, i, decl)
{
if (var_finalized_p (decl) || DECL_REALLY_EXTERN (decl)
/* Don't write it out if we haven't seen a definition. */
while (reconsider);
/* All used inline functions must have a definition at this point. */
- for (i = 0; VEC_iterate (tree, deferred_fns, i, decl); ++i)
+ FOR_EACH_VEC_ELT (tree, deferred_fns, i, decl)
{
if (/* Check online inline functions that were actually used. */
DECL_ODR_USED (decl) && DECL_DECLARED_INLINE_P (decl)
#pragma interface, etc.) we decided not to emit the
definition here. */
&& !DECL_INITIAL (decl)
- /* An explicit instantiation can be used to specify
- that the body is in another unit. It will have
- already verified there was a definition. */
- && !DECL_EXPLICIT_INSTANTIATION (decl))
+ /* Don't complain if the template was defined. */
+ && !(DECL_TEMPLATE_INSTANTIATION (decl)
+ && DECL_INITIAL (DECL_TEMPLATE_RESULT
+ (template_for_substitution (decl)))))
{
warning (0, "inline function %q+D used but never defined", decl);
/* Avoid a duplicate warning from check_global_declaration_1. */
}
/* So must decls that use a type with no linkage. */
- for (i = 0; VEC_iterate (tree, no_linkage_decls, i, decl); ++i)
+ FOR_EACH_VEC_ELT (tree, no_linkage_decls, i, decl)
if (!decl_defined_p (decl))
no_linkage_error (decl);
+ /* Then, do the Objective-C stuff. This is where all the
+ Objective-C module stuff gets generated (symtab,
+ class/protocol/selector lists etc). This must be done after C++
+ templates, destructors etc. so that selectors used in C++
+ templates are properly allocated. */
+ if (c_dialect_objc ())
+ objc_write_global_declarations ();
+
/* We give C linkage to static constructors and destructors. */
push_lang_context (lang_name_c);
/* Collect candidates for Java hidden aliases. */
candidates = collect_candidates_for_java_method_aliases ();
- cgraph_finalize_compilation_unit ();
+ timevar_stop (TV_PHASE_DEFERRED);
+ timevar_start (TV_PHASE_OPT_GEN);
+
+ finalize_compilation_unit ();
+
+ timevar_stop (TV_PHASE_OPT_GEN);
+ timevar_start (TV_PHASE_CHECK_DBGINFO);
/* Now, issue warnings about static, but not defined, functions,
etc., and emit debugging information. */
VEC_length (tree, pending_statics));
}
+ perform_deferred_noexcept_checks ();
+
/* Generate hidden aliases for Java. */
if (candidates)
{
}
}
- timevar_pop (TV_VARCONST);
-
if (flag_detailed_statistics)
{
dump_tree_statistics ();
#ifdef ENABLE_CHECKING
validate_conversion_obstack ();
#endif /* ENABLE_CHECKING */
+
+ timevar_stop (TV_PHASE_CHECK_DBGINFO);
}
/* FN is an OFFSET_REF, DOTSTAR_EXPR or MEMBER_REF indicating the
ARGS. */
tree
-build_offset_ref_call_from_tree (tree fn, VEC(tree,gc) **args)
+build_offset_ref_call_from_tree (tree fn, VEC(tree,gc) **args,
+ tsubst_flags_t complain)
{
tree orig_fn;
VEC(tree,gc) *orig_args = NULL;
because we depend on the form of FN. */
make_args_non_dependent (*args);
object = build_non_dependent_expr (object);
- if (TREE_CODE (fn) == DOTSTAR_EXPR)
- object = cp_build_unary_op (ADDR_EXPR, object, 0, tf_warning_or_error);
- VEC_safe_insert (tree, gc, *args, 0, object);
+ if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE)
+ {
+ if (TREE_CODE (fn) == DOTSTAR_EXPR)
+ object = cp_build_addr_expr (object, complain);
+ VEC_safe_insert (tree, gc, *args, 0, object);
+ }
/* Now that the arguments are done, transform FN. */
fn = build_non_dependent_expr (fn);
}
void B::g() { (this->*p)(); } */
if (TREE_CODE (fn) == OFFSET_REF)
{
- tree object_addr = cp_build_unary_op (ADDR_EXPR, object, 0,
- tf_warning_or_error);
+ tree object_addr = cp_build_addr_expr (object, complain);
fn = TREE_OPERAND (fn, 1);
- fn = get_member_function_from_ptrfunc (&object_addr, fn);
+ fn = get_member_function_from_ptrfunc (&object_addr, fn,
+ complain);
VEC_safe_insert (tree, gc, *args, 0, object_addr);
}
- expr = cp_build_function_call_vec (fn, args, tf_warning_or_error);
+ if (CLASS_TYPE_P (TREE_TYPE (fn)))
+ expr = build_op_call (fn, args, complain);
+ else
+ expr = cp_build_function_call_vec (fn, args, complain);
if (processing_template_decl && expr != error_mark_node)
expr = build_min_non_dep_call_vec (expr, orig_fn, orig_args);
/* Mark DECL (either a _DECL or a BASELINK) as "used" in the program.
If DECL is a specialization or implicitly declared class member,
- generate the actual definition. */
+ generate the actual definition. Return false if something goes
+ wrong, true otherwise. */
-void
+bool
mark_used (tree decl)
{
- HOST_WIDE_INT saved_processing_template_decl = 0;
-
/* If DECL is a BASELINK for a single function, then treat it just
like the DECL for the function. Otherwise, if the BASELINK is
for an overloaded function, we don't know which function was
actually used until after overload resolution. */
- if (TREE_CODE (decl) == BASELINK)
+ if (BASELINK_P (decl))
{
decl = BASELINK_FUNCTIONS (decl);
if (really_overloaded_fn (decl))
- return;
+ return true;
decl = OVL_CURRENT (decl);
}
if (DECL_CLONED_FUNCTION_P (decl))
TREE_USED (DECL_CLONED_FUNCTION (decl)) = 1;
+ /* Mark enumeration types as used. */
+ if (TREE_CODE (decl) == CONST_DECL)
+ used_types_insert (DECL_CONTEXT (decl));
+
if (TREE_CODE (decl) == FUNCTION_DECL
&& DECL_DELETED_FN (decl))
{
generate it properly; see maybe_add_lambda_conv_op. */
sorry ("converting lambda which uses %<...%> to "
"function pointer");
- return;
+ return false;
}
}
- error ("deleted function %q+D", decl);
- error ("used here");
- return;
+ error ("use of deleted function %qD", decl);
+ if (!maybe_explain_implicit_delete (decl))
+ error_at (DECL_SOURCE_LOCATION (decl), "declared here");
+ return false;
}
- /* If we don't need a value, then we don't need to synthesize DECL. */
- if (cp_unevaluated_operand != 0)
- return;
/* We can only check DECL_ODR_USED on variables or functions with
DECL_LANG_SPECIFIC set, and these are also the only decls that we
if ((TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != FUNCTION_DECL)
|| DECL_LANG_SPECIFIC (decl) == NULL
|| DECL_THUNK_P (decl))
- return;
+ {
+ if (!processing_template_decl && type_uses_auto (TREE_TYPE (decl)))
+ {
+ error ("use of %qD before deduction of %<auto%>", decl);
+ return false;
+ }
+ return true;
+ }
/* We only want to do this processing once. We don't need to keep trying
to instantiate inline templates, because unit-at-a-time will make sure
we get them compiled before functions that want to inline them. */
if (DECL_ODR_USED (decl))
- return;
+ return true;
/* If within finish_function, defer the rest until that function
finishes, otherwise it might recurse. */
if (defer_mark_used_calls)
{
VEC_safe_push (tree, gc, deferred_mark_used_calls, decl);
- return;
+ return true;
}
- /* Normally, we can wait until instantiation-time to synthesize
- DECL. However, if DECL is a static data member initialized with
- a constant, we need the value right now because a reference to
- such a data member is not value-dependent. */
- if (TREE_CODE (decl) == VAR_DECL
- && DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl)
- && DECL_CLASS_SCOPE_P (decl))
+ if (TREE_CODE (decl) == FUNCTION_DECL)
+ maybe_instantiate_noexcept (decl);
+
+ /* Normally, we can wait until instantiation-time to synthesize DECL.
+ However, if DECL is a static data member initialized with a constant
+ or a constexpr function, we need it right now because a reference to
+ such a data member or a call to such function is not value-dependent.
+ For a function that uses auto in the return type, we need to instantiate
+ it to find out its type. */
+ if ((decl_maybe_constant_var_p (decl)
+ || (TREE_CODE (decl) == FUNCTION_DECL
+ && (DECL_DECLARED_CONSTEXPR_P (decl)
+ || type_uses_auto (TREE_TYPE (TREE_TYPE (decl))))))
+ && DECL_LANG_SPECIFIC (decl)
+ && DECL_TEMPLATE_INFO (decl)
+ && !uses_template_parms (DECL_TI_ARGS (decl)))
{
- /* Don't try to instantiate members of dependent types. We
- cannot just use dependent_type_p here because this function
- may be called from fold_non_dependent_expr, and then we may
- see dependent types, even though processing_template_decl
- will not be set. */
- if (CLASSTYPE_TEMPLATE_INFO ((DECL_CONTEXT (decl)))
- && uses_template_parms (CLASSTYPE_TI_ARGS (DECL_CONTEXT (decl))))
- return;
- /* Pretend that we are not in a template, even if we are, so
- that the static data member initializer will be processed. */
- saved_processing_template_decl = processing_template_decl;
- processing_template_decl = 0;
+ /* Instantiating a function will result in garbage collection. We
+ must treat this situation as if we were within the body of a
+ function so as to avoid collecting live data only referenced from
+ the stack (such as overload resolution candidates). */
+ ++function_depth;
+ instantiate_decl (decl, /*defer_ok=*/false,
+ /*expl_inst_class_mem_p=*/false);
+ --function_depth;
+ }
+
+ if (type_uses_auto (TREE_TYPE (decl)))
+ {
+ error ("use of %qD before deduction of %<auto%>", decl);
+ return false;
}
+ /* If we don't need a value, then we don't need to synthesize DECL. */
+ if (cp_unevaluated_operand != 0)
+ return true;
+
if (processing_template_decl)
- return;
+ return true;
+
+ /* Check this too in case we're within fold_non_dependent_expr. */
+ if (DECL_TEMPLATE_INFO (decl)
+ && uses_template_parms (DECL_TI_ARGS (decl)))
+ return true;
DECL_ODR_USED (decl) = 1;
if (DECL_CLONED_FUNCTION_P (decl))
if (TREE_CODE (decl) == FUNCTION_DECL
&& DECL_NONSTATIC_MEMBER_FUNCTION_P (decl)
&& DECL_DEFAULTED_FN (decl)
+ /* A function defaulted outside the class is synthesized either by
+ cp_finish_decl or instantiate_decl. */
+ && !DECL_DEFAULTED_OUTSIDE_CLASS_P (decl)
&& ! DECL_INITIAL (decl))
{
+ /* Defer virtual destructors so that thunks get the right
+ linkage. */
+ if (DECL_VIRTUAL_P (decl) && !at_eof)
+ {
+ note_vague_linkage_fn (decl);
+ return true;
+ }
+
/* Remember the current location for a function we will end up
synthesizing. Then we can inform the user where it was
required in the case of error. */
on the stack (such as overload resolution candidates).
We could just let cp_write_global_declarations handle synthesizing
- this function, since we just added it to deferred_fns, but doing
+ this function by adding it to deferred_fns, but doing
it at the use site produces better error messages. */
++function_depth;
synthesize_method (decl);
times. Maintaining a stack of active functions is expensive,
and the inliner knows to instantiate any functions it might
need. Therefore, we always try to defer instantiation. */
- instantiate_decl (decl, /*defer_ok=*/true,
- /*expl_inst_class_mem_p=*/false);
+ {
+ ++function_depth;
+ instantiate_decl (decl, /*defer_ok=*/true,
+ /*expl_inst_class_mem_p=*/false);
+ --function_depth;
+ }
- processing_template_decl = saved_processing_template_decl;
+ return true;
}
#include "gt-cp-decl2.h"