call.c (build_op_delete_call): Do not forget the placement arguments when iterating through mutiple delete...
* call.c (build_op_delete_call): Do not forget the placement arguments when iterating through mutiple delete operators. * cp-tree.h (svaed_scope): Remove last_parms. (NEW_DELETE_OPNAME_P): New macro. (last_function_parms): Remove. (do_friend): Adjust prototype. * decl.c (grokparms): Return the PARM_DECLs directly, rather than using last_function_parms. (grokfndecl): Take the PARM_DECLs as an argument, rather than using last_function_parms. (grokdeclarator): Adjust accordingly. Do not form METHOD_TYPEs for class-specific operator new and operator delete. (grok_op_properties): Do not look for allocation functions with METHOD_TYPEs. (start_function): Use DECL_ARGUMENTS instead of last_function_parms. * decl.h (last_function_parms): Do not declare. * decl2.c (grokclassfn): Do not use last_function_parms. * friend.c (do_friend): Remove parmdecls parameter. * name-lookup.c (push_to_top_level): Do not save last_function_parms. (pop_from_top_level): Do not restore it. * pt.c (check_explicit_specialization): Do not adjust last_function_parms. * name-lookup.c (do_local_using_decl): Create a local binding for types brought in via using declarations. * name-lookup.c (lookup_arg_dependent): Handle block-scope function declarations correctly. * semantics.c (finish_id_expression): Correct handling of conversion operators to dependent types. * typeck.c (lookup_destructor): Allow the use of destructors from base classes. * g++.dg/init/placement3.C: New test. * g++.dg/template/spec13.C: New test. * g++.dg/lookup/using11.C: New test. * g++.dg/lookup/koenig3.C: New test. * g++.dg/template/operator2.C: New test. * g++.dg/expr/dtor3.C: New test. * g++.old-deja/g++.brendan/crash15.C: Remove incorrect dg-error marker. * g++.old-deja/g++.law/visibility28.C: Likewise. From-SVN: r79722
This commit is contained in:
parent
b40bc279e7
commit
4546865e5b
20 changed files with 222 additions and 88 deletions
|
@ -1,3 +1,42 @@
|
|||
2004-03-19 Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
* call.c (build_op_delete_call): Do not forget the placement
|
||||
arguments when iterating through mutiple delete operators.
|
||||
|
||||
* cp-tree.h (svaed_scope): Remove last_parms.
|
||||
(NEW_DELETE_OPNAME_P): New macro.
|
||||
(last_function_parms): Remove.
|
||||
(do_friend): Adjust prototype.
|
||||
* decl.c (grokparms): Return the PARM_DECLs directly, rather than
|
||||
using last_function_parms.
|
||||
(grokfndecl): Take the PARM_DECLs as an argument, rather than
|
||||
using last_function_parms.
|
||||
(grokdeclarator): Adjust accordingly. Do not form METHOD_TYPEs
|
||||
for class-specific operator new and operator delete.
|
||||
(grok_op_properties): Do not look for allocation functions with
|
||||
METHOD_TYPEs.
|
||||
(start_function): Use DECL_ARGUMENTS instead of
|
||||
last_function_parms.
|
||||
* decl.h (last_function_parms): Do not declare.
|
||||
* decl2.c (grokclassfn): Do not use last_function_parms.
|
||||
* friend.c (do_friend): Remove parmdecls parameter.
|
||||
* name-lookup.c (push_to_top_level): Do not save last_function_parms.
|
||||
(pop_from_top_level): Do not restore it.
|
||||
* pt.c (check_explicit_specialization): Do not adjust
|
||||
last_function_parms.
|
||||
|
||||
* name-lookup.c (do_local_using_decl): Create a local binding for
|
||||
types brought in via using declarations.
|
||||
|
||||
* name-lookup.c (lookup_arg_dependent): Handle block-scope
|
||||
function declarations correctly.
|
||||
|
||||
* semantics.c (finish_id_expression): Correct handling of
|
||||
conversion operators to dependent types.
|
||||
|
||||
* typeck.c (lookup_destructor): Allow the use of destructors from
|
||||
base classes.
|
||||
|
||||
2004-03-19 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
|
||||
|
||||
* cxx-pretty-print.c (pp_cxx_unqualified_id): Use
|
||||
|
|
|
@ -3979,15 +3979,15 @@ build_op_delete_call (enum tree_code code, tree addr, tree size,
|
|||
/* On the first pass, check the rest of the arguments. */
|
||||
if (pass == 0)
|
||||
{
|
||||
while (argtypes && t)
|
||||
tree a = argtypes;
|
||||
while (a && t)
|
||||
{
|
||||
if (!same_type_p (TREE_VALUE (argtypes),
|
||||
TREE_VALUE (t)))
|
||||
if (!same_type_p (TREE_VALUE (a), TREE_VALUE (t)))
|
||||
break;
|
||||
argtypes = TREE_CHAIN (argtypes);
|
||||
a = TREE_CHAIN (a);
|
||||
t = TREE_CHAIN (t);
|
||||
}
|
||||
if (!argtypes && !t)
|
||||
if (!a && !t)
|
||||
break;
|
||||
}
|
||||
/* On the second pass, the second argument must be
|
||||
|
|
|
@ -679,7 +679,6 @@ struct saved_scope GTY(())
|
|||
tree x_previous_class_type;
|
||||
tree x_previous_class_values;
|
||||
tree x_saved_tree;
|
||||
tree last_parms;
|
||||
|
||||
HOST_WIDE_INT x_processing_template_decl;
|
||||
int x_processing_specialization;
|
||||
|
@ -837,6 +836,14 @@ struct language_function GTY(())
|
|||
#define current_function_return_value \
|
||||
(cp_function_chain->x_return_value)
|
||||
|
||||
/* True if NAME is the IDENTIFIER_NODE for an overloaded "operator
|
||||
new" or "operator delete". */
|
||||
#define NEW_DELETE_OPNAME_P(NAME) \
|
||||
((NAME) == ansi_opname (NEW_EXPR) \
|
||||
|| (NAME) == ansi_opname (VEC_NEW_EXPR) \
|
||||
|| (NAME) == ansi_opname (DELETE_EXPR) \
|
||||
|| (NAME) == ansi_opname (VEC_DELETE_EXPR))
|
||||
|
||||
#define ansi_opname(CODE) \
|
||||
(operator_name_info[(int) (CODE)].identifier)
|
||||
#define ansi_assopname(CODE) \
|
||||
|
@ -3693,7 +3700,6 @@ extern tree check_elaborated_type_specifier (enum tag_types, tree, bool);
|
|||
extern void warn_extern_redeclared_static (tree, tree);
|
||||
|
||||
extern bool have_extern_spec;
|
||||
extern GTY(()) tree last_function_parms;
|
||||
|
||||
/* in decl2.c */
|
||||
extern bool check_java_method (tree);
|
||||
|
@ -3774,7 +3780,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, tree, enum overload_flags, tree, int);
|
||||
extern tree do_friend (tree, tree, tree, tree, enum overload_flags, tree, int);
|
||||
|
||||
/* in init.c */
|
||||
extern tree expand_member_init (tree);
|
||||
|
|
|
@ -52,7 +52,7 @@ Boston, MA 02111-1307, USA. */
|
|||
#include "debug.h"
|
||||
#include "timevar.h"
|
||||
|
||||
static tree grokparms (tree);
|
||||
static tree grokparms (tree, tree *);
|
||||
static const char *redeclaration_error_message (tree, tree);
|
||||
|
||||
static int decl_jump_unsafe (tree);
|
||||
|
@ -61,7 +61,7 @@ static int ambi_op_p (enum tree_code);
|
|||
static int unary_op_p (enum tree_code);
|
||||
static void push_local_name (tree);
|
||||
static tree grok_reference_init (tree, tree, tree, tree *);
|
||||
static tree grokfndecl (tree, tree, tree, tree, int,
|
||||
static tree grokfndecl (tree, tree, tree, tree, tree, int,
|
||||
enum overload_flags, tree,
|
||||
tree, int, int, int, int, int, int, tree);
|
||||
static tree grokvardecl (tree, tree, RID_BIT_TYPE *, int, int, tree);
|
||||
|
@ -207,9 +207,6 @@ tree static_aggregates;
|
|||
|
||||
tree integer_two_node, integer_three_node;
|
||||
|
||||
/* Similar, for last_function_parm_tags. */
|
||||
tree last_function_parms;
|
||||
|
||||
/* A list of all LABEL_DECLs in the function that have names. Here so
|
||||
we can clear out their names' definitions at the end of the
|
||||
function, and so we can check the validity of jumps to these labels. */
|
||||
|
@ -5419,6 +5416,7 @@ bad_specifiers (tree object,
|
|||
TYPE is type this FUNCTION_DECL should have, either FUNCTION_TYPE
|
||||
or METHOD_TYPE.
|
||||
DECLARATOR is the function's name.
|
||||
PARMS is a chain of PARM_DECLs for the function.
|
||||
VIRTUALP is truthvalue of whether the function is virtual or not.
|
||||
FLAGS are to be passed through to `grokclassfn'.
|
||||
QUALS are qualifiers indicating whether the function is `const'
|
||||
|
@ -5434,6 +5432,7 @@ static tree
|
|||
grokfndecl (tree ctype,
|
||||
tree type,
|
||||
tree declarator,
|
||||
tree parms,
|
||||
tree orig_declarator,
|
||||
int virtualp,
|
||||
enum overload_flags flags,
|
||||
|
@ -5456,6 +5455,7 @@ grokfndecl (tree ctype,
|
|||
type = build_exception_variant (type, raises);
|
||||
|
||||
decl = build_lang_decl (FUNCTION_DECL, declarator, type);
|
||||
DECL_ARGUMENTS (decl) = parms;
|
||||
/* Propagate volatile out from type to decl. */
|
||||
if (TYPE_VOLATILE (type))
|
||||
TREE_THIS_VOLATILE (decl) = 1;
|
||||
|
@ -5680,12 +5680,9 @@ grokfndecl (tree ctype,
|
|||
|
||||
if (old_decl && DECL_STATIC_FUNCTION_P (old_decl)
|
||||
&& TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)
|
||||
{
|
||||
/* Remove the `this' parm added by grokclassfn.
|
||||
XXX Isn't this done in start_function, too? */
|
||||
revert_static_member_fn (decl);
|
||||
last_function_parms = TREE_CHAIN (last_function_parms);
|
||||
}
|
||||
/* Remove the `this' parm added by grokclassfn.
|
||||
XXX Isn't this done in start_function, too? */
|
||||
revert_static_member_fn (decl);
|
||||
if (old_decl && DECL_ARTIFICIAL (old_decl))
|
||||
error ("definition of implicitly-declared `%D'", old_decl);
|
||||
|
||||
|
@ -6339,6 +6336,7 @@ grokdeclarator (tree declarator,
|
|||
tree in_namespace = NULL_TREE;
|
||||
tree returned_attrs = NULL_TREE;
|
||||
tree scope = NULL_TREE;
|
||||
tree parms = NULL_TREE;
|
||||
|
||||
RIDBIT_RESET_ALL (specbits);
|
||||
if (decl_context == FUNCDEF)
|
||||
|
@ -7411,7 +7409,7 @@ grokdeclarator (tree declarator,
|
|||
|
||||
declarator = TREE_OPERAND (declarator, 0);
|
||||
|
||||
arg_types = grokparms (inner_parms);
|
||||
arg_types = grokparms (inner_parms, &parms);
|
||||
|
||||
if (declarator && flags == DTOR_FLAG)
|
||||
{
|
||||
|
@ -7425,7 +7423,7 @@ grokdeclarator (tree declarator,
|
|||
{
|
||||
error ("destructors may not have parameters");
|
||||
arg_types = void_list_node;
|
||||
last_function_parms = NULL_TREE;
|
||||
parms = NULL_TREE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7592,7 +7590,11 @@ grokdeclarator (tree declarator,
|
|||
}
|
||||
else if (TREE_CODE (type) == FUNCTION_TYPE)
|
||||
{
|
||||
if (current_class_type == NULL_TREE || friendp)
|
||||
if (NEW_DELETE_OPNAME_P (sname))
|
||||
/* Overloaded operator new and operator delete
|
||||
are always static functions. */
|
||||
;
|
||||
else if (current_class_type == NULL_TREE || friendp)
|
||||
type
|
||||
= build_method_type_directly (ctype,
|
||||
TREE_TYPE (type),
|
||||
|
@ -7851,8 +7853,7 @@ grokdeclarator (tree declarator,
|
|||
type = build_cplus_array_type (TREE_TYPE (type), NULL_TREE);
|
||||
|
||||
/* Detect where we're using a typedef of function type to declare a
|
||||
function. last_function_parms will not be set, so we must create
|
||||
it now. */
|
||||
function. PARMS will not be set, so we must create it now. */
|
||||
|
||||
if (type == typedef_type && TREE_CODE (type) == FUNCTION_TYPE)
|
||||
{
|
||||
|
@ -7867,7 +7868,7 @@ grokdeclarator (tree declarator,
|
|||
decls = decl;
|
||||
}
|
||||
|
||||
last_function_parms = nreverse (decls);
|
||||
parms = nreverse (decls);
|
||||
}
|
||||
|
||||
/* If this is a type name (such as, in a cast or sizeof),
|
||||
|
@ -8061,10 +8062,7 @@ grokdeclarator (tree declarator,
|
|||
return void_type_node;
|
||||
}
|
||||
|
||||
if (declarator == ansi_opname (NEW_EXPR)
|
||||
|| declarator == ansi_opname (VEC_NEW_EXPR)
|
||||
|| declarator == ansi_opname (DELETE_EXPR)
|
||||
|| declarator == ansi_opname (VEC_DELETE_EXPR))
|
||||
if (NEW_DELETE_OPNAME_P (declarator))
|
||||
{
|
||||
if (virtualp)
|
||||
{
|
||||
|
@ -8087,6 +8085,7 @@ grokdeclarator (tree declarator,
|
|||
decl = grokfndecl (ctype, type,
|
||||
TREE_CODE (declarator) != TEMPLATE_ID_EXPR
|
||||
? declarator : dname,
|
||||
parms,
|
||||
declarator,
|
||||
virtualp, flags, quals, raises,
|
||||
friendp ? -1 : 0, friendp, publicp, inlinep,
|
||||
|
@ -8133,6 +8132,7 @@ grokdeclarator (tree declarator,
|
|||
decl = grokfndecl (ctype, type,
|
||||
TREE_CODE (declarator) != TEMPLATE_ID_EXPR
|
||||
? declarator : dname,
|
||||
parms,
|
||||
declarator,
|
||||
virtualp, flags, quals, raises,
|
||||
friendp ? -1 : 0, friendp, 1, 0, funcdef_flag,
|
||||
|
@ -8190,8 +8190,7 @@ grokdeclarator (tree declarator,
|
|||
}
|
||||
|
||||
decl = do_friend (ctype, declarator, decl,
|
||||
last_function_parms, *attrlist,
|
||||
flags, quals, funcdef_flag);
|
||||
*attrlist, flags, quals, funcdef_flag);
|
||||
return decl;
|
||||
}
|
||||
else
|
||||
|
@ -8304,7 +8303,8 @@ grokdeclarator (tree declarator,
|
|||
virtualp = 0;
|
||||
}
|
||||
}
|
||||
else if (TREE_CODE (type) == FUNCTION_TYPE && staticp < 2)
|
||||
else if (TREE_CODE (type) == FUNCTION_TYPE && staticp < 2
|
||||
&& !NEW_DELETE_OPNAME_P (original_name))
|
||||
type = build_method_type_directly (ctype,
|
||||
TREE_TYPE (type),
|
||||
TYPE_ARG_TYPES (type));
|
||||
|
@ -8314,7 +8314,7 @@ grokdeclarator (tree declarator,
|
|||
|| RIDBIT_SETP (RID_EXTERN, specbits)
|
||||
|| !RIDBIT_SETP (RID_STATIC, specbits));
|
||||
|
||||
decl = grokfndecl (ctype, type, original_name, declarator,
|
||||
decl = grokfndecl (ctype, type, original_name, parms, declarator,
|
||||
virtualp, flags, quals, raises,
|
||||
1, friendp,
|
||||
publicp, inlinep, funcdef_flag,
|
||||
|
@ -8552,10 +8552,10 @@ check_default_argument (tree decl, tree arg)
|
|||
flag. If unset, we append void_list_node. A parmlist declared
|
||||
as `(void)' is accepted as the empty parmlist.
|
||||
|
||||
Also set last_function_parms to the chain of PARM_DECLs. */
|
||||
*PARMS is set to the chain of PARM_DECLs created. */
|
||||
|
||||
static tree
|
||||
grokparms (tree first_parm)
|
||||
grokparms (tree first_parm, tree *parms)
|
||||
{
|
||||
tree result = NULL_TREE;
|
||||
tree decls = NULL_TREE;
|
||||
|
@ -8661,7 +8661,7 @@ grokparms (tree first_parm)
|
|||
result = nreverse (result);
|
||||
if (!ellipsis)
|
||||
result = chainon (result, void_list_node);
|
||||
last_function_parms = decls;
|
||||
*parms = decls;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -8914,21 +8914,9 @@ grok_op_properties (tree decl, int friendp, bool complain)
|
|||
}
|
||||
|
||||
if (operator_code == NEW_EXPR || operator_code == VEC_NEW_EXPR)
|
||||
{
|
||||
/* When the compiler encounters the definition of A::operator new, it
|
||||
doesn't look at the class declaration to find out if it's static. */
|
||||
if (methodp)
|
||||
revert_static_member_fn (decl);
|
||||
|
||||
TREE_TYPE (decl) = coerce_new_type (TREE_TYPE (decl));
|
||||
}
|
||||
TREE_TYPE (decl) = coerce_new_type (TREE_TYPE (decl));
|
||||
else if (operator_code == DELETE_EXPR || operator_code == VEC_DELETE_EXPR)
|
||||
{
|
||||
if (methodp)
|
||||
revert_static_member_fn (decl);
|
||||
|
||||
TREE_TYPE (decl) = coerce_delete_type (TREE_TYPE (decl));
|
||||
}
|
||||
TREE_TYPE (decl) = coerce_delete_type (TREE_TYPE (decl));
|
||||
else
|
||||
{
|
||||
/* An operator function must either be a non-static member function
|
||||
|
@ -10039,8 +10027,6 @@ start_function (tree declspecs, tree declarator, tree attrs, int flags)
|
|||
else
|
||||
doing_friend = 1;
|
||||
}
|
||||
|
||||
last_function_parms = DECL_ARGUMENTS (decl1);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -10091,7 +10077,6 @@ start_function (tree declspecs, tree declarator, tree attrs, int flags)
|
|||
&& TREE_CODE (TREE_TYPE (decl1)) == METHOD_TYPE)
|
||||
{
|
||||
revert_static_member_fn (decl1);
|
||||
last_function_parms = TREE_CHAIN (last_function_parms);
|
||||
ctype = NULL_TREE;
|
||||
}
|
||||
|
||||
|
@ -10138,7 +10123,7 @@ start_function (tree declspecs, tree declarator, tree attrs, int flags)
|
|||
|
||||
/* Save the parm names or decls from this function's declarator
|
||||
where store_parm_decls will find them. */
|
||||
current_function_parms = last_function_parms;
|
||||
current_function_parms = DECL_ARGUMENTS (decl1);
|
||||
|
||||
/* Make sure the parameter and return types are reasonable. When
|
||||
you declare a function, these types can be incomplete, but they
|
||||
|
|
|
@ -33,10 +33,6 @@ enum decl_context
|
|||
/* We need this in here to get the decl_context definition. */
|
||||
extern tree grokdeclarator (tree, tree, enum decl_context, int, tree*);
|
||||
|
||||
/* Parsing a function declarator leaves a list of parameter names
|
||||
or a chain or parameter decls here. */
|
||||
extern GTY(()) tree last_function_parms;
|
||||
|
||||
#ifdef DEBUG_CP_BINDING_LEVELS
|
||||
/* Purely for debugging purposes. */
|
||||
extern int debug_bindings_indentation;
|
||||
|
|
|
@ -336,11 +336,10 @@ grokclassfn (tree ctype, tree function, enum overload_flags flags, tree quals)
|
|||
qual_type = cp_build_qualified_type (type, this_quals);
|
||||
parm = build_artificial_parm (this_identifier, qual_type);
|
||||
c_apply_type_quals_to_decl (this_quals, parm);
|
||||
TREE_CHAIN (parm) = last_function_parms;
|
||||
last_function_parms = parm;
|
||||
TREE_CHAIN (parm) = DECL_ARGUMENTS (function);
|
||||
DECL_ARGUMENTS (function) = parm;
|
||||
}
|
||||
|
||||
DECL_ARGUMENTS (function) = last_function_parms;
|
||||
DECL_CONTEXT (function) = ctype;
|
||||
|
||||
if (flags == DTOR_FLAG)
|
||||
|
|
|
@ -314,17 +314,13 @@ make_friend_class (tree type, tree friend_type, bool complain)
|
|||
|
||||
DECL is the FUNCTION_DECL that the friend is.
|
||||
|
||||
In case we are parsing a friend which is part of an inline
|
||||
definition, we will need to store PARM_DECL chain that comes
|
||||
with it into the DECL_ARGUMENTS slot of the FUNCTION_DECL.
|
||||
|
||||
FLAGS is just used for `grokclassfn'.
|
||||
|
||||
QUALS say what special qualifies should apply to the object
|
||||
pointed to by `this'. */
|
||||
|
||||
tree
|
||||
do_friend (tree ctype, tree declarator, tree decl, tree parmdecls,
|
||||
do_friend (tree ctype, tree declarator, tree decl,
|
||||
tree attrlist, enum overload_flags flags, tree quals,
|
||||
int funcdef_flag)
|
||||
{
|
||||
|
@ -424,7 +420,6 @@ do_friend (tree ctype, tree declarator, tree decl, tree parmdecls,
|
|||
|
||||
Note that because classes all wind up being top-level
|
||||
in their scope, their friend wind up in top-level scope as well. */
|
||||
DECL_ARGUMENTS (decl) = parmdecls;
|
||||
if (funcdef_flag)
|
||||
SET_DECL_FRIEND_CONTEXT (decl, current_class_type);
|
||||
|
||||
|
|
|
@ -2272,7 +2272,10 @@ do_local_using_decl (tree decl, tree scope, tree name)
|
|||
push_local_binding (name, newval, PUSH_USING);
|
||||
}
|
||||
if (newtype)
|
||||
set_identifier_type_value (name, newtype);
|
||||
{
|
||||
push_local_binding (name, newtype, PUSH_USING);
|
||||
set_identifier_type_value (name, newtype);
|
||||
}
|
||||
|
||||
/* Emit debug info. */
|
||||
if (!processing_template_decl)
|
||||
|
@ -4474,11 +4477,15 @@ lookup_arg_dependent (tree name, tree fns, tree args)
|
|||
we found were brought into the current namespace via a using
|
||||
declaration, we have not really checked the namespace from which
|
||||
they came. Therefore, we check all namespaces here -- unless the
|
||||
function we have is from the current namespace. */
|
||||
function we have is from the current namespace. Even then, we
|
||||
must check all namespaces if the function is a local
|
||||
declaration; any other declarations present at namespace scope
|
||||
should be visible during argument-dependent lookup. */
|
||||
if (fns)
|
||||
fn = OVL_CURRENT (fns);
|
||||
if (fn && TREE_CODE (fn) == FUNCTION_DECL
|
||||
&& CP_DECL_CONTEXT (fn) != current_decl_namespace ())
|
||||
&& (CP_DECL_CONTEXT (fn) != current_decl_namespace ()
|
||||
|| DECL_LOCAL_FUNCTION_P (fn)))
|
||||
k.namespaces = NULL_TREE;
|
||||
else
|
||||
/* Setting NAMESPACES is purely an optimization; it prevents
|
||||
|
@ -4835,7 +4842,6 @@ push_to_top_level (void)
|
|||
s->bindings = b;
|
||||
s->need_pop_function_context = need_pop;
|
||||
s->function_decl = current_function_decl;
|
||||
s->last_parms = last_function_parms;
|
||||
|
||||
scope_chain = s;
|
||||
current_function_decl = NULL_TREE;
|
||||
|
@ -4873,7 +4879,6 @@ pop_from_top_level (void)
|
|||
if (s->need_pop_function_context)
|
||||
pop_function_context_from (NULL_TREE);
|
||||
current_function_decl = s->function_decl;
|
||||
last_function_parms = s->last_parms;
|
||||
timevar_pop (TV_NAME_LOOKUP);
|
||||
}
|
||||
|
||||
|
|
|
@ -1910,15 +1910,10 @@ check_explicit_specialization (tree declarator,
|
|||
|
||||
/* If we thought that the DECL was a member function, but it
|
||||
turns out to be specializing a static member function,
|
||||
make DECL a static member function as well. We also have
|
||||
to adjust last_function_parms to avoid confusing
|
||||
start_function later. */
|
||||
make DECL a static member function as well. */
|
||||
if (DECL_STATIC_FUNCTION_P (tmpl)
|
||||
&& DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
|
||||
{
|
||||
revert_static_member_fn (decl);
|
||||
last_function_parms = TREE_CHAIN (last_function_parms);
|
||||
}
|
||||
revert_static_member_fn (decl);
|
||||
|
||||
/* If this is a specialization of a member template of a
|
||||
template class. In we want to return the TEMPLATE_DECL,
|
||||
|
|
|
@ -2364,11 +2364,16 @@ finish_id_expression (tree id_expression,
|
|||
if (decl == error_mark_node)
|
||||
{
|
||||
/* Name lookup failed. */
|
||||
if (scope && (!TYPE_P (scope) || !dependent_type_p (scope)))
|
||||
if (scope
|
||||
&& (!TYPE_P (scope)
|
||||
|| (!dependent_type_p (scope)
|
||||
&& !(TREE_CODE (id_expression) == IDENTIFIER_NODE
|
||||
&& IDENTIFIER_TYPENAME_P (id_expression)
|
||||
&& dependent_type_p (TREE_TYPE (id_expression))))))
|
||||
{
|
||||
/* Qualified name lookup failed, and the qualifying name
|
||||
was not a dependent type. That is always an
|
||||
error. */
|
||||
/* If the qualifying type is non-dependent (and the name
|
||||
does not name a conversion operator to a dependent
|
||||
type), issue an error. */
|
||||
qualified_name_lookup_error (scope, id_expression);
|
||||
return error_mark_node;
|
||||
}
|
||||
|
@ -2378,6 +2383,8 @@ finish_id_expression (tree id_expression,
|
|||
*idk = CP_ID_KIND_UNQUALIFIED;
|
||||
return id_expression;
|
||||
}
|
||||
else
|
||||
decl = id_expression;
|
||||
}
|
||||
/* If DECL is a variable that would be out of scope under
|
||||
ANSI/ISO rules, but in scope in the ARM, name lookup
|
||||
|
|
|
@ -1788,6 +1788,7 @@ lookup_destructor (tree object, tree scope, tree dtor_name)
|
|||
{
|
||||
tree object_type = TREE_TYPE (object);
|
||||
tree dtor_type = TREE_OPERAND (dtor_name, 0);
|
||||
tree expr;
|
||||
|
||||
if (scope && !check_dtor_name (scope, dtor_name))
|
||||
{
|
||||
|
@ -1795,17 +1796,20 @@ lookup_destructor (tree object, tree scope, tree dtor_name)
|
|||
scope, dtor_type);
|
||||
return error_mark_node;
|
||||
}
|
||||
if (!same_type_p (dtor_type, TYPE_MAIN_VARIANT (object_type)))
|
||||
if (!DERIVED_FROM_P (dtor_type, TYPE_MAIN_VARIANT (object_type)))
|
||||
{
|
||||
error ("the type being destroyed is `%T', but the destructor refers to `%T'",
|
||||
TYPE_MAIN_VARIANT (object_type), dtor_type);
|
||||
return error_mark_node;
|
||||
}
|
||||
if (!TYPE_HAS_DESTRUCTOR (object_type))
|
||||
if (!TYPE_HAS_DESTRUCTOR (dtor_type))
|
||||
return build (PSEUDO_DTOR_EXPR, void_type_node, object, scope,
|
||||
dtor_type);
|
||||
return lookup_member (object_type, complete_dtor_identifier,
|
||||
expr = lookup_member (dtor_type, complete_dtor_identifier,
|
||||
/*protect=*/1, /*want_type=*/false);
|
||||
expr = (adjust_result_of_qualified_name_lookup
|
||||
(expr, dtor_type, object_type));
|
||||
return expr;
|
||||
}
|
||||
|
||||
/* This function is called by the parser to process a class member
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
2004-03-19 Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
* g++.dg/init/placement3.C: New test.
|
||||
|
||||
* g++.dg/template/spec13.C: New test.
|
||||
|
||||
* g++.dg/lookup/using11.C: New test.
|
||||
|
||||
* g++.dg/lookup/koenig3.C: New test.
|
||||
|
||||
* g++.dg/template/operator2.C: New test.
|
||||
|
||||
* g++.dg/expr/dtor3.C: New test.
|
||||
* g++.old-deja/g++.brendan/crash15.C: Remove incorrect dg-error
|
||||
marker.
|
||||
* g++.old-deja/g++.law/visibility28.C: Likewise.
|
||||
|
||||
2004-03-19 Paolo Bonzini <bonzini@gnu.org>
|
||||
|
||||
* gcc.dg/altivec-6.c: Use vector_size attribute, not mode.
|
||||
|
|
10
gcc/testsuite/g++.dg/expr/dtor3.C
Normal file
10
gcc/testsuite/g++.dg/expr/dtor3.C
Normal file
|
@ -0,0 +1,10 @@
|
|||
struct B {
|
||||
~B();
|
||||
};
|
||||
struct D : public B {
|
||||
~D();
|
||||
};
|
||||
|
||||
void f(D d) {
|
||||
d.B::~B();
|
||||
}
|
30
gcc/testsuite/g++.dg/init/placement3.C
Normal file
30
gcc/testsuite/g++.dg/init/placement3.C
Normal file
|
@ -0,0 +1,30 @@
|
|||
typedef __SIZE_TYPE__ size_t;
|
||||
extern "C" void *malloc (size_t);
|
||||
|
||||
int i;
|
||||
|
||||
struct S {
|
||||
S(int) {
|
||||
throw 3;
|
||||
}
|
||||
|
||||
void *operator new(size_t s, int) {
|
||||
++i;
|
||||
return malloc (s);
|
||||
}
|
||||
|
||||
void operator delete(void *, int) {
|
||||
--i;
|
||||
}
|
||||
|
||||
void operator delete(void *, int, int) ;
|
||||
};
|
||||
|
||||
int main () {
|
||||
try {
|
||||
new (7) S (12);
|
||||
} catch (int) {
|
||||
if (i)
|
||||
return 1;
|
||||
}
|
||||
}
|
13
gcc/testsuite/g++.dg/lookup/koenig3.C
Normal file
13
gcc/testsuite/g++.dg/lookup/koenig3.C
Normal file
|
@ -0,0 +1,13 @@
|
|||
extern "C" void abort ();
|
||||
|
||||
struct S {
|
||||
};
|
||||
void f(S, int) { abort(); }
|
||||
void f(S, double) {}
|
||||
|
||||
S s;
|
||||
|
||||
int main() {
|
||||
extern void f(S, int);
|
||||
f(s, 3.0);
|
||||
}
|
9
gcc/testsuite/g++.dg/lookup/using11.C
Normal file
9
gcc/testsuite/g++.dg/lookup/using11.C
Normal file
|
@ -0,0 +1,9 @@
|
|||
namespace N1 {
|
||||
enum e { a };
|
||||
void e(char);
|
||||
}
|
||||
|
||||
void f() {
|
||||
using N1::e;
|
||||
enum e x;
|
||||
}
|
8
gcc/testsuite/g++.dg/template/operator2.C
Normal file
8
gcc/testsuite/g++.dg/template/operator2.C
Normal file
|
@ -0,0 +1,8 @@
|
|||
template <typename T> struct A {};
|
||||
|
||||
struct B {
|
||||
operator A<B>();
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
void f() { B::operator A<T>; }
|
16
gcc/testsuite/g++.dg/template/spec13.C
Normal file
16
gcc/testsuite/g++.dg/template/spec13.C
Normal file
|
@ -0,0 +1,16 @@
|
|||
// { dg-options "-w" }
|
||||
|
||||
template <typename T>
|
||||
struct S {
|
||||
int i;
|
||||
template <typename U> void f(U) {}
|
||||
};
|
||||
|
||||
template<>
|
||||
template <typename U>
|
||||
void S<int>::f(U) { i; }
|
||||
|
||||
void f() {
|
||||
S<int> s;
|
||||
s.f<int>(3);
|
||||
}
|
|
@ -16,7 +16,7 @@ int
|
|||
main() {
|
||||
std::cout << "starting\n";
|
||||
B b;
|
||||
b.~A();// { dg-error "" } destructor
|
||||
b.~A();
|
||||
std::cout << "done\n";
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ public:
|
|||
class D : public B {
|
||||
public:
|
||||
virtual ~D() { printf( "D::~D\n"); }
|
||||
void operator = ( int i) { this->~B(); }// { dg-error "" } D has no ~B part to it
|
||||
void operator = ( int i) { this->~B(); }
|
||||
};
|
||||
|
||||
int
|
||||
|
|
Loading…
Add table
Reference in a new issue