Commit e2537f2c by Mark Mitchell Committed by Mark Mitchell

re PR c++/26912 (friend const member function specialization fails to compile)

	PR c++/26912
	* cp-tree.h (build_this_parm): Declare.
	(grok_method_quals): Remove.
	(build_memfn_type): Declare.
	(build_artificial_parm): Declare.
	(do_friend): Remove quals parameter.
	* decl.c (build_this_parm): New function.
	(grokfndecl): Use it.  Do not pass quals to grokclassfn.
	(grokdeclarator): Rename quals to memfn_quals.  Avoid allocating
	unnecessary TYPE_DECLs.  Correct qualification of member function
	types.  Tidy.
	* method.c (implicitly_declare_fn): Use build_this_parm.
	* friend.c (do_friend): Remove quals parameter.
	* decl2.c (grok_method_quals): Remove.
	(build_memfn_type): New function.
	(build_artificial_parm): Give it external linkage.
	(grokclassfn): Remove quals parameter.  Do not build "this"
	PARM_DECL here.
	PR c++/26912
	* g++.dg/template/friend41.C: New test.

From-SVN: r113213
parent d24b23bb
2006-04-23 Mark Mitchell <mark@codesourcery.com> 2006-04-23 Mark Mitchell <mark@codesourcery.com>
PR c++/26912
* cp-tree.h (build_this_parm): Declare.
(grok_method_quals): Remove.
(build_memfn_type): Declare.
(build_artificial_parm): Declare.
(do_friend): Remove quals parameter.
* decl.c (build_this_parm): New function.
(grokfndecl): Use it. Do not pass quals to grokclassfn.
(grokdeclarator): Rename quals to memfn_quals. Avoid allocating
unnecessary TYPE_DECLs. Correct qualification of member function
types. Tidy.
* method.c (implicitly_declare_fn): Use build_this_parm.
* friend.c (do_friend): Remove quals parameter.
* decl2.c (grok_method_quals): Remove.
(build_memfn_type): New function.
(build_artificial_parm): Give it external linkage.
(grokclassfn): Remove quals parameter. Do not build "this"
PARM_DECL here.
PR c++/26534 PR c++/26534
* cp-tree.h (is_bitfield_expr_with_lowered_type): New function. * cp-tree.h (is_bitfield_expr_with_lowered_type): New function.
* typeck.c (is_bitfield_expr_with_lowered_type): New function. * typeck.c (is_bitfield_expr_with_lowered_type): New function.
......
...@@ -3842,6 +3842,7 @@ extern int cp_complete_array_type (tree *, tree, bool); ...@@ -3842,6 +3842,7 @@ extern int cp_complete_array_type (tree *, tree, bool);
extern tree build_ptrmemfunc_type (tree); extern tree build_ptrmemfunc_type (tree);
extern tree build_ptrmem_type (tree, tree); extern tree build_ptrmem_type (tree, tree);
/* the grokdeclarator prototype is in decl.h */ /* the grokdeclarator prototype is in decl.h */
extern tree build_this_parm (tree, cp_cv_quals);
extern int copy_fn_p (tree); extern int copy_fn_p (tree);
extern tree get_scope_of_declarator (const cp_declarator *); extern tree get_scope_of_declarator (const cp_declarator *);
extern void grok_special_member_properties (tree); extern void grok_special_member_properties (tree);
...@@ -3899,12 +3900,11 @@ extern bool have_extern_spec; ...@@ -3899,12 +3900,11 @@ extern bool have_extern_spec;
/* in decl2.c */ /* in decl2.c */
extern bool check_java_method (tree); extern bool check_java_method (tree);
extern cp_cv_quals grok_method_quals (tree, tree, cp_cv_quals); extern tree build_memfn_type (tree, tree, cp_cv_quals);
extern void maybe_retrofit_in_chrg (tree); extern void maybe_retrofit_in_chrg (tree);
extern void maybe_make_one_only (tree); extern void maybe_make_one_only (tree);
extern void grokclassfn (tree, tree, extern void grokclassfn (tree, tree,
enum overload_flags, enum overload_flags);
cp_cv_quals);
extern tree grok_array_decl (tree, tree); extern tree grok_array_decl (tree, tree);
extern tree delete_sanity (tree, tree, bool, int); extern tree delete_sanity (tree, tree, bool, int);
extern tree check_classfn (tree, tree, tree); extern tree check_classfn (tree, tree, tree);
...@@ -3934,6 +3934,7 @@ extern tree cxx_callgraph_analyze_expr (tree *, int *, tree); ...@@ -3934,6 +3934,7 @@ extern tree cxx_callgraph_analyze_expr (tree *, int *, tree);
extern void mark_needed (tree); extern void mark_needed (tree);
extern bool decl_needed_p (tree); extern bool decl_needed_p (tree);
extern void note_vague_linkage_fn (tree); extern void note_vague_linkage_fn (tree);
extern tree build_artificial_parm (tree, tree);
/* in error.c */ /* in error.c */
extern void init_error (void); extern void init_error (void);
...@@ -3966,7 +3967,7 @@ extern tree cplus_expand_constant (tree); ...@@ -3966,7 +3967,7 @@ extern tree cplus_expand_constant (tree);
extern int is_friend (tree, tree); extern int is_friend (tree, tree);
extern void make_friend_class (tree, tree, bool); extern void make_friend_class (tree, tree, bool);
extern void add_friend (tree, tree, bool); extern void add_friend (tree, tree, bool);
extern tree do_friend (tree, tree, tree, tree, enum overload_flags, cp_cv_quals, bool); extern tree do_friend (tree, tree, tree, tree, enum overload_flags, bool);
/* in init.c */ /* in init.c */
extern tree expand_member_init (tree); extern tree expand_member_init (tree);
......
...@@ -5808,6 +5808,28 @@ check_class_member_definition_namespace (tree decl) ...@@ -5808,6 +5808,28 @@ check_class_member_definition_namespace (tree decl)
decl, DECL_CONTEXT (decl)); decl, DECL_CONTEXT (decl));
} }
/* Build a PARM_DECL for the "this" parameter. TYPE is the
METHOD_TYPE for a non-static member function; QUALS are the
cv-qualifiers that apply to the function. */
tree
build_this_parm (tree type, cp_cv_quals quals)
{
tree this_type;
tree qual_type;
tree parm;
cp_cv_quals this_quals;
this_type = TREE_VALUE (TYPE_ARG_TYPES (type));
/* The `this' parameter is implicitly `const'; it cannot be
assigned to. */
this_quals = (quals & TYPE_QUAL_RESTRICT) | TYPE_QUAL_CONST;
qual_type = cp_build_qualified_type (this_type, this_quals);
parm = build_artificial_parm (this_identifier, qual_type);
cp_apply_type_quals_to_decl (this_quals, parm);
return parm;
}
/* CTYPE is class type, or null if non-class. /* CTYPE is class type, or null if non-class.
TYPE is type this FUNCTION_DECL should have, either FUNCTION_TYPE TYPE is type this FUNCTION_DECL should have, either FUNCTION_TYPE
or METHOD_TYPE. or METHOD_TYPE.
...@@ -5854,6 +5876,13 @@ grokfndecl (tree ctype, ...@@ -5854,6 +5876,13 @@ grokfndecl (tree ctype,
type = build_exception_variant (type, raises); type = build_exception_variant (type, raises);
decl = build_lang_decl (FUNCTION_DECL, declarator, type); decl = build_lang_decl (FUNCTION_DECL, declarator, type);
if (TREE_CODE (type) == METHOD_TYPE)
{
tree parm;
parm = build_this_parm (type, quals);
TREE_CHAIN (parm) = parms;
parms = parm;
}
DECL_ARGUMENTS (decl) = parms; DECL_ARGUMENTS (decl) = parms;
/* Propagate volatile out from type to decl. */ /* Propagate volatile out from type to decl. */
if (TYPE_VOLATILE (type)) if (TYPE_VOLATILE (type))
...@@ -6057,7 +6086,7 @@ grokfndecl (tree ctype, ...@@ -6057,7 +6086,7 @@ grokfndecl (tree ctype,
if (sfk == sfk_constructor) if (sfk == sfk_constructor)
DECL_CONSTRUCTOR_P (decl) = 1; DECL_CONSTRUCTOR_P (decl) = 1;
grokclassfn (ctype, decl, flags, quals); grokclassfn (ctype, decl, flags);
} }
decl = check_explicit_specialization (orig_declarator, decl, decl = check_explicit_specialization (orig_declarator, decl,
...@@ -6765,7 +6794,6 @@ grokdeclarator (const cp_declarator *declarator, ...@@ -6765,7 +6794,6 @@ grokdeclarator (const cp_declarator *declarator,
{ {
tree type = NULL_TREE; tree type = NULL_TREE;
int longlong = 0; int longlong = 0;
int type_quals;
int virtualp, explicitp, friendp, inlinep, staticp; int virtualp, explicitp, friendp, inlinep, staticp;
int explicit_int = 0; int explicit_int = 0;
int explicit_char = 0; int explicit_char = 0;
...@@ -6792,7 +6820,11 @@ grokdeclarator (const cp_declarator *declarator, ...@@ -6792,7 +6820,11 @@ grokdeclarator (const cp_declarator *declarator,
tree dname = NULL_TREE; tree dname = NULL_TREE;
tree ctor_return_type = NULL_TREE; tree ctor_return_type = NULL_TREE;
enum overload_flags flags = NO_SPECIAL; enum overload_flags flags = NO_SPECIAL;
cp_cv_quals quals = TYPE_UNQUALIFIED; /* cv-qualifiers that apply to the declarator, for a declaration of
a member function. */
cp_cv_quals memfn_quals = TYPE_UNQUALIFIED;
/* cv-qualifiers that apply to the type specified by the DECLSPECS. */
int type_quals;
tree raises = NULL_TREE; tree raises = NULL_TREE;
int template_count = 0; int template_count = 0;
tree returned_attrs = NULL_TREE; tree returned_attrs = NULL_TREE;
...@@ -7451,7 +7483,7 @@ grokdeclarator (const cp_declarator *declarator, ...@@ -7451,7 +7483,7 @@ grokdeclarator (const cp_declarator *declarator,
} }
/* Pick up type qualifiers which should be applied to `this'. */ /* Pick up type qualifiers which should be applied to `this'. */
quals = declarator->u.function.qualifiers; memfn_quals = declarator->u.function.qualifiers;
/* Pick up the exception specifications. */ /* Pick up the exception specifications. */
raises = declarator->u.function.exception_specification; raises = declarator->u.function.exception_specification;
...@@ -7473,53 +7505,44 @@ grokdeclarator (const cp_declarator *declarator, ...@@ -7473,53 +7505,44 @@ grokdeclarator (const cp_declarator *declarator,
is the same as the class name, and we are defining is the same as the class name, and we are defining
a function, then it is a constructor/destructor, and a function, then it is a constructor/destructor, and
therefore returns a void type. */ therefore returns a void type. */
if (flags == DTOR_FLAG) /* ISO C++ 12.4/2. A destructor may not be declared
const or volatile. A destructor may not be
static.
ISO C++ 12.1. A constructor may not be declared
const or volatile. A constructor may not be
virtual. A constructor may not be static. */
if (staticp == 2)
error ((flags == DTOR_FLAG)
? "destructor cannot be static member function"
: "constructor cannot be static member function");
if (memfn_quals)
{ {
/* ISO C++ 12.4/2. A destructor may not be error ((flags == DTOR_FLAG)
declared const or volatile. A destructor may ? "destructors may not be cv-qualified"
not be static. */ : "constructors may not be cv-qualified");
if (staticp == 2) memfn_quals = TYPE_UNQUALIFIED;
error ("destructor cannot be static member function");
if (quals)
{
error ("destructors may not be cv-qualified");
quals = TYPE_UNQUALIFIED;
}
if (decl_context == FIELD)
{
if (! member_function_or_else (ctype,
current_class_type,
flags))
return void_type_node;
}
} }
else /* It's a constructor. */
if (decl_context == FIELD
&& !member_function_or_else (ctype,
current_class_type,
flags))
return void_type_node;
if (flags != DTOR_FLAG)
{ {
/* It's a constructor. */
if (explicitp == 1) if (explicitp == 1)
explicitp = 2; explicitp = 2;
/* ISO C++ 12.1. A constructor may not be
declared const or volatile. A constructor may
not be virtual. A constructor may not be
static. */
if (staticp == 2)
error ("constructor cannot be static member function");
if (virtualp) if (virtualp)
{ {
pedwarn ("constructors cannot be declared virtual"); pedwarn ("constructors cannot be declared virtual");
virtualp = 0; virtualp = 0;
} }
if (quals)
{
error ("constructors may not be cv-qualified");
quals = TYPE_UNQUALIFIED;
}
if (decl_context == FIELD) if (decl_context == FIELD)
{ {
if (! member_function_or_else (ctype,
current_class_type,
flags))
return void_type_node;
TYPE_HAS_CONSTRUCTOR (ctype) = 1; TYPE_HAS_CONSTRUCTOR (ctype) = 1;
if (sfk != sfk_constructor) if (sfk != sfk_constructor)
return NULL_TREE; return NULL_TREE;
...@@ -7560,7 +7583,6 @@ grokdeclarator (const cp_declarator *declarator, ...@@ -7560,7 +7583,6 @@ grokdeclarator (const cp_declarator *declarator,
} }
type = build_function_type (type, arg_types); type = build_function_type (type, arg_types);
type = cp_build_qualified_type (type, quals);
} }
break; break;
...@@ -7590,22 +7612,13 @@ grokdeclarator (const cp_declarator *declarator, ...@@ -7590,22 +7612,13 @@ grokdeclarator (const cp_declarator *declarator,
type_quals = TYPE_UNQUALIFIED; type_quals = TYPE_UNQUALIFIED;
if (declarator->kind == cdk_ptrmem if (declarator->kind == cdk_ptrmem
&& (TREE_CODE (type) == FUNCTION_TYPE && (TREE_CODE (type) == FUNCTION_TYPE || memfn_quals))
|| (quals && TREE_CODE (type) == METHOD_TYPE)))
{ {
tree dummy; memfn_quals |= cp_type_quals (type);
type = build_memfn_type (type,
/* If the type is a FUNCTION_TYPE, pick up the declarator->u.pointer.class_type,
qualifiers from that function type. No other memfn_quals);
qualifiers may be supplied. */ memfn_quals = TYPE_UNQUALIFIED;
if (TREE_CODE (type) == FUNCTION_TYPE)
quals = cp_type_quals (type);
dummy = build_decl (TYPE_DECL, NULL_TREE, type);
grok_method_quals (declarator->u.pointer.class_type,
dummy, quals);
type = TREE_TYPE (dummy);
quals = TYPE_UNQUALIFIED;
} }
if (declarator->kind == cdk_reference) if (declarator->kind == cdk_reference)
...@@ -7743,9 +7756,7 @@ grokdeclarator (const cp_declarator *declarator, ...@@ -7743,9 +7756,7 @@ grokdeclarator (const cp_declarator *declarator,
are always static functions. */ are always static functions. */
; ;
else else
type = build_method_type_directly (ctype, type = build_memfn_type (type, ctype, memfn_quals);
TREE_TYPE (type),
TYPE_ARG_TYPES (type));
} }
else if (declspecs->specs[(int)ds_typedef] else if (declspecs->specs[(int)ds_typedef]
&& current_class_type) && current_class_type)
...@@ -7837,6 +7848,18 @@ grokdeclarator (const cp_declarator *declarator, ...@@ -7837,6 +7848,18 @@ grokdeclarator (const cp_declarator *declarator,
in typenames, fields or parameters. */ in typenames, fields or parameters. */
if (current_lang_name == lang_name_java) if (current_lang_name == lang_name_java)
TYPE_FOR_JAVA (type) = 1; TYPE_FOR_JAVA (type) = 1;
/* This declaration:
typedef void f(int) const;
declares a function type which is not a member of any
particular class, but which is cv-qualified; for
example "f S::*" declares a pointer to a const-qualified
member function of S. We record the cv-qualification in the
function type. */
if (memfn_quals && TREE_CODE (type) == FUNCTION_TYPE)
type = cp_build_qualified_type (type, memfn_quals);
if (decl_context == FIELD) if (decl_context == FIELD)
decl = build_lang_decl (TYPE_DECL, unqualified_id, type); decl = build_lang_decl (TYPE_DECL, unqualified_id, type);
...@@ -7898,26 +7921,17 @@ grokdeclarator (const cp_declarator *declarator, ...@@ -7898,26 +7921,17 @@ grokdeclarator (const cp_declarator *declarator,
type with external linkage have external linkage. */ type with external linkage have external linkage. */
} }
if (quals) /* Any qualifiers on a function type typedef have already been
{ dealt with. */
if (ctype == NULL_TREE) if (memfn_quals && !ctype && TREE_CODE (type) == FUNCTION_TYPE)
{ memfn_quals = TYPE_UNQUALIFIED;
if (TREE_CODE (type) == METHOD_TYPE)
ctype = TYPE_METHOD_BASETYPE (type);
/* Any qualifiers on a function type typedef have
already been dealt with. */
else if (TREE_CODE (type) == FUNCTION_TYPE)
quals = TYPE_UNQUALIFIED;
}
if (ctype != NULL_TREE)
grok_method_quals (ctype, decl, quals);
}
if (signed_p if (signed_p
|| (typedef_decl && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl))) || (typedef_decl && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl)))
C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1; C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1;
bad_specifiers (decl, "type", virtualp, quals != TYPE_UNQUALIFIED, bad_specifiers (decl, "type", virtualp,
memfn_quals != TYPE_UNQUALIFIED,
inlinep, friendp, raises != NULL_TREE); inlinep, friendp, raises != NULL_TREE);
return decl; return decl;
...@@ -7965,7 +7979,7 @@ grokdeclarator (const cp_declarator *declarator, ...@@ -7965,7 +7979,7 @@ grokdeclarator (const cp_declarator *declarator,
/* The qualifiers on the function type become the qualifiers on /* The qualifiers on the function type become the qualifiers on
the non-static member function. */ the non-static member function. */
quals |= cp_type_quals (type); memfn_quals |= cp_type_quals (type);
} }
} }
...@@ -8022,7 +8036,7 @@ grokdeclarator (const cp_declarator *declarator, ...@@ -8022,7 +8036,7 @@ grokdeclarator (const cp_declarator *declarator,
type = void_type_node; type = void_type_node;
} }
} }
else if (quals) else if (memfn_quals)
{ {
if (ctype == NULL_TREE) if (ctype == NULL_TREE)
{ {
...@@ -8032,11 +8046,7 @@ grokdeclarator (const cp_declarator *declarator, ...@@ -8032,11 +8046,7 @@ grokdeclarator (const cp_declarator *declarator,
ctype = TYPE_METHOD_BASETYPE (type); ctype = TYPE_METHOD_BASETYPE (type);
} }
if (ctype) if (ctype)
{ type = build_memfn_type (type, ctype, memfn_quals);
tree dummy = build_decl (TYPE_DECL, unqualified_id, type);
grok_method_quals (ctype, dummy, quals);
type = TREE_TYPE (dummy);
}
} }
return type; return type;
...@@ -8094,7 +8104,8 @@ grokdeclarator (const cp_declarator *declarator, ...@@ -8094,7 +8104,8 @@ grokdeclarator (const cp_declarator *declarator,
{ {
decl = cp_build_parm_decl (unqualified_id, type); decl = cp_build_parm_decl (unqualified_id, type);
bad_specifiers (decl, "parameter", virtualp, quals != TYPE_UNQUALIFIED, bad_specifiers (decl, "parameter", virtualp,
memfn_quals != TYPE_UNQUALIFIED,
inlinep, friendp, raises != NULL_TREE); inlinep, friendp, raises != NULL_TREE);
} }
else if (decl_context == FIELD) else if (decl_context == FIELD)
...@@ -8156,9 +8167,7 @@ grokdeclarator (const cp_declarator *declarator, ...@@ -8156,9 +8167,7 @@ grokdeclarator (const cp_declarator *declarator,
} }
} }
else if (staticp < 2) else if (staticp < 2)
type = build_method_type_directly (ctype, type = build_memfn_type (type, ctype, memfn_quals);
TREE_TYPE (type),
TYPE_ARG_TYPES (type));
} }
/* Check that the name used for a destructor makes sense. */ /* Check that the name used for a destructor makes sense. */
...@@ -8193,7 +8202,7 @@ grokdeclarator (const cp_declarator *declarator, ...@@ -8193,7 +8202,7 @@ grokdeclarator (const cp_declarator *declarator,
? unqualified_id : dname, ? unqualified_id : dname,
parms, parms,
unqualified_id, unqualified_id,
virtualp, flags, quals, raises, virtualp, flags, memfn_quals, raises,
friendp ? -1 : 0, friendp, publicp, inlinep, friendp ? -1 : 0, friendp, publicp, inlinep,
sfk, sfk,
funcdef_flag, template_count, in_namespace, attrlist); funcdef_flag, template_count, in_namespace, attrlist);
...@@ -8241,7 +8250,7 @@ grokdeclarator (const cp_declarator *declarator, ...@@ -8241,7 +8250,7 @@ grokdeclarator (const cp_declarator *declarator,
? unqualified_id : dname, ? unqualified_id : dname,
parms, parms,
unqualified_id, unqualified_id,
virtualp, flags, quals, raises, virtualp, flags, memfn_quals, raises,
friendp ? -1 : 0, friendp, 1, 0, sfk, friendp ? -1 : 0, friendp, 1, 0, sfk,
funcdef_flag, template_count, in_namespace, funcdef_flag, template_count, in_namespace,
attrlist); attrlist);
...@@ -8298,7 +8307,8 @@ grokdeclarator (const cp_declarator *declarator, ...@@ -8298,7 +8307,8 @@ grokdeclarator (const cp_declarator *declarator,
} }
decl = do_friend (ctype, unqualified_id, decl, decl = do_friend (ctype, unqualified_id, decl,
*attrlist, flags, quals, funcdef_flag); *attrlist, flags,
funcdef_flag);
return decl; return decl;
} }
else else
...@@ -8377,7 +8387,8 @@ grokdeclarator (const cp_declarator *declarator, ...@@ -8377,7 +8387,8 @@ grokdeclarator (const cp_declarator *declarator,
} }
} }
bad_specifiers (decl, "field", virtualp, quals != TYPE_UNQUALIFIED, bad_specifiers (decl, "field", virtualp,
memfn_quals != TYPE_UNQUALIFIED,
inlinep, friendp, raises != NULL_TREE); inlinep, friendp, raises != NULL_TREE);
} }
} }
...@@ -8438,7 +8449,7 @@ grokdeclarator (const cp_declarator *declarator, ...@@ -8438,7 +8449,7 @@ grokdeclarator (const cp_declarator *declarator,
|| storage_class != sc_static); || storage_class != sc_static);
decl = grokfndecl (ctype, type, original_name, parms, unqualified_id, decl = grokfndecl (ctype, type, original_name, parms, unqualified_id,
virtualp, flags, quals, raises, virtualp, flags, memfn_quals, raises,
1, friendp, 1, friendp,
publicp, inlinep, sfk, funcdef_flag, publicp, inlinep, sfk, funcdef_flag,
template_count, in_namespace, attrlist); template_count, in_namespace, attrlist);
...@@ -8481,7 +8492,8 @@ grokdeclarator (const cp_declarator *declarator, ...@@ -8481,7 +8492,8 @@ grokdeclarator (const cp_declarator *declarator,
initialized, initialized,
(type_quals & TYPE_QUAL_CONST) != 0, (type_quals & TYPE_QUAL_CONST) != 0,
ctype ? ctype : in_namespace); ctype ? ctype : in_namespace);
bad_specifiers (decl, "variable", virtualp, quals != TYPE_UNQUALIFIED, bad_specifiers (decl, "variable", virtualp,
memfn_quals != TYPE_UNQUALIFIED,
inlinep, friendp, raises != NULL_TREE); inlinep, friendp, raises != NULL_TREE);
if (ctype) if (ctype)
......
...@@ -103,33 +103,28 @@ tree static_ctors; ...@@ -103,33 +103,28 @@ tree static_ctors;
tree static_dtors; tree static_dtors;
/* Incorporate `const' and `volatile' qualifiers for member functions.
FUNCTION is a TYPE_DECL or a FUNCTION_DECL. /* Return a member function type (a METHOD_TYPE), given FNTYPE (a
QUALS is a list of qualifiers. Returns any explicit FUNCTION_TYPE), CTYPE (class type), and QUALS (the cv-qualifiers
top-level qualifiers of the method's this pointer, anything other than that apply to the function). */
TYPE_UNQUALIFIED will be an extension. */
tree
int build_memfn_type (tree fntype, tree ctype, cp_cv_quals quals)
grok_method_quals (tree ctype, tree function, cp_cv_quals quals)
{ {
tree fntype = TREE_TYPE (function); tree raises;
tree raises = TYPE_RAISES_EXCEPTIONS (fntype); int type_quals;
int type_quals = TYPE_UNQUALIFIED;
int this_quals = TYPE_UNQUALIFIED;
type_quals = quals & ~TYPE_QUAL_RESTRICT; type_quals = quals & ~TYPE_QUAL_RESTRICT;
this_quals = quals & TYPE_QUAL_RESTRICT;
ctype = cp_build_qualified_type (ctype, type_quals); ctype = cp_build_qualified_type (ctype, type_quals);
fntype = build_method_type_directly (ctype, TREE_TYPE (fntype), fntype = build_method_type_directly (ctype, TREE_TYPE (fntype),
(TREE_CODE (fntype) == METHOD_TYPE (TREE_CODE (fntype) == METHOD_TYPE
? TREE_CHAIN (TYPE_ARG_TYPES (fntype)) ? TREE_CHAIN (TYPE_ARG_TYPES (fntype))
: TYPE_ARG_TYPES (fntype))); : TYPE_ARG_TYPES (fntype)));
raises = TYPE_RAISES_EXCEPTIONS (fntype);
if (raises) if (raises)
fntype = build_exception_variant (fntype, raises); fntype = build_exception_variant (fntype, raises);
TREE_TYPE (function) = fntype; return fntype;
return this_quals;
} }
/* Build a PARM_DECL with NAME and TYPE, and set DECL_ARG_TYPE /* Build a PARM_DECL with NAME and TYPE, and set DECL_ARG_TYPE
...@@ -149,7 +144,7 @@ cp_build_parm_decl (tree name, tree type) ...@@ -149,7 +144,7 @@ cp_build_parm_decl (tree name, tree type)
/* Returns a PARM_DECL for a parameter of the indicated TYPE, with the /* Returns a PARM_DECL for a parameter of the indicated TYPE, with the
indicated NAME. */ indicated NAME. */
static tree tree
build_artificial_parm (tree name, tree type) build_artificial_parm (tree name, tree type)
{ {
tree parm = cp_build_parm_decl (name, type); tree parm = cp_build_parm_decl (name, type);
...@@ -257,11 +252,9 @@ maybe_retrofit_in_chrg (tree fn) ...@@ -257,11 +252,9 @@ maybe_retrofit_in_chrg (tree fn)
QUALS are the qualifiers for the this pointer. */ QUALS are the qualifiers for the this pointer. */
void void
grokclassfn (tree ctype, tree function, enum overload_flags flags, grokclassfn (tree ctype, tree function, enum overload_flags flags)
cp_cv_quals quals)
{ {
tree fn_name = DECL_NAME (function); tree fn_name = DECL_NAME (function);
cp_cv_quals this_quals = TYPE_UNQUALIFIED;
/* Even within an `extern "C"' block, members get C++ linkage. See /* Even within an `extern "C"' block, members get C++ linkage. See
[dcl.link] for details. */ [dcl.link] for details. */
...@@ -274,28 +267,6 @@ grokclassfn (tree ctype, tree function, enum overload_flags flags, ...@@ -274,28 +267,6 @@ grokclassfn (tree ctype, tree function, enum overload_flags flags,
DECL_NAME (function) = fn_name; DECL_NAME (function) = fn_name;
} }
if (quals)
this_quals = grok_method_quals (ctype, function, quals);
if (TREE_CODE (TREE_TYPE (function)) == METHOD_TYPE)
{
/* Must add the class instance variable up front. */
/* Right now we just make this a pointer. But later
we may wish to make it special. */
tree type = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (function)));
tree qual_type;
tree parm;
/* The `this' parameter is implicitly `const'; it cannot be
assigned to. */
this_quals |= TYPE_QUAL_CONST;
qual_type = cp_build_qualified_type (type, this_quals);
parm = build_artificial_parm (this_identifier, qual_type);
cp_apply_type_quals_to_decl (this_quals, parm);
TREE_CHAIN (parm) = DECL_ARGUMENTS (function);
DECL_ARGUMENTS (function) = parm;
}
DECL_CONTEXT (function) = ctype; DECL_CONTEXT (function) = ctype;
if (flags == DTOR_FLAG) if (flags == DTOR_FLAG)
......
...@@ -399,15 +399,11 @@ make_friend_class (tree type, tree friend_type, bool complain) ...@@ -399,15 +399,11 @@ make_friend_class (tree type, tree friend_type, bool complain)
DECL is the FUNCTION_DECL that the friend is. DECL is the FUNCTION_DECL that the friend is.
FLAGS is just used for `grokclassfn'. FLAGS is just used for `grokclassfn'. */
QUALS say what special qualifies should apply to the object
pointed to by `this'. */
tree tree
do_friend (tree ctype, tree declarator, tree decl, do_friend (tree ctype, tree declarator, tree decl,
tree attrlist, enum overload_flags flags, tree attrlist, enum overload_flags flags,
cp_cv_quals quals,
bool funcdef_flag) bool funcdef_flag)
{ {
/* Every decl that gets here is a friend of something. */ /* Every decl that gets here is a friend of something. */
...@@ -456,8 +452,7 @@ do_friend (tree ctype, tree declarator, tree decl, ...@@ -456,8 +452,7 @@ do_friend (tree ctype, tree declarator, tree decl,
if (flags == NO_SPECIAL && declarator == cname) if (flags == NO_SPECIAL && declarator == cname)
DECL_CONSTRUCTOR_P (decl) = 1; DECL_CONSTRUCTOR_P (decl) = 1;
/* This will set up DECL_ARGUMENTS for us. */ grokclassfn (ctype, decl, flags);
grokclassfn (ctype, decl, flags, quals);
if (friend_depth) if (friend_depth)
{ {
......
...@@ -978,6 +978,7 @@ implicitly_declare_fn (special_function_kind kind, tree type, bool const_p) ...@@ -978,6 +978,7 @@ implicitly_declare_fn (special_function_kind kind, tree type, bool const_p)
tree fn_type; tree fn_type;
tree raises = empty_except_spec; tree raises = empty_except_spec;
tree rhs_parm_type = NULL_TREE; tree rhs_parm_type = NULL_TREE;
tree this_parm;
tree name; tree name;
HOST_WIDE_INT saved_processing_template_decl; HOST_WIDE_INT saved_processing_template_decl;
...@@ -1067,8 +1068,7 @@ implicitly_declare_fn (special_function_kind kind, tree type, bool const_p) ...@@ -1067,8 +1068,7 @@ implicitly_declare_fn (special_function_kind kind, tree type, bool const_p)
DECL_ASSIGNMENT_OPERATOR_P (fn) = 1; DECL_ASSIGNMENT_OPERATOR_P (fn) = 1;
SET_OVERLOADED_OPERATOR_CODE (fn, NOP_EXPR); SET_OVERLOADED_OPERATOR_CODE (fn, NOP_EXPR);
} }
/* Create the argument list. The call to "grokclassfn" will add the /* Create the explicit arguments. */
"this" parameter and any other implicit parameters. */
if (rhs_parm_type) if (rhs_parm_type)
{ {
/* Note that this parameter is *not* marked DECL_ARTIFICIAL; we /* Note that this parameter is *not* marked DECL_ARTIFICIAL; we
...@@ -1077,9 +1077,12 @@ implicitly_declare_fn (special_function_kind kind, tree type, bool const_p) ...@@ -1077,9 +1077,12 @@ implicitly_declare_fn (special_function_kind kind, tree type, bool const_p)
DECL_ARGUMENTS (fn) = cp_build_parm_decl (NULL_TREE, rhs_parm_type); DECL_ARGUMENTS (fn) = cp_build_parm_decl (NULL_TREE, rhs_parm_type);
TREE_READONLY (DECL_ARGUMENTS (fn)) = 1; TREE_READONLY (DECL_ARGUMENTS (fn)) = 1;
} }
/* Add the "this" parameter. */
this_parm = build_this_parm (fn_type, TYPE_UNQUALIFIED);
TREE_CHAIN (this_parm) = DECL_ARGUMENTS (fn);
DECL_ARGUMENTS (fn) = this_parm;
grokclassfn (type, fn, kind == sfk_destructor ? DTOR_FLAG : NO_SPECIAL, grokclassfn (type, fn, kind == sfk_destructor ? DTOR_FLAG : NO_SPECIAL);
TYPE_UNQUALIFIED);
grok_special_member_properties (fn); grok_special_member_properties (fn);
set_linkage_according_to_type (type, fn); set_linkage_according_to_type (type, fn);
rest_of_decl_compilation (fn, toplevel_bindings_p (), at_eof); rest_of_decl_compilation (fn, toplevel_bindings_p (), at_eof);
......
2006-04-23 Mark Mitchell <mark@codesourcery.com>
PR c++/26912
* g++.dg/template/friend41.C: New test.
2006-04-23 David Edelsohn <edelsohn@gnu.org> 2006-04-23 David Edelsohn <edelsohn@gnu.org>
* g++.dg/opt/pr15551.C: Include cstdio. * g++.dg/opt/pr15551.C: Include cstdio.
// PR c++/26912
struct Foo {
template<class T> int func() const;
};
class Bar {
friend int Foo::func<int>() const;
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment