diff options
author | Mark Mitchell <mark@codesourcery.com> | 2006-04-11 22:59:57 +0000 |
---|---|---|
committer | Mark Mitchell <mmitchel@gcc.gnu.org> | 2006-04-11 22:59:57 +0000 |
commit | 63c9a19053b37dac6129f6d3f9e8ac1e3d930798 (patch) | |
tree | 576c6a06a32b6a01b24c797b6728e740da468621 /gcc | |
parent | ba9d67765afcde479d0e77b43e08ae1d54c6144a (diff) | |
download | gcc-63c9a19053b37dac6129f6d3f9e8ac1e3d930798.zip gcc-63c9a19053b37dac6129f6d3f9e8ac1e3d930798.tar.gz gcc-63c9a19053b37dac6129f6d3f9e8ac1e3d930798.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 35 | ||||
-rw-r--r-- | gcc/cp/call.c | 64 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 8 | ||||
-rw-r--r-- | gcc/cp/decl.c | 20 | ||||
-rw-r--r-- | gcc/cp/init.c | 333 | ||||
-rw-r--r-- | gcc/cp/parser.c | 73 | ||||
-rw-r--r-- | gcc/cp/pt.c | 3 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 3 | ||||
-rw-r--r-- | gcc/cp/typeck2.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 12 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/parse/dtor7.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/parse/new1.C | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/parse/ptrmem4.C | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/new3.C | 17 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/pure1.C | 6 |
15 files changed, 370 insertions, 216 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index ea00b4b..a292155 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -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. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 0413a98..b79d03b 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -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), diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 4b15573..b488be6 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -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); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 45feb9f..3d8c2f8 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -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, diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 194b29b..0439e92 100644 --- a/gcc/cp/init.c +++ b/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; -} +/* 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. */ -/* Given a Java class, return a decl for the corresponding java.lang.Class. */ - -tree -build_java_class_ref (tree type) +static tree +build_raw_new_expr (tree placement, tree type, tree nelts, tree init, + int use_global_new) { - 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; + 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; } - -/* Called from cplus_expand_expr when expanding a NEW_EXPR. The return - value is immediately handed to expand_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 exp) +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), diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index c5e6b17..4c06784 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -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. */ diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index adabe76..b0650bf 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -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, diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 114f3d2..23ab2d8 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -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)) { diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index 49c58f8..8227a54 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -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 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f71c86b..565b64e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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 diff --git a/gcc/testsuite/g++.dg/parse/dtor7.C b/gcc/testsuite/g++.dg/parse/dtor7.C index 3525624..a809512 100644 --- a/gcc/testsuite/g++.dg/parse/dtor7.C +++ b/gcc/testsuite/g++.dg/parse/dtor7.C @@ -1,4 +1,4 @@ // PR c++/25856 struct A; // { dg-error "forward" } -A::~A() {} // { dg-error "undefined" } +A::~A() {} // { dg-error "incomplete" } diff --git a/gcc/testsuite/g++.dg/parse/new1.C b/gcc/testsuite/g++.dg/parse/new1.C index 31dad77..d61c446 100644 --- a/gcc/testsuite/g++.dg/parse/new1.C +++ b/gcc/testsuite/g++.dg/parse/new1.C @@ -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" } } }; diff --git a/gcc/testsuite/g++.dg/parse/ptrmem4.C b/gcc/testsuite/g++.dg/parse/ptrmem4.C new file mode 100644 index 0000000..fea08f2 --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/ptrmem4.C @@ -0,0 +1,4 @@ +// PR c++/26295 + +namespace A {} +int (A::*B)(); // { dg-error "namespace" } diff --git a/gcc/testsuite/g++.dg/template/new3.C b/gcc/testsuite/g++.dg/template/new3.C new file mode 100644 index 0000000..c6c1089 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/new3.C @@ -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(); +} diff --git a/gcc/testsuite/g++.dg/template/pure1.C b/gcc/testsuite/g++.dg/template/pure1.C new file mode 100644 index 0000000..ca9b94e --- /dev/null +++ b/gcc/testsuite/g++.dg/template/pure1.C @@ -0,0 +1,6 @@ +// PR c++/26122 + +struct A +{ + template<int> void foo() = 1; // { dg-error "pure" } +}; |