import GCC 4.1 branch from 20061021.

includes fixes for these 109 GCC PR's:

 4520 13685 13983 17519 19505 20256 22209 22313 23454 24367 25211
25468 25519 25636 25636 26435 26504 26570 26719 26764 26881 26969
26983 26991 26991 26993 27075 27184 27226 27287 27287 27291 27334
27363 27428 27489 27490 27537 27558 27565 27566 27616 27639 27681
27697 27721 27724 27768 27793 27793 27795 27827 27878 27889 27893
28029 28075 28136 28148 28150 28162 28170 28187 28207 28207 28218
28221 28238 28243 28247 28257 28259 28267 28283 28286 28299 28386
28402 28403 28418 28473 28490 28493 28621 28634 28636 28649 28651
28677 28683 28726 28814 28825 28862 28900 28924 28946 28952 28960
28980 29006 29091 29119 29132 29154 29198 29230 29290 29323
This commit is contained in:
mrg 2006-10-21 22:45:05 +00:00
parent f62548abf5
commit b738ee7f82
198 changed files with 6494 additions and 3621 deletions

View File

@ -4518,10 +4518,12 @@ build_x_va_arg (tree expr, tree type)
if (! pod_type_p (type))
{
/* Remove reference types so we don't ICE later on. */
tree type1 = non_reference (type);
/* Undefined behavior [expr.call] 5.2.2/7. */
warning (0, "cannot receive objects of non-POD type %q#T through %<...%>; "
"call will abort at runtime", type);
expr = convert (build_pointer_type (type), null_node);
expr = convert (build_pointer_type (type1), null_node);
expr = build2 (COMPOUND_EXPR, TREE_TYPE (expr),
call_builtin_trap (), expr);
expr = build_indirect_ref (expr, NULL);
@ -4821,6 +4823,12 @@ build_over_call (struct z_candidate *cand, int flags)
tree type = TREE_VALUE (parm);
conv = convs[i];
/* Don't make a copy here if build_call is going to. */
if (conv->kind == ck_rvalue
&& !TREE_ADDRESSABLE (complete_type (type)))
conv = conv->u.next;
val = convert_like_with_context
(conv, TREE_VALUE (arg), fn, i - is_method);
@ -5465,9 +5473,9 @@ build_new_method_call (tree instance, tree fns, tree args,
none-the-less evaluated. */
if (TREE_CODE (TREE_TYPE (cand->fn)) != METHOD_TYPE
&& !is_dummy_object (instance_ptr)
&& TREE_SIDE_EFFECTS (instance))
&& TREE_SIDE_EFFECTS (instance_ptr))
call = build2 (COMPOUND_EXPR, TREE_TYPE (call),
instance, call);
instance_ptr, call);
}
}
}

View File

@ -2800,6 +2800,7 @@ check_field_decls (tree t, tree *access_decls,
tree *next;
bool has_pointers;
int any_default_members;
int cant_pack = 0;
/* Assume there are no access declarations. */
*access_decls = NULL_TREE;
@ -2816,40 +2817,6 @@ check_field_decls (tree t, tree *access_decls,
next = &TREE_CHAIN (x);
if (TREE_CODE (x) == FIELD_DECL)
{
if (TYPE_PACKED (t))
{
if (!pod_type_p (TREE_TYPE (x)) && !TYPE_PACKED (TREE_TYPE (x)))
warning
(0,
"ignoring packed attribute on unpacked non-POD field %q+#D",
x);
else if (TYPE_ALIGN (TREE_TYPE (x)) > BITS_PER_UNIT)
DECL_PACKED (x) = 1;
}
if (DECL_C_BIT_FIELD (x) && integer_zerop (DECL_INITIAL (x)))
/* We don't treat zero-width bitfields as making a class
non-empty. */
;
else
{
tree element_type;
/* The class is non-empty. */
CLASSTYPE_EMPTY_P (t) = 0;
/* The class is not even nearly empty. */
CLASSTYPE_NEARLY_EMPTY_P (t) = 0;
/* If one of the data members contains an empty class,
so does T. */
element_type = strip_array_types (type);
if (CLASS_TYPE_P (element_type)
&& CLASSTYPE_CONTAINS_EMPTY_CLASS_P (element_type))
CLASSTYPE_CONTAINS_EMPTY_CLASS_P (t) = 1;
}
}
if (TREE_CODE (x) == USING_DECL)
{
/* Prune the access declaration from the list of fields. */
@ -2946,6 +2913,37 @@ check_field_decls (tree t, tree *access_decls,
type = strip_array_types (type);
if (TYPE_PACKED (t))
{
if (!pod_type_p (type) && !TYPE_PACKED (type))
{
warning
(0,
"ignoring packed attribute because of unpacked non-POD field %q+#D",
x);
cant_pack = 1;
}
else if (TYPE_ALIGN (TREE_TYPE (x)) > BITS_PER_UNIT)
DECL_PACKED (x) = 1;
}
if (DECL_C_BIT_FIELD (x) && integer_zerop (DECL_INITIAL (x)))
/* We don't treat zero-width bitfields as making a class
non-empty. */
;
else
{
/* The class is non-empty. */
CLASSTYPE_EMPTY_P (t) = 0;
/* The class is not even nearly empty. */
CLASSTYPE_NEARLY_EMPTY_P (t) = 0;
/* If one of the data members contains an empty class,
so does T. */
if (CLASS_TYPE_P (type)
&& CLASSTYPE_CONTAINS_EMPTY_CLASS_P (type))
CLASSTYPE_CONTAINS_EMPTY_CLASS_P (t) = 1;
}
/* This is used by -Weffc++ (see below). Warn only for pointers
to members which might hold dynamic memory. So do not warn
for pointers to functions or pointers to members. */
@ -3030,11 +3028,11 @@ check_field_decls (tree t, tree *access_decls,
is needed to free dynamic memory.
This seems enough for practical purposes. */
if (warn_ecpp
&& has_pointers
&& TYPE_HAS_CONSTRUCTOR (t)
&& TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t)
&& !(TYPE_HAS_INIT_REF (t) && TYPE_HAS_ASSIGN_REF (t)))
if (warn_ecpp
&& has_pointers
&& TYPE_HAS_CONSTRUCTOR (t)
&& TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t)
&& !(TYPE_HAS_INIT_REF (t) && TYPE_HAS_ASSIGN_REF (t)))
{
warning (0, "%q#T has pointer data members", t);
@ -3048,6 +3046,9 @@ check_field_decls (tree t, tree *access_decls,
warning (0, " but does not override %<operator=(const %T&)%>", t);
}
/* If any of the fields couldn't be packed, unset TYPE_PACKED. */
if (cant_pack)
TYPE_PACKED (t) = 0;
/* Check anonymous struct/anonymous union fields. */
finish_struct_anon (t);

View File

@ -589,6 +589,24 @@ is_invisiref_parm (tree t)
&& DECL_BY_REFERENCE (t));
}
/* Return true if the uid in both int tree maps are equal. */
int
cxx_int_tree_map_eq (const void *va, const void *vb)
{
const struct cxx_int_tree_map *a = (const struct cxx_int_tree_map *) va;
const struct cxx_int_tree_map *b = (const struct cxx_int_tree_map *) vb;
return (a->uid == b->uid);
}
/* Hash a UID in a cxx_int_tree_map. */
unsigned int
cxx_int_tree_map_hash (const void *item)
{
return ((const struct cxx_int_tree_map *)item)->uid;
}
/* Perform any pre-gimplification lowering of C++ front end trees to
GENERIC. */
@ -608,6 +626,25 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
return NULL;
}
/* Map block scope extern declarations to visible declarations with the
same name and type in outer scopes if any. */
if (cp_function_chain->extern_decl_map
&& (TREE_CODE (stmt) == FUNCTION_DECL || TREE_CODE (stmt) == VAR_DECL)
&& DECL_EXTERNAL (stmt))
{
struct cxx_int_tree_map *h, in;
in.uid = DECL_UID (stmt);
h = (struct cxx_int_tree_map *)
htab_find_with_hash (cp_function_chain->extern_decl_map,
&in, in.uid);
if (h)
{
*stmt_p = h->to;
*walk_subtrees = 0;
return NULL;
}
}
/* Other than invisiref parms, don't walk the same tree twice. */
if (pointer_set_contains (p_set, stmt))
{

View File

@ -719,6 +719,15 @@ struct saved_scope GTY(())
extern GTY(()) struct saved_scope *scope_chain;
struct cxx_int_tree_map GTY(())
{
unsigned int uid;
tree to;
};
extern unsigned int cxx_int_tree_map_hash (const void *);
extern int cxx_int_tree_map_eq (const void *, const void *);
/* Global state pertinent to the current function. */
struct language_function GTY(())
@ -746,6 +755,7 @@ struct language_function GTY(())
struct named_label_list *x_named_labels;
struct cp_binding_level *bindings;
VEC(tree,gc) *x_local_names;
htab_t GTY((param_is (struct cxx_int_tree_map))) extern_decl_map;
};
/* The current C++-specific per-function global variables. */
@ -3338,46 +3348,51 @@ extern GTY(()) tree static_dtors;
enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, OP_FLAG, TYPENAME_FLAG };
/* These are uses as bits in flags passed to build_new_method_call
to control its error reporting behavior.
LOOKUP_PROTECT means flag access violations.
LOOKUP_COMPLAIN mean complain if no suitable member function
matching the arguments is found.
LOOKUP_NORMAL is just a combination of these two.
LOOKUP_NONVIRTUAL means make a direct call to the member function found
LOOKUP_ONLYCONVERTING means that non-conversion constructors are not tried.
DIRECT_BIND means that if a temporary is created, it should be created so
that it lives as long as the current variable bindings; otherwise it
only lives until the end of the complete-expression. It also forces
direct-initialization in cases where other parts of the compiler have
already generated a temporary, such as reference initialization and the
catch parameter.
LOOKUP_NO_CONVERSION means that user-defined conversions are not
permitted. Built-in conversions are permitted.
LOOKUP_DESTRUCTOR means explicit call to destructor.
LOOKUP_NO_TEMP_BIND means temporaries will not be bound to references.
These are used in global lookup to support elaborated types and
qualifiers.
LOOKUP_PREFER_TYPES means not to accept objects, and possibly namespaces.
LOOKUP_PREFER_NAMESPACES means not to accept objects, and possibly types.
LOOKUP_PREFER_BOTH means class-or-namespace-name. */
/* These are uses as bits in flags passed to various functions to
control their behavior. Despite the LOOKUP_ prefix, many of these
do not control name lookup. ??? Functions using these flags should
probably be modified to accept explicit boolean flags for the
behaviors relevant to them. */
/* Check for access violations. */
#define LOOKUP_PROTECT (1 << 0)
/* Complain if no suitable member function matching the arguments is
found. */
#define LOOKUP_COMPLAIN (1 << 1)
#define LOOKUP_NORMAL (LOOKUP_PROTECT | LOOKUP_COMPLAIN)
/* Even if the function found by lookup is a virtual function, it
should be called directly. */
#define LOOKUP_NONVIRTUAL (1 << 2)
/* Non-converting (i.e., "explicit") constructors are not tried. */
#define LOOKUP_ONLYCONVERTING (1 << 3)
/* If a temporary is created, it should be created so that it lives
as long as the current variable bindings; otherwise it only lives
until the end of the complete-expression. It also forces
direct-initialization in cases where other parts of the compiler
have already generated a temporary, such as reference
initialization and the catch parameter. */
#define DIRECT_BIND (1 << 4)
/* User-defined conversions are not permitted. (Built-in conversions
are permitted.) */
#define LOOKUP_NO_CONVERSION (1 << 5)
/* The user has explicitly called a destructor. (Therefore, we do
not need to check that the object is non-NULL before calling the
destructor.) */
#define LOOKUP_DESTRUCTOR (1 << 6)
/* Do not permit references to bind to temporaries. */
#define LOOKUP_NO_TEMP_BIND (1 << 7)
/* Do not accept objects, and possibly namespaces. */
#define LOOKUP_PREFER_TYPES (1 << 8)
/* Do not accept objects, and possibly types. */
#define LOOKUP_PREFER_NAMESPACES (1 << 9)
/* Accept types or namespaces. */
#define LOOKUP_PREFER_BOTH (LOOKUP_PREFER_TYPES | LOOKUP_PREFER_NAMESPACES)
/* We are checking that a constructor can be called -- but we do not
actually plan to call it. */
#define LOOKUP_CONSTRUCTOR_CALLABLE (1 << 10)
/* Return friend decarations and un-declared builtin functions.
(Normally, these entities are registered in the symbol table, but
not found by lookup.) */
#define LOOKUP_HIDDEN (LOOKUP_CONSTRUCTOR_CALLABLE << 1)
#define LOOKUP_NAMESPACES_ONLY(F) \
(((F) & LOOKUP_PREFER_NAMESPACES) && !((F) & LOOKUP_PREFER_TYPES))
@ -4077,7 +4092,7 @@ extern int template_class_depth (tree);
extern int is_specialization_of (tree, tree);
extern bool is_specialization_of_friend (tree, tree);
extern int comp_template_args (tree, tree);
extern void maybe_process_partial_specialization (tree);
extern tree maybe_process_partial_specialization (tree);
extern tree most_specialized_instantiation (tree);
extern void print_candidates (tree);
extern void instantiate_pending_templates (int);

