Commit 03d0f4af by Mark Mitchell Committed by Mark Mitchell

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
parent 5d7045be
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.
......
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.
......
......@@ -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
......
......@@ -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 */
......
......@@ -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... */
......
......@@ -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. */
......
......@@ -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);
}
......
......@@ -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;
......
......@@ -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;
......
......@@ -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] = "->";
......
......@@ -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
......
......@@ -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
......
// 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
}
// 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.
// Build don't link:
template <class T>
struct S1 {
};
template <>
struct S1<int> {};
struct S2 {
friend class S1<int>;
};
// Build don't link:
template <class T>
void f(T t);
void f(T t) {}
template void f<int>(int);
template void f<>(long);
......
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.
......
......@@ -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
//-----------------------------------------------------------------------------
......
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.
......
......@@ -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);
......
......@@ -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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment