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:
Mark Mitchell 2004-03-20 00:18:24 +00:00 committed by Mark Mitchell
parent b40bc279e7
commit 4546865e5b
20 changed files with 222 additions and 88 deletions

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -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)

View File

@ -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);

View File

@ -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);
}

View File

@ -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,

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -0,0 +1,10 @@
struct B {
~B();
};
struct D : public B {
~D();
};
void f(D d) {
d.B::~B();
}

View 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;
}
}

View 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);
}

View File

@ -0,0 +1,9 @@
namespace N1 {
enum e { a };
void e(char);
}
void f() {
using N1::e;
enum e x;
}

View File

@ -0,0 +1,8 @@
template <typename T> struct A {};
struct B {
operator A<B>();
};
template <typename T>
void f() { B::operator A<T>; }

View 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);
}

View File

@ -16,7 +16,7 @@ int
main() {
std::cout << "starting\n";
B b;
b.~A();// { dg-error "" } destructor
b.~A();
std::cout << "done\n";
}

View File

@ -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