iomanip.h: Use __extension__ for `extern' explicit template instantiations.

* iomanip.h: Use __extension__ for `extern' explicit template
	instantiations.
	* sinst.cc: Don't explicitly instantiation string_char_traits<char>.
	* cinst.cc: Likewiwse, for complex<float>, complex<double>,
	complex<long double>.
	* extend.texi: Remove description of extension to explicit
	instantiation that is now endorsed by standard C++.
	* decl2.c (grok_array_decl): Add comment.
	(mark_used): Don't instantiate an explicit instantiation.
	* friend.c (make_friend_class): Remove bogus comment.  Fix check
	for partial specializations.
	* pt.c (check_explicit_specialization): Don't
	SET_DECL_EXPLICIT_INSTANTIATION here.
	(mark_decl_instantiated): Or here.
	(do_decl_instantiation): Do it here, instead.  Add checks for
	duplicate explicit instantiations, etc.  Tidy.
	(do_type_instantiation): Likewise.
	(instantiate_decl): Improve comments.  Complain about explicit
	instantiations where no definition is available.
	* cp-tree.h (ansi_null_node): Remove.
	* call.c (build_over_call): Warn about converting NULL to an
	arithmetic type.
	* cvt.c (build_expr_type_conversion): Likewise.  Use
	null_ptr_cst_p instead of expanding it inline.
	* decl.c (ansi_null_node): Remove.
	(init_decl_processing): Make null_node always have integral type.
	* except.c (build_throw): Warn about converting NULL to an
	arithmetic type.
	* lex.c (init_parse): Remove handling of ansi_null_node.
	* pt.c (type_unification_real): Don't convert NULL to void* type.
	* typeck.c (build_binary_op_nodefault): Fix NULL warnings.
	(convert_for_assignment): Warn about converting NULL to an
	arithmetic type.
	(convert_for_initialization): Likewise.

From-SVN: r21915
This commit is contained in:
Mark Mitchell 1998-08-23 12:47:24 +00:00 committed by Mark Mitchell
parent 5d7045be13
commit 03d0f4af2d
22 changed files with 348 additions and 139 deletions

View File

@ -1,3 +1,8 @@
Sun Aug 23 11:56:08 1998 Mark Mitchell <mark@markmitchell.com>
* extend.texi: Remove description of extension to explicit
instantiation that is now endorsed by standard C++.
Sun Aug 23 09:39:09 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
* config/arc/arc.c (arc_initialize_pic): Remove.

View File

@ -1,3 +1,34 @@
1998-08-23 Mark Mitchell <mark@markmitchell.com>
* decl2.c (grok_array_decl): Add comment.
(mark_used): Don't instantiate an explicit instantiation.
* friend.c (make_friend_class): Remove bogus comment. Fix check
for partial specializations.
* pt.c (check_explicit_specialization): Don't
SET_DECL_EXPLICIT_INSTANTIATION here.
(mark_decl_instantiated): Or here.
(do_decl_instantiation): Do it here, instead. Add checks for
duplicate explicit instantiations, etc. Tidy.
(do_type_instantiation): Likewise.
(instantiate_decl): Improve comments. Complain about explicit
instantiations where no definition is available.
* cp-tree.h (ansi_null_node): Remove.
* call.c (build_over_call): Warn about converting NULL to an
arithmetic type.
* cvt.c (build_expr_type_conversion): Likewise. Use
null_ptr_cst_p instead of expanding it inline.
* decl.c (ansi_null_node): Remove.
(init_decl_processing): Make null_node always have integral type.
* except.c (build_throw): Warn about converting NULL to an
arithmetic type.
* lex.c (init_parse): Remove handling of ansi_null_node.
* pt.c (type_unification_real): Don't convert NULL to void* type.
* typeck.c (build_binary_op_nodefault): Fix NULL warnings.
(convert_for_assignment): Warn about converting NULL to an
arithmetic type.
(convert_for_initialization): Likewise.
1998-08-20 Jason Merrill <jason@yorick.cygnus.com>
* tree.c (search_tree, no_linkage_helper, no_linkage_check): New fn.

View File

