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> Sun Aug 23 09:39:09 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
* config/arc/arc.c (arc_initialize_pic): Remove. * 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> 1998-08-20 Jason Merrill <jason@yorick.cygnus.com>
* tree.c (search_tree, no_linkage_helper, no_linkage_check): New fn. * tree.c (search_tree, no_linkage_helper, no_linkage_check): New fn.
......
...@@ -3331,7 +3331,14 @@ build_over_call (cand, args, flags) ...@@ -3331,7 +3331,14 @@ build_over_call (cand, args, flags)
"argument passing", fn, i - is_method); "argument passing", fn, i - is_method);
} }
else 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 #ifdef PROMOTE_PROTOTYPES
if ((TREE_CODE (type) == INTEGER_TYPE if ((TREE_CODE (type) == INTEGER_TYPE
......
...@@ -1918,7 +1918,6 @@ extern tree long_long_integer_type_node, long_long_unsigned_type_node; ...@@ -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 integer_two_node, integer_three_node;
extern tree boolean_type_node, boolean_true_node, boolean_false_node; extern tree boolean_type_node, boolean_true_node, boolean_false_node;
extern tree ansi_null_node;
extern tree null_node; extern tree null_node;
/* in pt.c */ /* in pt.c */
......
...@@ -946,6 +946,11 @@ build_expr_type_conversion (desires, expr, complain) ...@@ -946,6 +946,11 @@ build_expr_type_conversion (desires, expr, complain)
tree conv; tree conv;
tree winner = NULL_TREE; 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) if (TREE_CODE (basetype) == OFFSET_TYPE)
expr = resolve_offset_ref (expr); expr = resolve_offset_ref (expr);
expr = convert_from_reference (expr); expr = convert_from_reference (expr);
...@@ -955,8 +960,7 @@ build_expr_type_conversion (desires, expr, complain) ...@@ -955,8 +960,7 @@ build_expr_type_conversion (desires, expr, complain)
switch (TREE_CODE (basetype)) switch (TREE_CODE (basetype))
{ {
case INTEGER_TYPE: case INTEGER_TYPE:
if ((desires & WANT_NULL) && TREE_CODE (expr) == INTEGER_CST if ((desires & WANT_NULL) && null_ptr_cst_p (expr))
&& integer_zerop (expr))
return expr; return expr;
/* else fall through... */ /* else fall through... */
......
...@@ -429,13 +429,8 @@ tree static_aggregates; ...@@ -429,13 +429,8 @@ tree static_aggregates;
tree integer_zero_node; tree integer_zero_node;
tree null_pointer_node; tree null_pointer_node;
/* The value for __null (NULL), when -ansi is specified. As per the /* The value for __null (NULL), namely, a zero of an integer type with
standard, this is an implementation-defined null pointer constant. */ the same number of bits as a pointer. */
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}*'. */
tree null_node; tree null_node;
/* A node for the integer constants 1, 2, and 3. */ /* A node for the integer constants 1, 2, and 3. */
...@@ -6035,9 +6030,7 @@ init_decl_processing () ...@@ -6035,9 +6030,7 @@ init_decl_processing ()
/* Indirecting an UNKNOWN_TYPE node yields an UNKNOWN_TYPE node. */ /* Indirecting an UNKNOWN_TYPE node yields an UNKNOWN_TYPE node. */
TREE_TYPE (unknown_type_node) = unknown_type_node; TREE_TYPE (unknown_type_node) = unknown_type_node;
TREE_TYPE (ansi_null_node) = type_for_size (POINTER_SIZE, 0); TREE_TYPE (null_node) = type_for_size (POINTER_SIZE, 0);
if (!flag_ansi)
TREE_TYPE (null_node) = build_pointer_type (unknown_type_node);
/* Looking up TYPE_POINTER_TO and TYPE_REFERENCE_TO yield the same /* Looking up TYPE_POINTER_TO and TYPE_REFERENCE_TO yield the same
result. */ result. */
......
...@@ -1223,7 +1223,9 @@ grok_array_decl (array_expr, index_exp) ...@@ -1223,7 +1223,9 @@ grok_array_decl (array_expr, index_exp)
return build_opfncall (ARRAY_REF, LOOKUP_NORMAL, return build_opfncall (ARRAY_REF, LOOKUP_NORMAL,
array_expr, index_exp, NULL_TREE); 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) if (TREE_CODE (type) == ARRAY_TYPE)
p1 = array_expr; p1 = array_expr;
...@@ -4900,9 +4902,11 @@ mark_used (decl) ...@@ -4900,9 +4902,11 @@ mark_used (decl)
template, we now know that we will need to actually do the template, we now know that we will need to actually do the
instantiation. A TEMPLATE_DECL may also have DECL_TEMPLATE_INFO, instantiation. A TEMPLATE_DECL may also have DECL_TEMPLATE_INFO,
if it's a partial instantiation, but there's no need to 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 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); instantiate_decl (decl);
} }
......
...@@ -1278,10 +1278,7 @@ build_throw (e) ...@@ -1278,10 +1278,7 @@ build_throw (e)
return build_min (THROW_EXPR, void_type_node, e); return build_min (THROW_EXPR, void_type_node, e);
if (e == null_node) if (e == null_node)
{ cp_warning ("throwing NULL, which has integral, not pointer type");
cp_warning ("throwing NULL, which has integral, not pointer type");
e = ansi_null_node;
}
e = build1 (THROW_EXPR, void_type_node, e); e = build1 (THROW_EXPR, void_type_node, e);
TREE_SIDE_EFFECTS (e) = 1; TREE_SIDE_EFFECTS (e) = 1;
......
...@@ -262,15 +262,13 @@ make_friend_class (type, friend_type) ...@@ -262,15 +262,13 @@ make_friend_class (type, friend_type)
return; return;
} }
if (CLASSTYPE_TEMPLATE_SPECIALIZATION (friend_type)) if (CLASSTYPE_TEMPLATE_SPECIALIZATION (friend_type)
&& uses_template_parms (friend_type))
{ {
/* [temp.friend] /* [temp.friend]
Friend declarations shall not declare partial Friend declarations shall not declare partial
specializations. specializations. */
Note that CLASSTYPE_TEMPLATE_SPECIALIZATION is not set for
full specializations. */
cp_error ("partial specialization `%T' declared `friend'", cp_error ("partial specialization `%T' declared `friend'",
friend_type); friend_type);
return; return;
......
...@@ -781,11 +781,7 @@ init_parse (filename) ...@@ -781,11 +781,7 @@ init_parse (filename)
type_for_size here because integer_type_node and so forth are not 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 set up. Therefore, we don't set the type of these nodes until
init_decl_processing. */ init_decl_processing. */
ansi_null_node = build_int_2 (0, 0); null_node = build_int_2 (0, 0);
if (flag_ansi)
null_node = ansi_null_node;
else
null_node = build_int_2 (0, 0);
ridpointers[RID_NULL] = null_node; ridpointers[RID_NULL] = null_node;
opname_tab[(int) COMPONENT_REF] = "->"; opname_tab[(int) COMPONENT_REF] = "->";
......
...@@ -3244,25 +3244,18 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) ...@@ -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. */ /* Nonzero means set RESULT_TYPE to the common type of the args. */
int common = 0; 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. */ /* Apply default conversions. */
if (code == TRUTH_AND_EXPR || code == TRUTH_ANDIF_EXPR if (code == TRUTH_AND_EXPR || code == TRUTH_ANDIF_EXPR
|| code == TRUTH_OR_EXPR || code == TRUTH_ORIF_EXPR || code == TRUTH_OR_EXPR || code == TRUTH_ORIF_EXPR
|| code == TRUTH_XOR_EXPR) || code == TRUTH_XOR_EXPR)
{ {
op0 = decay_conversion (op0); op0 = decay_conversion (orig_op0);
op1 = decay_conversion (op1); op1 = decay_conversion (orig_op1);
} }
else else
{ {
op0 = default_conversion (op0); op0 = default_conversion (orig_op0);
op1 = default_conversion (op1); op1 = default_conversion (orig_op1);
} }
type0 = TREE_TYPE (op0); type0 = TREE_TYPE (op0);
...@@ -3961,15 +3954,19 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) ...@@ -3961,15 +3954,19 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
return error_mark_node; return error_mark_node;
} }
if (/* If OP0 is NULL and OP1 is not a pointer, or vice versa. */ /* Issue warnings about peculiar, but legal, uses of NULL. */
(orig_op0 == null_node if (/* It's reasonable to use pointer values as operands of &&
&& TREE_CODE (TREE_TYPE (orig_op1)) != POINTER_TYPE) and ||, so NULL is no exception. */
/* Or vice versa. */ !(code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR)
|| (orig_op1 == null_node && (/* If OP0 is NULL and OP1 is not a pointer, or vice versa. */
&& TREE_CODE (TREE_TYPE (orig_op0)) != POINTER_TYPE) (orig_op0 == null_node
/* Or, both are NULL and the operation was not a comparison. */ && TREE_CODE (TREE_TYPE (op1)) != POINTER_TYPE)
|| (orig_op0 == null_node && orig_op1 == null_node /* Or vice versa. */
&& code != EQ_EXPR && code != NE_EXPR)) || (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 /* Some sort of arithmetic operation involving NULL was
performed. Note that pointer-difference and pointer-addition performed. Note that pointer-difference and pointer-addition
have already been handled above, and so we don't end up here in 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) ...@@ -6593,6 +6590,10 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
register tree rhstype; register tree rhstype;
register enum tree_code coder = TREE_CODE (TREE_TYPE (rhs)); 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) if (coder == UNKNOWN_TYPE)
rhs = instantiate_type (type, rhs, 1); rhs = instantiate_type (type, rhs, 1);
...@@ -7046,6 +7047,10 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum) ...@@ -7046,6 +7047,10 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum)
register tree rhstype; register tree rhstype;
register enum tree_code coder; 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. /* 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. */ Strip such NOP_EXPRs, since RHS is used in non-lvalue context. */
if (TREE_CODE (rhs) == NOP_EXPR if (TREE_CODE (rhs) == NOP_EXPR
......
...@@ -3330,14 +3330,12 @@ instances required by your explicit instantiations (but not by any ...@@ -3330,14 +3330,12 @@ instances required by your explicit instantiations (but not by any
other files) without having to specify them as well. other files) without having to specify them as well.
g++ has extended the template instantiation syntax outlined in the g++ has extended the template instantiation syntax outlined in the
Working Paper to allow forward declaration of explicit instantiations, Working Paper to allow forward declaration of explicit instantiations
explicit instantiation of members of template classes and instantiation and instantiation of the compiler support data for a template class
of the compiler support data for a template class (i.e. the vtable) (i.e. the vtable) without instantiating any of its members:
without instantiating any of its members:
@example @example
extern template int max (int, int); extern template int max (int, int);
template void Foo<int>::f ();
inline template class Foo<int>; inline template class Foo<int>;
@end example @end example
......
// Build don't link: // Build don't run:
#include <cstddef> #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; int i = NULL; // WARNING - converting NULL to non-pointer type
float f; float z = NULL; // WARNING - converting NULL to non-pointer type
int a[2];
i != NULL; // WARNING - NULL used in arithmetic 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: // Build don't link:
template <class T> template <class T>
void f(T t); void f(T t) {}
template void f<int>(int); template void f<int>(int);
template void f<>(long); 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> 1998-08-17 Ulrich Drepper <drepper@cygnus.com>
* strfile.h: Define __PMT if not already defined. * strfile.h: Define __PMT if not already defined.
......
...@@ -68,8 +68,8 @@ public: ...@@ -68,8 +68,8 @@ public:
}; };
#ifdef __GNUG__ #ifdef __GNUG__
extern template class smanip<int>; __extension__ extern template class smanip<int>;
extern template class smanip<ios::fmtflags>; __extension__ extern template class smanip<ios::fmtflags>;
#endif #endif
template<class TP> template<class TP>
...@@ -81,10 +81,14 @@ inline ostream& operator<<(ostream& o, const smanip<TP>& m) ...@@ -81,10 +81,14 @@ inline ostream& operator<<(ostream& o, const smanip<TP>& m)
{ (*m._f)(o, m._a); return o;} { (*m._f)(o, m._a); return o;}
#ifdef __GNUG__ #ifdef __GNUG__
extern template istream& operator>>(istream&, const smanip<int>&); __extension__ extern
extern template istream& operator>>(istream&, const smanip<ios::fmtflags>&); template istream& operator>>(istream&, const smanip<int>&);
extern template ostream& operator<<(ostream&, const smanip<int>&); __extension__ extern
extern template ostream& operator<<(ostream&, const smanip<ios::fmtflags>&); 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 #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> 1998-08-17 Mark Mitchell <mark@markmitchell.com>
* stdexcept: Put things in the std namespace, if appropriate. * stdexcept: Put things in the std namespace, if appropriate.
......
...@@ -32,7 +32,6 @@ typedef complex<f> c; ...@@ -32,7 +32,6 @@ typedef complex<f> c;
typedef const c& ccr; typedef const c& ccr;
#ifdef MAIN #ifdef MAIN
template class complex<f>;
template c& __doapl (c*, ccr); template c& __doapl (c*, ccr);
template c& __doaml (c*, ccr); template c& __doaml (c*, ccr);
template c& __doami (c*, ccr); template c& __doami (c*, ccr);
......
...@@ -42,8 +42,11 @@ typedef char c; ...@@ -42,8 +42,11 @@ typedef char c;
typedef wchar_t c; typedef wchar_t c;
#endif #endif
#ifdef TRAITS #if defined(TRAITS) && !defined(C)
template class string_char_traits <c>; template class string_char_traits <c>;
#else
/* string_char_traits<char> is already explicitly specialized in
std/straits.h. */
#endif #endif
typedef basic_string <c> s; 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