aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/cp/ChangeLog15
-rw-r--r--gcc/cp/call.c17
-rw-r--r--gcc/cp/decl.c2
-rw-r--r--gcc/cp/parser.c28
-rw-r--r--gcc/cp/tree.c5
-rw-r--r--gcc/testsuite/ChangeLog11
-rw-r--r--gcc/testsuite/g++.dg/ext/packed8.C20
-rw-r--r--gcc/testsuite/g++.dg/template/crash30.C16
-rw-r--r--gcc/testsuite/g++.dg/template/crash31.C3
9 files changed, 102 insertions, 15 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 087fcc6..d28a020 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,18 @@
+2004-12-21 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/18378
+ * call.c (convert_like_real): Do not permit the use of a copy
+ constructor to copy a packed field.
+
+ PR c++/17413
+ * decl.c (grokdeclarator): Return error_mark_node, not
+ void_type_node, to indicate errors.
+ * parser.c (cp_parser_template_parameter_list): Robustify.
+ (cp_parser_template_parameter): Likewise.
+
+ PR c++/19034
+ * tree.c (cp_tree_equal): Handle OVERLOAD.
+
2004-12-22 Volker Reichelt <reichelt@igpm.rwth-aachen.de>
* decl.c (define_label): Use POP_TIMEVAR_AND_RETURN.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index af6f7d8..69e06e0 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -4288,13 +4288,12 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
if (convs->need_temporary_p || !lvalue_p (expr))
{
tree type = convs->u.next->type;
+ cp_lvalue_kind lvalue = real_lvalue_p (expr);
if (!CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (ref_type)))
{
/* If the reference is volatile or non-const, we
cannot create a temporary. */
- cp_lvalue_kind lvalue = real_lvalue_p (expr);
-
if (lvalue & clk_bitfield)
error ("cannot bind bitfield %qE to %qT",
expr, ref_type);
@@ -4305,6 +4304,20 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
error ("cannot bind rvalue %qE to %qT", expr, ref_type);
return error_mark_node;
}
+ /* If the source is a packed field, and we must use a copy
+ constructor, then building the target expr will require
+ binding the field to the reference parameter to the
+ copy constructor, and we'll end up with an infinite
+ loop. If we can use a bitwise copy, then we'll be
+ OK. */
+ if ((lvalue & clk_packed)
+ && CLASS_TYPE_P (type)
+ && !TYPE_HAS_TRIVIAL_INIT_REF (type))
+ {
+ error ("cannot bind packed field %qE to %qT",
+ expr, ref_type);
+ return error_mark_node;
+ }
expr = build_target_expr_with_type (expr, type);
}
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index ed0604c..be1addd 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -6745,7 +6745,7 @@ grokdeclarator (const cp_declarator *declarator,
&& ! (ctype && !declspecs->any_specifiers_p))
{
error ("declaration of %qD as non-function", dname);
- return void_type_node;
+ return error_mark_node;
}
/* Anything declared one level down from the top level
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index dc650d4..5654f11 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -8016,9 +8016,10 @@ cp_parser_template_parameter_list (cp_parser* parser)
/* Parse the template-parameter. */
parameter = cp_parser_template_parameter (parser, &is_non_type);
/* Add it to the list. */
- parameter_list = process_template_parm (parameter_list,
- parameter,
- is_non_type);
+ if (parameter != error_mark_node)
+ parameter_list = process_template_parm (parameter_list,
+ parameter,
+ is_non_type);
/* Peek at the next token. */
token = cp_lexer_peek_token (parser->lexer);
/* If it's not a `,', we're done. */
@@ -8037,15 +8038,17 @@ cp_parser_template_parameter_list (cp_parser* parser)
type-parameter
parameter-declaration
- Returns a TREE_LIST. The TREE_VALUE represents the parameter. The
- TREE_PURPOSE is the default value, if any. *IS_NON_TYPE is set to
- true iff this parameter is a non-type parameter. */
+ If all goes well, returns a TREE_LIST. The TREE_VALUE represents
+ the parameter. The TREE_PURPOSE is the default value, if any.
+ Returns ERROR_MARK_NODE on failure. *IS_NON_TYPE is set to true
+ iff this parameter is a non-type parameter. */
static tree
cp_parser_template_parameter (cp_parser* parser, bool *is_non_type)
{
cp_token *token;
cp_parameter_declarator *parameter_declarator;
+ tree parm;
/* Assume it is a type parameter or a template parameter. */
*is_non_type = false;
@@ -8094,12 +8097,13 @@ cp_parser_template_parameter (cp_parser* parser, bool *is_non_type)
parameter_declarator
= cp_parser_parameter_declaration (parser, /*template_parm_p=*/true,
/*parenthesized_p=*/NULL);
- return (build_tree_list
- (parameter_declarator->default_argument,
- grokdeclarator (parameter_declarator->declarator,
- &parameter_declarator->decl_specifiers,
- PARM, /*initialized=*/0,
- /*attrlist=*/NULL)));
+ parm = grokdeclarator (parameter_declarator->declarator,
+ &parameter_declarator->decl_specifiers,
+ PARM, /*initialized=*/0,
+ /*attrlist=*/NULL);
+ if (parm == error_mark_node)
+ return error_mark_node;
+ return build_tree_list (parameter_declarator->default_argument, parm);
}
/* Parse a type-parameter.
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index a4b470e..2b6ef71 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -1544,6 +1544,11 @@ cp_tree_equal (tree t1, tree t2)
return same_type_p (PTRMEM_CST_CLASS (t1), PTRMEM_CST_CLASS (t2));
+ case OVERLOAD:
+ if (OVL_FUNCTION (t1) != OVL_FUNCTION (t2))
+ return false;
+ return cp_tree_equal (OVL_CHAIN (t1), OVL_CHAIN (t2));
+
default:
break;
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 7d62fc4..74f7374 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,14 @@
+2004-12-21 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/18378
+ * g++.dg/ext/packed8.C: New test.
+
+ PR c++/13268
+ * g++.dg/template/crash31.C: New test.
+
+ PR c++/19034
+ * g++.dg/template/crash30.C: New test.
+
2004-12-21 Andrew Pinski <pinskia@physics.uc.edu>
PR C++/18984
diff --git a/gcc/testsuite/g++.dg/ext/packed8.C b/gcc/testsuite/g++.dg/ext/packed8.C
new file mode 100644
index 0000000..a68fa2c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/packed8.C
@@ -0,0 +1,20 @@
+// PR c++/18378
+
+class A
+{
+public:
+ int i;
+
+ A() {}
+ A(const A& a) { i = a.i; }
+};
+
+class B
+{
+ A a __attribute__((packed));
+
+public:
+ B() {}
+ A GetA() { return a; } // { dg-error "" }
+};
+
diff --git a/gcc/testsuite/g++.dg/template/crash30.C b/gcc/testsuite/g++.dg/template/crash30.C
new file mode 100644
index 0000000..145b076
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/crash30.C
@@ -0,0 +1,16 @@
+// PR c++/19034
+
+template< bool C > struct B
+{
+};
+
+template<typename S> int foo();
+template<typename S> int foo1();
+
+template<typename T> struct bar : public B <(sizeof(foo<T>()) == 1)>
+{
+};
+
+template<typename T> struct bar1 : public B <(sizeof(foo1<T>()) == 1)>
+{
+};
diff --git a/gcc/testsuite/g++.dg/template/crash31.C b/gcc/testsuite/g++.dg/template/crash31.C
new file mode 100644
index 0000000..7d66b1b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/crash31.C
@@ -0,0 +1,3 @@
+// PR c++/13268
+
+template<operator< struct A {}; // { dg-error "" }