mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-25 12:31:19 +08:00
decl2.c (build_anon_union_vars): Don't crash on empty sub-unions.
1998-05-25 Mark Mitchell <mark@markmitchell.com> * decl2.c (build_anon_union_vars): Don't crash on empty sub-unions. * cp-tree.h (processing_template_parmlist): Declare. * decl.c (pushtag): Don't call push_template_decl when we shouldn't. * pt.c (processing_template_parmlist): New variable. (TMPL_ARGS_HAVE_MULTIPLE_LEVELS): New macro. (complete_template_args): Use it. (add_to_template_args): Likewise. (innermost_args): Likewise. (tsubst): Likewise. (begin_template_parm_list): Use processing_template_parmlist. (end_template_parm_list): Likewise. * cp-tree.h (ANON_UNION_TYPE_P): New macro. * decl.c (grokdeclarator): Use it. * decl2.c (grok_x_components): Likewise. * init.c (initializing_context): Likewise. * method.c (do_build_copy_constructor): Likewise. (do_build_assign_ref): Likewise. * search.c (compute_access): Likewise. * typeck.c (build_component_ref): Likewise. * decl.c (grokdeclarator): Don't give a cv-qualified version of an unnamed type a typedef name "for linkage purposes". * pt.c (lookup_template_class): Don't look at IDENTIFIER_CLASS_VALUE when there's no current_class_type. * method.c (build_overload_int): Handle error cases gracefully. * pt.c (instantiate_decl): Handle static member variables correctly. * pt.c (tsubst): Use the tsubst'd type when producing new TEMPLATE_PARM_INDEX nodes. From-SVN: r20045
This commit is contained in:
parent
c21f27a762
commit
67ffc8124f
@ -1,3 +1,42 @@
|
||||
1998-05-25 Mark Mitchell <mark@markmitchell.com>
|
||||
|
||||
* decl2.c (build_anon_union_vars): Don't crash on empty sub-unions.
|
||||
|
||||
* cp-tree.h (processing_template_parmlist): Declare.
|
||||
* decl.c (pushtag): Don't call push_template_decl when we
|
||||
shouldn't.
|
||||
* pt.c (processing_template_parmlist): New variable.
|
||||
(TMPL_ARGS_HAVE_MULTIPLE_LEVELS): New macro.
|
||||
(complete_template_args): Use it.
|
||||
(add_to_template_args): Likewise.
|
||||
(innermost_args): Likewise.
|
||||
(tsubst): Likewise.
|
||||
(begin_template_parm_list): Use processing_template_parmlist.
|
||||
(end_template_parm_list): Likewise.
|
||||
|
||||
* cp-tree.h (ANON_UNION_TYPE_P): New macro.
|
||||
* decl.c (grokdeclarator): Use it.
|
||||
* decl2.c (grok_x_components): Likewise.
|
||||
* init.c (initializing_context): Likewise.
|
||||
* method.c (do_build_copy_constructor): Likewise.
|
||||
(do_build_assign_ref): Likewise.
|
||||
* search.c (compute_access): Likewise.
|
||||
* typeck.c (build_component_ref): Likewise.
|
||||
|
||||
* decl.c (grokdeclarator): Don't give a cv-qualified version of an
|
||||
unnamed type a typedef name "for linkage purposes".
|
||||
|
||||
* pt.c (lookup_template_class): Don't look at
|
||||
IDENTIFIER_CLASS_VALUE when there's no current_class_type.
|
||||
|
||||
* method.c (build_overload_int): Handle error cases gracefully.
|
||||
|
||||
* pt.c (instantiate_decl): Handle static member variables
|
||||
correctly.
|
||||
|
||||
* pt.c (tsubst): Use the tsubst'd type when producing new
|
||||
TEMPLATE_PARM_INDEX nodes.
|
||||
|
||||
1998-05-24 Mark Mitchell <mark@markmitchell.com>
|
||||
|
||||
* tree.c (cp_tree_equal): Handle pointers to member functions.
|
||||
|
@ -1452,6 +1452,11 @@ extern int flag_new_for_scope;
|
||||
|
||||
#define ANON_UNION_P(NODE) (DECL_NAME (NODE) == 0)
|
||||
|
||||
/* Nonzero if TYPE is an anonymous union type. */
|
||||
#define ANON_UNION_TYPE_P(TYPE) \
|
||||
(TREE_CODE (TYPE) == UNION_TYPE \
|
||||
&& ANON_AGGRNAME_P (TYPE_IDENTIFIER (TYPE)))
|
||||
|
||||
#define UNKNOWN_TYPE LANG_TYPE
|
||||
|
||||
/* Define fields and accessors for nodes representing declared names. */
|
||||
@ -2644,6 +2649,7 @@ extern int comp_template_args PROTO((tree, tree));
|
||||
|
||||
extern int processing_specialization;
|
||||
extern int processing_explicit_instantiation;
|
||||
extern int processing_template_parmlist;
|
||||
|
||||
/* in repo.c */
|
||||
extern void repo_template_used PROTO((tree));
|
||||
|
@ -2291,9 +2291,15 @@ pushtag (name, type, globalize)
|
||||
friend class S2;
|
||||
};
|
||||
|
||||
declares S2 to be at global scope. */
|
||||
|| (processing_template_decl >
|
||||
template_class_depth (current_class_type))))
|
||||
declares S2 to be at global scope. We must be
|
||||
careful, however, of the following case:
|
||||
|
||||
template <class A*> struct S;
|
||||
|
||||
which declares a non-template class `A'. */
|
||||
|| (!processing_template_parmlist
|
||||
&& (processing_template_decl >
|
||||
template_class_depth (current_class_type)))))
|
||||
{
|
||||
d = push_template_decl_real (d, globalize);
|
||||
/* If the current binding level is the binding level for
|
||||
@ -8750,8 +8756,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
|
||||
/* Static anonymous unions are dealt with here. */
|
||||
if (staticp && decl_context == TYPENAME
|
||||
&& TREE_CODE (declspecs) == TREE_LIST
|
||||
&& TREE_CODE (TREE_VALUE (declspecs)) == UNION_TYPE
|
||||
&& ANON_AGGRNAME_P (TYPE_IDENTIFIER (TREE_VALUE (declspecs))))
|
||||
&& ANON_UNION_TYPE_P (TREE_VALUE (declspecs)))
|
||||
decl_context = FIELD;
|
||||
|
||||
/* Give error if `const,' `volatile,' `inline,' `friend,' or `virtual'
|
||||
@ -9659,6 +9664,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
|
||||
refer to it, so nothing needs know about the name change.
|
||||
The TYPE_NAME field was filled in by build_struct_xref. */
|
||||
if (type != error_mark_node
|
||||
&& !TYPE_READONLY (type) && !TYPE_VOLATILE (type)
|
||||
&& TYPE_NAME (type)
|
||||
&& TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
|
||||
&& ANON_AGGRNAME_P (TYPE_IDENTIFIER (type)))
|
||||
|
@ -865,8 +865,7 @@ grok_x_components (specs, components)
|
||||
{
|
||||
case VAR_DECL:
|
||||
/* Static anonymous unions come out as VAR_DECLs. */
|
||||
if (TREE_CODE (TREE_TYPE (t)) == UNION_TYPE
|
||||
&& ANON_AGGRNAME_P (TYPE_IDENTIFIER (TREE_TYPE (t))))
|
||||
if (ANON_UNION_TYPE_P (TREE_TYPE (t)))
|
||||
return t;
|
||||
|
||||
/* We return SPECS here, because in the parser it was ending
|
||||
@ -904,8 +903,7 @@ grok_x_components (specs, components)
|
||||
tcode = enum_type_node;
|
||||
|
||||
t = xref_tag (tcode, TYPE_IDENTIFIER (t), NULL_TREE, 0);
|
||||
if (TREE_CODE (t) == UNION_TYPE
|
||||
&& ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))
|
||||
if (ANON_UNION_TYPE_P (t))
|
||||
{
|
||||
/* See also shadow_tag. */
|
||||
|
||||
@ -2176,7 +2174,11 @@ build_anon_union_vars (anon_decl, elems, static_p, external_p)
|
||||
|
||||
if (DECL_NAME (field) == NULL_TREE
|
||||
&& TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
|
||||
{
|
||||
decl = build_anon_union_vars (field, elems, static_p, external_p);
|
||||
if (!decl)
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
decl = build_decl (VAR_DECL, DECL_NAME (field), TREE_TYPE (field));
|
||||
|
@ -866,7 +866,7 @@ initializing_context (field)
|
||||
|
||||
/* Anonymous union members can be initialized in the first enclosing
|
||||
non-anonymous union context. */
|
||||
while (t && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))
|
||||
while (t && ANON_UNION_TYPE_P (t))
|
||||
t = TYPE_CONTEXT (t);
|
||||
return t;
|
||||
}
|
||||
|
@ -515,7 +515,13 @@ build_overload_int (value, in_template)
|
||||
id = ansi_opname [(int) TREE_CODE (value)];
|
||||
my_friendly_assert (id != NULL_TREE, 0);
|
||||
name = IDENTIFIER_POINTER (id);
|
||||
my_friendly_assert (name[0] == '_' && name[1] == '_', 0);
|
||||
if (name[0] != '_' || name[1] != '_')
|
||||
/* On some erroneous inputs, we can get here with VALUE a
|
||||
LOOKUP_EXPR. In that case, the NAME will be the
|
||||
identifier for "<invalid operator>". We must survive
|
||||
this routine in order to issue a sensible error
|
||||
message, so we fall through to the case below. */
|
||||
goto bad_value;
|
||||
|
||||
for (i = 0; i < operands; ++i)
|
||||
{
|
||||
@ -553,6 +559,7 @@ build_overload_int (value, in_template)
|
||||
This should cause assembler errors we'll notice. */
|
||||
|
||||
static int n;
|
||||
bad_value:
|
||||
sprintf (digit_buffer, " *%d", n++);
|
||||
OB_PUTCP (digit_buffer);
|
||||
}
|
||||
@ -2180,8 +2187,7 @@ do_build_copy_constructor (fndecl)
|
||||
continue;
|
||||
}
|
||||
else if ((t = TREE_TYPE (field)) != NULL_TREE
|
||||
&& TREE_CODE (t) == UNION_TYPE
|
||||
&& ANON_AGGRNAME_P (TYPE_IDENTIFIER (t))
|
||||
&& ANON_UNION_TYPE_P (t)
|
||||
&& TYPE_FIELDS (t) != NULL_TREE)
|
||||
{
|
||||
do
|
||||
@ -2190,8 +2196,7 @@ do_build_copy_constructor (fndecl)
|
||||
field = largest_union_member (t);
|
||||
}
|
||||
while ((t = TREE_TYPE (field)) != NULL_TREE
|
||||
&& TREE_CODE (t) == UNION_TYPE
|
||||
&& ANON_AGGRNAME_P (TYPE_IDENTIFIER (t))
|
||||
&& ANON_UNION_TYPE_P (t)
|
||||
&& TYPE_FIELDS (t) != NULL_TREE);
|
||||
}
|
||||
else
|
||||
@ -2290,8 +2295,7 @@ do_build_assign_ref (fndecl)
|
||||
continue;
|
||||
}
|
||||
else if ((t = TREE_TYPE (field)) != NULL_TREE
|
||||
&& TREE_CODE (t) == UNION_TYPE
|
||||
&& ANON_AGGRNAME_P (TYPE_IDENTIFIER (t))
|
||||
&& ANON_UNION_TYPE_P (t)
|
||||
&& TYPE_FIELDS (t) != NULL_TREE)
|
||||
{
|
||||
do
|
||||
@ -2301,8 +2305,7 @@ do_build_assign_ref (fndecl)
|
||||
field = largest_union_member (t);
|
||||
}
|
||||
while ((t = TREE_TYPE (field)) != NULL_TREE
|
||||
&& TREE_CODE (t) == UNION_TYPE
|
||||
&& ANON_AGGRNAME_P (TYPE_IDENTIFIER (t))
|
||||
&& ANON_UNION_TYPE_P (t)
|
||||
&& TYPE_FIELDS (t) != NULL_TREE);
|
||||
}
|
||||
else
|
||||
|
51
gcc/cp/pt.c
51
gcc/cp/pt.c
@ -63,6 +63,7 @@ int minimal_parse_mode;
|
||||
|
||||
int processing_specialization;
|
||||
int processing_explicit_instantiation;
|
||||
int processing_template_parmlist;
|
||||
static int template_header_count;
|
||||
|
||||
static tree saved_trees;
|
||||
@ -115,6 +116,14 @@ static int check_cv_quals_for_unify PROTO((int, tree, tree));
|
||||
static tree tsubst_template_arg_vector PROTO((tree, tree));
|
||||
static void regenerate_decl_from_template PROTO((tree, tree));
|
||||
|
||||
/* Nonzero if ARGVEC contains multiple levels of template arguments. */
|
||||
#define TMPL_ARGS_HAVE_MULTIPLE_LEVELS(NODE) \
|
||||
(NODE != NULL_TREE \
|
||||
&& TREE_CODE (NODE) == TREE_VEC \
|
||||
&& TREE_VEC_LENGTH (NODE) > 0 \
|
||||
&& TREE_VEC_ELT (NODE, 0) != NULL_TREE \
|
||||
&& TREE_CODE (TREE_VEC_ELT (NODE, 0)) == TREE_VEC)
|
||||
|
||||
/* Do any processing required when DECL (a member template declaration
|
||||
using TEMPLATE_PARAMETERS as its innermost parameter list) is
|
||||
finished. Returns the TEMPLATE_DECL corresponding to DECL, unless
|
||||
@ -388,7 +397,7 @@ complete_template_args (tmpl, extra_args, unbound_only)
|
||||
my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 0);
|
||||
my_friendly_assert (TREE_CODE (extra_args) == TREE_VEC, 0);
|
||||
|
||||
if (TREE_CODE (TREE_VEC_ELT (extra_args, 0)) == TREE_VEC)
|
||||
if (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (extra_args))
|
||||
extra_arg_depth = TREE_VEC_LENGTH (extra_args);
|
||||
else
|
||||
extra_arg_depth = 1;
|
||||
@ -411,7 +420,7 @@ complete_template_args (tmpl, extra_args, unbound_only)
|
||||
TEMPLATE_DECL with DECL_TEMPLATE_INFO. DECL_TI_ARGS is
|
||||
all the bound template arguments. */
|
||||
args = DECL_TI_ARGS (tmpl);
|
||||
if (TREE_CODE (TREE_VEC_ELT (args, 0)) != TREE_VEC)
|
||||
if (!TMPL_ARGS_HAVE_MULTIPLE_LEVELS (args))
|
||||
depth = 1;
|
||||
else
|
||||
depth = TREE_VEC_LENGTH (args);
|
||||
@ -485,7 +494,7 @@ add_to_template_args (args, extra_args)
|
||||
{
|
||||
tree new_args;
|
||||
|
||||
if (TREE_CODE (TREE_VEC_ELT (args, 0)) != TREE_VEC)
|
||||
if (!TMPL_ARGS_HAVE_MULTIPLE_LEVELS (args))
|
||||
{
|
||||
new_args = make_tree_vec (2);
|
||||
TREE_VEC_ELT (new_args, 0) = args;
|
||||
@ -529,6 +538,7 @@ begin_template_parm_list ()
|
||||
pushlevel (0);
|
||||
declare_pseudo_global_level ();
|
||||
++processing_template_decl;
|
||||
++processing_template_parmlist;
|
||||
note_template_header (0);
|
||||
}
|
||||
|
||||
@ -1452,6 +1462,8 @@ end_template_parm_list (parms)
|
||||
for (parm = parms, nparms = 0; parm; parm = TREE_CHAIN (parm), nparms++)
|
||||
TREE_VEC_ELT (saved_parmlist, nparms) = parm;
|
||||
|
||||
--processing_template_parmlist;
|
||||
|
||||
return saved_parmlist;
|
||||
}
|
||||
|
||||
@ -2858,6 +2870,7 @@ lookup_template_class (d1, arglist, in_decl, context)
|
||||
{
|
||||
if (context)
|
||||
push_decl_namespace (context);
|
||||
if (current_class_type != NULL_TREE)
|
||||
template =
|
||||
maybe_get_template_decl_from_type_decl
|
||||
(IDENTIFIER_CLASS_VALUE (d1));
|
||||
@ -3993,7 +4006,7 @@ innermost_args (args, is_spec)
|
||||
tree args;
|
||||
int is_spec;
|
||||
{
|
||||
if (args != NULL_TREE && TREE_CODE (TREE_VEC_ELT (args, 0)) == TREE_VEC)
|
||||
if (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (args))
|
||||
return TREE_VEC_ELT (args, TREE_VEC_LENGTH (args) - 1 - is_spec);
|
||||
return args;
|
||||
}
|
||||
@ -4189,8 +4202,7 @@ tsubst (t, args, in_decl)
|
||||
{
|
||||
tree arg = NULL_TREE;
|
||||
|
||||
if (TREE_VEC_ELT (args, 0) != NULL_TREE
|
||||
&& TREE_CODE (TREE_VEC_ELT (args, 0)) == TREE_VEC)
|
||||
if (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (args))
|
||||
{
|
||||
levels = TREE_VEC_LENGTH (args);
|
||||
if (level <= levels)
|
||||
@ -4275,7 +4287,7 @@ tsubst (t, args, in_decl)
|
||||
break;
|
||||
|
||||
case TEMPLATE_PARM_INDEX:
|
||||
r = reduce_template_parm_level (t, TREE_TYPE (t), levels);
|
||||
r = reduce_template_parm_level (t, type, levels);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -6220,14 +6232,14 @@ unify (tparms, targs, parm, arg, strict, explicit_mask)
|
||||
/* The PARM is not one we're trying to unify. Just check
|
||||
to see if it matches ARG. */
|
||||
return (TREE_CODE (arg) == TREE_CODE (parm)
|
||||
&& cp_tree_equal (parm, arg)) ? 0 : 1;
|
||||
&& cp_tree_equal (parm, arg) > 0) ? 0 : 1;
|
||||
|
||||
idx = TEMPLATE_PARM_IDX (parm);
|
||||
targ = TREE_VEC_ELT (targs, idx);
|
||||
|
||||
if (targ)
|
||||
{
|
||||
int i = cp_tree_equal (targ, arg);
|
||||
int i = (cp_tree_equal (targ, arg) > 0);
|
||||
if (i == 1)
|
||||
return 0;
|
||||
else if (i == 0)
|
||||
@ -7082,17 +7094,6 @@ instantiate_decl (d)
|
||||
lineno = DECL_SOURCE_LINE (d);
|
||||
input_filename = DECL_SOURCE_FILE (d);
|
||||
|
||||
/* We need to set up DECL_INITIAL regardless of pattern_defined if the
|
||||
variable is a static const initialized in the class body. */
|
||||
if (TREE_CODE (d) == VAR_DECL
|
||||
&& ! DECL_INITIAL (d) && DECL_INITIAL (code_pattern))
|
||||
{
|
||||
pushclass (DECL_CONTEXT (d), 2);
|
||||
DECL_INITIAL (d) = tsubst_expr (DECL_INITIAL (code_pattern), args,
|
||||
tmpl);
|
||||
cp_finish_decl (d, DECL_INITIAL (d), NULL_TREE, 0, LOOKUP_NORMAL);
|
||||
}
|
||||
|
||||
if (pattern_defined)
|
||||
{
|
||||
repo_template_used (d);
|
||||
@ -7123,11 +7124,17 @@ instantiate_decl (d)
|
||||
&& ! (TREE_CODE (d) == FUNCTION_DECL && DECL_INLINE (d)))
|
||||
goto out;
|
||||
|
||||
/* Defer all templates except inline functions used in another function. */
|
||||
if (! pattern_defined
|
||||
if (TREE_CODE (d) == VAR_DECL
|
||||
&& DECL_INITIAL (d) == NULL_TREE
|
||||
&& DECL_INITIAL (code_pattern) != NULL_TREE)
|
||||
/* We need to set up DECL_INITIAL regardless of pattern_defined if
|
||||
the variable is a static const initialized in the class body. */;
|
||||
else if (! pattern_defined
|
||||
|| (! (TREE_CODE (d) == FUNCTION_DECL && DECL_INLINE (d) && nested)
|
||||
&& ! at_eof))
|
||||
{
|
||||
/* Defer all templates except inline functions used in another
|
||||
function. */
|
||||
lineno = line;
|
||||
input_filename = file;
|
||||
|
||||
|
@ -969,8 +969,7 @@ compute_access (basetype_path, field)
|
||||
/* Fields coming from nested anonymous unions have their DECL_CLASS_CONTEXT
|
||||
slot set to the union type rather than the record type containing
|
||||
the anonymous union. */
|
||||
if (context && TREE_CODE (context) == UNION_TYPE
|
||||
&& ANON_AGGRNAME_P (TYPE_IDENTIFIER (context)))
|
||||
if (context && ANON_UNION_TYPE_P (context))
|
||||
context = TYPE_CONTEXT (context);
|
||||
|
||||
/* Virtual function tables are never private. But we should know that
|
||||
|
@ -2065,8 +2065,8 @@ build_component_ref (datum, component, basetype_path, protect)
|
||||
{
|
||||
tree context = DECL_FIELD_CONTEXT (field);
|
||||
tree base = context;
|
||||
while (base != basetype && TYPE_NAME (base)
|
||||
&& ANON_AGGRNAME_P (TYPE_IDENTIFIER (base)))
|
||||
while (!comptypes (base, basetype,1) && TYPE_NAME (base)
|
||||
&& ANON_UNION_TYPE_P (base))
|
||||
{
|
||||
base = TYPE_CONTEXT (base);
|
||||
}
|
||||
@ -2096,7 +2096,7 @@ build_component_ref (datum, component, basetype_path, protect)
|
||||
basetype = base;
|
||||
|
||||
/* Handle things from anon unions here... */
|
||||
if (TYPE_NAME (context) && ANON_AGGRNAME_P (TYPE_IDENTIFIER (context)))
|
||||
if (TYPE_NAME (context) && ANON_UNION_TYPE_P (context))
|
||||
{
|
||||
tree subfield = lookup_anon_field (basetype, context);
|
||||
tree subdatum = build_component_ref (datum, subfield,
|
||||
|
13
gcc/testsuite/g++.old-deja/g++.other/typedef1.C
Normal file
13
gcc/testsuite/g++.old-deja/g++.other/typedef1.C
Normal file
@ -0,0 +1,13 @@
|
||||
// Build don't link:
|
||||
|
||||
typedef const struct {
|
||||
int x;
|
||||
} Test;
|
||||
|
||||
void foo(Test);
|
||||
|
||||
void foo(Test t)
|
||||
{
|
||||
t.x = 0; // ERROR - assignment of read-only member
|
||||
return;
|
||||
}
|
12
gcc/testsuite/g++.old-deja/g++.pt/crash5.C
Normal file
12
gcc/testsuite/g++.old-deja/g++.pt/crash5.C
Normal file
@ -0,0 +1,12 @@
|
||||
// Build don't link:
|
||||
|
||||
template <class T, int i>
|
||||
struct K {
|
||||
void f();
|
||||
};
|
||||
|
||||
template <class T>
|
||||
void
|
||||
K<T, i>::f()
|
||||
{ // ERROR - template parameters
|
||||
}
|
25
gcc/testsuite/g++.old-deja/g++.pt/memtemp75.C
Normal file
25
gcc/testsuite/g++.old-deja/g++.pt/memtemp75.C
Normal file
@ -0,0 +1,25 @@
|
||||
// Build don't link:
|
||||
|
||||
void
|
||||
print(const int& i)
|
||||
{
|
||||
}
|
||||
|
||||
template<class A>
|
||||
class bar
|
||||
{
|
||||
public:
|
||||
template<void (*B)(const A& a)>
|
||||
void doit(const A& a)
|
||||
{
|
||||
B(a);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
bar<int> b;
|
||||
b.template doit<print>(2);
|
||||
}
|
30
gcc/testsuite/g++.old-deja/g++.pt/spec18.C
Normal file
30
gcc/testsuite/g++.old-deja/g++.pt/spec18.C
Normal file
@ -0,0 +1,30 @@
|
||||
// Build don't link:
|
||||
|
||||
template<class A, class B>
|
||||
void foo(const A& a, const B& b)
|
||||
{
|
||||
}
|
||||
|
||||
template<class A, class B>
|
||||
void foo(const A& a, const int& b)
|
||||
{
|
||||
}
|
||||
|
||||
template<class A*, class B>
|
||||
void foo(const A*& a, const B& b)
|
||||
{
|
||||
}
|
||||
|
||||
template<>
|
||||
void foo(const int&, const double&)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
foo("98239", 23);
|
||||
foo(232, 1.022);
|
||||
}
|
||||
|
21
gcc/testsuite/g++.old-deja/g++.pt/static2.C
Normal file
21
gcc/testsuite/g++.old-deja/g++.pt/static2.C
Normal file
@ -0,0 +1,21 @@
|
||||
// Build don't link:
|
||||
|
||||
template <class A>
|
||||
class TEST
|
||||
{
|
||||
public:
|
||||
TEST (A) {}
|
||||
};
|
||||
|
||||
template <class A>
|
||||
class TEST2
|
||||
{
|
||||
static A i;
|
||||
};
|
||||
|
||||
template <class A>
|
||||
A TEST2 <A>::i (0);
|
||||
|
||||
TEST2 <TEST <int> > a;
|
||||
|
||||
template class TEST2 <TEST <int> >;
|
Loading…
x
Reference in New Issue
Block a user