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)
*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);
}
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;
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
{
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
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;
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)
}
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)))
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),
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);
return build_call (global_delete_fndecl, build_tree_list (NULL_TREE, addr));
}
\f
-/* 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". */
/* 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. */
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
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;
}
}
- 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
}
}
+ 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
alloc_call = build_new_method_call (build_dummy_object (elt_type),
fns, args,
/*conversion_path=*/NULL_TREE,
- LOOKUP_NORMAL);
+ LOOKUP_NORMAL,
+ &alloc_fn);
}
else
{
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)
/* 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
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. */;
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;
+}
\f
static tree
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;
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.
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
{
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;
}
/* 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),
= (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,
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;
}
/* 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
/* 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;
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))
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. */