View File

@ -863,14 +863,17 @@ convert_to_void (tree expr, const char *implicit)
int is_volatile = TYPE_VOLATILE (type);
int is_complete = COMPLETE_TYPE_P (complete_type (type));
/* Can't load the value if we don't know the type. */
if (is_volatile && !is_complete)
warning (0, "object of incomplete type %qT will not be accessed in %s",
type, implicit ? implicit : "void context");
else if (is_reference && is_volatile)
/* Don't load the value if this is an implicit dereference, or if
the type needs to be handled by ctors/dtors. */
else if (is_volatile && (is_reference || TREE_ADDRESSABLE (type)))
warning (0, "object of type %qT will not be accessed in %s",
TREE_TYPE (TREE_OPERAND (expr, 0)),
implicit ? implicit : "void context");
if (is_reference || !is_volatile || !is_complete)
if (is_reference || !is_volatile || !is_complete || TREE_ADDRESSABLE (type))
expr = TREE_OPERAND (expr, 0);
break;
@ -904,9 +907,13 @@ convert_to_void (tree expr, const char *implicit)
expr = void_zero_node;
}
else if (implicit && probe == expr && is_overloaded_fn (probe))
/* Only warn when there is no &. */
warning (0, "%s is a reference, not call, to function %qE",
implicit, expr);
{
/* Only warn when there is no &. */
warning (0, "%s is a reference, not call, to function %qE",
implicit, expr);
if (TREE_CODE (expr) == COMPONENT_REF)
expr = TREE_OPERAND (expr, 0);
}
}
if (expr != error_mark_node && !VOID_TYPE_P (TREE_TYPE (expr)))
@ -956,6 +963,8 @@ convert_to_void (tree expr, const char *implicit)
}
expr = build1 (CONVERT_EXPR, void_type_node, expr);
}
if (! TREE_SIDE_EFFECTS (expr))
expr = void_zero_node;
return expr;
}

View File

@ -587,7 +587,8 @@ check_classfn (tree ctype, tree function, tree template_parms)
{
int ix;
bool is_template;
tree pushed_scope;
if (DECL_USE_TEMPLATE (function)
&& !(TREE_CODE (function) == TEMPLATE_DECL
&& DECL_TEMPLATE_SPECIALIZATION (function))
@ -617,16 +618,18 @@ check_classfn (tree ctype, tree function, tree template_parms)
/* OK, is this a definition of a member template? */
is_template = (template_parms != NULL_TREE);
/* We must enter the scope here, because conversion operators are
named by target type, and type equivalence relies on typenames
resolving within the scope of CTYPE. */
pushed_scope = push_scope (ctype);
ix = class_method_index_for_fn (complete_type (ctype), function);
if (ix >= 0)
{
VEC(tree,gc) *methods = CLASSTYPE_METHOD_VEC (ctype);
tree fndecls, fndecl = 0;
bool is_conv_op;
tree pushed_scope;
const char *format = NULL;
pushed_scope = push_scope (ctype);
for (fndecls = VEC_index (tree, methods, ix);
fndecls; fndecls = OVL_NEXT (fndecls))
{
@ -665,10 +668,13 @@ check_classfn (tree ctype, tree function, tree template_parms)
== DECL_TI_TEMPLATE (fndecl))))
break;
}
if (pushed_scope)
pop_scope (pushed_scope);
if (fndecls)
return OVL_CURRENT (fndecls);
{
if (pushed_scope)
pop_scope (pushed_scope);
return OVL_CURRENT (fndecls);
}
error ("prototype for %q#D does not match any in class %qT",
function, ctype);
is_conv_op = DECL_CONV_FN_P (fndecl);
@ -707,8 +713,10 @@ check_classfn (tree ctype, tree function, tree template_parms)
else if (!COMPLETE_TYPE_P (ctype))
cxx_incomplete_type_error (function, ctype);
else
error ("no %q#D member function declared in class %qT",
function, ctype);
{
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
@ -716,6 +724,9 @@ check_classfn (tree ctype, tree function, tree template_parms)
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;
}
@ -807,14 +818,6 @@ grokfield (const cp_declarator *declarator,
const char *asmspec = 0;
int flags = LOOKUP_ONLYCONVERTING;
if (!declspecs->any_specifiers_p
&& declarator->kind == cdk_id
&& declarator->u.id.qualifying_scope
&& TREE_CODE (declarator->u.id.unqualified_name) == IDENTIFIER_NODE)
/* Access declaration */
return do_class_using_decl (declarator->u.id.qualifying_scope,
declarator->u.id.unqualified_name);
if (init
&& TREE_CODE (init) == TREE_LIST
&& TREE_VALUE (init) == error_mark_node
@ -878,7 +881,7 @@ grokfield (const cp_declarator *declarator,
return void_type_node;
}
if (asmspec_tree)
if (asmspec_tree && asmspec_tree != error_mark_node)
asmspec = TREE_STRING_POINTER (asmspec_tree);
if (init)
@ -3252,6 +3255,8 @@ mark_used (tree decl)
}
TREE_USED (decl) = 1;
if (DECL_CLONED_FUNCTION_P (decl))
TREE_USED (DECL_CLONED_FUNCTION (decl)) = 1;
/* If we don't need a value, then we don't need to synthesize DECL. */
if (skip_evaluation)
return;

View File

@ -600,7 +600,8 @@ build_throw (tree exp)
if (processing_template_decl)
{
current_function_returns_abnormally = 1;
if (cfun)
current_function_returns_abnormally = 1;
return build_min (THROW_EXPR, void_type_node, exp);
}

View File

@ -78,13 +78,8 @@ is_friend (tree type, tree supplicant)
else
/* It's a type. */
{
/* Nested classes are implicitly friends of their enclosing types, as
per core issue 45 (this is a change from the standard). */
for (context = supplicant;
context && TYPE_P (context);
context = TYPE_CONTEXT (context))
if (type == context)
return 1;
if (same_type_p (supplicant, type))
return 1;
list = CLASSTYPE_FRIEND_CLASSES (TREE_TYPE (TYPE_MAIN_DECL (type)));
for (; list ; list = TREE_CHAIN (list))
@ -98,13 +93,24 @@ is_friend (tree type, tree supplicant)
}
}
if (declp && DECL_FUNCTION_MEMBER_P (supplicant))
context = DECL_CONTEXT (supplicant);
else if (! declp)
/* Local classes have the same access as the enclosing function. */
context = decl_function_context (TYPE_MAIN_DECL (supplicant));
if (declp)
{
if (DECL_FUNCTION_MEMBER_P (supplicant))
context = DECL_CONTEXT (supplicant);
else
context = NULL_TREE;
}
else
context = NULL_TREE;
{
if (TYPE_CONTEXT (supplicant)
&& TYPE_P (TYPE_CONTEXT (supplicant)))
/* Nested classes get the same access as their enclosing types, as
per DR 45 (this is a change from the standard). */
context = TYPE_CONTEXT (supplicant);
else
/* Local classes have the same access as the enclosing function. */
context = decl_function_context (TYPE_MAIN_DECL (supplicant));
}
/* A namespace is not friend to anybody. */
if (context && TREE_CODE (context) == NAMESPACE_DECL)

View File

@ -179,7 +179,8 @@ build_zero_init (tree type, tree nelts, bool static_storage_p)
items with static storage duration that are not otherwise
initialized are initialized to zero. */
;
else if (SCALAR_TYPE_P (type))
else if (SCALAR_TYPE_P (type)
|| TREE_CODE (type) == COMPLEX_TYPE)
init = convert (type, integer_zero_node);
else if (CLASS_TYPE_P (type))
{
@ -223,6 +224,11 @@ build_zero_init (tree type, tree nelts, bool static_storage_p)
nelts, integer_one_node);
else
max_index = array_type_nelts (type);
/* If we have an error_mark here, we should just return error mark
as we don't know the size of the array yet. */
if (max_index == error_mark_node)
return error_mark_node;
gcc_assert (TREE_CODE (max_index) == INTEGER_CST);
/* A zero-sized array, which is accepted as an extension, will
@ -249,6 +255,8 @@ build_zero_init (tree type, tree nelts, bool static_storage_p)
/* Build a constructor to contain the initializations. */
init = build_constructor (type, v);
}
else if (TREE_CODE (type) == VECTOR_TYPE)
init = fold_convert (type, integer_zero_node);
else
gcc_assert (TREE_CODE (type) == REFERENCE_TYPE);
@ -1669,7 +1677,7 @@ build_new (tree placement, tree type, tree nelts, tree init,
{
tree rval;
if (type == error_mark_node)
if (placement == error_mark_node || type == error_mark_node)
return error_mark_node;
if (processing_template_decl)
@ -1847,10 +1855,14 @@ build_new_1 (tree exp)
function context. Methinks that's not it's purvey. So we'll do
our own VLA layout later. */
vla_p = true;
full_type = build_cplus_array_type (type, NULL_TREE);
index = convert (sizetype, nelts);
index = size_binop (MINUS_EXPR, index, size_one_node);
TYPE_DOMAIN (full_type) = build_index_type (index);
index = build_index_type (index);
full_type = build_cplus_array_type (type, NULL_TREE);
/* We need a copy of the type as build_array_type will return a shared copy
of the incomplete array type. */
full_type = build_distinct_type_copy (full_type);
TYPE_DOMAIN (full_type) = index;
}
else
{

View File

@ -504,7 +504,7 @@ handle_pragma_interface (cpp_reader* dfile ATTRIBUTE_UNUSED )
else
filename = ggc_strdup (TREE_STRING_POINTER (fname));
finfo = get_fileinfo (filename);
finfo = get_fileinfo (input_filename);
if (impl_file_chain == 0)
{
@ -810,7 +810,7 @@ cxx_make_type (enum tree_code code)
/* Set up some flags that give proper default behavior. */
if (IS_AGGR_TYPE_CODE (code))
{
struct c_fileinfo *finfo = get_fileinfo (lbasename (input_filename));
struct c_fileinfo *finfo = get_fileinfo (input_filename);
SET_CLASSTYPE_INTERFACE_UNKNOWN_X (t, finfo->interface_unknown);
CLASSTYPE_INTERFACE_ONLY (t) = finfo->interface_only;
}

View File

@ -2797,6 +2797,9 @@ mangle_conv_op_name_for_type (const tree type)
void **slot;
tree identifier;
if (type == error_mark_node)
return error_mark_node;
if (conv_type_names == NULL)
conv_type_names = htab_create_ggc (31, &hash_type, &compare_type, NULL);

View File

@ -418,6 +418,7 @@ use_thunk (tree thunk_fndecl, bool emit_p)
TREE_CHAIN (x) = t;
DECL_CONTEXT (x) = thunk_fndecl;
SET_DECL_RTL (x, NULL_RTX);
DECL_HAS_VALUE_EXPR_P (x) = 0;
t = x;
}
a = nreverse (t);
@ -945,6 +946,10 @@ locate_copy (tree type, void *client_)
if (!parms)
continue;
src_type = non_reference (TREE_VALUE (parms));
if (src_type == error_mark_node)
return NULL_TREE;
if (!same_type_ignoring_top_level_qualifiers_p (src_type, type))
continue;
if (!sufficient_parms_p (TREE_CHAIN (parms)))

View File

@ -602,9 +602,6 @@ pushdecl_maybe_friend (tree x, bool is_friend)
{
int different_binding_level = 0;
if (TREE_CODE (x) == FUNCTION_DECL || DECL_FUNCTION_TEMPLATE_P (x))
check_default_args (x);
if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
name = TREE_OPERAND (name, 0);
@ -669,14 +666,28 @@ pushdecl_maybe_friend (tree x, bool is_friend)
if (decls_match (x, t))
/* The standard only says that the local extern
inherits linkage from the previous decl; in
particular, default args are not shared. We must
also tell cgraph to treat these decls as the same,
or we may neglect to emit an "unused" static - we
do this by making the DECL_UIDs equal, which should
be viewed as a kludge. FIXME. */
particular, default args are not shared. Add
the decl into a hash table to make sure only
the previous decl in this case is seen by the
middle end. */
{
struct cxx_int_tree_map *h;
void **loc;
TREE_PUBLIC (x) = TREE_PUBLIC (t);
DECL_UID (x) = DECL_UID (t);
if (cp_function_chain->extern_decl_map == NULL)
cp_function_chain->extern_decl_map
= htab_create_ggc (20, cxx_int_tree_map_hash,
cxx_int_tree_map_eq, NULL);
h = GGC_NEW (struct cxx_int_tree_map);
h->uid = DECL_UID (x);
h->to = t;
loc = htab_find_slot_with_hash
(cp_function_chain->extern_decl_map, h,
h->uid, INSERT);
*(struct cxx_int_tree_map **) loc = h;
}
}
else if (TREE_CODE (t) == PARM_DECL)
@ -733,6 +744,9 @@ pushdecl_maybe_friend (tree x, bool is_friend)
}
}
if (TREE_CODE (x) == FUNCTION_DECL || DECL_FUNCTION_TEMPLATE_P (x))
check_default_args (x);
check_template_shadow (x);
/* If this is a function conjured up by the backend, massage it
@ -2584,6 +2598,9 @@ push_class_level_binding (tree name, tree x)
if (!class_binding_level)
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, true);
if (name == error_mark_node)
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, false);
/* Check for invalid member names. */
gcc_assert (TYPE_BEING_DEFINED (current_class_type));
/* We could have been passed a tree list if this is an ambiguous
@ -2738,6 +2755,9 @@ do_class_using_decl (tree scope, tree name)
tree base_binfo;
int i;
if (name == error_mark_node)
return NULL_TREE;
if (!scope || !TYPE_P (scope))
{
error ("using-declaration for non-member at class scope");
@ -2790,18 +2810,19 @@ do_class_using_decl (tree scope, tree name)
class type. However, if all of the base classes are
non-dependent, then we can avoid delaying the check until
instantiation. */
if (!scope_dependent_p && !bases_dependent_p)
if (!scope_dependent_p)
{
base_kind b_kind;
tree binfo;
binfo = lookup_base (current_class_type, scope, ba_any, &b_kind);
if (b_kind < bk_proper_base)
{
error_not_base_type (scope, current_class_type);
return NULL_TREE;
if (!bases_dependent_p)
{
error_not_base_type (scope, current_class_type);
return NULL_TREE;
}
}
if (!name_dependent_p)
else if (!name_dependent_p)
{
decl = lookup_member (binfo, name, 0, false);
if (!decl)
@ -3671,10 +3692,8 @@ unqualified_namespace_lookup (tree name, int flags)
if (b)
{
if (b->value && hidden_name_p (b->value))
/* Ignore anticipated built-in functions and friends. */
;
else
if (b->value
&& ((flags & LOOKUP_HIDDEN) || !hidden_name_p (b->value)))
binding.value = b->value;
binding.type = b->type;
}
@ -3977,18 +3996,18 @@ lookup_name_real (tree name, int prefer_type, int nonclass, bool block_p,
continue;
/* If this is the kind of thing we're looking for, we're done. */
if (qualify_lookup (iter->value, flags)
&& !hidden_name_p (iter->value))
if (qualify_lookup (iter->value, flags))
binding = iter->value;
else if ((flags & LOOKUP_PREFER_TYPES)
&& qualify_lookup (iter->type, flags)
&& !hidden_name_p (iter->type))
&& qualify_lookup (iter->type, flags))
binding = iter->type;
else
binding = NULL_TREE;
if (binding)
{
/* Only namespace-scope bindings can be hidden. */
gcc_assert (!hidden_name_p (binding));
val = binding;
break;
}
@ -4873,7 +4892,11 @@ pushtag (tree name, tree type, tag_scope scope)
pushdecl_class_level (decl);
}
else if (b->kind != sk_template_parms)
decl = pushdecl_with_scope (decl, b, /*is_friend=*/false);
{
decl = pushdecl_with_scope (decl, b, /*is_friend=*/false);
if (decl == error_mark_node)
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
}
TYPE_CONTEXT (type) = DECL_CONTEXT (decl);

View File

@ -982,6 +982,24 @@ make_parameter_declarator (cp_decl_specifier_seq *decl_specifiers,
return parameter;
}
/* Returns true iff DECLARATOR is a declaration for a function. */
static bool
function_declarator_p (const cp_declarator *declarator)
{
while (declarator)
{
if (declarator->kind == cdk_function
&& declarator->declarator->kind == cdk_id)
return true;
if (declarator->kind == cdk_id
|| declarator->kind == cdk_error)
return false;
declarator = declarator->declarator;
}
return false;
}
/* The parser. */
/* Overview
@ -1464,8 +1482,8 @@ static tree cp_parser_builtin_offsetof
static void cp_parser_statement
(cp_parser *, tree);
static tree cp_parser_labeled_statement
(cp_parser *, tree);
static void cp_parser_label_for_labeled_statement
(cp_parser *);
static tree cp_parser_expression_statement
(cp_parser *, tree);
static tree cp_parser_compound_statement
@ -1531,8 +1549,8 @@ static tree cp_parser_qualified_namespace_specifier
(cp_parser *);
static void cp_parser_namespace_alias_definition
(cp_parser *);
static void cp_parser_using_declaration
(cp_parser *);
static bool cp_parser_using_declaration
(cp_parser *, bool);
static void cp_parser_using_directive
(cp_parser *);
static void cp_parser_asm_definition
@ -1958,6 +1976,49 @@ cp_parser_simulate_error (cp_parser* parser)
return false;
}
/* Check for repeated decl-specifiers. */
static void
cp_parser_check_decl_spec (cp_decl_specifier_seq *decl_specs)
{
cp_decl_spec ds;
for (ds = ds_first; ds != ds_last; ++ds)
{
unsigned count = decl_specs->specs[(int)ds];
if (count < 2)
continue;
/* The "long" specifier is a special case because of "long long". */
if (ds == ds_long)
{
if (count > 2)
error ("%<long long long%> is too long for GCC");
else if (pedantic && !in_system_header && warn_long_long)
pedwarn ("ISO C++ does not support %<long long%>");
}
else if (count > 1)
{
static const char *const decl_spec_names[] = {
"signed",
"unsigned",
"short",
"long",
"const",
"volatile",
"restrict",
"inline",
"virtual",
"explicit",
"friend",
"typedef",
"__complex",
"__thread"
};
error ("duplicate %qs", decl_spec_names[(int)ds]);
}
}
}
/* This function is called when a type is defined. If type
definitions are forbidden at this point, an error message is
issued. */
@ -2070,8 +2131,12 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree scope, tree id)
/* If the lookup found a template-name, it means that the user forgot
to specify an argument list. Emit a useful error message. */
if (TREE_CODE (decl) == TEMPLATE_DECL)
error ("invalid use of template-name %qE without an argument list",
decl);
error ("invalid use of template-name %qE without an argument list", decl);
else if (TREE_CODE (id) == BIT_NOT_EXPR)
error ("invalid use of destructor %qD as a type", id);
else if (TREE_CODE (decl) == TYPE_DECL)
/* Something like 'unsigned A a;' */
error ("invalid combination of multiple type-specifiers");
else if (!parser->scope)
{
/* Issue an error message. */
@ -2164,8 +2229,7 @@ cp_parser_parse_and_diagnose_invalid_type_name (cp_parser *parser)
cp_parser_abort_tentative_parse (parser);
return false;
}
if (!cp_parser_parse_definitely (parser)
|| TREE_CODE (id) != IDENTIFIER_NODE)
if (!cp_parser_parse_definitely (parser) || TREE_CODE (id) == TYPE_DECL)
return false;
/* Emit a diagnostic for the invalid type. */
@ -3339,9 +3403,27 @@ cp_parser_unqualified_id (cp_parser* parser,
object_scope = parser->object_scope;
qualifying_scope = parser->qualifying_scope;
/* Check for invalid scopes. */
if (scope == error_mark_node)
{
if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
cp_lexer_consume_token (parser->lexer);
return error_mark_node;
}
if (scope && TREE_CODE (scope) == NAMESPACE_DECL)
{
if (!cp_parser_uncommitted_to_tentative_parse_p (parser))
error ("scope %qT before %<~%> is not a class-name", scope);
cp_parser_simulate_error (parser);
if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
cp_lexer_consume_token (parser->lexer);
return error_mark_node;
}
gcc_assert (!scope || TYPE_P (scope));
/* If the name is of the form "X::~X" it's OK. */
token = cp_lexer_peek_token (parser->lexer);
if (scope && TYPE_P (scope)
if (scope
&& token->type == CPP_NAME
&& (cp_lexer_peek_nth_token (parser->lexer, 2)->type
== CPP_OPEN_PAREN)
@ -3423,7 +3505,7 @@ cp_parser_unqualified_id (cp_parser* parser,
destructor is the same as the name of the qualifying
class. That allows us to keep parsing after running
into ill-formed destructor names. */
if (type_decl == error_mark_node && scope && TYPE_P (scope))
if (type_decl == error_mark_node && scope)
return build_nt (BIT_NOT_EXPR, scope);
else if (type_decl == error_mark_node)
return error_mark_node;
@ -3434,6 +3516,7 @@ cp_parser_unqualified_id (cp_parser* parser,
if (!cp_parser_uncommitted_to_tentative_parse_p (parser))
error ("declaration of %<~%T%> as member of %qT",
type_decl, scope);
cp_parser_simulate_error (parser);
return error_mark_node;
}
@ -3538,6 +3621,17 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
{
/* Grab the nested-name-specifier and continue the loop. */
cp_parser_pre_parsed_nested_name_specifier (parser);
/* If we originally encountered this nested-name-specifier
with IS_DECLARATION set to false, we will not have
resolved TYPENAME_TYPEs, so we must do so here. */
if (is_declaration
&& TREE_CODE (parser->scope) == TYPENAME_TYPE)
{
new_scope = resolve_typename_type (parser->scope,
/*only_current_p=*/false);
if (new_scope != error_mark_node)
parser->scope = new_scope;
}
success = true;
continue;
}
@ -4499,7 +4593,7 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
}
if (scope && name && BASELINK_P (name))
adjust_result_of_qualified_name_lookup
(name, BINFO_TYPE (BASELINK_BINFO (name)), scope);
(name, BINFO_TYPE (BASELINK_ACCESS_BINFO (name)), scope);
postfix_expression
= finish_class_member_access_expr (postfix_expression, name,
template_p);
@ -6017,6 +6111,7 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr)
cp_token *token;
location_t statement_location;
restart:
/* There is no statement yet. */
statement = NULL_TREE;
/* Peek at the next token. */
@ -6033,9 +6128,11 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr)
{
case RID_CASE:
case RID_DEFAULT:
statement = cp_parser_labeled_statement (parser,
in_statement_expr);
break;
/* Looks like a labeled-statement with a case label.
Parse the label, and then use tail recursion to parse
the statement. */
cp_parser_label_for_labeled_statement (parser);
goto restart;
case RID_IF:
case RID_SWITCH:
@ -6080,7 +6177,13 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr)
labeled-statement. */
token = cp_lexer_peek_nth_token (parser->lexer, 2);
if (token->type == CPP_COLON)
statement = cp_parser_labeled_statement (parser, in_statement_expr);
{
/* Looks like a labeled-statement with an ordinary label.
Parse the label, and then use tail recursion to parse
the statement. */
cp_parser_label_for_labeled_statement (parser);
goto restart;
}
}
/* Anything that starts with a `{' must be a compound-statement. */
else if (token->type == CPP_OPEN_BRACE)
@ -6122,26 +6225,23 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr)
SET_EXPR_LOCATION (statement, statement_location);
}
/* Parse a labeled-statement.
/* Parse the label for a labeled-statement, i.e.
labeled-statement:
identifier : statement
case constant-expression : statement
default : statement
identifier :
case constant-expression :
default :
GNU Extension:
case constant-expression ... constant-expression : statement
labeled-statement:
case constant-expression ... constant-expression : statement
Returns the new CASE_LABEL_EXPR, for a `case' or `default' label.
For an ordinary label, returns a LABEL_EXPR. */
static tree
cp_parser_labeled_statement (cp_parser* parser, tree in_statement_expr)
When a label is parsed without errors, the label is added to the
parse tree by the finish_* functions, so this function doesn't
have to return the label. */
static void
cp_parser_label_for_labeled_statement (cp_parser* parser)
{
cp_token *token;
tree statement = error_mark_node;
/* The next token should be an identifier. */
token = cp_lexer_peek_token (parser->lexer);
@ -6149,7 +6249,7 @@ cp_parser_labeled_statement (cp_parser* parser, tree in_statement_expr)
&& token->type != CPP_KEYWORD)
{
cp_parser_error (parser, "expected labeled-statement");
return error_mark_node;
return;
}
switch (token->keyword)
@ -6184,7 +6284,7 @@ cp_parser_labeled_statement (cp_parser* parser, tree in_statement_expr)
if (!parser->in_switch_statement_p)
error ("case label %qE not within a switch statement", expr);
else
statement = finish_case_label (expr, expr_hi);
finish_case_label (expr, expr_hi);
}
break;
@ -6194,22 +6294,17 @@ cp_parser_labeled_statement (cp_parser* parser, tree in_statement_expr)
if (!parser->in_switch_statement_p)
error ("case label not within a switch statement");
else
statement = finish_case_label (NULL_TREE, NULL_TREE);
finish_case_label (NULL_TREE, NULL_TREE);
break;
default:
/* Anything else must be an ordinary label. */
statement = finish_label_stmt (cp_parser_identifier (parser));
finish_label_stmt (cp_parser_identifier (parser));
break;
}
/* Require the `:' token. */
cp_parser_require (parser, CPP_COLON, "`:'");
/* Parse the labeled statement. */
cp_parser_statement (parser, in_statement_expr);
/* Return the label, in the case of a `case' or `default' label. */
return statement;
}
/* Parse an expression-statement.
@ -7057,7 +7152,8 @@ cp_parser_block_declaration (cp_parser *parser,
cp_parser_using_directive (parser);
/* Otherwise, it's a using-declaration. */
else
cp_parser_using_declaration (parser);
cp_parser_using_declaration (parser,
/*access_declaration_p=*/false);
}
/* If the next keyword is `__label__' we have a label declaration. */
else if (token1->keyword == RID_LABEL)
@ -7286,7 +7382,6 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
int* declares_class_or_enum)
{
bool constructor_possible_p = !parser->in_declarator_p;
cp_decl_spec ds;
/* Clear DECL_SPECS. */
clear_decl_specs (decl_specs);
@ -7461,41 +7556,7 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
flags |= CP_PARSER_FLAGS_OPTIONAL;
}
/* Check for repeated decl-specifiers. */
for (ds = ds_first; ds != ds_last; ++ds)
{
unsigned count = decl_specs->specs[(int)ds];
if (count < 2)
continue;
/* The "long" specifier is a special case because of "long long". */
if (ds == ds_long)
{
if (count > 2)
error ("%<long long long%> is too long for GCC");
else if (pedantic && !in_system_header && warn_long_long)
pedwarn ("ISO C++ does not support %<long long%>");
}
else if (count > 1)
{
static const char *const decl_spec_names[] = {
"signed",
"unsigned",
"short",
"long",
"const",
"volatile",
"restrict",
"inline",
"virtual",
"explicit",
"friend",
"typedef",
"__complex",
"__thread"
};
error ("duplicate %qs", decl_spec_names[(int)ds]);
}
}
cp_parser_check_decl_spec (decl_specs);
/* Don't allow a friend specifier with a class definition. */
if (decl_specs->specs[(int) ds_friend] != 0
@ -10459,14 +10520,21 @@ cp_parser_qualified_namespace_specifier (cp_parser* parser)
return cp_parser_namespace_name (parser);
}
/* Parse a using-declaration.
/* Parse a using-declaration, or, if ACCESS_DECLARATION_P is true, an
access declaration.
using-declaration:
using typename [opt] :: [opt] nested-name-specifier unqualified-id ;
using :: unqualified-id ; */
using :: unqualified-id ;
static void
cp_parser_using_declaration (cp_parser* parser)
access-declaration:
qualified-id ;
*/
static bool
cp_parser_using_declaration (cp_parser* parser,
bool access_declaration_p)
{
cp_token *token;
bool typename_p = false;
@ -10475,18 +10543,23 @@ cp_parser_using_declaration (cp_parser* parser)
tree identifier;
tree qscope;
/* Look for the `using' keyword. */
cp_parser_require_keyword (parser, RID_USING, "`using'");
/* Peek at the next token. */
token = cp_lexer_peek_token (parser->lexer);
/* See if it's `typename'. */
if (token->keyword == RID_TYPENAME)
if (access_declaration_p)
cp_parser_parse_tentatively (parser);
else
{
/* Remember that we've seen it. */
typename_p = true;
/* Consume the `typename' token. */
cp_lexer_consume_token (parser->lexer);
/* Look for the `using' keyword. */
cp_parser_require_keyword (parser, RID_USING, "`using'");
/* Peek at the next token. */
token = cp_lexer_peek_token (parser->lexer);
/* See if it's `typename'. */
if (token->keyword == RID_TYPENAME)
{
/* Remember that we've seen it. */
typename_p = true;
/* Consume the `typename' token. */
cp_lexer_consume_token (parser->lexer);
}
}
/* Look for the optional global scope qualification. */
@ -10513,12 +10586,26 @@ cp_parser_using_declaration (cp_parser* parser)
if (!qscope)
qscope = global_namespace;
if (access_declaration_p && cp_parser_error_occurred (parser))
/* Something has already gone wrong; there's no need to parse
further. Since an error has occurred, the return value of
cp_parser_parse_definitely will be false, as required. */
return cp_parser_parse_definitely (parser);
/* Parse the unqualified-id. */
identifier = cp_parser_unqualified_id (parser,
/*template_keyword_p=*/false,
/*check_dependency_p=*/true,
/*declarator_p=*/true);
if (access_declaration_p)
{
if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
cp_parser_simulate_error (parser);
if (!cp_parser_parse_definitely (parser))
return false;
}
/* The function we call to handle a using-declaration is different
depending on what scope we are in. */
if (qscope == error_mark_node || identifier == error_mark_node)
@ -10552,6 +10639,8 @@ cp_parser_using_declaration (cp_parser* parser)
/* Look for the final `;'. */
cp_parser_require (parser, CPP_SEMICOLON, "`;'");
return true;
}
/* Parse a using-directive.
@ -10996,8 +11085,7 @@ cp_parser_init_declarator (cp_parser* parser,
is_non_constant_init = true;
if (is_initialized)
{
if (declarator->kind == cdk_function
&& declarator->declarator->kind == cdk_id
if (function_declarator_p (declarator)
&& initialization_kind == CPP_EQ)
initializer = cp_parser_pure_specifier (parser);
else
@ -11895,7 +11983,7 @@ cp_parser_type_specifier_seq (cp_parser* parser,
flags |= CP_PARSER_FLAGS_NO_USER_DEFINED_TYPES;
}
return;
cp_parser_check_decl_spec (type_specifier_seq);
}
/* Parse a parameter-declaration-clause.
@ -13168,7 +13256,7 @@ cp_parser_class_head (cp_parser* parser,
if (template_id_p)
{
type = TREE_TYPE (id);
maybe_process_partial_specialization (type);
type = maybe_process_partial_specialization (type);
if (nested_name_specifier)
pushed_scope = push_scope (nested_name_specifier);
}
@ -13419,8 +13507,8 @@ cp_parser_member_declaration (cp_parser* parser)
if (cp_lexer_next_token_is_keyword (parser->lexer, RID_USING))
{
/* Parse the using-declaration. */
cp_parser_using_declaration (parser);
cp_parser_using_declaration (parser,
/*access_declaration_p=*/false);
return;
}
@ -13440,6 +13528,9 @@ cp_parser_member_declaration (cp_parser* parser)
return;
}
if (cp_parser_using_declaration (parser, /*access_declaration=*/true))
return;
/* Parse the decl-specifier-seq. */
cp_parser_decl_specifier_seq (parser,
CP_PARSER_FLAGS_OPTIONAL,
@ -13653,8 +13744,7 @@ cp_parser_member_declaration (cp_parser* parser)
for a pure-specifier; otherwise, we look for a
constant-initializer. When we call `grokfield', it will
perform more stringent semantics checks. */
if (declarator->kind == cdk_function
&& declarator->declarator->kind == cdk_id)
if (function_declarator_p (declarator))
initializer = cp_parser_pure_specifier (parser);
else
/* Parse the initializer. */

View File

@ -690,13 +690,20 @@ check_explicit_instantiation_namespace (tree spec)
/* The TYPE is being declared. If it is a template type, that means it
is a partial specialization. Do appropriate error-checking. */
void
tree
maybe_process_partial_specialization (tree type)
{
tree context;
if (type == error_mark_node)
return;
return error_mark_node;
if (TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM)
{
error ("name of class shadows template template parameter %qD",
TYPE_NAME (type));
return error_mark_node;
}
context = TYPE_CONTEXT (type);
@ -781,7 +788,12 @@ maybe_process_partial_specialization (tree type)
}
}
else if (processing_specialization)
error ("explicit specialization of non-template %qT", type);
{
error ("explicit specialization of non-template %qT", type);
return error_mark_node;
}
return type;
}
/* Returns nonzero if we can optimize the retrieval of specializations
@ -1177,7 +1189,7 @@ register_specialization (tree spec, tree tmpl, tree args, bool is_friend)
{
error ("specialization of %qD after instantiation",
fn);
return spec;
return error_mark_node;
}
else
{
@ -2217,8 +2229,8 @@ comp_template_parms (tree parms1, tree parms2)
for (i = 0; i < TREE_VEC_LENGTH (t2); ++i)
{
tree parm1 = TREE_VALUE (TREE_VEC_ELT (t1, i));
tree parm2 = TREE_VALUE (TREE_VEC_ELT (t2, i));
tree parm1 = TREE_VALUE (TREE_VEC_ELT (t1, i));
tree parm2 = TREE_VALUE (TREE_VEC_ELT (t2, i));
if (TREE_CODE (parm1) != TREE_CODE (parm2))
return 0;
@ -2848,6 +2860,7 @@ check_default_tmpl_args (tree decl, tree parms, int is_primary, int is_partial)
for (i = 0; i < ntparms; ++i)
{
tree parm = TREE_VEC_ELT (inner_parms, i);
if (TREE_PURPOSE (parm))
seen_def_arg_p = 1;
else if (seen_def_arg_p)
@ -2912,18 +2925,20 @@ check_default_tmpl_args (tree decl, tree parms, int is_primary, int is_partial)
ntparms = TREE_VEC_LENGTH (inner_parms);
for (i = 0; i < ntparms; ++i)
if (TREE_PURPOSE (TREE_VEC_ELT (inner_parms, i)))
{
if (msg)
{
error (msg, decl);
msg = 0;
}
{
if (TREE_PURPOSE (TREE_VEC_ELT (inner_parms, i)))
{
if (msg)
{
error (msg, decl);
msg = 0;
}
/* Clear out the default argument so that we are not
confused later. */
TREE_PURPOSE (TREE_VEC_ELT (inner_parms, i)) = NULL_TREE;
}
/* Clear out the default argument so that we are not
confused later. */
TREE_PURPOSE (TREE_VEC_ELT (inner_parms, i)) = NULL_TREE;
}
}
/* At this point, if we're still interested in issuing messages,
they must apply to classes surrounding the object declared. */
@ -3003,7 +3018,13 @@ push_template_decl_real (tree decl, bool is_friend)
DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace);
/* See if this is a primary template. */
primary = template_parm_scope_p ();
if (is_friend && ctx)
/* A friend template that specifies a class context, i.e.
template <typename T> friend void A<T>::f();
is not primary. */
primary = 0;
else
primary = template_parm_scope_p ();
if (primary)
{
@ -3849,11 +3870,8 @@ convert_template_argument (tree parm,
tree in_decl)
{
tree val;
tree inner_args;
int is_type, requires_type, is_tmpl_type, requires_tmpl_type;
inner_args = INNERMOST_TEMPLATE_ARGS (args);
if (TREE_CODE (arg) == TREE_LIST
&& TREE_CODE (TREE_VALUE (arg)) == OFFSET_REF)
{
@ -3945,7 +3963,7 @@ convert_template_argument (tree parm,
if (coerce_template_template_parms (parmparm, argparm,
complain, in_decl,
inner_args))
args))
{
val = arg;
@ -5252,6 +5270,10 @@ tsubst_friend_function (tree decl, tree args)
else
new_friend_result_template_info = NULL_TREE;
/* Make the init_value nonzero so pushdecl knows this is a defn. */
if (new_friend_is_defn)
DECL_INITIAL (new_friend) = error_mark_node;
/* Inside pushdecl_namespace_level, we will push into the
current namespace. However, the friend function should go
into the namespace of the template. */
@ -5412,8 +5434,21 @@ tsubst_friend_class (tree friend_tmpl, tree args)
push_nested_class (tsubst (context, args, tf_none, NULL_TREE));
}
/* First, we look for a class template. */
tmpl = lookup_name (DECL_NAME (friend_tmpl), /*prefer_type=*/0);
/* Look for a class template declaration. We look for hidden names
because two friend declarations of the same template are the
same. For example, in:
struct A {
template <typename> friend class F;
};
template <typename> struct B {
template <typename> friend class F;
};
both F templates are the same. */
tmpl = lookup_name_real (DECL_NAME (friend_tmpl), 0, 0,
/*block_p=*/true, 0,
LOOKUP_COMPLAIN | LOOKUP_HIDDEN);
/* But, if we don't find one, it might be because we're in a
situation like this:
@ -6671,7 +6706,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
tree tmpl = NULL_TREE;
tree ctx;
tree type = NULL_TREE;
int local_p;
bool local_p;
if (TREE_CODE (t) == TYPE_DECL)
{
@ -6689,40 +6724,64 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
}
}
/* Assume this is a non-local variable. */
local_p = 0;
/* Check to see if we already have the specialization we
need. */
spec = NULL_TREE;
if (DECL_CLASS_SCOPE_P (t) || DECL_NAMESPACE_SCOPE_P (t))
{
/* T is a static data member or namespace-scope entity.
We have to substitute into namespace-scope variables
(even though such entities are never templates) because
of cases like:
template <class T> void f() { extern T t; }
if (TYPE_P (CP_DECL_CONTEXT (t)))
ctx = tsubst_aggr_type (DECL_CONTEXT (t), args,
complain,
in_decl, /*entering_scope=*/1);
else if (DECL_NAMESPACE_SCOPE_P (t))
ctx = DECL_CONTEXT (t);
where the entity referenced is not known until
instantiation time. */
local_p = false;
ctx = DECL_CONTEXT (t);
if (DECL_CLASS_SCOPE_P (t))
{
ctx = tsubst_aggr_type (ctx, args,
complain,
in_decl, /*entering_scope=*/1);
/* If CTX is unchanged, then T is in fact the
specialization we want. That situation occurs when
referencing a static data member within in its own
class. We can use pointer equality, rather than
same_type_p, because DECL_CONTEXT is always
canonical. */
if (ctx == DECL_CONTEXT (t))
spec = t;
}
if (!spec)
{
tmpl = DECL_TI_TEMPLATE (t);
gen_tmpl = most_general_template (tmpl);
argvec = tsubst (DECL_TI_ARGS (t), args, complain, in_decl);
spec = (retrieve_specialization
(gen_tmpl, argvec,
/*class_specializations_p=*/false));
}
}
else
{
/* A local variable. */
local_p = true;
/* Subsequent calls to pushdecl will fill this in. */
ctx = NULL_TREE;
local_p = 1;
spec = retrieve_local_specialization (t);
}
/* Check to see if we already have this specialization. */
if (!local_p)
{
tmpl = DECL_TI_TEMPLATE (t);
gen_tmpl = most_general_template (tmpl);
argvec = tsubst (DECL_TI_ARGS (t), args, complain, in_decl);
spec = retrieve_specialization (gen_tmpl, argvec,
/*class_specializations_p=*/false);
}
else
spec = retrieve_local_specialization (t);
/* If we already have the specialization we need, there is
nothing more to do. */
if (spec)
{
r = spec;
break;
}
/* Create a new node for the specialization we need. */
r = copy_decl (t);
if (TREE_CODE (r) == VAR_DECL)
{
@ -7088,6 +7147,15 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
max = tsubst_template_arg (omax, args, complain, in_decl);
max = fold_decl_constant_value (max);
if (TREE_CODE (max) != INTEGER_CST
&& TREE_CODE (max) != TEMPLATE_PARM_INDEX
&& !at_function_scope_p ())
{
if (complain & tf_error)
error ("array bound is not an integer constant");
return error_mark_node;
}
/* [temp.deduct]
Type deduction may fail for any of the following
@ -7100,7 +7168,6 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
indicated by the state of complain), so that
another substitution can be found. */
return error_mark_node;
else if (TREE_CODE (max) == INTEGER_CST
&& INT_CST_LT (max, integer_zero_node))
{
@ -7149,10 +7216,20 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
{
if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
{
int quals;
gcc_assert (TYPE_P (arg));
/* cv-quals from the template are discarded when
substituting in a function or reference type. */
if (TREE_CODE (arg) == FUNCTION_TYPE
|| TREE_CODE (arg) == METHOD_TYPE
|| TREE_CODE (arg) == REFERENCE_TYPE)
quals = cp_type_quals (arg);
else
quals = cp_type_quals (arg) | cp_type_quals (t);
return cp_build_qualified_type_real
(arg, cp_type_quals (arg) | cp_type_quals (t),
complain | tf_ignore_bad_quals);
(arg, quals, complain | tf_ignore_bad_quals);
}
else if (TREE_CODE (t) == BOUND_TEMPLATE_TEMPLATE_PARM)
{
@ -7607,6 +7684,7 @@ tsubst_baselink (tree baselink, tree object_type,
tree name;
tree qualifying_scope;
tree fns;
tree optype;
tree template_args = 0;
bool template_id_p = false;
@ -7620,6 +7698,7 @@ tsubst_baselink (tree baselink, tree object_type,
ambiguous now. Therefore, we perform the lookup again. */
qualifying_scope = BINFO_TYPE (BASELINK_ACCESS_BINFO (baselink));
fns = BASELINK_FUNCTIONS (baselink);
optype = BASELINK_OPTYPE (baselink);
if (TREE_CODE (fns) == TEMPLATE_ID_EXPR)
{
template_id_p = true;
@ -7647,6 +7726,9 @@ tsubst_baselink (tree baselink, tree object_type,
= build_nt (TEMPLATE_ID_EXPR,
BASELINK_FUNCTIONS (baselink),
template_args);
/* Update the conversion operator type. */
BASELINK_OPTYPE (baselink)
= tsubst (optype, args, complain, in_decl);
if (!object_type)
object_type = current_class_type;
@ -7763,7 +7845,11 @@ tsubst_qualified_id (tree qualified_id, tree args,
/*template_arg_p=*/false));
}
if (TREE_CODE (expr) != SCOPE_REF)
/* Expressions do not generally have reference type. */
if (TREE_CODE (expr) != SCOPE_REF
/* However, if we're about to form a pointer-to-member, we just
want the referenced member referenced. */
&& TREE_CODE (expr) != OFFSET_REF)
expr = convert_from_reference (expr);
return expr;
@ -10270,21 +10356,56 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
{
tree parm_max;
tree arg_max;
parm_max = TYPE_MAX_VALUE (TYPE_DOMAIN (parm));
arg_max = TYPE_MAX_VALUE (TYPE_DOMAIN (arg));
bool parm_cst;
bool arg_cst;
/* Our representation of array types uses "N - 1" as the
TYPE_MAX_VALUE for an array with "N" elements, if "N" is
not an integer constant. */
if (TREE_CODE (parm_max) == MINUS_EXPR)
not an integer constant. We cannot unify arbitrarily
complex expressions, so we eliminate the MINUS_EXPRs
here. */
parm_max = TYPE_MAX_VALUE (TYPE_DOMAIN (parm));
parm_cst = TREE_CODE (parm_max) == INTEGER_CST;
if (!parm_cst)
{
arg_max = fold_build2 (PLUS_EXPR,
integer_type_node,
arg_max,
TREE_OPERAND (parm_max, 1));
gcc_assert (TREE_CODE (parm_max) == MINUS_EXPR);
parm_max = TREE_OPERAND (parm_max, 0);
}
arg_max = TYPE_MAX_VALUE (TYPE_DOMAIN (arg));
arg_cst = TREE_CODE (arg_max) == INTEGER_CST;
if (!arg_cst)
{
/* The ARG_MAX may not be a simple MINUS_EXPR, if we are
trying to unify the type of a variable with the type
of a template parameter. For example:
template <unsigned int N>
void f (char (&) [N]);
int g();
void h(int i) {
char a[g(i)];
f(a);
}
Here, the type of the ARG will be "int [g(i)]", and
may be a SAVE_EXPR, etc. */
if (TREE_CODE (arg_max) != MINUS_EXPR)
return 1;
arg_max = TREE_OPERAND (arg_max, 0);
}
/* If only one of the bounds used a MINUS_EXPR, compensate
by adding one to the other bound. */
if (parm_cst && !arg_cst)
parm_max = fold_build2 (PLUS_EXPR,
integer_type_node,
parm_max,
integer_one_node);
else if (arg_cst && !parm_cst)
arg_max = fold_build2 (PLUS_EXPR,
integer_type_node,
arg_max,
integer_one_node);
if (unify (tparms, targs, parm_max, arg_max, UNIFY_ALLOW_INTEGER))
return 1;
@ -12518,7 +12639,8 @@ type_dependent_expression_p (tree expression)
return false;
/* An unresolved name is always dependent. */
if (TREE_CODE (expression) == IDENTIFIER_NODE)
if (TREE_CODE (expression) == IDENTIFIER_NODE
|| TREE_CODE (expression) == USING_DECL)
return true;
/* Some expression forms are never type-dependent. */

View File

@ -40,13 +40,12 @@ Boston, MA 02110-1301, USA. */
static char *extract_string (char **);
static const char *get_base_filename (const char *);
static void open_repo_file (const char *);
static FILE *open_repo_file (const char *);
static char *afgets (FILE *);
static void reopen_repo_file_for_write (void);
static FILE *reopen_repo_file_for_write (void);
static GTY(()) tree pending_repo;
static char *repo_name;
static FILE *repo_file;
static const char *old_args, *old_dir, *old_main;
@ -118,14 +117,14 @@ get_base_filename (const char *filename)
return lbasename (filename);
}
static void
static FILE *
open_repo_file (const char *filename)
{
const char *p;
const char *s = get_base_filename (filename);
if (s == NULL)
return;
return NULL;
p = lbasename (s);
p = strrchr (p, '.');
@ -136,7 +135,7 @@ open_repo_file (const char *filename)
memcpy (repo_name, s, p - s);
memcpy (repo_name + (p - s), ".rpo", 5);
repo_file = fopen (repo_name, "r");
return fopen (repo_name, "r");
}
static char *
@ -155,6 +154,7 @@ void
init_repo (void)
{
char *buf;
FILE *repo_file;
if (! flag_use_repository)
return;
@ -167,7 +167,7 @@ init_repo (void)
if (!temporary_obstack_initialized_p)
gcc_obstack_init (&temporary_obstack);
open_repo_file (main_input_filename);
repo_file = open_repo_file (main_input_filename);
if (repo_file == 0)
return;
@ -205,16 +205,18 @@ init_repo (void)
fclose (repo_file);
}
static void
static FILE *
reopen_repo_file_for_write (void)
{
repo_file = fopen (repo_name, "w");
FILE *repo_file = fopen (repo_name, "w");
if (repo_file == 0)
{
error ("can't create repository information file %qs", repo_name);
flag_use_repository = 0;
}
return repo_file;
}
/* Emit any pending repos. */
@ -224,14 +226,15 @@ finish_repo (void)
{
tree t;
char *dir, *args;
FILE *repo_file;
if (!flag_use_repository)
return;
if (errorcount || sorrycount)
goto out;
return;
reopen_repo_file_for_write ();
repo_file = reopen_repo_file_for_write ();
if (repo_file == 0)
goto out;

View File

@ -342,11 +342,10 @@ get_tinfo_decl (tree type)
tree name;
tree d;
if (COMPLETE_TYPE_P (type)
&& TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
if (variably_modified_type_p (type, /*fn=*/NULL_TREE))
{
error ("cannot create type information for type %qT because "
"its size is variable",
"it involves types of variable size",
type);
return error_mark_node;
}

View File

@ -792,8 +792,8 @@ friend_accessible_p (tree scope, tree decl, tree binfo)
if (protected_accessible_p (decl, TREE_VALUE (t), binfo))
return 1;
/* Nested classes are implicitly friends of their enclosing types, as
per core issue 45 (this is a change from the standard). */
/* Nested classes have the same access as their enclosing types, as
per DR 45 (this is a change from the standard). */
if (TYPE_P (scope))
for (t = TYPE_CONTEXT (scope); t && TYPE_P (t); t = TYPE_CONTEXT (t))
if (protected_accessible_p (decl, t, binfo))
@ -1209,7 +1209,8 @@ lookup_member (tree xbasetype, tree name, int protect, bool want_type)
}
else
{
gcc_assert (IS_AGGR_TYPE_CODE (TREE_CODE (xbasetype)));
if (!IS_AGGR_TYPE_CODE (TREE_CODE (xbasetype)))
return NULL_TREE;
type = xbasetype;
xbasetype = NULL_TREE;
}
@ -1480,14 +1481,13 @@ adjust_result_of_qualified_name_lookup (tree decl,
tree context_class)
{
if (context_class && context_class != error_mark_node
&& CLASS_TYPE_P (context_class)
&& CLASS_TYPE_P (qualifying_scope)
&& DERIVED_FROM_P (qualifying_scope, context_class)
&& BASELINK_P (decl))
{
tree base;
gcc_assert (CLASS_TYPE_P (context_class));
/* Look for the QUALIFYING_SCOPE as a base of the CONTEXT_CLASS.
Because we do not yet know which function will be chosen by
overload resolution, we cannot yet check either accessibility

View File

@ -1294,6 +1294,10 @@ tree
finish_label_stmt (tree name)
{
tree decl = define_label (input_location, name);
if (decl == error_mark_node)
return error_mark_node;
return add_stmt (build_stmt (LABEL_EXPR, decl));
}
@ -1503,9 +1507,11 @@ check_accessibility_of_qualified_id (tree decl,
its bases. */
qualifying_type = currently_open_derived_class (scope);
if (qualifying_type && IS_AGGR_TYPE_CODE (TREE_CODE (qualifying_type)))
/* It is possible for qualifying type to be a TEMPLATE_TYPE_PARM
or similar in a default argument value. */
if (qualifying_type
/* It is possible for qualifying type to be a TEMPLATE_TYPE_PARM
or similar in a default argument value. */
&& CLASS_TYPE_P (qualifying_type)
&& !dependent_type_p (qualifying_type))
perform_or_defer_access_check (TYPE_BINFO (qualifying_type), decl);
}
@ -2129,19 +2135,8 @@ check_template_template_default_arg (tree argument)
&& TREE_CODE (argument) != UNBOUND_CLASS_TEMPLATE)
{
if (TREE_CODE (argument) == TYPE_DECL)
{
tree t = TREE_TYPE (argument);
/* Try to emit a slightly smarter error message if we detect
that the user is using a template instantiation. */
if (CLASSTYPE_TEMPLATE_INFO (t)
&& CLASSTYPE_TEMPLATE_INSTANTIATION (t))
error ("invalid use of type %qT as a default value for a "
"template template-parameter", t);
else
error ("invalid use of %qD as a default value for a template "
"template-parameter", argument);
}
error ("invalid use of type %qT as a default value for a template "
"template-parameter", TREE_TYPE (argument));
else
error ("invalid default argument for a template template parameter");
return error_mark_node;
@ -2207,7 +2202,7 @@ begin_class_definition (tree t)
before. */
if (! TYPE_ANONYMOUS_P (t))
{
struct c_fileinfo *finfo = get_fileinfo (lbasename (input_filename));
struct c_fileinfo *finfo = get_fileinfo (input_filename);
CLASSTYPE_INTERFACE_ONLY (t) = finfo->interface_only;
SET_CLASSTYPE_INTERFACE_UNKNOWN_X
(t, finfo->interface_unknown);
@ -2889,8 +2884,9 @@ finish_offsetof (tree expr)
|| TREE_CODE (TREE_TYPE (expr)) == METHOD_TYPE
|| TREE_CODE (TREE_TYPE (expr)) == UNKNOWN_TYPE)
{
error ("cannot apply %<offsetof%> to member function %qD",
TREE_OPERAND (expr, 1));
if (TREE_CODE (expr) == COMPONENT_REF)
expr = TREE_OPERAND (expr, 1);
error ("cannot apply %<offsetof%> to member function %qD", expr);
return error_mark_node;
}
return fold_offsetof (expr);

View File

@ -827,7 +827,8 @@ int
is_overloaded_fn (tree x)
{
/* A baselink is also considered an overloaded function. */
if (TREE_CODE (x) == OFFSET_REF)
if (TREE_CODE (x) == OFFSET_REF
|| TREE_CODE (x) == COMPONENT_REF)
x = TREE_OPERAND (x, 1);
if (BASELINK_P (x))
x = BASELINK_FUNCTIONS (x);
@ -856,6 +857,8 @@ get_first_fn (tree from)
{
gcc_assert (is_overloaded_fn (from));
/* A baselink is also considered an overloaded function. */
if (TREE_CODE (from) == COMPONENT_REF)
from = TREE_OPERAND (from, 1);
if (BASELINK_P (from))
from = BASELINK_FUNCTIONS (from);
return OVL_CURRENT (from);
@ -2188,9 +2191,11 @@ decl_linkage (tree decl)
return lk_internal;
}
/* EXP is an expression that we want to pre-evaluate. Returns via INITP an
expression to perform the pre-evaluation, and returns directly an
expression to use the precalculated result. */
/* EXP is an expression that we want to pre-evaluate. Returns (in
*INITP) an expression that will perform the pre-evaluation. The
value returned by this function is a side-effect free expression
equivalent to the pre-evaluated expression. Callers must ensure
that *INITP is evaluated before EXP. */
tree
stabilize_expr (tree exp, tree* initp)
@ -2198,9 +2203,7 @@ stabilize_expr (tree exp, tree* initp)
tree init_expr;
if (!TREE_SIDE_EFFECTS (exp))
{
init_expr = NULL_TREE;
}
init_expr = NULL_TREE;
else if (!real_lvalue_p (exp)
|| !TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (exp)))
{
@ -2214,8 +2217,9 @@ stabilize_expr (tree exp, tree* initp)
exp = TARGET_EXPR_SLOT (init_expr);
exp = build_indirect_ref (exp, 0);
}
*initp = init_expr;
gcc_assert (!TREE_SIDE_EFFECTS (exp));
return exp;
}
@ -2232,8 +2236,10 @@ add_stmt_to_compound (tree orig, tree new)
return build2 (COMPOUND_EXPR, void_type_node, orig, new);
}
/* Like stabilize_expr, but for a call whose args we want to
pre-evaluate. */
/* Like stabilize_expr, but for a call whose arguments we want to
pre-evaluate. CALL is modified in place to use the pre-evaluated
arguments, while, upon return, *INITP contains an expression to
compute the arguments. */
void
stabilize_call (tree call, tree *initp)
@ -2258,50 +2264,58 @@ stabilize_call (tree call, tree *initp)
*initp = inits;
}
/* Like stabilize_expr, but for an initialization. If we are initializing
an object of class type, we don't want to introduce an extra temporary,
so we look past the TARGET_EXPR and stabilize the arguments of the call
instead. */
/* Like stabilize_expr, but for an initialization.
If the initialization is for an object of class type, this function
takes care not to introduce additional temporaries.
Returns TRUE iff the expression was successfully pre-evaluated,
i.e., if INIT is now side-effect free, except for, possible, a
single call to a constructor. */
bool
stabilize_init (tree init, tree *initp)
{
tree t = init;
*initp = NULL_TREE;
if (t == error_mark_node)
return true;
if (TREE_CODE (t) == INIT_EXPR
&& TREE_CODE (TREE_OPERAND (t, 1)) != TARGET_EXPR)
TREE_OPERAND (t, 1) = stabilize_expr (TREE_OPERAND (t, 1), initp);
else
{
if (TREE_CODE (t) == INIT_EXPR)
t = TREE_OPERAND (t, 1);
if (TREE_CODE (t) == TARGET_EXPR)
t = TARGET_EXPR_INITIAL (t);
if (TREE_CODE (t) == COMPOUND_EXPR)
t = expr_last (t);
if (TREE_CODE (t) == CONSTRUCTOR
&& EMPTY_CONSTRUCTOR_P (t))
{
/* Default-initialization. */
*initp = NULL_TREE;
return true;
}
/* If the initializer is a COND_EXPR, we can't preevaluate
anything. */
if (TREE_CODE (t) == COND_EXPR)
return false;
/* The TARGET_EXPR might be initializing via bitwise copy from
another variable; leave that alone. */
if (TREE_SIDE_EFFECTS (t))
stabilize_call (t, initp);
TREE_OPERAND (t, 1) = stabilize_expr (TREE_OPERAND (t, 1), initp);
return true;
}
return true;
if (TREE_CODE (t) == INIT_EXPR)
t = TREE_OPERAND (t, 1);
if (TREE_CODE (t) == TARGET_EXPR)
t = TARGET_EXPR_INITIAL (t);
if (TREE_CODE (t) == COMPOUND_EXPR)
t = expr_last (t);
if (TREE_CODE (t) == CONSTRUCTOR
&& EMPTY_CONSTRUCTOR_P (t))
/* Default-initialization. */
return true;
/* If the initializer is a COND_EXPR, we can't preevaluate
anything. */
if (TREE_CODE (t) == COND_EXPR)
return false;
if (TREE_CODE (t) == CALL_EXPR
|| TREE_CODE (t) == AGGR_INIT_EXPR)
{
stabilize_call (t, initp);
return true;
}
/* The initialization is being performed via a bitwise copy -- and
the item copied may have side effects. */
return TREE_SIDE_EFFECTS (init);
}
/* Like "fold", but should be used whenever we might be processing the

View File

@ -1233,38 +1233,44 @@ compparms (tree parms1, tree parms2)
tree
cxx_sizeof_or_alignof_type (tree type, enum tree_code op, bool complain)
{
enum tree_code type_code;
tree value;
const char *op_name;
bool dependent_p;
gcc_assert (op == SIZEOF_EXPR || op == ALIGNOF_EXPR);
if (type == error_mark_node)
return error_mark_node;
if (dependent_type_p (type))
type = non_reference (type);
if (TREE_CODE (type) == METHOD_TYPE)
{
if (complain && (pedantic || warn_pointer_arith))
pedwarn ("invalid application of %qs to a member function",
operator_name_info[(int) op].name);
value = size_one_node;
}
dependent_p = dependent_type_p (type);
if (!dependent_p)
complete_type (type);
if (dependent_p
/* VLA types will have a non-constant size. In the body of an
uninstantiated template, we don't need to try to compute the
value, because the sizeof expression is not an integral
constant expression in that case. And, if we do try to
compute the value, we'll likely end up with SAVE_EXPRs, which
the template substitution machinery does not expect to see. */
|| (processing_template_decl
&& COMPLETE_TYPE_P (type)
&& TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST))
{
value = build_min (op, size_type_node, type);
TREE_READONLY (value) = 1;
return value;
}
op_name = operator_name_info[(int) op].name;
type = non_reference (type);
type_code = TREE_CODE (type);
if (type_code == METHOD_TYPE)
{
if (complain && (pedantic || warn_pointer_arith))
pedwarn ("invalid application of %qs to a member function", op_name);
value = size_one_node;
}
else
value = c_sizeof_or_alignof_type (complete_type (type),
op == SIZEOF_EXPR,
complain);
return value;
return c_sizeof_or_alignof_type (complete_type (type),
op == SIZEOF_EXPR,
complain);
}
/* Process a sizeof or alignof expression where the operand is an
@ -2922,16 +2928,6 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
switch (code)
{
case PLUS_EXPR:
/* Handle the pointer + int case. */
if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
return cp_pointer_int_sum (PLUS_EXPR, op0, op1);
else if (code1 == POINTER_TYPE && code0 == INTEGER_TYPE)
return cp_pointer_int_sum (PLUS_EXPR, op1, op0);
else
common = 1;
break;
case MINUS_EXPR:
/* Subtraction of two similar pointers.
We must subtract them as integers, then divide by object size. */
@ -2939,11 +2935,33 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
&& same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (type0),
TREE_TYPE (type1)))
return pointer_diff (op0, op1, common_type (type0, type1));
/* Handle pointer minus int. Just like pointer plus int. */
else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
return cp_pointer_int_sum (MINUS_EXPR, op0, op1);
else
common = 1;
/* In all other cases except pointer - int, the usual arithmetic
rules aply. */
else if (!(code0 == POINTER_TYPE && code1 == INTEGER_TYPE))
{
common = 1;
break;
}
/* The pointer - int case is just like pointer + int; fall
through. */
case PLUS_EXPR:
if ((code0 == POINTER_TYPE || code1 == POINTER_TYPE)
&& (code0 == INTEGER_TYPE || code1 == INTEGER_TYPE))
{
tree ptr_operand;
tree int_operand;
ptr_operand = ((code0 == POINTER_TYPE) ? op0 : op1);
int_operand = ((code0 == INTEGER_TYPE) ? op0 : op1);
if (processing_template_decl)
{
result_type = TREE_TYPE (ptr_operand);
break;
}
return cp_pointer_int_sum (code,
ptr_operand,
int_operand);
}
common = 1;
break;
case MULT_EXPR:
@ -3853,7 +3871,7 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert)
else if (!(arg = build_expr_type_conversion (WANT_INT | WANT_ENUM,
arg, true)))
errstring = "wrong type argument to bit-complement";
else if (!noconvert)
else if (!noconvert && CP_INTEGRAL_TYPE_P (TREE_TYPE (arg)))
arg = perform_integral_promotions (arg);
break;
@ -6222,6 +6240,10 @@ maybe_warn_about_returning_address_of_local (tree retval)
}
}
while (TREE_CODE (whats_returned) == COMPONENT_REF
|| TREE_CODE (whats_returned) == ARRAY_REF)
whats_returned = TREE_OPERAND (whats_returned, 0);
if (DECL_P (whats_returned)
&& DECL_NAME (whats_returned)
&& DECL_FUNCTION_SCOPE_P (whats_returned)

View File

@ -401,7 +401,12 @@ cxx_incomplete_type_diagnostic (tree value, tree type, int diag_type)
break;
case TEMPLATE_TYPE_PARM:
p_msg ("invalid use of template type parameter");
p_msg ("invalid use of template type parameter %qT", type);
break;
case BOUND_TEMPLATE_TEMPLATE_PARM:
p_msg ("invalid use of template template parameter %qT",
TYPE_NAME (type));
break;
case UNKNOWN_TYPE:
@ -719,6 +724,15 @@ digest_init (tree type, tree init)
return error_mark_node;
}
if (TREE_CODE (type) == ARRAY_TYPE
&& TREE_CODE (init) != CONSTRUCTOR)
{
error ("array must be initialized with a brace-enclosed"
" initializer");
return error_mark_node;
}
return convert_for_initialization (NULL_TREE, type, init,
LOOKUP_NORMAL | LOOKUP_ONLYCONVERTING,
"initialization", NULL_TREE, 0);
@ -788,7 +802,10 @@ process_init_constructor_array (tree type, tree init)
{
gcc_assert (TREE_CODE (ce->index) == INTEGER_CST);
if (compare_tree_int (ce->index, i) != 0)
sorry ("non-trivial designated initializers not supported");
{
ce->value = error_mark_node;
sorry ("non-trivial designated initializers not supported");
}
}
else
ce->index = size_int (i);
@ -908,7 +925,10 @@ process_init_constructor_record (tree type, tree init)
|| TREE_CODE (ce->index) == IDENTIFIER_NODE);
if (ce->index != field
&& ce->index != DECL_NAME (field))
sorry ("non-trivial designated initializers not supported");
{
ce->value = error_mark_node;
sorry ("non-trivial designated initializers not supported");
}
}
gcc_assert (ce->value);

View File

@ -1,3 +1,15 @@
2006-10-19 Joseph S. Myers <joseph@codesourcery.com>
* sv.po: Update.
2006-10-05 Joseph S. Myers <joseph@codesourcery.com>
* sv.po: Update.
2006-09-03 Joseph S. Myers <joseph@codesourcery.com>
* sv.po: Update.
2006-06-25 Joseph S. Myers <joseph@codesourcery.com>
* de.po: Update.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,26 @@
/* { dg-do assemble } */
/* This testcase requires entries in the debug_range section in DWARF which
refer to a vague linkage function. */
struct s
{
~s ();
};
bool f1 ();
s f2 (s);
template<int x> void
f3(const s & a)
{
while (f1 () && f1 ())
{
s c = f2(a);
}
}
int main()
{
f3<0>(s ());
return 0;
}

View File

@ -0,0 +1,40 @@
/* { dg-do run } */
/* { dg-require-effective-target arm32 } */
/* Test to catch off-by-one errors in arm/pr-support.c. */
#if defined (__VFP_FP__) && !defined (__SOFTFP__)
#include <iostream>
#include <stdlib.h>
using namespace std;
static void donkey ()
{
asm volatile ("fcpyd d9, %P0" : : "w" (1.2345) : "d9");
throw 1;
}
int main()
{
try
{
donkey ();
}
catch (int foo)
{
return 0;
}
return 1;
}
#else
int main()
{
return 0;
}
#endif

View File

@ -0,0 +1,10 @@
// PR c++/28523
class A {};
class B : public A {};
int main()
{
throw (A) B();
return 0;
}

View File

@ -0,0 +1,8 @@
// PR c++/28250
// { dg-do compile }
void foo()
{
try { throw; }
catch () {} // { dg-error "type-specifier" }
}

View File

@ -0,0 +1,25 @@
// PR middle-end/28493
extern "C" void abort ();
struct Command *ptr;
struct Command {
Command() { ptr = this; }
virtual ~Command() { if (ptr != this) abort(); }
};
void tryfunc()
{
Command cmd;
throw 1;
}
int main()
{
try
{
tryfunc();
}
catch (int) { }
}

View File

@ -0,0 +1,8 @@
// PR c++/28343
// { dg-do compile }
struct A
{
int i __asm__(int); // { dg-error "before" }
static int j __asm__(int); // { dg-error "before" }
};

View File

@ -0,0 +1,6 @@
/* { dg-options "" } */
/* { dg-do compile } */
// Testing if we can do a new of a complex type
// PR C++/28450
void* q = new __complex__ int ();

View File

@ -9,6 +9,7 @@ struct bar {
int a = __builtin_offsetof(bar, foo); // { dg-error "static data member" }
int b = __builtin_offsetof(bar, baz); // { dg-error "member function" }
int b0 = __builtin_offsetof(bar, baz[0]); // { dg-error "function" }
int c = __builtin_offsetof(bar, ~bar); // { dg-error "member function" }
typedef int I;

View File

@ -0,0 +1,14 @@
// PR c++/13983, c++/17519
// The typedef and the array were causing us to miss that A<int> is
// a packed type.
template <class T>
struct A {
A();
} __attribute__((packed));
typedef A<int> Ai;
struct B {
Ai a[2];
} __attribute__((packed));

View File

@ -0,0 +1,11 @@
// { dg-do compile }
// { dg-options "" }
struct A
{
int i;
int z[1];
};
A a = { z:{} }; // { dg-error "unimplemented" }

View File

@ -0,0 +1,13 @@
// Test to make sure we do not ICE on this invalid program.
// { dg-do compile }
// { dg-options "" }
struct A
{
static int i;
int j;
};
A a = { i:0 }; // { dg-error "non-static data member" }

View File

@ -13,12 +13,12 @@
typedef A = 0; /* { dg-error "initialized" "A" } */
/* { dg-warning "no type" "A warns" { target *-*-* } 14 } */
A a; /* { dg-bogus "" "A error cascade" } */
A a; /* { dg-error "does not name a type" "A error cascade" } */
/* Case B: with a type also. */
typedef int B = 0; /* { dg-error "initialized" "B" } */
B b; /* { dg-bogus "" "B error cascade" } */
B b; /* { dg-error "does not name a type" "B error cascade" } */
/* C and D are the same as A and B, but wrapped in a structure;
field declarations go by a different code path in C++ (ick). */
@ -31,3 +31,8 @@ struct S {
typedef int D = 0; /* { dg-error "initialized" "D" } */
D d; /* { dg-bogus "" "D error cascade" } */
};
template<int> void foo()
{
typedef int i = 0; /* { dg-error "is initialized" } */
}

View File

@ -0,0 +1,12 @@
/* { dg-do compile } */
/* { dg-options "" } */
// PR c++/28302
int __attribute__((vector_size(8))) x;
void foo()
{
~x;
}

View File

@ -0,0 +1,6 @@
/* { dg-options "" } */
/* { dg-do compile } */
// Testing if we can do a new of a vector
// PR C++/28450
void* q = new int __attribute__((vector_size(8))) ();

View File

@ -0,0 +1,21 @@
// PR c++/29318
// { dg-options "" }
#include <typeinfo>
void f(int i) {
try {
int a[i];
throw &a; // { dg-error "variable size" }
} catch (int (&)[i]) { // { dg-error "variable size" }
}
}
int main()
{
int i = 5;
int va[i];
const std::type_info& info(typeid(&va)); // { dg-error "variable size" }
return 0;
}

View File

@ -0,0 +1,25 @@
// PR c++/29138
class A
{
public:
int i;
class A1
{
int j;
};
};
class B : private A
{
public:
A::i;
A::A1;
};
void
f ()
{
B b;
B::A1 a1;
}

View File

@ -0,0 +1,16 @@
// PR c++/28259
// { dg-do compile }
struct A
{
virtual A* foo();
};
struct B : virtual A; // { dg-error "before" }
struct C : A
{
virtual B* foo();
};
B* C::foo() { return 0; }

View File

@ -0,0 +1,16 @@
// PR c++/26957
struct LongDouble {
char ld[16];
};
struct DynAny {
virtual void insert_longdouble(LongDouble value) = 0;
};
struct TAO_DynCommon : public virtual DynAny {
virtual void insert_longdouble (LongDouble value);
};
void TAO_DynCommon::insert_longdouble (LongDouble value) { }

View File

@ -0,0 +1,6 @@
// PR C++/29002
// We ICE trying to set the "zero" initializer on the incomplete
// array
struct A {};
int A::* x[]; // { dg-error "size" }

View File

@ -0,0 +1,6 @@
// PR C++/29002
// We ICE trying to set the "zero" initializer on the incomplete
// array
struct A {A();int A::* t;};
A x[]; // { dg-error "size" }

View File

@ -0,0 +1,7 @@
// PR c++/29175
// { dg-options "" }
void foo(int i)
{
int x[][i] = { 0 }; // { dg-error "variable-sized|storage size" }
}

View File

@ -3,6 +3,6 @@
int x = { 2 };
const char * y = { "hello" };
int a = 2;
int b = { 2,3 }; // { dg-error "too many initializers" }
int b = { 2,3 }; // { dg-error "requires one element in initializer" }
int c = { { 2 } } ; // { dg-error "braces around scalar initializer" }
int d = {}; // { dg-error "requires one element in initializer" }

View File

@ -0,0 +1,8 @@
// PR c++/28148
struct foo {
public:
virtual int bar(int);
};
void (foo::*__Virtual__foo__Var1)() = (void (foo::*)())(&foo::bar);

View File

@ -0,0 +1,7 @@
// PR c++/28338
void foo()
{
{ static const int& i = 0; }
{ static const int& i = 0; }
}

View File

@ -0,0 +1,16 @@
// PR c++/26577
// The call to bar() was causing an inappropriate dereference of *this,
// which led to an abort in cp_expr_size.
struct A
{
A(const A&);
A& operator=(const A&);
static void bar();
void baz() volatile;
};
void A::baz() volatile
{
bar();
}

View File

@ -0,0 +1,22 @@
// PR c++/18681
// Bug: The friend declaration in A failed to give C::D access to A::B
// as specified in DR 45.
class A
{
struct B;
friend class C;
};
class C
{
struct D
{
void f();
};
};
void C::D::f()
{
A::B* p;
}

View File

@ -0,0 +1,56 @@
// PR c++/27768
// Alias grouping was losing some may_aliases, causing us to think
// the store to w.p was dead.
// { dg-do run }
// { dg-options "-O2" }
int N = 1;
struct VA
{
int *p, *q, *r;
VA() : p(), q() {}
VA(const VA&) : p(), q() {}
~VA() { if (p) --N; }
};
inline void foo(VA, VA, VA) {}
struct VB
{
VA va;
VB() {}
VB(const VB&)
{
va.p = new int(va.q - va.p);
va.r = va.p + (va.q - va.p);
foo(va, va, va);
}
};
struct VC : VB { char c; };
struct V : VC {};
struct WA
{
struct X {};
X **p, **q, **r;
WA() : p() {}
~WA() { if (p) --N; }
};
struct W : WA {};
int main()
{
{
V v, u(v);
W w;
}
return N;
}

View File

@ -0,0 +1,106 @@
/* PR rtl-optimization/23454 */
/* Submitted by Matthias Klose <doko@debian.org> */
/* { dg-do compile } */
/* { dg-options "-O3" } */
typedef unsigned long long int ulonglong;
typedef long long int longlong;
typedef unsigned int uint32;
typedef unsigned int uint;
typedef unsigned long int ulong;
class Item {
public:
bool null_value;
virtual longlong val_int()=0;
};
typedef struct st_tree_element {
struct st_tree_element *left,*right;
uint32 count;
} TREE_ELEMENT;
typedef struct st_tree {
uint offset_to_key,elements_in_tree,size_of_element,memory_limit,allocated;
void *custom_arg;
bool with_delete;
uint flag;
} TREE;
class field_info
{
public:
ulong treemem, tree_elements, empty, nulls, min_length, max_length;
uint room_in_tree;
bool found;
TREE tree;
Item *item;
};
class field_ulonglong: public field_info
{
ulonglong min_arg, max_arg;
ulonglong sum, sum_sqr;
void add();
};
extern char *longlong10_to_str(longlong val,char *dst,int radix);
extern void delete_tree(TREE*);
extern TREE_ELEMENT *tree_insert(TREE *tree,void *custom_arg);
static int compare_ulonglong(const ulonglong *s, const ulonglong *t)
{
return ((*s < *t) ? -1 : *s > *t ? 1 : 0);
}
void field_ulonglong::add()
{
char buff[(255*3 +1)];
longlong num = item->val_int();
uint length = (uint) (longlong10_to_str(num, buff, 10) - buff);
TREE_ELEMENT *element;
if (item->null_value)
{
nulls++;
return;
}
if (num == 0)
empty++;
if (room_in_tree)
{
if (!(element = tree_insert(&tree, tree.custom_arg)))
{
room_in_tree = 0;
delete_tree(&tree);
}
else if (element->count == 1)
{
room_in_tree = 0;
delete_tree(&tree);
}
}
if (!found)
{
found = 1;
min_arg = max_arg = sum = num;
sum_sqr = num * num;
min_length = max_length = length;
}
else if (num != 0)
{
sum += num;
sum_sqr += num * num;
if (length < min_length)
min_length = length;
if (length > max_length)
max_length = length;
if (compare_ulonglong((ulonglong*) &num, &min_arg) < 0)
min_arg = num;
if (compare_ulonglong((ulonglong*) &num, &max_arg) > 0)
max_arg = num;
}
}

View File

@ -0,0 +1,14 @@
// PR C++/28906: new on an array causes incomplete arrays to
// become complete with the wrong size.
// the bounds of xvalue_store was being set to include want
// which was incorrect.
// { dg-do compile }
extern unsigned char xvalue_store[];
bool reserve (int want)
{
new unsigned char[want];
}
unsigned char xvalue_store[257];

View File

@ -0,0 +1,19 @@
// PR C++/28906: new on an array causes incomplete arrays to
// become complete with the wrong size.
// The sizeof machineMain should be 5 and not 100.
// { dg-do run }
extern char machineMain[];
void sort (long len)
{
new char[100];
}
char machineMain[] = "main";
int main(void)
{
if (sizeof(machineMain)!=sizeof("main"))
__builtin_abort();
}

View File

@ -0,0 +1,9 @@
// Check to make sure changing from an incomplete
// array type to a complete one does not change other
// incomplete array type's bounds.
// { dg-do compile }
extern unsigned char xvalue_store[];
extern unsigned char xvalue_store1[];
unsigned char xvalue_store[7];
unsigned char xvalue_store1[9];

View File

@ -0,0 +1,47 @@
// PR c++/28274
// { dg-do "compile" }
void f1(int, int, int, int, int = 0);
void f1(int, int, int, int = 0, int);
void f1(int, int, int = 0, int, int);
void f1(int = 0, int, int, int, int); // { dg-error "default" }
void f2(int, int, int, int, int = 0) {}
void f2(int, int, int, int = 0, int);
void f2(int, int, int = 0, int, int);
void f2(int = 0, int, int, int, int); // { dg-error "default" }
void f3(int, int, int, int, int = 0);
void f3(int, int, int, int = 0, int) {}
void f3(int, int, int = 0, int, int);
void f3(int = 0, int, int, int, int); // { dg-error "default" }
void f4(int, int, int, int, int = 0);
void f4(int, int, int, int = 0, int);
void f4(int, int, int = 0, int, int) {}
void f4(int = 0, int, int, int, int); // { dg-error "default" }
void f5(int, int, int, int, int = 0);
void f5(int, int, int, int = 0, int);
void f5(int, int, int = 0, int, int);
void f5(int = 0, int, int, int, int) {} // { dg-error "default" }
struct A
{
void F1(int, int, int = 0);
void F2(int, int, int = 0);
};
void A::F1(int, int = 0, int) {}
void A::F2(int = 0, int, int) {} // { dg-error "default" }
template<int> struct B
{
void F1(int, int, int = 0);
void F2(int, int, int = 0);
};
template<int N> void B<N>::F1(int, int = 0, int) {}
template<int N> void B<N>::F2(int = 0, int, int) {} // { dg-error "default" }

View File

@ -0,0 +1,10 @@
//PR c++/28258
struct A
{ // { dg-error "" }
A(void x); // { dg-error "invalid use|incomplete type|candidates" }
};
struct B : A {}; // { dg-error "no matching function for call" }
B b; // { dg-error "synthesized method" }

View File

@ -8,5 +8,5 @@ namespace N {}
void foo(void)
{
N::~A(); // { dg-error "not a member" }
N::~A(); // { dg-error "not a class-name" }
}

View File

@ -0,0 +1,7 @@
//PR c++/27820
void foo()
{
L: L: ; // { dg-error "duplicate label" }
}

View File

@ -0,0 +1,14 @@
// PR c++/28267
// { dg-do compile }
struct A
{
A();
void* operator new(__SIZE_TYPE__, int = X); // { dg-error "not declared" }
void operator delete(void*, int);
};
void foo()
{
new A;
}

View File

@ -0,0 +1,8 @@
// Test to make sure we do not ICE on this invalid program.
struct A
{
template<int> void foo();
void bar() { this.A::foo<0>(); } // { dg-error "" }
};

View File

@ -0,0 +1,9 @@
// Test to make sure we do not ICE on this invalid program.
template<int> void foo(struct {}*); // { dg-error "" }
void bar()
{
foo<0>(0); // { dg-error "" }
}

View File

@ -0,0 +1,11 @@
// Test to make sure we do not ICE on this invalid program.
struct A {};
template<typename T> void A::foo(T) {} // { dg-error "" }
void bar()
{
A::foo(1); // { dg-error "no matching function for call" }
}

View File

@ -0,0 +1,7 @@
// Test to make sure we do not ICE on this invalid program.
// { dg-options "" }
struct A {};
void A::foo(); // { dg-error "member function declared in class|outside of class is not definition" }

View File

@ -0,0 +1,11 @@
// PR c++/28257
// { dg-do compile }
struct A
{
int i;
void foo()
{
int A::i = i; // { dg-error "qualified" }
}
};

View File

@ -0,0 +1,7 @@
// PR c++/27572
// { dg-do compile }
void f1(typedef) {} // { dg-error "no type|typedef declaration" }
void f2(typedef x) {} // { dg-error "no type|typedef declaration" }
void f3(typedef x[]) {} // { dg-error "no type|typedef declaration" }
void f4(typedef int x) {} // { dg-error "typedef declaration" }

View File

@ -0,0 +1,13 @@
// PR c++/18698
// The compiler was giving an error message for invalid syntax
// that irrelevantly talked about using-declarations.
template<int> struct A
{
::A~(); // { dg-bogus "using-declaration" }
};
// Instead of the bogus error we get 3 separate errors.
// { dg-error "no type" "" { target *-*-* } 7 }
// { dg-error "::" "" { target *-*-* } 7 }
// { dg-error "~" "" { target *-*-* } 7 }

View File

@ -0,0 +1,8 @@
// PR c++/28249
// { dg-do compile }
void foo()
{
try {}
catch (long long long) {} // { dg-error "long long long" }
}

View File

@ -0,0 +1,8 @@
// PR c++/28878
// { dg-do compile }
template<int>
void foo()
[
throw; // { dg-error "expected" }
} // { dg-error "expected" }

View File

@ -0,0 +1,9 @@
// PR c++/27508
// { dg-do compile }
namespace N
{
struct A { ~A(); };
}
N::~A () {} // { dg-error "not a class-name" }

View File

@ -0,0 +1,12 @@
// PR c++/28606
// { dg-do compile }
struct A
{
~A A(); // { dg-error "destructor" }
};
struct B
{
A::~B B(); // { dg-error "as member of" }
};

View File

@ -0,0 +1,6 @@
// PR c++/29408
template <class T> class a
{
~a<T>();
};

View File

@ -0,0 +1,5 @@
// PR c++/27508
// { dg-do compile }
struct A;
using ::~A; // { dg-error "not a class-name" }

View File

@ -0,0 +1,18 @@
// PR c++/28056
void f1();
namespace N {
void f2();
}
class C {
static void f3();
};
void foo() {
void ::f1(); // { dg-error "qualified" }
void N::f2(); // { dg-error "qualified" }
void C::f3(); // { dg-error "qualified" }
void ::f4(); // { dg-error "qualified" }
}

View File

@ -0,0 +1,4 @@
// PR c++/28593
// { dg-do compile }
void *p = new (::X; // { dg-error "declared|type-specifier" }

View File

@ -0,0 +1,11 @@
// PR c++/28506
struct A
{
virtual void* foo() = 1; // { dg-error "pure" }
};
struct B
{
void operator()()() = 1; // { dg-error "pure|function|initializer" }
};

View File

@ -0,0 +1,13 @@
// PR c++/28595
template<int> struct A
{
static const int i;
};
template<int N> struct B
{
char c[A<N>::i], d; // { dg-error "constant" }
};
B<0> b;

View File

@ -0,0 +1,9 @@
// PR c++/28886
template<typename> struct A;
template<typename T, int N> struct A<T[N]> {};
template<typename T, int N> struct A<const T[N]> {};
A<const int[1]> a;

View File

@ -0,0 +1,30 @@
// PR c++/28385
// instantiating op() with void()() was making the compiler think that 'fcn'
// was const, so it could eliminate the call.
// { dg-do run }
extern "C" void abort (void);
int barcnt = 0;
class Foo {
public:
template<typename T>
void operator()(const T& fcn) {
fcn();
}
};
void bar() {
barcnt++;
}
int main() {
Foo myFoo;
myFoo(bar);
myFoo(&bar);
if (barcnt != 2)
abort ();
return 0;
}

View File

@ -0,0 +1,16 @@
// PR c++/28557
struct A
{
template<typename T> operator T() { return T(); }
};
template<int> void foo()
{
A().operator int();
}
void bar()
{
foo<0>();
}

View File

@ -5,7 +5,7 @@ class A
{
public:
static const EnumType size = max; // { dg-error "" }
int table[size];
int table[size]; // { dg-error "constant" }
};
template <class EnumType>
const EnumType A<EnumType>::size;

View File

@ -0,0 +1,13 @@
// PR c++/28363
// { dg-do compile }
template<typename T, template<int> class = T> // { dg-error "invalid use of type" }
struct A;
typedef int I;
template<template<int> class = I> // { dg-error "invalid use of type" }
struct B;
struct S;
template<template<int> class = S> // { dg-error "invalid use of type" }
struct C;

View File

@ -0,0 +1,16 @@
// PR c++/28048
template<typename T> struct Boom;
template<typename T, bool D = Boom<T>::Internal::Value> // <--ICE
struct Foo
{
};
template<typename T> struct Boom
{
struct Internal
{
static const bool Value = false;
};
};

View File

@ -5,5 +5,5 @@
template<int> struct A
{
~A<0>(); // { dg-error "declaration" }
~A<0>(); // { dg-error "parse error|declaration" }
};

View File

@ -0,0 +1,17 @@
// PR c++/28025
class BaseSubmit
{
template<class T> friend class PeriodicSubmit;
};
template<class ID>
class ValuesSubmit
{
template<class T> friend class PeriodicSubmit;
};
class A;
class MultiSubmit : public ValuesSubmit<A>
{
};

View File

@ -0,0 +1,9 @@
// PR c++/27714
template<typename> struct A
{
static void* operator new(__SIZE_TYPE__);
template <typename T> friend void* A<T>::operator new(__SIZE_TYPE__);
};
A<int> a;

View File

@ -2,5 +2,5 @@
template <class T> struct Base {};
template <class T> struct Derived: public Base<T> {
typename Derived::template Base<double>* p1; // { dg-error "" }
typename Derived::template Base<double>* p1;
};

View File

@ -0,0 +1,15 @@
// PR c++/29080
struct Base {
template<class C> void method() { }
};
struct Left : public Base { };
struct Right : public Base { };
struct Join : public Left, public Right { };
void function()
{
Join join;
join.Left::method<int>();
}

View File

@ -11,4 +11,4 @@ template <int> struct A
template <B> struct C {}; // { dg-error "not a valid type" }
};
A<0> a; // { dg-error "instantiated" }
A<0> a; // { dg-error "instantiated" }

View File

@ -0,0 +1,10 @@
// PR c++/28346
template<int> struct A
{
int& i;
A();
~A() { &A::i; } // { dg-error "reference" }
};
A<0> a; // { dg-error "instantiated" }

View File

@ -0,0 +1,5 @@
// PR c++/28710
// { dg-do compile }
template<int> union A; // { dg-error "previous" }
struct A; // { dg-error "non-template" }

View File

@ -0,0 +1,14 @@
// PR c++/29435
template < class T > struct A {};
template < int> void g()
{
sizeof (A < int>);
}
template < class T > struct B;
template < int> void f()
{
sizeof (B<int>); // { dg-error "incomplete" }
}

View File

@ -0,0 +1,10 @@
// PR c++/28058
template<int> struct A
{
A() {}
};
A<0> a;
template<> A<0>::A() {} // { dg-error "specialization|invalid" }

View File

@ -0,0 +1,13 @@
// PR c++/28235
template<typename> struct A
{
static const bool i = true;
template<bool = i> struct B {};
B<> b;
};
void f() {
A<int> a1, a2;
a1.b = a2.b;
}

View File

@ -0,0 +1,7 @@
// PR c++/28337
template <int> void foo()
{
(0 ? "" : "X") + 1;
}

View File

@ -0,0 +1,11 @@
// PR c++/27424
// Bug: failing to substitute the 'int' into C
template<typename T> struct A
{
template<template<T> class> struct B {};
template<T> struct C;
B<C> b;
};
A<int> a;

View File

@ -0,0 +1,5 @@
// PR c++/28853
// { dg-do compile }
template<template<int> class A>
int A<0>::i; // { dg-error "template template parameter" }

View File

@ -0,0 +1,8 @@
// PR c++/28860
// { dg-do compile}
template<template<int> class A>
class A<0>; // { dg-error "shadows template template parameter" }
template<template<int> class B>
class B<0> {}; // { dg-error "shadows template template parameter" }

View File

@ -0,0 +1,9 @@
// PR c++/27572
// { dg-do compile }
template<typedef> void foo(); // { dg-error "no type|typedef declaration" }
void bar()
{
foo<int>(); // { dg-error "matching" }
}

View File

@ -0,0 +1,7 @@
// PR c++/27572
// { dg-do compile }
template<typedef,int> struct A1; // { dg-error "no type|typedef declaration" }
template<typedef x,int> struct A2; // { dg-error "no type|typedef declaration" }
template<typedef x[],int> struct A3; // { dg-error "no type|typedef declaration" }
template<typedef int x, int> struct A4; // { dg-error "typedef declaration" }

Some files were not shown because too many files have changed in this diff Show More