@ -3331,7 +3331,14 @@ build_over_call (cand, args, flags)
"argument passing", fn, i - is_method);
}
else
val = convert_like (conv, TREE_VALUE (arg));
{
/* Issue warnings about peculiar, but legal, uses of NULL. */
if (ARITHMETIC_TYPE_P (TREE_VALUE (parm))
&& TREE_VALUE (arg) == null_node)
cp_warning ("converting NULL to non-pointer type");
val = convert_like (conv, TREE_VALUE (arg));
}
#ifdef PROMOTE_PROTOTYPES
if ((TREE_CODE (type) == INTEGER_TYPE

View File

@ -1918,7 +1918,6 @@ extern tree long_long_integer_type_node, long_long_unsigned_type_node;
extern tree integer_two_node, integer_three_node;
extern tree boolean_type_node, boolean_true_node, boolean_false_node;
extern tree ansi_null_node;
extern tree null_node;
/* in pt.c */

View File

@ -946,6 +946,11 @@ build_expr_type_conversion (desires, expr, complain)
tree conv;
tree winner = NULL_TREE;
if (expr == null_node
&& (desires & WANT_INT)
&& !(desires & WANT_NULL))
cp_warning ("converting NULL to non-pointer type");
if (TREE_CODE (basetype) == OFFSET_TYPE)
expr = resolve_offset_ref (expr);
expr = convert_from_reference (expr);
@ -955,8 +960,7 @@ build_expr_type_conversion (desires, expr, complain)
switch (TREE_CODE (basetype))
{
case INTEGER_TYPE:
if ((desires & WANT_NULL) && TREE_CODE (expr) == INTEGER_CST
&& integer_zerop (expr))
if ((desires & WANT_NULL) && null_ptr_cst_p (expr))
return expr;
/* else fall through... */

View File

@ -429,13 +429,8 @@ tree static_aggregates;
tree integer_zero_node;
tree null_pointer_node;
/* The value for __null (NULL), when -ansi is specified. As per the
standard, this is an implementation-defined null pointer constant. */
tree ansi_null_node;
/* The value for __null (NULL). With -ansi, this is just
ansi_null_node. Without -ansi, this is a zero-valued pointer
constant of type `{unknown type}*'. */
/* The value for __null (NULL), namely, a zero of an integer type with
the same number of bits as a pointer. */
tree null_node;
/* A node for the integer constants 1, 2, and 3. */
@ -6035,9 +6030,7 @@ init_decl_processing ()
/* Indirecting an UNKNOWN_TYPE node yields an UNKNOWN_TYPE node. */
TREE_TYPE (unknown_type_node) = unknown_type_node;
TREE_TYPE (ansi_null_node) = type_for_size (POINTER_SIZE, 0);
if (!flag_ansi)
TREE_TYPE (null_node) = build_pointer_type (unknown_type_node);
TREE_TYPE (null_node) = type_for_size (POINTER_SIZE, 0);
/* Looking up TYPE_POINTER_TO and TYPE_REFERENCE_TO yield the same
result. */

View File

@ -1223,7 +1223,9 @@ grok_array_decl (array_expr, index_exp)
return build_opfncall (ARRAY_REF, LOOKUP_NORMAL,
array_expr, index_exp, NULL_TREE);
/* Otherwise, create an ARRAY_REF for a pointer or array type. */
/* Otherwise, create an ARRAY_REF for a pointer or array type. It
is a little-known fact that, if `a' is an array and `i' is an
int, you can write `i[a]', which means the same thing as `a[i]'. */
if (TREE_CODE (type) == ARRAY_TYPE)
p1 = array_expr;
@ -4900,9 +4902,11 @@ mark_used (decl)
template, we now know that we will need to actually do the
instantiation. A TEMPLATE_DECL may also have DECL_TEMPLATE_INFO,
if it's a partial instantiation, but there's no need to
instantiate such a thing. */
instantiate such a thing. We check that DECL is not an explicit
instantiation because that is not checked in instantiate_decl. */
if (TREE_CODE (decl) != TEMPLATE_DECL
&& DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl))
&& DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl)
&& !DECL_EXPLICIT_INSTANTIATION (decl))
instantiate_decl (decl);
}

View File

@ -1278,10 +1278,7 @@ build_throw (e)
return build_min (THROW_EXPR, void_type_node, e);
if (e == null_node)
{
cp_warning ("throwing NULL, which has integral, not pointer type");
e = ansi_null_node;
}
cp_warning ("throwing NULL, which has integral, not pointer type");
e = build1 (THROW_EXPR, void_type_node, e);
TREE_SIDE_EFFECTS (e) = 1;

