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
This commit is contained in:
parent
d24b23bb89
commit
e2537f2c03
8 changed files with 163 additions and 146 deletions
|
@ -1,5 +1,24 @@
|
|||
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
|
||||
* cp-tree.h (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);
|
|||
extern tree build_ptrmemfunc_type (tree);
|
||||
extern tree build_ptrmem_type (tree, tree);
|
||||
/* the grokdeclarator prototype is in decl.h */
|
||||
extern tree build_this_parm (tree, cp_cv_quals);
|
||||
extern int copy_fn_p (tree);
|
||||
extern tree get_scope_of_declarator (const cp_declarator *);
|
||||
extern void grok_special_member_properties (tree);
|
||||
|
@ -3899,12 +3900,11 @@ extern bool have_extern_spec;
|
|||
|
||||
/* in decl2.c */
|
||||
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_make_one_only (tree);
|
||||
extern void grokclassfn (tree, tree,
|
||||
enum overload_flags,
|
||||
cp_cv_quals);
|
||||
enum overload_flags);
|
||||
extern tree grok_array_decl (tree, tree);
|
||||
extern tree delete_sanity (tree, tree, bool, int);
|
||||
extern tree check_classfn (tree, tree, tree);
|
||||
|
@ -3934,6 +3934,7 @@ extern tree cxx_callgraph_analyze_expr (tree *, int *, tree);
|
|||
extern void mark_needed (tree);
|
||||
extern bool decl_needed_p (tree);
|
||||
extern void note_vague_linkage_fn (tree);
|
||||
extern tree build_artificial_parm (tree, tree);
|
||||
|
||||
/* in error.c */
|
||||
extern void init_error (void);
|
||||
|
@ -3966,7 +3967,7 @@ extern tree cplus_expand_constant (tree);
|
|||
extern int is_friend (tree, tree);
|
||||
extern void make_friend_class (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 */
|
||||
extern tree expand_member_init (tree);
|
||||
|
|
192
gcc/cp/decl.c
192
gcc/cp/decl.c
|
@ -5808,6 +5808,28 @@ check_class_member_definition_namespace (tree 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.
|
||||
TYPE is type this FUNCTION_DECL should have, either FUNCTION_TYPE
|
||||
or METHOD_TYPE.
|
||||
|
@ -5854,6 +5876,13 @@ grokfndecl (tree ctype,
|
|||
type = build_exception_variant (type, raises);
|
||||
|
||||
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;
|
||||
/* Propagate volatile out from type to decl. */
|
||||
if (TYPE_VOLATILE (type))
|
||||
|
@ -6057,7 +6086,7 @@ grokfndecl (tree ctype,
|
|||
if (sfk == sfk_constructor)
|
||||
DECL_CONSTRUCTOR_P (decl) = 1;
|
||||
|
||||
grokclassfn (ctype, decl, flags, quals);
|
||||
grokclassfn (ctype, decl, flags);
|
||||
}
|
||||
|
||||
decl = check_explicit_specialization (orig_declarator, decl,
|
||||
|
@ -6765,7 +6794,6 @@ grokdeclarator (const cp_declarator *declarator,
|
|||
{
|
||||
tree type = NULL_TREE;
|
||||
int longlong = 0;
|
||||
int type_quals;
|
||||
int virtualp, explicitp, friendp, inlinep, staticp;
|
||||
int explicit_int = 0;
|
||||
int explicit_char = 0;
|
||||
|
@ -6792,7 +6820,11 @@ grokdeclarator (const cp_declarator *declarator,
|
|||
tree dname = NULL_TREE;
|
||||
tree ctor_return_type = NULL_TREE;
|
||||
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;
|
||||
int template_count = 0;
|
||||
tree returned_attrs = NULL_TREE;
|
||||
|
@ -7451,7 +7483,7 @@ grokdeclarator (const cp_declarator *declarator,
|
|||
}
|
||||
|
||||
/* 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. */
|
||||
raises = declarator->u.function.exception_specification;
|
||||
|
@ -7473,53 +7505,44 @@ grokdeclarator (const cp_declarator *declarator,
|
|||
is the same as the class name, and we are defining
|
||||
a function, then it is a constructor/destructor, and
|
||||
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
|
||||
declared const or volatile. A destructor may
|
||||
not be static. */
|
||||
if (staticp == 2)
|
||||
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;
|
||||
}
|
||||
error ((flags == DTOR_FLAG)
|
||||
? "destructors may not be cv-qualified"
|
||||
: "constructors may not be cv-qualified");
|
||||
memfn_quals = TYPE_UNQUALIFIED;
|
||||
}
|
||||
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)
|
||||
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)
|
||||
{
|
||||
pedwarn ("constructors cannot be declared virtual");
|
||||
virtualp = 0;
|
||||
}
|
||||
if (quals)
|
||||
{
|
||||
error ("constructors 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;
|
||||
TYPE_HAS_CONSTRUCTOR (ctype) = 1;
|
||||
if (sfk != sfk_constructor)
|
||||
return NULL_TREE;
|
||||
|
@ -7560,7 +7583,6 @@ grokdeclarator (const cp_declarator *declarator,
|
|||
}
|
||||
|
||||
type = build_function_type (type, arg_types);
|
||||
type = cp_build_qualified_type (type, quals);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -7590,22 +7612,13 @@ grokdeclarator (const cp_declarator *declarator,
|
|||
type_quals = TYPE_UNQUALIFIED;
|
||||
|
||||
if (declarator->kind == cdk_ptrmem
|
||||
&& (TREE_CODE (type) == FUNCTION_TYPE
|
||||
|| (quals && TREE_CODE (type) == METHOD_TYPE)))
|
||||
&& (TREE_CODE (type) == FUNCTION_TYPE || memfn_quals))
|
||||
{
|
||||
tree dummy;
|
||||
|
||||
/* If the type is a FUNCTION_TYPE, pick up the
|
||||
qualifiers from that function type. No other
|
||||
qualifiers may be supplied. */
|
||||
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;
|
||||
memfn_quals |= cp_type_quals (type);
|
||||
type = build_memfn_type (type,
|
||||
declarator->u.pointer.class_type,
|
||||
memfn_quals);
|
||||
memfn_quals = TYPE_UNQUALIFIED;
|
||||
}
|
||||
|
||||
if (declarator->kind == cdk_reference)
|
||||
|
@ -7743,9 +7756,7 @@ grokdeclarator (const cp_declarator *declarator,
|
|||
are always static functions. */
|
||||
;
|
||||
else
|
||||
type = build_method_type_directly (ctype,
|
||||
TREE_TYPE (type),
|
||||
TYPE_ARG_TYPES (type));
|
||||
type = build_memfn_type (type, ctype, memfn_quals);
|
||||
}
|
||||
else if (declspecs->specs[(int)ds_typedef]
|
||||
&& current_class_type)
|
||||
|
@ -7837,6 +7848,18 @@ grokdeclarator (const cp_declarator *declarator,
|
|||
in typenames, fields or parameters. */
|
||||
if (current_lang_name == lang_name_java)
|
||||
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)
|
||||
decl = build_lang_decl (TYPE_DECL, unqualified_id, type);
|
||||
|
@ -7898,26 +7921,17 @@ grokdeclarator (const cp_declarator *declarator,
|
|||
type with external linkage have external linkage. */
|
||||
}
|
||||
|
||||
if (quals)
|
||||
{
|
||||
if (ctype == NULL_TREE)
|
||||
{
|
||||
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);
|
||||
}
|
||||
/* Any qualifiers on a function type typedef have already been
|
||||
dealt with. */
|
||||
if (memfn_quals && !ctype && TREE_CODE (type) == FUNCTION_TYPE)
|
||||
memfn_quals = TYPE_UNQUALIFIED;
|
||||
|
||||
if (signed_p
|
||||
|| (typedef_decl && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl)))
|
||||
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);
|
||||
|
||||
return decl;
|
||||
|
@ -7965,7 +7979,7 @@ grokdeclarator (const cp_declarator *declarator,
|
|||
|
||||
/* The qualifiers on the function type become the qualifiers on
|
||||
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,
|
|||
type = void_type_node;
|
||||
}
|
||||
}
|
||||
else if (quals)
|
||||
else if (memfn_quals)
|
||||
{
|
||||
if (ctype == NULL_TREE)
|
||||
{
|
||||
|
@ -8032,11 +8046,7 @@ grokdeclarator (const cp_declarator *declarator,
|
|||
ctype = TYPE_METHOD_BASETYPE (type);
|
||||
}
|
||||
if (ctype)
|
||||
{
|
||||
tree dummy = build_decl (TYPE_DECL, unqualified_id, type);
|
||||
grok_method_quals (ctype, dummy, quals);
|
||||
type = TREE_TYPE (dummy);
|
||||
}
|
||||
type = build_memfn_type (type, ctype, memfn_quals);
|
||||
}
|
||||
|
||||
return type;
|
||||
|
@ -8094,7 +8104,8 @@ grokdeclarator (const cp_declarator *declarator,
|
|||
{
|
||||
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);
|
||||
}
|
||||
else if (decl_context == FIELD)
|
||||
|
@ -8156,9 +8167,7 @@ grokdeclarator (const cp_declarator *declarator,
|
|||
}
|
||||
}
|
||||
else if (staticp < 2)
|
||||
type = build_method_type_directly (ctype,
|
||||
TREE_TYPE (type),
|
||||
TYPE_ARG_TYPES (type));
|
||||
type = build_memfn_type (type, ctype, memfn_quals);
|
||||
}
|
||||
|
||||
/* Check that the name used for a destructor makes sense. */
|
||||
|
@ -8193,7 +8202,7 @@ grokdeclarator (const cp_declarator *declarator,
|
|||
? unqualified_id : dname,
|
||||
parms,
|
||||
unqualified_id,
|
||||
virtualp, flags, quals, raises,
|
||||
virtualp, flags, memfn_quals, raises,
|
||||
friendp ? -1 : 0, friendp, publicp, inlinep,
|
||||
sfk,
|
||||
funcdef_flag, template_count, in_namespace, attrlist);
|
||||
|
@ -8241,7 +8250,7 @@ grokdeclarator (const cp_declarator *declarator,
|
|||
? unqualified_id : dname,
|
||||
parms,
|
||||
unqualified_id,
|
||||
virtualp, flags, quals, raises,
|
||||
virtualp, flags, memfn_quals, raises,
|
||||
friendp ? -1 : 0, friendp, 1, 0, sfk,
|
||||
funcdef_flag, template_count, in_namespace,
|
||||
attrlist);
|
||||
|
@ -8298,7 +8307,8 @@ grokdeclarator (const cp_declarator *declarator,
|
|||
}
|
||||
|
||||
decl = do_friend (ctype, unqualified_id, decl,
|
||||
*attrlist, flags, quals, funcdef_flag);
|
||||
*attrlist, flags,
|
||||
funcdef_flag);
|
||||
return decl;
|
||||
}
|
||||
else
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -8438,7 +8449,7 @@ grokdeclarator (const cp_declarator *declarator,
|
|||
|| storage_class != sc_static);
|
||||
|
||||
decl = grokfndecl (ctype, type, original_name, parms, unqualified_id,
|
||||
virtualp, flags, quals, raises,
|
||||
virtualp, flags, memfn_quals, raises,
|
||||
1, friendp,
|
||||
publicp, inlinep, sfk, funcdef_flag,
|
||||
template_count, in_namespace, attrlist);
|
||||
|
@ -8481,7 +8492,8 @@ grokdeclarator (const cp_declarator *declarator,
|
|||
initialized,
|
||||
(type_quals & TYPE_QUAL_CONST) != 0,
|
||||
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);
|
||||
|
||||
if (ctype)
|
||||
|
|
|
@ -103,33 +103,28 @@ tree static_ctors;
|
|||
tree static_dtors;
|
||||
|
||||
|
||||
/* Incorporate `const' and `volatile' qualifiers for member functions.
|
||||
FUNCTION is a TYPE_DECL or a FUNCTION_DECL.
|
||||
QUALS is a list of qualifiers. Returns any explicit
|
||||
top-level qualifiers of the method's this pointer, anything other than
|
||||
TYPE_UNQUALIFIED will be an extension. */
|
||||
|
||||
int
|
||||
grok_method_quals (tree ctype, tree function, cp_cv_quals quals)
|
||||
/* Return a member function type (a METHOD_TYPE), given FNTYPE (a
|
||||
FUNCTION_TYPE), CTYPE (class type), and QUALS (the cv-qualifiers
|
||||
that apply to the function). */
|
||||
|
||||
tree
|
||||
build_memfn_type (tree fntype, tree ctype, cp_cv_quals quals)
|
||||
{
|
||||
tree fntype = TREE_TYPE (function);
|
||||
tree raises = TYPE_RAISES_EXCEPTIONS (fntype);
|
||||
int type_quals = TYPE_UNQUALIFIED;
|
||||
int this_quals = TYPE_UNQUALIFIED;
|
||||
tree raises;
|
||||
int type_quals;
|
||||
|
||||
type_quals = quals & ~TYPE_QUAL_RESTRICT;
|
||||
this_quals = quals & TYPE_QUAL_RESTRICT;
|
||||
|
||||
ctype = cp_build_qualified_type (ctype, type_quals);
|
||||
fntype = build_method_type_directly (ctype, TREE_TYPE (fntype),
|
||||
(TREE_CODE (fntype) == METHOD_TYPE
|
||||
? TREE_CHAIN (TYPE_ARG_TYPES (fntype))
|
||||
: TYPE_ARG_TYPES (fntype)));
|
||||
raises = TYPE_RAISES_EXCEPTIONS (fntype);
|
||||
if (raises)
|
||||
fntype = build_exception_variant (fntype, raises);
|
||||
|
||||
TREE_TYPE (function) = fntype;
|
||||
return this_quals;
|
||||
return fntype;
|
||||
}
|
||||
|
||||
/* 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)
|
|||
/* Returns a PARM_DECL for a parameter of the indicated TYPE, with the
|
||||
indicated NAME. */
|
||||
|
||||
static tree
|
||||
tree
|
||||
build_artificial_parm (tree name, tree type)
|
||||
{
|
||||
tree parm = cp_build_parm_decl (name, type);
|
||||
|
@ -257,11 +252,9 @@ maybe_retrofit_in_chrg (tree fn)
|
|||
QUALS are the qualifiers for the this pointer. */
|
||||
|
||||
void
|
||||
grokclassfn (tree ctype, tree function, enum overload_flags flags,
|
||||
cp_cv_quals quals)
|
||||
grokclassfn (tree ctype, tree function, enum overload_flags flags)
|
||||
{
|
||||
tree fn_name = DECL_NAME (function);
|
||||
cp_cv_quals this_quals = TYPE_UNQUALIFIED;
|
||||
|
||||
/* Even within an `extern "C"' block, members get C++ linkage. See
|
||||
[dcl.link] for details. */
|
||||
|
@ -274,28 +267,6 @@ grokclassfn (tree ctype, tree function, enum overload_flags flags,
|
|||
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;
|
||||
|
||||
if (flags == DTOR_FLAG)
|
||||
|
|
|
@ -399,15 +399,11 @@ make_friend_class (tree type, tree friend_type, bool complain)
|
|||
|
||||
DECL is the FUNCTION_DECL that the friend is.
|
||||
|
||||
FLAGS is just used for `grokclassfn'.
|
||||
|
||||
QUALS say what special qualifies should apply to the object
|
||||
pointed to by `this'. */
|
||||
FLAGS is just used for `grokclassfn'. */
|
||||
|
||||
tree
|
||||
do_friend (tree ctype, tree declarator, tree decl,
|
||||
tree attrlist, enum overload_flags flags,
|
||||
cp_cv_quals quals,
|
||||
bool funcdef_flag)
|
||||
{
|
||||
/* Every decl that gets here is a friend of something. */
|
||||
|
@ -456,8 +452,7 @@ do_friend (tree ctype, tree declarator, tree decl,
|
|||
if (flags == NO_SPECIAL && declarator == cname)
|
||||
DECL_CONSTRUCTOR_P (decl) = 1;
|
||||
|
||||
/* This will set up DECL_ARGUMENTS for us. */
|
||||
grokclassfn (ctype, decl, flags, quals);
|
||||
grokclassfn (ctype, decl, flags);
|
||||
|
||||
if (friend_depth)
|
||||
{
|
||||
|
|
|
@ -978,6 +978,7 @@ implicitly_declare_fn (special_function_kind kind, tree type, bool const_p)
|
|||
tree fn_type;
|
||||
tree raises = empty_except_spec;
|
||||
tree rhs_parm_type = NULL_TREE;
|
||||
tree this_parm;
|
||||
tree name;
|
||||
HOST_WIDE_INT saved_processing_template_decl;
|
||||
|
||||
|
@ -1067,8 +1068,7 @@ implicitly_declare_fn (special_function_kind kind, tree type, bool const_p)
|
|||
DECL_ASSIGNMENT_OPERATOR_P (fn) = 1;
|
||||
SET_OVERLOADED_OPERATOR_CODE (fn, NOP_EXPR);
|
||||
}
|
||||
/* Create the argument list. The call to "grokclassfn" will add the
|
||||
"this" parameter and any other implicit parameters. */
|
||||
/* Create the explicit arguments. */
|
||||
if (rhs_parm_type)
|
||||
{
|
||||
/* 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)
|
|||
DECL_ARGUMENTS (fn) = cp_build_parm_decl (NULL_TREE, rhs_parm_type);
|
||||
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,
|
||||
TYPE_UNQUALIFIED);
|
||||
grokclassfn (type, fn, kind == sfk_destructor ? DTOR_FLAG : NO_SPECIAL);
|
||||
grok_special_member_properties (fn);
|
||||
set_linkage_according_to_type (type, fn);
|
||||
rest_of_decl_compilation (fn, toplevel_bindings_p (), at_eof);
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
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>
|
||||
|
||||
* g++.dg/opt/pr15551.C: Include cstdio.
|
||||
|
|
11
gcc/testsuite/g++.dg/template/friend41.C
Normal file
11
gcc/testsuite/g++.dg/template/friend41.C
Normal file
|
@ -0,0 +1,11 @@
|
|||
// PR c++/26912
|
||||
|
||||
struct Foo {
|
||||
template<class T> int func() const;
|
||||
};
|
||||
|
||||
class Bar {
|
||||
friend int Foo::func<int>() const;
|
||||
};
|
||||
|
||||
|
Loading…
Add table
Reference in a new issue