diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a87e9d41127..f059d699c75 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +Sun Aug 23 11:56:08 1998 Mark Mitchell + + * 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 * config/arc/arc.c (arc_initialize_pic): Remove. diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index c5f938b990f..bf714bf06f7 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,34 @@ +1998-08-23 Mark Mitchell + + * 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 * tree.c (search_tree, no_linkage_helper, no_linkage_check): New fn. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 5234a4b1762..3eb08178683 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -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 diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index b567b950638..82dc430bb2e 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -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 */ diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c index 1c6447a61b7..99289e824e3 100644 --- a/gcc/cp/cvt.c +++ b/gcc/cp/cvt.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... */ diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 251cbef8508..a93685d810c 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -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. */ diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 8e1d0c791ed..8d923be461c 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -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); } diff --git a/gcc/cp/except.c b/gcc/cp/except.c index 9a239485213..b441c6b628d 100644 --- a/gcc/cp/except.c +++ b/gcc/cp/except.c @@ -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; diff --git a/gcc/cp/friend.c b/gcc/cp/friend.c index db50258af71..a566d0504f5 100644 --- a/gcc/cp/friend.c +++ b/gcc/cp/friend.c @@ -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; diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c index 998817bc0b0..8ded741b576 100644 --- a/gcc/cp/lex.c +++ b/gcc/cp/lex.c @@ -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] = "->"; diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index b0202b13198..f156fe186bb 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -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; } diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 00a1add42b3..3f7995311cb 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -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 diff --git a/gcc/extend.texi b/gcc/extend.texi index 0fb01f444f5..45b31b82322 100644 --- a/gcc/extend.texi +++ b/gcc/extend.texi @@ -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::f (); inline template class Foo; @end example diff --git a/gcc/testsuite/g++.old-deja/g++.other/null1.C b/gcc/testsuite/g++.old-deja/g++.other/null1.C index 9965a4387a4..1c72d1cf8f8 100644 --- a/gcc/testsuite/g++.old-deja/g++.other/null1.C +++ b/gcc/testsuite/g++.old-deja/g++.other/null1.C @@ -1,12 +1,40 @@ -// Build don't link: +// Build don't run: #include -void f() +void g(int) {} +extern void g(void*); + +template +void h() {} + +void k(int) {} + +template +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(); // WARNING - NULL bound to integer template parameter + l(NULL); // WARNING - converting NULL to int + NULL && NULL; // No warning: converting NULL to bool is OK } diff --git a/gcc/testsuite/g++.old-deja/g++.pt/explicit70.C b/gcc/testsuite/g++.old-deja/g++.pt/explicit70.C new file mode 100644 index 00000000000..ade83fdc443 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.pt/explicit70.C @@ -0,0 +1,43 @@ +// Build don't link: + +template +void f(T) {} + +template +struct S { + static T t; +}; + +template +T S::t; + +template void f(int); +template void f(int); // ERROR - duplicate explicit instantiation +template int S::t; +template int S::t; // ERROR - duplicate explicit instantiation +template class S; +template class S; // ERROR - duplicate explicit instantiation + +extern template void f(double); // WARNING - extern not allowed +inline template class S; // WARNING - inline not allowed + +template +struct S {}; + +template class S; // OK - explicit instantiation of partial + // specialization + +template <> +struct S {}; // ERROR - explicit specialization + +template class S; // ERROR - explicit instantiation after + +template <> +void f(long double) {} // ERROR - explicit specialization + +template void f(long double); // ERROR - explicit instantiation after + +template +void g(T); + +template void g(int); // ERROR - no definition of g. diff --git a/gcc/testsuite/g++.old-deja/g++.pt/friend31.C b/gcc/testsuite/g++.old-deja/g++.pt/friend31.C new file mode 100644 index 00000000000..15a380b462a --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.pt/friend31.C @@ -0,0 +1,12 @@ +// Build don't link: + +template +struct S1 { +}; + +template <> +struct S1 {}; + +struct S2 { + friend class S1; +}; diff --git a/gcc/testsuite/g++.old-deja/g++.pt/instantiate1.C b/gcc/testsuite/g++.old-deja/g++.pt/instantiate1.C index 1d9c7580a68..11f9c781988 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/instantiate1.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/instantiate1.C @@ -1,7 +1,7 @@ // Build don't link: template -void f(T t); +void f(T t) {} template void f(int); template void f<>(long); diff --git a/libio/ChangeLog b/libio/ChangeLog index dfd5299e0fa..ee9ce72478e 100644 --- a/libio/ChangeLog +++ b/libio/ChangeLog @@ -1,3 +1,8 @@ +1998-08-23 Mark Mitchell + + * iomanip.h: Use __extension__ for `extern' explicit template + instantiations. + 1998-08-17 Ulrich Drepper * strfile.h: Define __PMT if not already defined. diff --git a/libio/iomanip.h b/libio/iomanip.h index d80e98ed604..7c0232ed1e1 100644 --- a/libio/iomanip.h +++ b/libio/iomanip.h @@ -68,8 +68,8 @@ public: }; #ifdef __GNUG__ -extern template class smanip; -extern template class smanip; +__extension__ extern template class smanip; +__extension__ extern template class smanip; #endif template @@ -81,10 +81,14 @@ inline ostream& operator<<(ostream& o, const smanip& m) { (*m._f)(o, m._a); return o;} #ifdef __GNUG__ -extern template istream& operator>>(istream&, const smanip&); -extern template istream& operator>>(istream&, const smanip&); -extern template ostream& operator<<(ostream&, const smanip&); -extern template ostream& operator<<(ostream&, const smanip&); +__extension__ extern +template istream& operator>>(istream&, const smanip&); +__extension__ extern +template istream& operator>>(istream&, const smanip&); +__extension__ extern +template ostream& operator<<(ostream&, const smanip&); +__extension__ extern +template ostream& operator<<(ostream&, const smanip&); #endif //----------------------------------------------------------------------------- diff --git a/libstdc++/ChangeLog b/libstdc++/ChangeLog index c9570fefbcf..2cb0d0a9255 100644 --- a/libstdc++/ChangeLog +++ b/libstdc++/ChangeLog @@ -1,3 +1,9 @@ +1998-08-23 Mark Mitchell + + * sinst.cc: Don't explicitly instantiation string_char_traits. + * cinst.cc: Likewiwse, for complex, complex, + complex. + 1998-08-17 Mark Mitchell * stdexcept: Put things in the std namespace, if appropriate. diff --git a/libstdc++/cinst.cc b/libstdc++/cinst.cc index 010f3cad5e6..983e8a9caa7 100644 --- a/libstdc++/cinst.cc +++ b/libstdc++/cinst.cc @@ -32,7 +32,6 @@ typedef complex c; typedef const c& ccr; #ifdef MAIN -template class complex; template c& __doapl (c*, ccr); template c& __doaml (c*, ccr); template c& __doami (c*, ccr); diff --git a/libstdc++/sinst.cc b/libstdc++/sinst.cc index 79c31a36933..0b3617ece62 100644 --- a/libstdc++/sinst.cc +++ b/libstdc++/sinst.cc @@ -42,8 +42,11 @@ typedef char c; typedef wchar_t c; #endif -#ifdef TRAITS +#if defined(TRAITS) && !defined(C) template class string_char_traits ; +#else +/* string_char_traits is already explicitly specialized in + std/straits.h. */ #endif typedef basic_string s;