re PR c++/26122 (Pure specifiers for templates causing trouble)
* g++.dg/parse/dtor7.C: New test. * g++.dg/parse/new1.C: Add error marker. * g++.dg/template/new3.C: New test. PR c++/26122 * g++.dg/template/pure1.C: New test. PR c++/26295 * g++.dg/parse/ptrmem4.C: New test. From-SVN: r112869
This commit is contained in:
parent
ba9d67765a
commit
63c9a19053
15 changed files with 374 additions and 220 deletions
|
@ -1,3 +1,38 @@
|
|||
2006-04-11 Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
* cp-tree.h (build_operator_new_call): Adjust prototype.
|
||||
(build_new_method_call): Likewise.
|
||||
(build_op_delete_call): Likewise.
|
||||
* init.c (build_raw_new_expr): New function.
|
||||
(build_new_1): Pass information as parameters, rather than
|
||||
bundling it into a NEW_EXPR.
|
||||
(build_new): Adjust accordingly.
|
||||
(build_vec_delete_1): Adjust for changes to build_op_delete_call.
|
||||
(build_delete): Likewise.
|
||||
* decl.c (finish_destructor_body): Likewise.
|
||||
* call.c (build_operator_new_call): Return the allocation function
|
||||
used.
|
||||
(build_op_delete_call): Take allocation function as parameter.
|
||||
(build_special_member_call): Adjust call to build_new_method_call.
|
||||
(build_new_method_call): Return function called.
|
||||
* pt.c (tsubst_copy_and_build): Adjust call to
|
||||
build_new_method_call.
|
||||
* semantics.c (finish_call_expr): Likewise.
|
||||
* parser.c (cp_parser_postfix_expression): Likewise.
|
||||
* typeck2.c (cxx_incomplete_type_diagnostic): Refer to
|
||||
"incomplete", not "undefined", types.
|
||||
|
||||
PR c++/26295
|
||||
* decl.c (grokdeclarator): Remove namespace-handling code for
|
||||
pointers-to-members.
|
||||
* parser.c (cp_parser_ptr_operator): Check for qualified names
|
||||
using namespaces.
|
||||
|
||||
PR c++/26122
|
||||
* parser.c (cp_parser_init_declarator): Adjust logic for deciding
|
||||
whether or not to look for a pure-specifier.
|
||||
(cp_parser_member_declaration): Likewise.
|
||||
|
||||
2006-04-08 Kazu Hirata <kazu@codesourcery.com>
|
||||
|
||||
* decl2.c, pt.c, semantics.c: Fix comment typos.
|
||||
|
|
|
@ -2817,16 +2817,21 @@ build_new_function_call (tree fn, tree args, bool koenig_p)
|
|||
required by the allocation, and is updated if that is changed here.
|
||||
*COOKIE_SIZE is non-NULL if a cookie should be used. If this
|
||||
function determines that no cookie should be used, after all,
|
||||
*COOKIE_SIZE is set to NULL_TREE. */
|
||||
*COOKIE_SIZE is set to NULL_TREE. If FN is non-NULL, it will be
|
||||
set, upon return, to the allocation function called. */
|
||||
|
||||
tree
|
||||
build_operator_new_call (tree fnname, tree args, tree *size, tree *cookie_size)
|
||||
build_operator_new_call (tree fnname, tree args,
|
||||
tree *size, tree *cookie_size,
|
||||
tree *fn)
|
||||
{
|
||||
tree fns;
|
||||
struct z_candidate *candidates;
|
||||
struct z_candidate *cand;
|
||||
bool any_viable_p;
|
||||
|
||||
if (fn)
|
||||
*fn = NULL_TREE;
|
||||
args = tree_cons (NULL_TREE, *size, args);
|
||||
args = resolve_args (args);
|
||||
if (args == error_mark_node)
|
||||
|
@ -2904,6 +2909,10 @@ build_operator_new_call (tree fnname, tree args, tree *size, tree *cookie_size)
|
|||
*cookie_size = NULL_TREE;
|
||||
}
|
||||
|
||||
/* Tell our caller which function we decided to call. */
|
||||
if (fn)
|
||||
*fn = cand->fn;
|
||||
|
||||
/* Build the CALL_EXPR. */
|
||||
return build_over_call (cand, LOOKUP_NORMAL);
|
||||
}
|
||||
|
@ -3930,11 +3939,14 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3,
|
|||
SIZE is the size of the memory block to be deleted.
|
||||
GLOBAL_P is true if the delete-expression should not consider
|
||||
class-specific delete operators.
|
||||
PLACEMENT is the corresponding placement new call, or NULL_TREE. */
|
||||
PLACEMENT is the corresponding placement new call, or NULL_TREE.
|
||||
If PLACEMENT is non-NULL, then ALLOC_FN is the allocation function
|
||||
called to perform the placement new. */
|
||||
|
||||
tree
|
||||
build_op_delete_call (enum tree_code code, tree addr, tree size,
|
||||
bool global_p, tree placement)
|
||||
bool global_p, tree placement,
|
||||
tree alloc_fn)
|
||||
{
|
||||
tree fn = NULL_TREE;
|
||||
tree fns, fnname, argtypes, args, type;
|
||||
|
@ -3970,18 +3982,12 @@ build_op_delete_call (enum tree_code code, tree addr, tree size,
|
|||
|
||||
if (placement)
|
||||
{
|
||||
tree alloc_fn;
|
||||
tree call_expr;
|
||||
|
||||
/* Find the allocation function that is being called. */
|
||||
call_expr = placement;
|
||||
/* Extract the function. */
|
||||
alloc_fn = get_callee_fndecl (call_expr);
|
||||
/* Get the parmaeter types for the allocation function that is
|
||||
being called. */
|
||||
gcc_assert (alloc_fn != NULL_TREE);
|
||||
/* Then the second parm type. */
|
||||
argtypes = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (alloc_fn)));
|
||||
/* Also the second argument. */
|
||||
args = TREE_CHAIN (TREE_OPERAND (call_expr, 1));
|
||||
args = TREE_CHAIN (TREE_OPERAND (placement, 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -5181,7 +5187,7 @@ build_special_member_call (tree instance, tree name, tree args,
|
|||
|
||||
return build_new_method_call (instance, fns, args,
|
||||
TYPE_BINFO (BINFO_TYPE (binfo)),
|
||||
flags);
|
||||
flags, /*fn=*/NULL);
|
||||
}
|
||||
|
||||
/* Return the NAME, as a C string. The NAME indicates a function that
|
||||
|
@ -5229,11 +5235,13 @@ name_as_c_string (tree name, tree type, bool *free_p)
|
|||
return pretty_name;
|
||||
}
|
||||
|
||||
/* Build a call to "INSTANCE.FN (ARGS)". */
|
||||
/* Build a call to "INSTANCE.FN (ARGS)". If FN_P is non-NULL, it will
|
||||
be set, upon return, to the function called. */
|
||||
|
||||
tree
|
||||
build_new_method_call (tree instance, tree fns, tree args,
|
||||
tree conversion_path, int flags)
|
||||
tree conversion_path, int flags,
|
||||
tree *fn_p)
|
||||
{
|
||||
struct z_candidate *candidates = 0, *cand;
|
||||
tree explicit_targs = NULL_TREE;
|
||||
|
@ -5255,6 +5263,10 @@ build_new_method_call (tree instance, tree fns, tree args,
|
|||
|
||||
gcc_assert (instance != NULL_TREE);
|
||||
|
||||
/* We don't know what function we're going to call, yet. */
|
||||
if (fn_p)
|
||||
*fn_p = NULL_TREE;
|
||||
|
||||
if (error_operand_p (instance)
|
||||
|| error_operand_p (fns)
|
||||
|| args == error_mark_node)
|
||||
|
@ -5411,8 +5423,10 @@ build_new_method_call (tree instance, tree fns, tree args,
|
|||
}
|
||||
else
|
||||
{
|
||||
fn = cand->fn;
|
||||
|
||||
if (!(flags & LOOKUP_NONVIRTUAL)
|
||||
&& DECL_PURE_VIRTUAL_P (cand->fn)
|
||||
&& DECL_PURE_VIRTUAL_P (fn)
|
||||
&& instance == current_class_ref
|
||||
&& (DECL_CONSTRUCTOR_P (current_function_decl)
|
||||
|| DECL_DESTRUCTOR_P (current_function_decl)))
|
||||
|
@ -5421,27 +5435,29 @@ build_new_method_call (tree instance, tree fns, tree args,
|
|||
warning (0, (DECL_CONSTRUCTOR_P (current_function_decl) ?
|
||||
"abstract virtual %q#D called from constructor"
|
||||
: "abstract virtual %q#D called from destructor"),
|
||||
cand->fn);
|
||||
fn);
|
||||
|
||||
if (TREE_CODE (TREE_TYPE (cand->fn)) == METHOD_TYPE
|
||||
if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE
|
||||
&& is_dummy_object (instance_ptr))
|
||||
{
|
||||
error ("cannot call member function %qD without object",
|
||||
cand->fn);
|
||||
fn);
|
||||
call = error_mark_node;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (DECL_VINDEX (cand->fn) && ! (flags & LOOKUP_NONVIRTUAL)
|
||||
if (DECL_VINDEX (fn) && ! (flags & LOOKUP_NONVIRTUAL)
|
||||
&& resolves_to_fixed_type_p (instance, 0))
|
||||
flags |= LOOKUP_NONVIRTUAL;
|
||||
|
||||
/* Now we know what function is being called. */
|
||||
if (fn_p)
|
||||
*fn_p = fn;
|
||||
/* Build the actuall CALL_EXPR. */
|
||||
call = build_over_call (cand, flags);
|
||||
|
||||
/* In an expression of the form `a->f()' where `f' turns
|
||||
out to be a static member function, `a' is
|
||||
none-the-less evaluated. */
|
||||
if (TREE_CODE (TREE_TYPE (cand->fn)) != METHOD_TYPE
|
||||
if (TREE_CODE (TREE_TYPE (fn)) != METHOD_TYPE
|
||||
&& !is_dummy_object (instance_ptr)
|
||||
&& TREE_SIDE_EFFECTS (instance))
|
||||
call = build2 (COMPOUND_EXPR, TREE_TYPE (call),
|
||||
|
|
|
@ -3710,11 +3710,13 @@ extern bool sufficient_parms_p (tree);
|
|||
extern tree type_decays_to (tree);
|
||||
extern tree build_user_type_conversion (tree, tree, int);
|
||||
extern tree build_new_function_call (tree, tree, bool);
|
||||
extern tree build_operator_new_call (tree, tree, tree *, tree *);
|
||||
extern tree build_new_method_call (tree, tree, tree, tree, int);
|
||||
extern tree build_operator_new_call (tree, tree, tree *, tree *,
|
||||
tree *);
|
||||
extern tree build_new_method_call (tree, tree, tree, tree, int,
|
||||
tree *);
|
||||
extern tree build_special_member_call (tree, tree, tree, tree, int);
|
||||
extern tree build_new_op (enum tree_code, int, tree, tree, tree, bool *);
|
||||
extern tree build_op_delete_call (enum tree_code, tree, tree, bool, tree);
|
||||
extern tree build_op_delete_call (enum tree_code, tree, tree, bool, tree, tree);
|
||||
extern bool can_convert (tree, tree);
|
||||
extern bool can_convert_arg (tree, tree, tree, int);
|
||||
extern bool can_convert_arg_bad (tree, tree, tree);
|
||||
|
|
|
@ -7619,15 +7619,9 @@ grokdeclarator (const cp_declarator *declarator,
|
|||
type = build_ptrmemfunc_type (build_pointer_type (type));
|
||||
else if (declarator->kind == cdk_ptrmem)
|
||||
{
|
||||
/* We might have parsed a namespace as the class type. */
|
||||
if (TREE_CODE (declarator->u.pointer.class_type)
|
||||
== NAMESPACE_DECL)
|
||||
{
|
||||
error ("%qD is a namespace",
|
||||
declarator->u.pointer.class_type);
|
||||
type = build_pointer_type (type);
|
||||
}
|
||||
else if (declarator->u.pointer.class_type == error_mark_node)
|
||||
gcc_assert (TREE_CODE (declarator->u.pointer.class_type)
|
||||
!= NAMESPACE_DECL);
|
||||
if (declarator->u.pointer.class_type == error_mark_node)
|
||||
/* We will already have complained. */
|
||||
type = error_mark_node;
|
||||
else
|
||||
|
@ -10801,9 +10795,11 @@ finish_destructor_body (void)
|
|||
an implicit definition), non-placement operator delete shall
|
||||
be looked up in the scope of the destructor's class and if
|
||||
found shall be accessible and unambiguous. */
|
||||
exprstmt = build_op_delete_call
|
||||
(DELETE_EXPR, current_class_ptr, virtual_size,
|
||||
/*global_p=*/false, NULL_TREE);
|
||||
exprstmt = build_op_delete_call(DELETE_EXPR, current_class_ptr,
|
||||
virtual_size,
|
||||
/*global_p=*/false,
|
||||
/*placement=*/NULL_TREE,
|
||||
/*alloc_fn=*/NULL_TREE);
|
||||
|
||||
if_stmt = begin_if_stmt ();
|
||||
finish_if_stmt_cond (build2 (BIT_AND_EXPR, integer_type_node,
|
||||
|
|
341
gcc/cp/init.c
341
gcc/cp/init.c
|
@ -52,7 +52,6 @@ static void expand_cleanup_for_base (tree, tree);
|
|||
static tree get_temp_regvar (tree, tree);
|
||||
static tree dfs_initialize_vtbl_ptrs (tree, void *);
|
||||
static tree build_default_init (tree, tree);
|
||||
static tree build_new_1 (tree);
|
||||
static tree build_dtor_call (tree, special_function_kind, int);
|
||||
static tree build_field_list (tree, tree, int *);
|
||||
static tree build_vtbl_address (tree);
|
||||
|
@ -1560,127 +1559,38 @@ build_builtin_delete_call (tree addr)
|
|||
return build_call (global_delete_fndecl, build_tree_list (NULL_TREE, addr));
|
||||
}
|
||||
|
||||
/* Generate a representation for a C++ "new" expression. PLACEMENT is
|
||||
a TREE_LIST of placement-new arguments (or NULL_TREE if none). If
|
||||
NELTS is NULL, TYPE is the type of the storage to be allocated. If
|
||||
NELTS is not NULL, then this is an array-new allocation; TYPE is
|
||||
the type of the elements in the array and NELTS is the number of
|
||||
elements in the array. INIT, if non-NULL, is the initializer for
|
||||
the new object. If USE_GLOBAL_NEW is true, then the user
|
||||
explicitly wrote "::new" rather than just "new". */
|
||||
|
||||
tree
|
||||
build_new (tree placement, tree type, tree nelts, tree init,
|
||||
int use_global_new)
|
||||
{
|
||||
tree rval;
|
||||
|
||||
if (type == error_mark_node)
|
||||
return error_mark_node;
|
||||
|
||||
if (processing_template_decl)
|
||||
{
|
||||
rval = build_min (NEW_EXPR, build_pointer_type (type),
|
||||
placement, type, nelts, init);
|
||||
NEW_EXPR_USE_GLOBAL (rval) = use_global_new;
|
||||
TREE_SIDE_EFFECTS (rval) = 1;
|
||||
return rval;
|
||||
}
|
||||
|
||||
if (nelts)
|
||||
{
|
||||
if (!build_expr_type_conversion (WANT_INT | WANT_ENUM, nelts, false))
|
||||
pedwarn ("size in array new must have integral type");
|
||||
nelts = save_expr (cp_convert (sizetype, nelts));
|
||||
if (nelts == integer_zero_node)
|
||||
warning (0, "zero size array reserves no space");
|
||||
}
|
||||
|
||||
/* ``A reference cannot be created by the new operator. A reference
|
||||
is not an object (8.2.2, 8.4.3), so a pointer to it could not be
|
||||
returned by new.'' ARM 5.3.3 */
|
||||
if (TREE_CODE (type) == REFERENCE_TYPE)
|
||||
{
|
||||
error ("new cannot be applied to a reference type");
|
||||
type = TREE_TYPE (type);
|
||||
}
|
||||
|
||||
if (TREE_CODE (type) == FUNCTION_TYPE)
|
||||
{
|
||||
error ("new cannot be applied to a function type");
|
||||
return error_mark_node;
|
||||
}
|
||||
|
||||
rval = build4 (NEW_EXPR, build_pointer_type (type), placement, type,
|
||||
nelts, init);
|
||||
NEW_EXPR_USE_GLOBAL (rval) = use_global_new;
|
||||
TREE_SIDE_EFFECTS (rval) = 1;
|
||||
rval = build_new_1 (rval);
|
||||
if (rval == error_mark_node)
|
||||
return error_mark_node;
|
||||
|
||||
/* Wrap it in a NOP_EXPR so warn_if_unused_value doesn't complain. */
|
||||
rval = build1 (NOP_EXPR, TREE_TYPE (rval), rval);
|
||||
TREE_NO_WARNING (rval) = 1;
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
/* Given a Java class, return a decl for the corresponding java.lang.Class. */
|
||||
|
||||
tree
|
||||
build_java_class_ref (tree type)
|
||||
{
|
||||
tree name = NULL_TREE, class_decl;
|
||||
static tree CL_suffix = NULL_TREE;
|
||||
if (CL_suffix == NULL_TREE)
|
||||
CL_suffix = get_identifier("class$");
|
||||
if (jclass_node == NULL_TREE)
|
||||
{
|
||||
jclass_node = IDENTIFIER_GLOBAL_VALUE (get_identifier ("jclass"));
|
||||
if (jclass_node == NULL_TREE)
|
||||
fatal_error ("call to Java constructor, while %<jclass%> undefined");
|
||||
|
||||
jclass_node = TREE_TYPE (jclass_node);
|
||||
}
|
||||
|
||||
/* Mangle the class$ field. */
|
||||
{
|
||||
tree field;
|
||||
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
|
||||
if (DECL_NAME (field) == CL_suffix)
|
||||
{
|
||||
mangle_decl (field);
|
||||
name = DECL_ASSEMBLER_NAME (field);
|
||||
break;
|
||||
}
|
||||
if (!field)
|
||||
internal_error ("can't find class$");
|
||||
}
|
||||
|
||||
class_decl = IDENTIFIER_GLOBAL_VALUE (name);
|
||||
if (class_decl == NULL_TREE)
|
||||
{
|
||||
class_decl = build_decl (VAR_DECL, name, TREE_TYPE (jclass_node));
|
||||
TREE_STATIC (class_decl) = 1;
|
||||
DECL_EXTERNAL (class_decl) = 1;
|
||||
TREE_PUBLIC (class_decl) = 1;
|
||||
DECL_ARTIFICIAL (class_decl) = 1;
|
||||
DECL_IGNORED_P (class_decl) = 1;
|
||||
pushdecl_top_level (class_decl);
|
||||
make_decl_rtl (class_decl);
|
||||
}
|
||||
return class_decl;
|
||||
}
|
||||
|
||||
|
||||
/* Called from cplus_expand_expr when expanding a NEW_EXPR. The return
|
||||
value is immediately handed to expand_expr. */
|
||||
/* Build and return a NEW_EXPR. If NELTS is non-NULL, TYPE[NELTS] is
|
||||
the type of the object being allocated; otherwise, it's just TYPE.
|
||||
INIT is the initializer, if any. USE_GLOBAL_NEW is true if the
|
||||
user explicitly wrote "::operator new". PLACEMENT, if non-NULL, is
|
||||
the TREE_LIST of arguments to be provided as arguments to a
|
||||
placement new operator. This routine performs no semantic checks;
|
||||
it just creates and returns a NEW_EXPR. */
|
||||
|
||||
static tree
|
||||
build_new_1 (tree exp)
|
||||
build_raw_new_expr (tree placement, tree type, tree nelts, tree init,
|
||||
int use_global_new)
|
||||
{
|
||||
tree new_expr;
|
||||
|
||||
new_expr = build4 (NEW_EXPR, build_pointer_type (type), placement, type,
|
||||
nelts, init);
|
||||
NEW_EXPR_USE_GLOBAL (new_expr) = use_global_new;
|
||||
TREE_SIDE_EFFECTS (new_expr) = 1;
|
||||
|
||||
return new_expr;
|
||||
}
|
||||
|
||||
/* Generate code for a new-expression, including calling the "operator
|
||||
new" function, initializing the object, and, if an exception occurs
|
||||
during construction, cleaning up. The arguments are as for
|
||||
build_raw_new_expr. */
|
||||
|
||||
static tree
|
||||
build_new_1 (tree placement, tree type, tree nelts, tree init,
|
||||
bool globally_qualified_p)
|
||||
|
||||
{
|
||||
tree placement, init;
|
||||
tree size, rval;
|
||||
/* True iff this is a call to "operator new[]" instead of just
|
||||
"operator new". */
|
||||
|
@ -1700,14 +1610,9 @@ build_new_1 (tree exp)
|
|||
/* The type of the new-expression. (This type is always a pointer
|
||||
type.) */
|
||||
tree pointer_type;
|
||||
/* The type pointed to by POINTER_TYPE. This type may be different
|
||||
from ELT_TYPE for a multi-dimensional array; ELT_TYPE is never an
|
||||
ARRAY_TYPE, but TYPE may be an ARRAY_TYPE. */
|
||||
tree type;
|
||||
/* A pointer type pointing to the FULL_TYPE. */
|
||||
tree full_pointer_type;
|
||||
tree outer_nelts = NULL_TREE;
|
||||
tree nelts = NULL_TREE;
|
||||
tree alloc_call, alloc_expr;
|
||||
/* The address returned by the call to "operator new". This node is
|
||||
a VAR_DECL and is therefore reusable. */
|
||||
|
@ -1715,8 +1620,6 @@ build_new_1 (tree exp)
|
|||
tree alloc_fn;
|
||||
tree cookie_expr, init_expr;
|
||||
int nothrow, check_new;
|
||||
/* Nonzero if the user wrote `::new' rather than just `new'. */
|
||||
int globally_qualified_p;
|
||||
int use_java_new = 0;
|
||||
/* If non-NULL, the number of extra bytes to allocate at the
|
||||
beginning of the storage allocated for an array-new expression in
|
||||
|
@ -1736,12 +1639,6 @@ build_new_1 (tree exp)
|
|||
tree data_addr;
|
||||
tree init_preeval_expr = NULL_TREE;
|
||||
|
||||
placement = TREE_OPERAND (exp, 0);
|
||||
type = TREE_OPERAND (exp, 1);
|
||||
nelts = TREE_OPERAND (exp, 2);
|
||||
init = TREE_OPERAND (exp, 3);
|
||||
globally_qualified_p = NEW_EXPR_USE_GLOBAL (exp);
|
||||
|
||||
if (nelts)
|
||||
{
|
||||
tree index;
|
||||
|
@ -1770,7 +1667,7 @@ build_new_1 (tree exp)
|
|||
}
|
||||
}
|
||||
|
||||
if (!complete_type_or_else (type, exp))
|
||||
if (!complete_type_or_else (type, NULL_TREE))
|
||||
return error_mark_node;
|
||||
|
||||
/* If our base type is an array, then make sure we know how many elements
|
||||
|
@ -1815,30 +1712,31 @@ build_new_1 (tree exp)
|
|||
}
|
||||
}
|
||||
|
||||
alloc_fn = NULL_TREE;
|
||||
|
||||
/* Allocate the object. */
|
||||
if (! placement && TYPE_FOR_JAVA (elt_type))
|
||||
{
|
||||
tree class_addr, alloc_decl;
|
||||
tree class_addr;
|
||||
tree class_decl = build_java_class_ref (elt_type);
|
||||
static const char alloc_name[] = "_Jv_AllocObject";
|
||||
|
||||
use_java_new = 1;
|
||||
alloc_decl = NULL;
|
||||
if (!get_global_value_if_present (get_identifier (alloc_name),
|
||||
&alloc_decl))
|
||||
&alloc_fn))
|
||||
{
|
||||
error ("call to Java constructor with %qs undefined", alloc_name);
|
||||
return error_mark_node;
|
||||
}
|
||||
else if (really_overloaded_fn (alloc_decl))
|
||||
else if (really_overloaded_fn (alloc_fn))
|
||||
{
|
||||
error ("%qD should never be overloaded", alloc_decl);
|
||||
error ("%qD should never be overloaded", alloc_fn);
|
||||
return error_mark_node;
|
||||
}
|
||||
alloc_decl = OVL_CURRENT (alloc_decl);
|
||||
alloc_fn = OVL_CURRENT (alloc_fn);
|
||||
class_addr = build1 (ADDR_EXPR, jclass_node, class_decl);
|
||||
alloc_call = (build_function_call
|
||||
(alloc_decl,
|
||||
(alloc_fn,
|
||||
build_tree_list (NULL_TREE, class_addr)));
|
||||
}
|
||||
else
|
||||
|
@ -1879,7 +1777,8 @@ build_new_1 (tree exp)
|
|||
alloc_call = build_new_method_call (build_dummy_object (elt_type),
|
||||
fns, args,
|
||||
/*conversion_path=*/NULL_TREE,
|
||||
LOOKUP_NORMAL);
|
||||
LOOKUP_NORMAL,
|
||||
&alloc_fn);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1891,13 +1790,16 @@ build_new_1 (tree exp)
|
|||
cookie_size = NULL_TREE;
|
||||
|
||||
alloc_call = build_operator_new_call (fnname, placement,
|
||||
&size, &cookie_size);
|
||||
&size, &cookie_size,
|
||||
&alloc_fn);
|
||||
}
|
||||
}
|
||||
|
||||
if (alloc_call == error_mark_node)
|
||||
return error_mark_node;
|
||||
|
||||
gcc_assert (alloc_fn != NULL_TREE);
|
||||
|
||||
/* In the simple case, we can stop now. */
|
||||
pointer_type = build_pointer_type (type);
|
||||
if (!cookie_size && !is_initialized)
|
||||
|
@ -1913,8 +1815,6 @@ build_new_1 (tree exp)
|
|||
/* Strip any COMPOUND_EXPRs from ALLOC_CALL. */
|
||||
while (TREE_CODE (alloc_call) == COMPOUND_EXPR)
|
||||
alloc_call = TREE_OPERAND (alloc_call, 1);
|
||||
alloc_fn = get_callee_fndecl (alloc_call);
|
||||
gcc_assert (alloc_fn != NULL_TREE);
|
||||
|
||||
/* Now, check to see if this function is actually a placement
|
||||
allocation function. This can happen even when PLACEMENT is NULL
|
||||
|
@ -2079,7 +1979,9 @@ build_new_1 (tree exp)
|
|||
cleanup = build_op_delete_call (dcode, alloc_node, size,
|
||||
globally_qualified_p,
|
||||
(placement_allocation_fn_p
|
||||
? alloc_call : NULL_TREE));
|
||||
? alloc_call : NULL_TREE),
|
||||
(placement_allocation_fn_p
|
||||
? alloc_fn : NULL_TREE));
|
||||
|
||||
if (!cleanup)
|
||||
/* We're done. */;
|
||||
|
@ -2163,6 +2065,134 @@ build_new_1 (tree exp)
|
|||
|
||||
return rval;
|
||||
}
|
||||
|
||||
/* Generate a representation for a C++ "new" expression. PLACEMENT is
|
||||
a TREE_LIST of placement-new arguments (or NULL_TREE if none). If
|
||||
NELTS is NULL, TYPE is the type of the storage to be allocated. If
|
||||
NELTS is not NULL, then this is an array-new allocation; TYPE is
|
||||
the type of the elements in the array and NELTS is the number of
|
||||
elements in the array. INIT, if non-NULL, is the initializer for
|
||||
the new object, or void_zero_node to indicate an initializer of
|
||||
"()". If USE_GLOBAL_NEW is true, then the user explicitly wrote
|
||||
"::new" rather than just "new". */
|
||||
|
||||
tree
|
||||
build_new (tree placement, tree type, tree nelts, tree init,
|
||||
int use_global_new)
|
||||
{
|
||||
tree rval;
|
||||
tree orig_placement;
|
||||
tree orig_nelts;
|
||||
tree orig_init;
|
||||
|
||||
if (type == error_mark_node)
|
||||
return error_mark_node;
|
||||
|
||||
orig_placement = placement;
|
||||
orig_nelts = nelts;
|
||||
orig_init = init;
|
||||
|
||||
if (processing_template_decl)
|
||||
{
|
||||
if (dependent_type_p (type)
|
||||
|| any_type_dependent_arguments_p (placement)
|
||||
|| (nelts && type_dependent_expression_p (nelts))
|
||||
|| (init != void_zero_node
|
||||
&& any_type_dependent_arguments_p (init)))
|
||||
return build_raw_new_expr (placement, type, nelts, init,
|
||||
use_global_new);
|
||||
placement = build_non_dependent_args (placement);
|
||||
if (nelts)
|
||||
nelts = build_non_dependent_expr (nelts);
|
||||
if (init != void_zero_node)
|
||||
init = build_non_dependent_args (init);
|
||||
}
|
||||
|
||||
if (nelts)
|
||||
{
|
||||
if (!build_expr_type_conversion (WANT_INT | WANT_ENUM, nelts, false))
|
||||
pedwarn ("size in array new must have integral type");
|
||||
nelts = save_expr (cp_convert (sizetype, nelts));
|
||||
if (nelts == integer_zero_node)
|
||||
warning (0, "zero size array reserves no space");
|
||||
}
|
||||
|
||||
/* ``A reference cannot be created by the new operator. A reference
|
||||
is not an object (8.2.2, 8.4.3), so a pointer to it could not be
|
||||
returned by new.'' ARM 5.3.3 */
|
||||
if (TREE_CODE (type) == REFERENCE_TYPE)
|
||||
{
|
||||
error ("new cannot be applied to a reference type");
|
||||
type = TREE_TYPE (type);
|
||||
}
|
||||
|
||||
if (TREE_CODE (type) == FUNCTION_TYPE)
|
||||
{
|
||||
error ("new cannot be applied to a function type");
|
||||
return error_mark_node;
|
||||
}
|
||||
|
||||
rval = build_new_1 (placement, type, nelts, init, use_global_new);
|
||||
if (rval == error_mark_node)
|
||||
return error_mark_node;
|
||||
|
||||
if (processing_template_decl)
|
||||
return build_raw_new_expr (orig_placement, type, orig_nelts, orig_init,
|
||||
use_global_new);
|
||||
|
||||
/* Wrap it in a NOP_EXPR so warn_if_unused_value doesn't complain. */
|
||||
rval = build1 (NOP_EXPR, TREE_TYPE (rval), rval);
|
||||
TREE_NO_WARNING (rval) = 1;
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
/* Given a Java class, return a decl for the corresponding java.lang.Class. */
|
||||
|
||||
tree
|
||||
build_java_class_ref (tree type)
|
||||
{
|
||||
tree name = NULL_TREE, class_decl;
|
||||
static tree CL_suffix = NULL_TREE;
|
||||
if (CL_suffix == NULL_TREE)
|
||||
CL_suffix = get_identifier("class$");
|
||||
if (jclass_node == NULL_TREE)
|
||||
{
|
||||
jclass_node = IDENTIFIER_GLOBAL_VALUE (get_identifier ("jclass"));
|
||||
if (jclass_node == NULL_TREE)
|
||||
fatal_error ("call to Java constructor, while %<jclass%> undefined");
|
||||
|
||||
jclass_node = TREE_TYPE (jclass_node);
|
||||
}
|
||||
|
||||
/* Mangle the class$ field. */
|
||||
{
|
||||
tree field;
|
||||
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
|
||||
if (DECL_NAME (field) == CL_suffix)
|
||||
{
|
||||
mangle_decl (field);
|
||||
name = DECL_ASSEMBLER_NAME (field);
|
||||
break;
|
||||
}
|
||||
if (!field)
|
||||
internal_error ("can't find class$");
|
||||
}
|
||||
|
||||
class_decl = IDENTIFIER_GLOBAL_VALUE (name);
|
||||
if (class_decl == NULL_TREE)
|
||||
{
|
||||
class_decl = build_decl (VAR_DECL, name, TREE_TYPE (jclass_node));
|
||||
TREE_STATIC (class_decl) = 1;
|
||||
DECL_EXTERNAL (class_decl) = 1;
|
||||
TREE_PUBLIC (class_decl) = 1;
|
||||
DECL_ARTIFICIAL (class_decl) = 1;
|
||||
DECL_IGNORED_P (class_decl) = 1;
|
||||
pushdecl_top_level (class_decl);
|
||||
make_decl_rtl (class_decl);
|
||||
}
|
||||
return class_decl;
|
||||
}
|
||||
|
||||
static tree
|
||||
build_vec_delete_1 (tree base, tree maxindex, tree type,
|
||||
|
@ -2257,7 +2287,8 @@ build_vec_delete_1 (tree base, tree maxindex, tree type,
|
|||
deallocate_expr = build_op_delete_call (VEC_DELETE_EXPR,
|
||||
base_tbd, virtual_size,
|
||||
use_global_delete & 1,
|
||||
NULL_TREE);
|
||||
/*placement=*/NULL_TREE,
|
||||
/*alloc_fn=*/NULL_TREE);
|
||||
}
|
||||
|
||||
body = loop;
|
||||
|
@ -2646,7 +2677,8 @@ build_dtor_call (tree exp, special_function_kind dtor_kind, int flags)
|
|||
return build_new_method_call (exp, fn,
|
||||
/*args=*/NULL_TREE,
|
||||
/*conversion_path=*/NULL_TREE,
|
||||
flags);
|
||||
flags,
|
||||
/*fn_p=*/NULL);
|
||||
}
|
||||
|
||||
/* Generate a call to a destructor. TYPE is the type to cast ADDR to.
|
||||
|
@ -2742,9 +2774,11 @@ build_delete (tree type, tree addr, special_function_kind auto_delete,
|
|||
if (auto_delete != sfk_deleting_destructor)
|
||||
return void_zero_node;
|
||||
|
||||
return build_op_delete_call
|
||||
(DELETE_EXPR, addr, cxx_sizeof_nowarn (type), use_global_delete,
|
||||
NULL_TREE);
|
||||
return build_op_delete_call (DELETE_EXPR, addr,
|
||||
cxx_sizeof_nowarn (type),
|
||||
use_global_delete,
|
||||
/*placement=*/NULL_TREE,
|
||||
/*alloc_fn=*/NULL_TREE);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2780,7 +2814,8 @@ build_delete (tree type, tree addr, special_function_kind auto_delete,
|
|||
addr,
|
||||
cxx_sizeof_nowarn (type),
|
||||
/*global_p=*/false,
|
||||
NULL_TREE);
|
||||
/*placement=*/NULL_TREE,
|
||||
/*alloc_fn=*/NULL_TREE);
|
||||
/* Call the complete object destructor. */
|
||||
auto_delete = sfk_complete_destructor;
|
||||
}
|
||||
|
@ -2790,7 +2825,9 @@ build_delete (tree type, tree addr, special_function_kind auto_delete,
|
|||
/* Make sure we have access to the member op delete, even though
|
||||
we'll actually be calling it from the destructor. */
|
||||
build_op_delete_call (DELETE_EXPR, addr, cxx_sizeof_nowarn (type),
|
||||
/*global_p=*/false, NULL_TREE);
|
||||
/*global_p=*/false,
|
||||
/*placement=*/NULL_TREE,
|
||||
/*alloc_fn=*/NULL_TREE);
|
||||
}
|
||||
|
||||
expr = build_dtor_call (build_indirect_ref (addr, NULL),
|
||||
|
|
|
@ -4262,7 +4262,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p)
|
|||
= (build_new_method_call
|
||||
(instance, fn, args, NULL_TREE,
|
||||
(idk == CP_ID_KIND_QUALIFIED
|
||||
? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL)));
|
||||
? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL),
|
||||
/*fn_p=*/NULL));
|
||||
else
|
||||
postfix_expression
|
||||
= finish_call_expr (postfix_expression, args,
|
||||
|
@ -10887,6 +10888,10 @@ cp_parser_init_declarator (cp_parser* parser,
|
|||
tree decl = NULL_TREE;
|
||||
tree scope;
|
||||
bool is_initialized;
|
||||
/* Only valid if IS_INITIALIZED is true. In that case, CPP_EQ if
|
||||
initialized with "= ..", CPP_OPEN_PAREN if initialized with
|
||||
"(...)". */
|
||||
enum cpp_ttype initialization_kind;
|
||||
bool is_parenthesized_init;
|
||||
bool is_non_constant_init;
|
||||
int ctor_dtor_or_conv_p;
|
||||
|
@ -11001,16 +11006,24 @@ cp_parser_init_declarator (cp_parser* parser,
|
|||
}
|
||||
|
||||
/* An `=' or an `(' indicates an initializer. */
|
||||
is_initialized = (token->type == CPP_EQ
|
||||
|| token->type == CPP_OPEN_PAREN);
|
||||
/* If the init-declarator isn't initialized and isn't followed by a
|
||||
`,' or `;', it's not a valid init-declarator. */
|
||||
if (!is_initialized
|
||||
&& token->type != CPP_COMMA
|
||||
&& token->type != CPP_SEMICOLON)
|
||||
if (token->type == CPP_EQ
|
||||
|| token->type == CPP_OPEN_PAREN)
|
||||
{
|
||||
cp_parser_error (parser, "expected initializer");
|
||||
return error_mark_node;
|
||||
is_initialized = true;
|
||||
initialization_kind = token->type;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If the init-declarator isn't initialized and isn't followed by a
|
||||
`,' or `;', it's not a valid init-declarator. */
|
||||
if (token->type != CPP_COMMA
|
||||
&& token->type != CPP_SEMICOLON)
|
||||
{
|
||||
cp_parser_error (parser, "expected initializer");
|
||||
return error_mark_node;
|
||||
}
|
||||
is_initialized = false;
|
||||
initialization_kind = CPP_EOF;
|
||||
}
|
||||
|
||||
/* Because start_decl has side-effects, we should only call it if we
|
||||
|
@ -11081,9 +11094,16 @@ cp_parser_init_declarator (cp_parser* parser,
|
|||
|
||||
/* Parse the initializer. */
|
||||
if (is_initialized)
|
||||
initializer = cp_parser_initializer (parser,
|
||||
&is_parenthesized_init,
|
||||
&is_non_constant_init);
|
||||
{
|
||||
if (declarator->kind == cdk_function
|
||||
&& declarator->declarator->kind == cdk_id
|
||||
&& initialization_kind == CPP_EQ)
|
||||
initializer = cp_parser_pure_specifier (parser);
|
||||
else
|
||||
initializer = cp_parser_initializer (parser,
|
||||
&is_parenthesized_init,
|
||||
&is_non_constant_init);
|
||||
}
|
||||
else
|
||||
{
|
||||
initializer = NULL_TREE;
|
||||
|
@ -11730,17 +11750,23 @@ cp_parser_ptr_operator (cp_parser* parser,
|
|||
if (!cp_parser_error_occurred (parser)
|
||||
&& cp_parser_require (parser, CPP_MULT, "`*'"))
|
||||
{
|
||||
/* The type of which the member is a member is given by the
|
||||
current SCOPE. */
|
||||
*type = parser->scope;
|
||||
/* The next name will not be qualified. */
|
||||
parser->scope = NULL_TREE;
|
||||
parser->qualifying_scope = NULL_TREE;
|
||||
parser->object_scope = NULL_TREE;
|
||||
/* Indicate that the `*' operator was used. */
|
||||
code = INDIRECT_REF;
|
||||
/* Look for the optional cv-qualifier-seq. */
|
||||
*cv_quals = cp_parser_cv_qualifier_seq_opt (parser);
|
||||
|
||||
if (TREE_CODE (parser->scope) == NAMESPACE_DECL)
|
||||
error ("%qD is a namespace", parser->scope);
|
||||
else
|
||||
{
|
||||
/* The type of which the member is a member is given by the
|
||||
current SCOPE. */
|
||||
*type = parser->scope;
|
||||
/* The next name will not be qualified. */
|
||||
parser->scope = NULL_TREE;
|
||||
parser->qualifying_scope = NULL_TREE;
|
||||
parser->object_scope = NULL_TREE;
|
||||
/* Look for the optional cv-qualifier-seq. */
|
||||
*cv_quals = cp_parser_cv_qualifier_seq_opt (parser);
|
||||
}
|
||||
}
|
||||
/* If that didn't work we don't have a ptr-operator. */
|
||||
if (!cp_parser_parse_definitely (parser))
|
||||
|
@ -13710,7 +13736,8 @@ 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)
|
||||
if (declarator->kind == cdk_function
|
||||
&& declarator->declarator->kind == cdk_id)
|
||||
initializer = cp_parser_pure_specifier (parser);
|
||||
else
|
||||
/* Parse the initializer. */
|
||||
|
|
|
@ -8896,7 +8896,8 @@ tsubst_copy_and_build (tree t,
|
|||
(TREE_OPERAND (function, 0),
|
||||
TREE_OPERAND (function, 1),
|
||||
call_args, NULL_TREE,
|
||||
qualified_p ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL));
|
||||
qualified_p ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL,
|
||||
/*fn_p=*/NULL));
|
||||
}
|
||||
return finish_call_expr (function, call_args,
|
||||
/*disallow_virtual=*/qualified_p,
|
||||
|
|
|
@ -1844,7 +1844,8 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p)
|
|||
|
||||
result = build_new_method_call (object, fn, args, NULL_TREE,
|
||||
(disallow_virtual
|
||||
? LOOKUP_NONVIRTUAL : 0));
|
||||
? LOOKUP_NONVIRTUAL : 0),
|
||||
/*fn_p=*/NULL);
|
||||
}
|
||||
else if (is_overloaded_fn (fn))
|
||||
{
|
||||
|
|
|
@ -377,7 +377,7 @@ cxx_incomplete_type_diagnostic (tree value, tree type, int diag_type)
|
|||
case UNION_TYPE:
|
||||
case ENUMERAL_TYPE:
|
||||
if (!decl)
|
||||
p_msg ("invalid use of undefined type %q#T", type);
|
||||
p_msg ("invalid use of incomplete type %q#T", type);
|
||||
if (!TYPE_TEMPLATE_INFO (type))
|
||||
p_msg ("forward declaration of %q+#T", type);
|
||||
else
|
||||
|
|
|
@ -1,3 +1,15 @@
|
|||
2006-04-11 Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
* g++.dg/parse/dtor7.C: New test.
|
||||
* g++.dg/parse/new1.C: Add error marker.
|
||||
* g++.dg/template/new3.C: New test.
|
||||
|
||||
PR c++/26122
|
||||
* g++.dg/template/pure1.C: New test.
|
||||
|
||||
PR c++/26295
|
||||
* g++.dg/parse/ptrmem4.C: New test.
|
||||
|
||||
2006-04-10 Jeff Law <law@redhat.com>
|
||||
|
||||
PR/27087
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// PR c++/25856
|
||||
|
||||
struct A; // { dg-error "forward" }
|
||||
A::~A() {} // { dg-error "undefined" }
|
||||
A::~A() {} // { dg-error "incomplete" }
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
struct T;
|
||||
struct T; // { dg-error "forward" }
|
||||
T* manage(T* t);
|
||||
template <class Obj> struct ObjectSlot0_ {
|
||||
void create() {
|
||||
void* tmp = manage(new T());
|
||||
void* tmp = manage(new T()); // { dg-error "incomplete" }
|
||||
}
|
||||
};
|
||||
|
|
4
gcc/testsuite/g++.dg/parse/ptrmem4.C
Normal file
4
gcc/testsuite/g++.dg/parse/ptrmem4.C
Normal file
|
@ -0,0 +1,4 @@
|
|||
// PR c++/26295
|
||||
|
||||
namespace A {}
|
||||
int (A::*B)(); // { dg-error "namespace" }
|
17
gcc/testsuite/g++.dg/template/new3.C
Normal file
17
gcc/testsuite/g++.dg/template/new3.C
Normal file
|
@ -0,0 +1,17 @@
|
|||
extern void *operator new(__SIZE_TYPE__); // { dg-error "candidate" }
|
||||
|
||||
template <class T >
|
||||
struct C
|
||||
{
|
||||
void f() {
|
||||
int* node;
|
||||
new (&node) int(0); // { dg-error "new" }
|
||||
}
|
||||
};
|
||||
|
||||
void* operator new(__SIZE_TYPE__, void* __p);
|
||||
|
||||
void g() {
|
||||
C<int> c;
|
||||
c.f();
|
||||
}
|
6
gcc/testsuite/g++.dg/template/pure1.C
Normal file
6
gcc/testsuite/g++.dg/template/pure1.C
Normal file
|
@ -0,0 +1,6 @@
|
|||
// PR c++/26122
|
||||
|
||||
struct A
|
||||
{
|
||||
template<int> void foo() = 1; // { dg-error "pure" }
|
||||
};
|
Loading…
Add table
Reference in a new issue