View File

@ -262,15 +262,13 @@ make_friend_class (type, friend_type)
return;
}
if (CLASSTYPE_TEMPLATE_SPECIALIZATION (friend_type))
if (CLASSTYPE_TEMPLATE_SPECIALIZATION (friend_type)
&& uses_template_parms (friend_type))
{
/* [temp.friend]
Friend declarations shall not declare partial
specializations.
Note that CLASSTYPE_TEMPLATE_SPECIALIZATION is not set for
full specializations. */
specializations. */
cp_error ("partial specialization `%T' declared `friend'",
friend_type);
return;

View File

@ -781,11 +781,7 @@ init_parse (filename)
type_for_size here because integer_type_node and so forth are not
set up. Therefore, we don't set the type of these nodes until
init_decl_processing. */
ansi_null_node = build_int_2 (0, 0);
if (flag_ansi)
null_node = ansi_null_node;
else
null_node = build_int_2 (0, 0);
null_node = build_int_2 (0, 0);
ridpointers[RID_NULL] = null_node;
opname_tab[(int) COMPONENT_REF] = "->";

View File

@ -1299,14 +1299,9 @@ check_explicit_specialization (declarator, decl, template_count, flags)
if (explicit_instantiation)
{
/* We don't set DECL_EXPLICIT_INSTANTIATION here; that
is done by do_decl_instantiation later. */
decl = instantiate_template (tmpl, innermost_args (targs));
if (!DECL_TEMPLATE_SPECIALIZATION (decl))
/* There doesn't seem to be anything in the draft to
prevent a specialization from being explicitly
instantiated. We're careful not to destroy the
information indicating that this is a
specialization here. */
SET_DECL_EXPLICIT_INSTANTIATION (decl);
return decl;
}
@ -6595,12 +6590,6 @@ type_unification_real (tparms, targs, parms, args, subr,
arg = TREE_TYPE (arg);
}
#endif
if (! flag_ansi && arg == TREE_TYPE (null_node))
{
warning ("using type void* for NULL");
arg = ptr_type_node;
}
if (!subr)
maybe_adjust_types_for_deduction (strict, &parm, &arg);
@ -7109,14 +7098,15 @@ unify (tparms, targs, parm, arg, strict, explicit_mask)
}
}
/* Called if RESULT is explicitly instantiated, or is a member of an
explicitly instantiated class, or if using -frepo and the
instantiation of RESULT has been assigned to this file. */
void
mark_decl_instantiated (result, extern_p)
tree result;
int extern_p;
{
if (DECL_TEMPLATE_INSTANTIATION (result))
SET_DECL_EXPLICIT_INSTANTIATION (result);
if (TREE_CODE (result) != FUNCTION_DECL)
/* The TREE_PUBLIC flag for function declarations will have been
set correctly by tsubst. */
@ -7458,39 +7448,69 @@ do_decl_instantiation (declspecs, declarator, storage)
cp_error ("explicit instantiation of non-template `%#D'", decl);
return;
}
/* If we've already seen this template instance, use it. */
if (TREE_CODE (decl) == VAR_DECL)
else if (TREE_CODE (decl) == VAR_DECL)
{
/* There is an asymmetry here in the way VAR_DECLs and
FUNCTION_DECLs are handled by grokdeclarator. In the case of
the latter, the DECL we get back will be marked as a
template instantiation, and the appropriate
DECL_TEMPLATE_INFO will be set up. This does not happen for
VAR_DECLs so we do the lookup here. Probably, grokdeclarator
should handle VAR_DECLs as it currently handles
FUNCTION_DECLs. */
result = lookup_field (DECL_CONTEXT (decl), DECL_NAME (decl), 0, 0);
if (result && TREE_CODE (result) != VAR_DECL)
result = NULL_TREE;
{
cp_error ("no matching template for `%D' found", result);
return;
}
}
else if (TREE_CODE (decl) != FUNCTION_DECL)
{
cp_error ("explicit instantiation of `%#D'", decl);
return;
}
else if (DECL_TEMPLATE_SPECIALIZATION (decl))
/* [temp.spec]
No program shall both explicitly instantiate and explicitly
specialize a template. */
{
cp_error ("explicit instantiation of `%#D' after", decl);
cp_error_at ("explicit specialization here", decl);
return;
}
else if (DECL_TEMPLATE_INSTANTIATION (decl))
else
result = decl;
if (! result)
/* Check for various error cases. Note that if the explicit
instantiation is legal the RESULT will currently be marked as an
*implicit* instantiation; DECL_EXPLICIT_INSTANTIATION is not set
until we get here. */
if (DECL_TEMPLATE_SPECIALIZATION (result))
{
cp_error ("no matching template for `%D' found", decl);
/* [temp.spec]
No program shall both explicitly instantiate and explicitly
specialize a template. */
cp_error ("explicit instantiation of `%#D' after", result);
cp_error_at ("explicit specialization here", result);
return;
}
else if (DECL_EXPLICIT_INSTANTIATION (result))
{
/* [temp.spec]
if (! DECL_TEMPLATE_INFO (result))
No program shall explicitly instantiate any template more
than once.
We check DECL_INTERFACE_KNOWN so as not to complain when the
first instantiation was `extern' and the second is not, and
EXTERN_P for the opposite case. */
if (DECL_INTERFACE_KNOWN (result) && !extern_p)
cp_error ("duplicate explicit instantiation of `%#D'", result);
/* If we've already instantiated the template, just return now. */
if (DECL_INTERFACE_KNOWN (result))
return;
}
else if (!DECL_IMPLICIT_INSTANTIATION (result))
{
cp_error ("no matching template for `%D' found", result);
return;
}
else if (!DECL_TEMPLATE_INFO (result))
{
cp_pedwarn ("explicit instantiation of non-template `%#D'", result);
return;
@ -7502,11 +7522,16 @@ do_decl_instantiation (declspecs, declarator, storage)
if (storage == NULL_TREE)
;
else if (storage == ridpointers[(int) RID_EXTERN])
extern_p = 1;
{
if (pedantic)
cp_pedwarn ("ANSI C++ forbids the use of `extern' on explicit instantiations");
extern_p = 1;
}
else
cp_error ("storage class `%D' applied to template instantiation",
storage);
SET_DECL_EXPLICIT_INSTANTIATION (result);
mark_decl_instantiated (result, extern_p);
repo_template_instantiated (result, extern_p);
if (! extern_p)
@ -7561,31 +7586,56 @@ do_type_instantiation (t, storage)
return;
}
if (storage == NULL_TREE)
/* OK */;
else if (storage == ridpointers[(int) RID_INLINE])
nomem_p = 1;
else if (storage == ridpointers[(int) RID_EXTERN])
extern_p = 1;
else if (storage == ridpointers[(int) RID_STATIC])
static_p = 1;
else
if (storage != NULL_TREE)
{
cp_error ("storage class `%D' applied to template instantiation",
storage);
extern_p = 0;
if (pedantic)
cp_pedwarn("ANSI C++ forbids the use of `%s' on explicit instantiations",
IDENTIFIER_POINTER (storage));
if (storage == ridpointers[(int) RID_INLINE])
nomem_p = 1;
else if (storage == ridpointers[(int) RID_EXTERN])
extern_p = 1;
else if (storage == ridpointers[(int) RID_STATIC])
static_p = 1;
else
{
cp_error ("storage class `%D' applied to template instantiation",
storage);
extern_p = 0;
}
}
/* We've already instantiated this. */
if (CLASSTYPE_EXPLICIT_INSTANTIATION (t) && ! CLASSTYPE_INTERFACE_ONLY (t)
&& extern_p)
return;
if (! CLASSTYPE_TEMPLATE_SPECIALIZATION (t))
if (CLASSTYPE_TEMPLATE_SPECIALIZATION (t))
{
mark_class_instantiated (t, extern_p);
repo_template_instantiated (t, extern_p);
/* [temp.spec]
No program shall both explicitly instantiate and explicitly
specialize a template. */
cp_error ("explicit instantiation of `%#T' after", t);
cp_error_at ("explicit specialization here", t);
return;
}
else if (CLASSTYPE_EXPLICIT_INSTANTIATION (t))
{
/* [temp.spec]
No program shall explicitly instantiate any template more
than once.
If CLASSTYPE_INTERFACE_ONLY, then the first explicit
instantiation was `extern', and if EXTERN_P then the second
is. Both cases are OK. */
if (!CLASSTYPE_INTERFACE_ONLY (t) && !extern_p)
cp_error ("duplicate explicit instantiation of `%#T'", t);
/* If we've already instantiated the template, just return now. */
if (!CLASSTYPE_INTERFACE_ONLY (t))
return;
}
mark_class_instantiated (t, extern_p);
repo_template_instantiated (t, extern_p);
if (nomem_p)
return;
@ -7593,6 +7643,25 @@ do_type_instantiation (t, storage)
{
tree tmp;
/* In contrast to implicit instantiation, where only the
declarations, and not the definitions, of members are
instantiated, we have here:
[temp.explicit]
The explicit instantiation of a class template specialization
implies the instantiation of all of its members not
previously explicitly specialized in the translation unit
containing the explicit instantiation.
Of course, we can't instantiate member template classes, since
we don't have any arguments for them. Note that the standard
is unclear on whether the instatiation of the members are
*explicit* instantiations or not. We choose to be generous,
and not set DECL_EXPLICIT_INSTANTIATION. Therefore, we allow
the explicit instantiation of a class where some of the members
have no definition in the current translation unit. */
if (! static_p)
for (tmp = TYPE_METHODS (t); tmp; tmp = TREE_CHAIN (tmp))
if (TREE_CODE (tmp) == FUNCTION_DECL
@ -7613,19 +7682,6 @@ do_type_instantiation (t, storage)
instantiate_decl (tmp);
}
/* In contrast to implicit instantiation, where only the
declarations, and not the definitions, of members are
instantiated, we have here:
[temp.explicit]
The explicit instantiation of a class template specialization
implies the instantiation of all of its members not
previously explicitly specialized in the translation unit
containing the explicit instantiation.
Of course, we can't instantiate member template classes, since
we don't have any arguments for them. */
for (tmp = CLASSTYPE_TAGS (t); tmp; tmp = TREE_CHAIN (tmp))
if (IS_AGGR_TYPE (TREE_VALUE (tmp))
&& !uses_template_parms (CLASSTYPE_TI_ARGS (TREE_VALUE (tmp))))
@ -7783,7 +7839,11 @@ instantiate_decl (d)
if ((TREE_CODE (d) == FUNCTION_DECL && DECL_INITIAL (d))
|| (TREE_CODE (d) == VAR_DECL && !DECL_IN_AGGR_P (d)))
/* D has already been instantiated. */
/* D has already been instantiated. It might seem reasonable to
check whether or not D is an explict instantiation, and, if so,
stop here. But when an explicit instantiation is deferred
until the end of the compilation, DECL_EXPLICIT_INSTANTIATION
is set, even though we still need to do the instantiation. */
return d;
/* If we already have a specialization of this declaration, then
@ -7911,6 +7971,18 @@ instantiate_decl (d)
lineno = line;
input_filename = file;
if (at_eof && !pattern_defined
&& DECL_EXPLICIT_INSTANTIATION (d))
/* [temp.explicit]
The definition of a non-exported function template, a
non-exported member function template, or a non-exported
member function or static data member of a class template
shall be present in every translation unit in which it is
explicitly instantiated. */
cp_error ("explicit instantiation of `%D' but no definition available",
d);
add_pending_template (d);
goto out;
}

