diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 025defa26b9..59cb2af7158 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,19 @@ +2001-11-15 Jason Merrill + + * parse.y: Add ... IDENTIFIER SCOPE and ... PTYPENAME SCOPE expansions. + * decl.c (make_typename_type): Handle getting a class template. + * search.c (lookup_field_r): A class template is good enough for + want_type. + + * call.c (convert_like_real): Only use cp_convert for the bad part. + (standard_conversion): Also allow bad int->enum. + * typeck.c (ptr_reasonably_similar): Also allow functions to + interconvert. Pointers to same-size integers are reasonably + similar. + + * cvt.c (convert_to_void): If we build a new COND_EXPR, always + give it void type. + 2001-11-15 Nathan Sidwell PR g++/3154 @@ -17,12 +33,12 @@ 2001-11-14 Richard Sandiford - * decl.c (check_initializer): Try to complete the type of an - array element before checking whether it's complete. Don't - complain about arrays with complete element types but an - unknown size. - (cp_finish_decl): Build the hierarchical constructor before - calling maybe_deduce_size_from_array_init. + * decl.c (check_initializer): Try to complete the type of an + array element before checking whether it's complete. Don't + complain about arrays with complete element types but an + unknown size. + (cp_finish_decl): Build the hierarchical constructor before + calling maybe_deduce_size_from_array_init. 2001-11-14 Joseph S. Myers diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 43d2baf1fb1..91bc0978ad2 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -753,6 +753,14 @@ standard_conversion (to, from, expr) conv = build_conv (STD_CONV, to, conv); ICS_BAD_FLAG (conv) = 1; } + else if (tcode == ENUMERAL_TYPE && fcode == INTEGER_TYPE + && TYPE_PRECISION (to) == TYPE_PRECISION (from)) + { + /* For backwards brain damage compatibility, allow interconversion of + enums and integers with a pedwarn. */ + conv = build_conv (STD_CONV, to, conv); + ICS_BAD_FLAG (conv) = 1; + } else if (tcode == POINTER_TYPE && fcode == POINTER_TYPE) { enum tree_code ufcode = TREE_CODE (TREE_TYPE (from)); @@ -3748,7 +3756,7 @@ convert_like_real (convs, expr, fn, argnum, inner) tree t = convs; for (; t; t = TREE_OPERAND (t, 0)) { - if (TREE_CODE (t) == USER_CONV) + if (TREE_CODE (t) == USER_CONV || !ICS_BAD_FLAG (t)) { expr = convert_like_real (t, expr, fn, argnum, 1); break; diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c index 81d05777308..960552c8e6a 100644 --- a/gcc/cp/cvt.c +++ b/gcc/cp/cvt.c @@ -936,10 +936,8 @@ convert_to_void (expr, implicit) tree new_op1 = convert_to_void (op1, implicit); tree new_op2 = convert_to_void (op2, implicit); - if (new_op1 != op1 || new_op2 != op2) - expr = build (COND_EXPR, - implicit ? TREE_TYPE (expr) : void_type_node, - TREE_OPERAND (expr, 0), new_op1, new_op2); + expr = build (COND_EXPR, void_type_node, + TREE_OPERAND (expr, 0), new_op1, new_op2); break; } diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 5098b576055..ed6b6bf90b5 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -5652,6 +5652,11 @@ make_typename_type (context, name, complain) if (TREE_CODE (name) == TEMPLATE_DECL) name = TREE_OPERAND (fullname, 0) = DECL_NAME (name); } + if (TREE_CODE (name) == TEMPLATE_DECL) + { + cp_error ("`%D' used without template parameters", name); + return error_mark_node; + } if (TREE_CODE (name) != IDENTIFIER_NODE) my_friendly_abort (2000); diff --git a/gcc/cp/method.c b/gcc/cp/method.c index 4a12823dea2..24fd379933a 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -513,6 +513,9 @@ use_thunk (thunk_fndecl, emit_p) referenced. */ TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (thunk_fndecl)) = 1; + /* But we don't want debugging information about it. */ + DECL_IGNORED_P (thunk_fndecl) = 1; + expand_body (finish_function (0)); } diff --git a/gcc/cp/parse.y b/gcc/cp/parse.y index 12e8e2634b5..449ea9830d0 100644 --- a/gcc/cp/parse.y +++ b/gcc/cp/parse.y @@ -3021,6 +3021,13 @@ nested_name_specifier: | nested_name_specifier TEMPLATE explicit_template_type SCOPE { got_scope = $$ = make_typename_type ($1, $3, /*complain=*/1); } + /* Error handling per Core 125. */ + | nested_name_specifier IDENTIFIER SCOPE + { got_scope = $$ + = make_typename_type ($1, $2, /*complain=*/1); } + | nested_name_specifier PTYPENAME SCOPE + { got_scope = $$ + = make_typename_type ($1, $2, /*complain=*/1); } ; /* Why the @#$%^& do type_name and notype_identifier need to be expanded @@ -3050,16 +3057,6 @@ nested_name_specifier_1: } | template_type SCOPE { got_scope = $$ = complete_type (TREE_TYPE ($1)); } -/* These break 'const i;' - | IDENTIFIER SCOPE - { - failed_scope: - cp_error ("`%D' is not an aggregate typedef", - lastiddecl ? lastiddecl : $$); - $$ = error_mark_node; - } - | PTYPENAME SCOPE - { goto failed_scope; } */ ; typename_sub: diff --git a/gcc/cp/search.c b/gcc/cp/search.c index e7076f5f9ec..e09aa23ff3b 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -1367,7 +1367,8 @@ lookup_field_r (binfo, data) /* If we're looking up a type (as with an elaborated type specifier) we ignore all non-types we find. */ - if (lfi->want_type && TREE_CODE (nval) != TYPE_DECL) + if (lfi->want_type && TREE_CODE (nval) != TYPE_DECL + && !DECL_CLASS_TEMPLATE_P (nval)) { if (lfi->name == TYPE_IDENTIFIER (type)) { @@ -1727,9 +1728,9 @@ lookup_fnfields_1 (type, name) } /* Walk the class hierarchy dominated by TYPE. FN is called for each - type in the hierarchy, in a breadth-first preorder traversal. . + type in the hierarchy, in a breadth-first preorder traversal. If it ever returns a non-NULL value, that value is immediately - returned and the walk is terminated. At each node FN, is passed a + returned and the walk is terminated. At each node, FN is passed a BINFO indicating the path from the curently visited base-class to TYPE. Before each base-class is walked QFN is called. If the value returned is non-zero, the base-class is walked; otherwise it diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index dda76fe2fcd..85dc1d38e14 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -6822,6 +6822,13 @@ ptr_reasonably_similar (to, from) COMPARE_BASE | COMPARE_RELAXED)) continue; + if (TREE_CODE (to) == INTEGER_TYPE + && TYPE_PRECISION (to) == TYPE_PRECISION (from)) + return 1; + + if (TREE_CODE (to) == FUNCTION_TYPE) + return 1; + if (TREE_CODE (to) != POINTER_TYPE) return comptypes (TYPE_MAIN_VARIANT (to), TYPE_MAIN_VARIANT (from), diff --git a/gcc/testsuite/g++.dg/ext/conv1.C b/gcc/testsuite/g++.dg/ext/conv1.C index 4c0d848c8cc..6c16fe48418 100644 --- a/gcc/testsuite/g++.dg/ext/conv1.C +++ b/gcc/testsuite/g++.dg/ext/conv1.C @@ -13,4 +13,7 @@ int main () f (i); f (v); g (v); + enum { a } b = i; + void (*p2)(int) = p; + unsigned *ip = &i; } diff --git a/gcc/testsuite/g++.dg/overload/cond1.C b/gcc/testsuite/g++.dg/overload/cond1.C new file mode 100644 index 00000000000..74f0f3c49e3 --- /dev/null +++ b/gcc/testsuite/g++.dg/overload/cond1.C @@ -0,0 +1,24 @@ +// Test that converting a COND_EXPR to void doesn't result in trying to +// bitwise copy a class with a nontrivial copy constructor (and thus a +// compiler abort). + +// { dg-options "-O" } + +struct A { + virtual ~A() { } +}; + +A a1, a2; +inline A& one () { return a1; } +inline A& two () { return a2; } + +inline void f (int i) +{ + i ? a1 : a2; + i ? one() : two(); +} + +int main () +{ + f (1); +} diff --git a/gcc/testsuite/g++.dg/template/type1.C b/gcc/testsuite/g++.dg/template/type1.C new file mode 100644 index 00000000000..cd5cf5f0cd3 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/type1.C @@ -0,0 +1,8 @@ +// Test for helpful error messages on invalid nested-name-specifiers. + +struct A { + template struct B { static int c; }; +}; + +int A::B::c; // { dg-error "parameters" } +int A::C::d; // { dg-error "no type" }