aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>2005-06-03 16:16:46 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>2005-06-03 16:16:46 +0000
commit7e45bd18daca810d7ecbd83ffcd9e97d31de0f12 (patch)
tree70ac825253c7f826918234c12f73d0876c812aa0
parent83cd747fd944f49180cc60ddb1c3a9f889fb6b63 (diff)
downloadgcc-7e45bd18daca810d7ecbd83ffcd9e97d31de0f12.zip
gcc-7e45bd18daca810d7ecbd83ffcd9e97d31de0f12.tar.gz
gcc-7e45bd18daca810d7ecbd83ffcd9e97d31de0f12.tar.bz2
re PR c++/21336 (Internal compiler error when using custom new operators)
PR c++/21336 * cp-tree.h (grok_op_properties): Remove friendp parameter. * decl.c (grokfndecl): Adjust call. (grok_op_properties): Determine the class of which the function is a member by looking at its DECL_CONTEXT, not current_class_type. * pt.c (tsubst_decl): Adjust call to grok_op_properties. PR c++/21336 * g++.dg/template/new2.C: New test. From-SVN: r100541
-rw-r--r--gcc/cp/ChangeLog9
-rw-r--r--gcc/cp/cp-tree.h2
-rw-r--r--gcc/cp/decl.c86
-rw-r--r--gcc/cp/pt.c3
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/template/new2.C14
6 files changed, 76 insertions, 43 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 8b68706..28dc483 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,12 @@
+2005-06-03 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/21336
+ * cp-tree.h (grok_op_properties): Remove friendp parameter.
+ * decl.c (grokfndecl): Adjust call.
+ (grok_op_properties): Determine the class of which the function is
+ a member by looking at its DECL_CONTEXT, not current_class_type.
+ * pt.c (tsubst_decl): Adjust call to grok_op_properties.
+
2005-06-02 Nathan Sidwell <nathan@codesourcery.com>
* method.c (synthesize_method): Add addtional arg to warning call.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index f4f5a12..0f3dfa5 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -3766,7 +3766,7 @@ extern int copy_fn_p (tree);
extern tree get_scope_of_declarator (const cp_declarator *);
extern void grok_special_member_properties (tree);
extern int grok_ctor_properties (tree, tree);
-extern void grok_op_properties (tree, int, bool);
+extern void grok_op_properties (tree, bool);
extern tree xref_tag (enum tag_types, tree, tag_scope, bool);
extern tree xref_tag_from_type (tree, tree, tag_scope);
extern void xref_basetypes (tree, tree);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 6f1394b..6b278ae 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -5610,7 +5610,7 @@ grokfndecl (tree ctype,
}
if (IDENTIFIER_OPNAME_P (DECL_NAME (decl)))
- grok_op_properties (decl, friendp, /*complain=*/true);
+ grok_op_properties (decl, /*complain=*/true);
if (ctype && decl_function_context (decl))
DECL_NO_STATIC_CHAIN (decl) = 1;
@@ -8608,7 +8608,7 @@ unary_op_p (enum tree_code code)
errors are issued for invalid declarations. */
void
-grok_op_properties (tree decl, int friendp, bool complain)
+grok_op_properties (tree decl, bool complain)
{
tree argtypes = TYPE_ARG_TYPES (TREE_TYPE (decl));
tree argtype;
@@ -8616,6 +8616,7 @@ grok_op_properties (tree decl, int friendp, bool complain)
tree name = DECL_NAME (decl);
enum tree_code operator_code;
int arity;
+ tree class_type;
/* Count the number of arguments. */
for (argtype = argtypes, arity = 0;
@@ -8623,8 +8624,9 @@ grok_op_properties (tree decl, int friendp, bool complain)
argtype = TREE_CHAIN (argtype))
++arity;
- if (current_class_type == NULL_TREE)
- friendp = 1;
+ class_type = DECL_CONTEXT (decl);
+ if (class_type && !CLASS_TYPE_P (class_type))
+ class_type = NULL_TREE;
if (DECL_CONV_FN_P (decl))
operator_code = TYPE_EXPR;
@@ -8653,30 +8655,28 @@ grok_op_properties (tree decl, int friendp, bool complain)
gcc_assert (operator_code != LAST_CPLUS_TREE_CODE);
SET_OVERLOADED_OPERATOR_CODE (decl, operator_code);
- if (! friendp)
- {
- switch (operator_code)
- {
- case NEW_EXPR:
- TYPE_HAS_NEW_OPERATOR (current_class_type) = 1;
- break;
+ if (class_type)
+ switch (operator_code)
+ {
+ case NEW_EXPR:
+ TYPE_HAS_NEW_OPERATOR (class_type) = 1;
+ break;
- case DELETE_EXPR:
- TYPE_GETS_DELETE (current_class_type) |= 1;
- break;
+ case DELETE_EXPR:
+ TYPE_GETS_DELETE (class_type) |= 1;
+ break;
- case VEC_NEW_EXPR:
- TYPE_HAS_ARRAY_NEW_OPERATOR (current_class_type) = 1;
- break;
+ case VEC_NEW_EXPR:
+ TYPE_HAS_ARRAY_NEW_OPERATOR (class_type) = 1;
+ break;
- case VEC_DELETE_EXPR:
- TYPE_GETS_DELETE (current_class_type) |= 2;
- break;
+ case VEC_DELETE_EXPR:
+ TYPE_GETS_DELETE (class_type) |= 2;
+ break;
- default:
- break;
- }
- }
+ default:
+ break;
+ }
/* [basic.std.dynamic.allocation]/1:
@@ -8755,32 +8755,38 @@ grok_op_properties (tree decl, int friendp, bool complain)
if (operator_code == CALL_EXPR)
return;
- if (IDENTIFIER_TYPENAME_P (name) && ! DECL_TEMPLATE_INFO (decl))
+ /* Warn about conversion operators that will never be used. */
+ if (IDENTIFIER_TYPENAME_P (name)
+ && ! DECL_TEMPLATE_INFO (decl)
+ && warn_conversion
+ /* Warn only declaring the function; there is no need to
+ warn again about out-of-class definitions. */
+ && class_type == current_class_type)
{
tree t = TREE_TYPE (name);
- if (! friendp)
- {
- int ref = (TREE_CODE (t) == REFERENCE_TYPE);
- const char *what = 0;
+ int ref = (TREE_CODE (t) == REFERENCE_TYPE);
+ const char *what = 0;
- if (ref)
- t = TYPE_MAIN_VARIANT (TREE_TYPE (t));
+ if (ref)
+ t = TYPE_MAIN_VARIANT (TREE_TYPE (t));
- if (TREE_CODE (t) == VOID_TYPE)
- what = "void";
- else if (t == current_class_type)
+ if (TREE_CODE (t) == VOID_TYPE)
+ what = "void";
+ else if (class_type)
+ {
+ if (t == class_type)
what = "the same type";
/* Don't force t to be complete here. */
else if (IS_AGGR_TYPE (t)
&& COMPLETE_TYPE_P (t)
- && DERIVED_FROM_P (t, current_class_type))
+ && DERIVED_FROM_P (t, class_type))
what = "a base class";
-
- if (what && warn_conversion)
- warning (0, "conversion to %s%s will never use a type "
- "conversion operator",
- ref ? "a reference to " : "", what);
}
+
+ if (what)
+ warning (0, "conversion to %s%s will never use a type "
+ "conversion operator",
+ ref ? "a reference to " : "", what);
}
if (operator_code == COND_EXPR)
{
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 8a0a430..ad1e5f3 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -6494,8 +6494,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
clone_function_decl (r, /*update_method_vec_p=*/0);
}
else if (IDENTIFIER_OPNAME_P (DECL_NAME (r)))
- grok_op_properties (r, DECL_FRIEND_P (r),
- (complain & tf_error) != 0);
+ grok_op_properties (r, (complain & tf_error) != 0);
if (DECL_FRIEND_P (t) && DECL_FRIEND_CONTEXT (t))
SET_DECL_FRIEND_CONTEXT (r,
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 2b3cbc2..5238734 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2005-06-03 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/21336
+ * g++.dg/template/new2.C: New test.
+
2005-06-03 Josh Conner <jconner@apple.com>
* gcc.dg/ppc-vector-memcpy.c (foo): Use non-zero values for
diff --git a/gcc/testsuite/g++.dg/template/new2.C b/gcc/testsuite/g++.dg/template/new2.C
new file mode 100644
index 0000000..682ca6e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/new2.C
@@ -0,0 +1,14 @@
+// PR c++/21336
+
+typedef __SIZE_TYPE__ size_t;
+template<class _T> void* operator new( size_t Size, _T&);
+struct B {
+ int a;
+ int* m() {
+ return new(a) int;
+ }
+};
+B* n() {
+ return new B();
+}
+