View File

@ -3244,25 +3244,18 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
/* Nonzero means set RESULT_TYPE to the common type of the args. */
int common = 0;
/* Unless -ansi is specified, __null has pointer type. But, then,
things like `7 != NULL' result in errors about comparisons
between pointers and integers. So, here, we replace __null with
an appropriate null pointer constant. */
op0 = (orig_op0 == null_node) ? ansi_null_node : orig_op0;
op1 = (orig_op1 == null_node) ? ansi_null_node : orig_op1;
/* Apply default conversions. */
if (code == TRUTH_AND_EXPR || code == TRUTH_ANDIF_EXPR
|| code == TRUTH_OR_EXPR || code == TRUTH_ORIF_EXPR
|| code == TRUTH_XOR_EXPR)
{
op0 = decay_conversion (op0);
op1 = decay_conversion (op1);
op0 = decay_conversion (orig_op0);
op1 = decay_conversion (orig_op1);
}
else
{
op0 = default_conversion (op0);
op1 = default_conversion (op1);
op0 = default_conversion (orig_op0);
op1 = default_conversion (orig_op1);
}
type0 = TREE_TYPE (op0);
@ -3961,15 +3954,19 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
return error_mark_node;
}
if (/* If OP0 is NULL and OP1 is not a pointer, or vice versa. */
(orig_op0 == null_node
&& TREE_CODE (TREE_TYPE (orig_op1)) != POINTER_TYPE)
/* Or vice versa. */
|| (orig_op1 == null_node
&& TREE_CODE (TREE_TYPE (orig_op0)) != POINTER_TYPE)
/* Or, both are NULL and the operation was not a comparison. */
|| (orig_op0 == null_node && orig_op1 == null_node
&& code != EQ_EXPR && code != NE_EXPR))
/* Issue warnings about peculiar, but legal, uses of NULL. */
if (/* It's reasonable to use pointer values as operands of &&
and ||, so NULL is no exception. */
!(code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR)
&& (/* If OP0 is NULL and OP1 is not a pointer, or vice versa. */
(orig_op0 == null_node
&& TREE_CODE (TREE_TYPE (op1)) != POINTER_TYPE)
/* Or vice versa. */
|| (orig_op1 == null_node
&& TREE_CODE (TREE_TYPE (op0)) != POINTER_TYPE)
/* Or, both are NULL and the operation was not a comparison. */
|| (orig_op0 == null_node && orig_op1 == null_node
&& code != EQ_EXPR && code != NE_EXPR)))
/* Some sort of arithmetic operation involving NULL was
performed. Note that pointer-difference and pointer-addition
have already been handled above, and so we don't end up here in
@ -6593,6 +6590,10 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
register tree rhstype;
register enum tree_code coder = TREE_CODE (TREE_TYPE (rhs));
/* Issue warnings about peculiar, but legal, uses of NULL. */
if (ARITHMETIC_TYPE_P (type) && rhs == null_node)
cp_warning ("converting NULL to non-pointer type");
if (coder == UNKNOWN_TYPE)
rhs = instantiate_type (type, rhs, 1);
@ -7046,6 +7047,10 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum)
register tree rhstype;
register enum tree_code coder;
/* Issue warnings about peculiar, but legal, uses of NULL. */
if (ARITHMETIC_TYPE_P (type) && rhs == null_node)
cp_warning ("converting NULL to non-pointer type");
/* build_c_cast puts on a NOP_EXPR to make the result not an lvalue.
Strip such NOP_EXPRs, since RHS is used in non-lvalue context. */
if (TREE_CODE (rhs) == NOP_EXPR

View File

@ -3330,14 +3330,12 @@ instances required by your explicit instantiations (but not by any
other files) without having to specify them as well.
g++ has extended the template instantiation syntax outlined in the
Working Paper to allow forward declaration of explicit instantiations,
explicit instantiation of members of template classes and instantiation
of the compiler support data for a template class (i.e. the vtable)
without instantiating any of its members:
Working Paper to allow forward declaration of explicit instantiations
and instantiation of the compiler support data for a template class
(i.e. the vtable) without instantiating any of its members:
@example
extern template int max (int, int);
template void Foo<int>::f ();
inline template class Foo<int>;
@end example

View File

@ -1,12 +1,40 @@
// Build don't link:
// Build don't run:
#include <cstddef>
void f()
void g(int) {}
extern void g(void*);
template <int I>
void h() {}
void k(int) {}
template <class T>
void l(T);
template <>
void l(int) {}
int main()
{
int i;
float f;
int i = NULL; // WARNING - converting NULL to non-pointer type
float z = NULL; // WARNING - converting NULL to non-pointer type
int a[2];
i != NULL; // WARNING - NULL used in arithmetic
f != NULL; // WARNING - NULL used in arithmetic
NULL != z; // WARNING - NULL used in arithmetic
k != NULL; // No warning: decay conversion
NULL != a; // Likewise.
-NULL; // WARNING - converting NULL to non-pointer type
+NULL; // WARNING - converting NULL to non-pointer type
~NULL; // WARNING - converting NULL to non-pointer type
a[NULL] = 3; // WARNING - converting NULL to non-pointer-type
i = NULL; // WARNING - converting NULL to non-pointer type
z = NULL; // WARNING - converting NULL to non-pointer type
k(NULL); // WARNING - converting NULL to int
g(NULL); // WARNING - converting NULL to int
h<NULL>(); // WARNING - NULL bound to integer template parameter
l(NULL); // WARNING - converting NULL to int
NULL && NULL; // No warning: converting NULL to bool is OK
}

View File

@ -0,0 +1,43 @@
// Build don't link:
template <class T>
void f(T) {}
template <class T>
struct S {
static T t;
};
template <class T>
T S<T>::t;
template void f(int);
template void f(int); // ERROR - duplicate explicit instantiation
template int S<int>::t;
template int S<int>::t; // ERROR - duplicate explicit instantiation
template class S<double>;
template class S<double>; // ERROR - duplicate explicit instantiation
extern template void f(double); // WARNING - extern not allowed
inline template class S<float>; // WARNING - inline not allowed
template <class T>
struct S<T*> {};
template class S<void*>; // OK - explicit instantiation of partial
// specialization
template <>
struct S<long double> {}; // ERROR - explicit specialization
template class S<long double>; // ERROR - explicit instantiation after
template <>
void f(long double) {} // ERROR - explicit specialization
template void f(long double); // ERROR - explicit instantiation after
template <class T>
void g(T);
template void g(int); // ERROR - no definition of g.

View File

@ -0,0 +1,12 @@
// Build don't link:
template <class T>
struct S1 {
};
template <>
struct S1<int> {};
struct S2 {
friend class S1<int>;
};

View File

@ -1,7 +1,7 @@
// Build don't link:
template <class T>
void f(T t);
void f(T t) {}
template void f<int>(int);
template void f<>(long);

View File

@ -1,3 +1,8 @@
1998-08-23 Mark Mitchell <mark@markmitchell.com>
* iomanip.h: Use __extension__ for `extern' explicit template
instantiations.
1998-08-17 Ulrich Drepper <drepper@cygnus.com>
* strfile.h: Define __PMT if not already defined.

View File

@ -68,8 +68,8 @@ public:
};
#ifdef __GNUG__
extern template class smanip<int>;
extern template class smanip<ios::fmtflags>;
__extension__ extern template class smanip<int>;
__extension__ extern template class smanip<ios::fmtflags>;
#endif
template<class TP>
@ -81,10 +81,14 @@ inline ostream& operator<<(ostream& o, const smanip<TP>& m)
{ (*m._f)(o, m._a); return o;}
#ifdef __GNUG__
extern template istream& operator>>(istream&, const smanip<int>&);
extern template istream& operator>>(istream&, const smanip<ios::fmtflags>&);
extern template ostream& operator<<(ostream&, const smanip<int>&);
extern template ostream& operator<<(ostream&, const smanip<ios::fmtflags>&);
__extension__ extern
template istream& operator>>(istream&, const smanip<int>&);
__extension__ extern
template istream& operator>>(istream&, const smanip<ios::fmtflags>&);
__extension__ extern
template ostream& operator<<(ostream&, const smanip<int>&);
__extension__ extern
template ostream& operator<<(ostream&, const smanip<ios::fmtflags>&);
#endif
//-----------------------------------------------------------------------------

View File

@ -1,3 +1,9 @@
1998-08-23 Mark Mitchell <mark@markmitchell.com>
* sinst.cc: Don't explicitly instantiation string_char_traits<char>.
* cinst.cc: Likewiwse, for complex<float>, complex<double>,
complex<long double>.
1998-08-17 Mark Mitchell <mark@markmitchell.com>
* stdexcept: Put things in the std namespace, if appropriate.

View File

@ -32,7 +32,6 @@ typedef complex<f> c;
typedef const c& ccr;
#ifdef MAIN
template class complex<f>;
template c& __doapl (c*, ccr);
template c& __doaml (c*, ccr);
template c& __doami (c*, ccr);

View File

@ -42,8 +42,11 @@ typedef char c;
typedef wchar_t c;
#endif
#ifdef TRAITS
#if defined(TRAITS) && !defined(C)
template class string_char_traits <c>;
#else
/* string_char_traits<char> is already explicitly specialized in
std/straits.h. */
#endif
typedef basic_string <c> s;