This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH: PR c++/17435, c++/18140
- From: Mark Mitchell <mark at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Wed, 27 Oct 2004 22:21:24 -0700
- Subject: C++ PATCH: PR c++/17435, c++/18140
- Reply-to: mark at codesourcery dot com
This patch fixes two more C++ regressions:
* 17435
This PR concerns one of the very tricky bits of C++, both from the
point of view of the specification and the implementation. In
particular, the fact that binding a reference to a temporary can
extend the lifetime of the temporary. (This results in object
lifetimes for automatic variables that do not nest; weird.) We were
copying just the base class portion of a derived class object when
doing this, which is not correct; fixed by finding the base class
object later in the game.
* 18140
This was a rejects-valid PR caused by Giovanni's patch to make ">>"
be treated as the end of a template argument, as an attempt at
better error-recovery. That did not work in the case that the ">>"
was actually legitimately interpreted as a shift operator. A
consequence is that one of the tests in g++.dg/template/error10.C
now issues marginally inferior error messages, but correctness
first.
Tested on i686-pc-linux-gnu, applied on the mainline. The c++/18140
fix will also be applied to the 3.4 branch shortly.
--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com
2004-10-27 Mark Mitchell <mark@codesourcery.com>
PR c++/17435
* call.c (convert_like_real): Fix formatting.
(initialize_reference): When binding a temporary to a base class,
ensure that the nominal copy made is to the derived class, not the
base class.
PR c++/18140
* parser.c (cp_parser_next_token_ends_template_argument_p): Do not
include ">>".
2004-10-27 Mark Mitchell <mark@codesourcery.com>
PR c++/17435
* g++.dg/init/ref12.C: New test.
PR c++/18140
* g++.dg/template/shift1.C: New test.
* g++.dg/template/error10.C: Adjust error markers.
Index: cp/call.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/call.c,v
retrieving revision 1.516
diff -c -5 -p -r1.516 call.c
*** cp/call.c 21 Oct 2004 21:23:38 -0000 1.516
--- cp/call.c 28 Oct 2004 05:03:52 -0000
*************** convert_like_real (conversion *convs, tr
*** 4237,4247 ****
if (inner >= 0
&& TREE_CODE (TREE_TYPE (expr)) != ARRAY_TYPE)
expr = decl_constant_value (expr);
if (convs->check_copy_constructor_p)
check_constructor_callable (totype, expr);
! return expr;
case ck_ambig:
/* Call build_user_type_conversion again for the error. */
return build_user_type_conversion
(totype, convs->u.expr, LOOKUP_NORMAL);
--- 4237,4247 ----
if (inner >= 0
&& TREE_CODE (TREE_TYPE (expr)) != ARRAY_TYPE)
expr = decl_constant_value (expr);
if (convs->check_copy_constructor_p)
check_constructor_callable (totype, expr);
! return expr;
case ck_ambig:
/* Call build_user_type_conversion again for the error. */
return build_user_type_conversion
(totype, convs->u.expr, LOOKUP_NORMAL);
*************** initialize_reference (tree type, tree ex
*** 6465,6475 ****
/* Skip over the REF_BIND. */
conv = conv->u.next;
/* If the next conversion is a BASE_CONV, skip that too -- but
remember that the conversion was required. */
! if (conv->kind == ck_base && conv->need_temporary_p)
{
if (conv->check_copy_constructor_p)
check_constructor_callable (TREE_TYPE (expr), expr);
base_conv_type = conv->type;
conv = conv->u.next;
--- 6465,6475 ----
/* Skip over the REF_BIND. */
conv = conv->u.next;
/* If the next conversion is a BASE_CONV, skip that too -- but
remember that the conversion was required. */
! if (conv->kind == ck_base)
{
if (conv->check_copy_constructor_p)
check_constructor_callable (TREE_TYPE (expr), expr);
base_conv_type = conv->type;
conv = conv->u.next;
*************** initialize_reference (tree type, tree ex
*** 6535,6544 ****
--- 6535,6549 ----
static_aggregates = tree_cons (NULL_TREE, var,
static_aggregates);
}
/* Use its address to initialize the reference variable. */
expr = build_address (var);
+ if (base_conv_type)
+ expr = convert_to_base (expr,
+ build_pointer_type (base_conv_type),
+ /*check_access=*/true,
+ /*nonnull=*/true);
expr = build2 (COMPOUND_EXPR, TREE_TYPE (expr), init, expr);
}
else
/* Take the address of EXPR. */
expr = build_unary_op (ADDR_EXPR, expr, 0);
Index: cp/parser.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/parser.c,v
retrieving revision 1.271
diff -c -5 -p -r1.271 parser.c
*** cp/parser.c 27 Oct 2004 02:23:12 -0000 1.271
--- cp/parser.c 28 Oct 2004 05:03:54 -0000
*************** cp_parser_next_token_starts_class_defini
*** 15472,15493 ****
token = cp_lexer_peek_token (parser->lexer);
return (token->type == CPP_OPEN_BRACE || token->type == CPP_COLON);
}
/* Returns TRUE iff the next token is the "," or ">" ending a
! template-argument. ">>" is also accepted (after the full
! argument was parsed) because it's probably a typo for "> >",
! and there is a specific diagnostic for this. */
static bool
cp_parser_next_token_ends_template_argument_p (cp_parser *parser)
{
cp_token *token;
token = cp_lexer_peek_token (parser->lexer);
! return (token->type == CPP_COMMA || token->type == CPP_GREATER
! || token->type == CPP_RSHIFT);
}
/* Returns TRUE iff the n-th token is a ">", or the n-th is a "[" and the
(n+1)-th is a ":" (which is a possible digraph typo for "< ::"). */
--- 15472,15490 ----
token = cp_lexer_peek_token (parser->lexer);
return (token->type == CPP_OPEN_BRACE || token->type == CPP_COLON);
}
/* Returns TRUE iff the next token is the "," or ">" ending a
! template-argument. */
static bool
cp_parser_next_token_ends_template_argument_p (cp_parser *parser)
{
cp_token *token;
token = cp_lexer_peek_token (parser->lexer);
! return (token->type == CPP_COMMA || token->type == CPP_GREATER);
}
/* Returns TRUE iff the n-th token is a ">", or the n-th is a "[" and the
(n+1)-th is a ":" (which is a possible digraph typo for "< ::"). */
Index: testsuite/g++.dg/init/ref12.C
===================================================================
RCS file: testsuite/g++.dg/init/ref12.C
diff -N testsuite/g++.dg/init/ref12.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/init/ref12.C 28 Oct 2004 05:03:54 -0000
***************
*** 0 ****
--- 1,29 ----
+ // PR c++/17435
+
+ extern "C" void abort ();
+
+ bool ok;
+
+ struct A
+ {
+ void func() const
+ {
+ ok = 1;
+ }
+
+ ~A()
+ {
+ if (!ok)
+ abort ();
+ }
+ };
+
+ struct B : public A
+ {
+ };
+
+ int main()
+ {
+ A const& r1 = B();
+ r1.func();
+ }
Index: testsuite/g++.dg/template/error10.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.dg/template/error10.C,v
retrieving revision 1.2
diff -c -5 -p -r1.2 error10.C
*** testsuite/g++.dg/template/error10.C 23 Sep 2004 21:27:17 -0000 1.2
--- testsuite/g++.dg/template/error10.C 28 Oct 2004 05:03:54 -0000
*************** L<H() >> 5> l; // { dg-error "" "non-co
*** 64,70 ****
template <void (*)(void)>
struct K {};
void KFunc(void);
! A<K<&KFunc>> k1; // { dg-error "should be '> >' within" }
! K<&KFunc>> k2; // { dg-error "spurious '>>'" }
--- 64,70 ----
template <void (*)(void)>
struct K {};
void KFunc(void);
! A<K<&KFunc>> k1; // { dg-error "" }
! K<&KFunc>> k2; // { dg-error "" }
Index: testsuite/g++.dg/template/shift1.C
===================================================================
RCS file: testsuite/g++.dg/template/shift1.C
diff -N testsuite/g++.dg/template/shift1.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/template/shift1.C 28 Oct 2004 05:03:54 -0000
***************
*** 0 ****
--- 1,10 ----
+ // PR c++/18140
+
+ template <int N> struct IntHolder {
+ static const int value = N;
+ };
+
+ template <int N, int S> struct ShrIntHolder {
+ static const int value = IntHolder< N>>S >::value;
+ };
+