aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>2003-03-08 09:12:54 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>2003-03-08 09:12:54 +0000
commit089d6ea74bea18d183968d655d7dd2c4e336ab03 (patch)
tree6b4defb4aeefb856b583b42ac040705d6ebed502 /gcc
parent6fef42173faf90a30b4fa0c565754173a74236b7 (diff)
downloadgcc-089d6ea74bea18d183968d655d7dd2c4e336ab03.zip
gcc-089d6ea74bea18d183968d655d7dd2c4e336ab03.tar.gz
gcc-089d6ea74bea18d183968d655d7dd2c4e336ab03.tar.bz2
re PR c++/9809 (when are builtins brought into view)
PR c++/9809 * g++.dg/parse/builtin1.C: New test. PR c++/9982 * g++.dg/abi/cookie1.C: New test. * g++.dg/abi/cookie2.C: Likewise. PR c++/9524 * g++.dg/parse/field1.C: New test. PR c++/9912 * g++.dg/parse/class1.C: New test. * g++.dg/parse/namespace7.C: Likewise. * g++.old-deja/g++.other/decl5.C: Remove XFAILs. From-SVN: r63977
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog24
-rw-r--r--gcc/cp/call.c5
-rw-r--r--gcc/cp/cp-tree.h3
-rw-r--r--gcc/cp/decl2.c98
-rw-r--r--gcc/cp/init.c143
-rw-r--r--gcc/cp/parser.c24
-rw-r--r--gcc/testsuite/ChangeLog17
-rw-r--r--gcc/testsuite/g++.dg/abi/cookie1.C15
-rw-r--r--gcc/testsuite/g++.dg/abi/cookie2.C16
-rw-r--r--gcc/testsuite/g++.dg/parse/builtin1.C16
-rw-r--r--gcc/testsuite/g++.dg/parse/class1.C10
-rw-r--r--gcc/testsuite/g++.dg/parse/namespace7.C8
-rw-r--r--gcc/testsuite/g++.dg/template/field1.C12
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/decl5.C4
14 files changed, 289 insertions, 106 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 6c18b30..4acff21 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,27 @@
+2003-03-08 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/9809
+ * call.c (add_function_candidate): Skip builtin fuctions that have
+ not yet been declared.
+
+ PR c++/9982
+ * init.c (build_new_1): Correct logic for determining whether or
+ not to use an array cookie.
+
+ PR c++/9524
+ * parser.c (cp_parser_postfix_expression): Call
+ finish_non_static_data_member, even when processing_template_decl.
+
+ PR c++/9912
+ * cp-tree.h (is_ancestor): New function.
+ (handle_class_head): Change prototype.
+ * decl2.c (is_namespace_ancestor): Rename to ...
+ (namespace_anecestor): ... this.
+ (set_decl_namespace): Adjust accordingly.
+ (handle_class_head): Remove unncessary parameters.
+ * parser.c (cp_parser_class_head): Check that
+ nested-name-specifiers are used appropriately.
+
2003-03-07 Mark Mitchell <mark@codesourcery.com>
* call.c (reference_binding): Remove REF_IS_VAR parameter.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index a25da46..64da5a4 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -1382,6 +1382,11 @@ add_function_candidate (struct z_candidate **candidates,
tree orig_arglist;
int viable = 1;
+ /* Built-in functions that haven't been declared don't really
+ exist. */
+ if (DECL_ANTICIPATED (fn))
+ return NULL;
+
/* The `this', `in_chrg' and VTT arguments to constructors are not
considered in overload resolution. */
if (DECL_CONSTRUCTOR_P (fn))
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 53a4db6..3ab95cc 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -3724,6 +3724,7 @@ extern tree lookup_name_current_level (tree);
extern tree lookup_type_current_level (tree);
extern tree lookup_name_real (tree, int, int, int, int);
extern tree namespace_ancestor (tree, tree);
+extern bool is_ancestor (tree, tree);
extern tree unqualified_namespace_lookup (tree, int, tree *);
extern tree check_for_out_of_scope_variable (tree);
extern bool lookup_using_namespace (tree, tree, tree, tree, int, tree *);
@@ -3850,7 +3851,7 @@ extern tree do_class_using_decl (tree);
extern void do_using_directive (tree);
extern void check_default_args (tree);
extern void mark_used (tree);
-extern tree handle_class_head (enum tag_types, tree, tree, tree, bool, bool *);
+extern tree handle_class_head (enum tag_types, tree, tree, tree);
extern tree lookup_arg_dependent (tree, tree, tree);
extern void finish_static_data_member_decl (tree, tree, tree, int);
extern tree cp_build_parm_decl (tree, tree);
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 52170da..f85fef2 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -62,7 +62,6 @@ typedef struct priority_info_s {
static void mark_vtable_entries (tree);
static void grok_function_init (tree, tree);
static bool maybe_emit_vtables (tree);
-static bool is_namespace_ancestor (tree, tree);
static void add_using_namespace (tree, tree, bool);
static tree ambiguous_decl (tree, tree, tree,int);
static tree build_anon_union_vars (tree);
@@ -3352,18 +3351,36 @@ build_call_from_tree (tree fn, tree args, bool disallow_virtual)
return finish_call_expr (fn, args, disallow_virtual);
}
-/* Return 1 if root encloses child. */
+/* Returns true if ROOT (a namespace, class, or function) encloses
+ CHILD. CHILD may be either a class type or a namespace. */
-static bool
-is_namespace_ancestor (tree root, tree child)
+bool
+is_ancestor (tree root, tree child)
{
- if (root == child)
- return true;
+ my_friendly_assert ((TREE_CODE (root) == NAMESPACE_DECL
+ || TREE_CODE (root) == FUNCTION_DECL
+ || CLASS_TYPE_P (root)), 20030307);
+ my_friendly_assert ((TREE_CODE (child) == NAMESPACE_DECL
+ || CLASS_TYPE_P (child)),
+ 20030307);
+
+ /* The global namespace encloses everything. */
if (root == global_namespace)
return true;
- if (child == global_namespace)
- return false;
- return is_namespace_ancestor (root, CP_DECL_CONTEXT (child));
+
+ while (true)
+ {
+ /* If we've run out of scopes, stop. */
+ if (!child)
+ return false;
+ /* If we've reached the ROOT, it encloses CHILD. */
+ if (root == child)
+ return true;
+ /* Go out one level. */
+ if (TYPE_P (child))
+ child = TYPE_NAME (child);
+ child = DECL_CONTEXT (child);
+ }
}
@@ -3374,7 +3391,7 @@ tree
namespace_ancestor (tree ns1, tree ns2)
{
timevar_push (TV_NAME_LOOKUP);
- if (is_namespace_ancestor (ns1, ns2))
+ if (is_ancestor (ns1, ns2))
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, ns1);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP,
namespace_ancestor (CP_DECL_CONTEXT (ns1), ns2));
@@ -3636,7 +3653,7 @@ set_decl_namespace (tree decl, tree scope, bool friendp)
scope = ORIGINAL_NAMESPACE (scope);
/* It is ok for friends to be qualified in parallel space. */
- if (!friendp && !is_namespace_ancestor (current_namespace, scope))
+ if (!friendp && !is_ancestor (current_namespace, scope))
error ("declaration of `%D' not in a namespace surrounding `%D'",
decl, scope);
DECL_CONTEXT (decl) = FROB_CONTEXT (scope);
@@ -4494,28 +4511,28 @@ mark_used (tree decl)
instantiate_decl (decl, /*defer_ok=*/1);
}
-/* Helper function for class_head_decl and class_head_defn
- nonterminals. AGGR is the class, union or struct tag. SCOPE is the
- explicit scope used (NULL for no scope resolution). ID is the
- name. DEFN_P is true, if this is a definition of the class and
- NEW_TYPE_P is set to nonzero, if we push into the scope containing
- the to be defined aggregate.
-
- Return a TYPE_DECL for the type declared by ID in SCOPE. */
+/* Called when a class-head is encountered. TAG_KIND is the class-key
+ for the class. SCOPE, if non-NULL, is the type or namespace
+ indicated in the nested-name-specifier for the declaration of the
+ class. ID is the name of the class, if any; it may be a TYPE_DECL,
+ or an IDENTIFIER_NODE. ATTRIBUTES are attributes that apply to the
+ class.
+
+ Return a TYPE_DECL for the class being defined. */
tree
handle_class_head (enum tag_types tag_kind, tree scope, tree id,
- tree attributes, bool defn_p, bool *new_type_p)
+ tree attributes)
{
tree decl = NULL_TREE;
tree current = current_scope ();
bool xrefd_p = false;
-
+ bool new_type_p;
+ tree context;
+
if (current == NULL_TREE)
current = current_namespace;
- *new_type_p = false;
-
if (scope)
{
if (TREE_CODE (id) == TYPE_DECL)
@@ -4552,7 +4569,7 @@ handle_class_head (enum tag_types tag_kind, tree scope, tree id,
if (!decl)
{
- decl = TYPE_MAIN_DECL (xref_tag (tag_kind, id, attributes, !defn_p));
+ decl = TYPE_MAIN_DECL (xref_tag (tag_kind, id, attributes, false));
xrefd_p = true;
}
@@ -4562,24 +4579,21 @@ handle_class_head (enum tag_types tag_kind, tree scope, tree id,
return error_mark_node;
}
- if (defn_p)
- {
- /* For a definition, we want to enter the containing scope
- before looking up any base classes etc. Only do so, if this
- is different to the current scope. */
- tree context = CP_DECL_CONTEXT (decl);
-
- *new_type_p = (current != context
- && TREE_CODE (context) != TEMPLATE_TYPE_PARM
- && TREE_CODE (context) != BOUND_TEMPLATE_TEMPLATE_PARM);
- if (*new_type_p)
- push_scope (context);
-
- if (!xrefd_p
- && PROCESSING_REAL_TEMPLATE_DECL_P ()
- && !CLASSTYPE_TEMPLATE_SPECIALIZATION (TREE_TYPE (decl)))
- decl = push_template_decl (decl);
- }
+ /* For a definition, we want to enter the containing scope before
+ looking up any base classes etc. Only do so, if this is different
+ to the current scope. */
+ context = CP_DECL_CONTEXT (decl);
+
+ new_type_p = (current != context
+ && TREE_CODE (context) != TEMPLATE_TYPE_PARM
+ && TREE_CODE (context) != BOUND_TEMPLATE_TEMPLATE_PARM);
+ if (new_type_p)
+ push_scope (context);
+
+ if (!xrefd_p
+ && PROCESSING_REAL_TEMPLATE_DECL_P ()
+ && !CLASSTYPE_TEMPLATE_SPECIALIZATION (TREE_TYPE (decl)))
+ decl = push_template_decl (decl);
return decl;
}
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 1b86513..2e4ecc2 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -2163,13 +2163,11 @@ build_new_1 (exp)
tree cookie_expr, init_expr;
int has_array = 0;
enum tree_code code;
- int use_cookie, nothrow, check_new;
+ int nothrow, check_new;
/* Nonzero if the user wrote `::new' rather than just `new'. */
int globally_qualified_p;
- /* Nonzero if we're going to call a global operator new, rather than
- a class-specific version. */
- int use_global_new;
int use_java_new = 0;
+ bool check_cookie = false;
/* If non-NULL, the number of extra bytes to allocate at the
beginning of the storage allocated for an array-new expression in
order to store the number of elements. */
@@ -2177,6 +2175,7 @@ build_new_1 (exp)
/* True if the function we are calling is a placement allocation
function. */
bool placement_allocation_fn_p;
+ tree args;
placement = TREE_OPERAND (exp, 0);
type = TREE_OPERAND (exp, 1);
@@ -2211,10 +2210,6 @@ build_new_1 (exp)
if (!complete_type_or_else (true_type, exp))
return error_mark_node;
- size = size_in_bytes (true_type);
- if (has_array)
- size = size_binop (MULT_EXPR, size, convert (sizetype, nelts));
-
if (TREE_CODE (true_type) == VOID_TYPE)
{
error ("invalid type `void' for new");
@@ -2224,42 +2219,11 @@ build_new_1 (exp)
if (abstract_virtuals_error (NULL_TREE, true_type))
return error_mark_node;
- /* Figure out whether or not we're going to use the global operator
- new. */
- if (!globally_qualified_p
- && IS_AGGR_TYPE (true_type)
- && (has_array
- ? TYPE_HAS_ARRAY_NEW_OPERATOR (true_type)
- : TYPE_HAS_NEW_OPERATOR (true_type)))
- use_global_new = 0;
- else
- use_global_new = 1;
-
- /* We only need cookies for arrays containing types for which we
- need cookies. */
- if (!has_array || !TYPE_VEC_NEW_USES_COOKIE (true_type))
- use_cookie = 0;
- /* When using placement new, users may not realize that they need
- the extra storage. We require that the operator called be
- the global placement operator new[]. */
- else if (placement && !TREE_CHAIN (placement)
- && same_type_p (TREE_TYPE (TREE_VALUE (placement)),
- ptr_type_node))
- use_cookie = !use_global_new;
- /* Otherwise, we need the cookie. */
- else
- use_cookie = 1;
-
- /* Compute the number of extra bytes to allocate, now that we know
- whether or not we need the cookie. */
- if (use_cookie)
- {
- cookie_size = get_cookie_size (true_type);
- size = size_binop (PLUS_EXPR, size, cookie_size);
- }
+ size = size_in_bytes (true_type);
+ if (has_array)
+ size = size_binop (MULT_EXPR, size, convert (sizetype, nelts));
/* Allocate the object. */
-
if (! placement && TYPE_FOR_JAVA (true_type))
{
tree class_addr, alloc_decl;
@@ -2281,20 +2245,42 @@ build_new_1 (exp)
else
{
tree fnname;
- tree args;
- args = tree_cons (NULL_TREE, size, placement);
fnname = ansi_opname (code);
- if (use_global_new)
- alloc_call = (build_new_function_call
- (lookup_function_nonclass (fnname, args),
- args));
+ if (!globally_qualified_p
+ && CLASS_TYPE_P (true_type)
+ && (has_array
+ ? TYPE_HAS_ARRAY_NEW_OPERATOR (true_type)
+ : TYPE_HAS_NEW_OPERATOR (true_type)))
+ {
+ /* Use a class-specific operator new. */
+ /* If a cookie is required, add some extra space. */
+ if (has_array && TYPE_VEC_NEW_USES_COOKIE (true_type))
+ {
+ cookie_size = get_cookie_size (true_type);
+ size = size_binop (PLUS_EXPR, size, cookie_size);
+ }
+ /* Create the argument list. */
+ args = tree_cons (NULL_TREE, size, placement);
+ /* Call the function. */
+ alloc_call = build_method_call (build_dummy_object (true_type),
+ fnname, args,
+ TYPE_BINFO (true_type),
+ LOOKUP_NORMAL);
+ }
else
- alloc_call = build_method_call (build_dummy_object (true_type),
- fnname, args,
- TYPE_BINFO (true_type),
- LOOKUP_NORMAL);
+ {
+ /* Use a global operator new. */
+ /* Create the argument list. */
+ args = tree_cons (NULL_TREE, size, placement);
+ /* Call the function. */
+ alloc_call
+ = build_new_function_call (lookup_function_nonclass (fnname, args),
+ args);
+ /* We may need to add a cookie. */
+ check_cookie = true;
+ }
}
if (alloc_call == error_mark_node)
@@ -2308,6 +2294,53 @@ build_new_1 (exp)
t = TREE_OPERAND (t, 1);
alloc_fn = get_callee_fndecl (t);
my_friendly_assert (alloc_fn != NULL_TREE, 20020325);
+
+ /* If we postponed deciding whether or not to use a cookie until
+ after we knew what function was being called, that time is
+ now. */
+ if (check_cookie)
+ {
+ /* If a cookie is required, add some extra space. Whether
+ or not a cookie is required cannot be determined until
+ after we know which function was called. */
+ if (has_array && TYPE_VEC_NEW_USES_COOKIE (true_type))
+ {
+ bool use_cookie = true;
+ if (!abi_version_at_least (2))
+ {
+ /* In G++ 3.2, the check was implemented incorrectly; it
+ looked at the placement expression, rather than the
+ type of the function. */
+ if (placement && !TREE_CHAIN (placement)
+ && same_type_p (TREE_TYPE (TREE_VALUE (placement)),
+ ptr_type_node))
+ use_cookie = false;
+ }
+ else
+ {
+ tree arg_types;
+
+ arg_types = TYPE_ARG_TYPES (TREE_TYPE (alloc_fn));
+ /* Skip the size_t parameter. */
+ arg_types = TREE_CHAIN (arg_types);
+ /* Check the remaining parameters (if any). */
+ if (arg_types
+ && !TREE_CHAIN (arg_types)
+ && same_type_p (TREE_TYPE (TREE_VALUE (arg_types)),
+ ptr_type_node))
+ use_cookie = false;
+ }
+ /* If we need a cookie, adjust the number of bytes allocated. */
+ if (use_cookie)
+ {
+ cookie_size = get_cookie_size (true_type);
+ size = size_binop (PLUS_EXPR, size, cookie_size);
+ /* Update the argument list to reflect the adjusted size. */
+ TREE_VALUE (args) = cookie_size;
+ }
+ }
+ }
+
/* Now, check to see if this function is actually a placement
allocation function. This can happen even when PLACEMENT is NULL
because we might have something like:
@@ -2337,7 +2370,7 @@ build_new_1 (exp)
alloc_expr = alloc_call;
- if (use_cookie)
+ if (cookie_size)
/* Adjust so we're pointing to the start of the object. */
alloc_expr = build (PLUS_EXPR, TREE_TYPE (alloc_expr),
alloc_expr, cookie_size);
@@ -2351,7 +2384,7 @@ build_new_1 (exp)
alloc_node = TREE_OPERAND (alloc_expr, 0);
/* Now initialize the cookie. */
- if (use_cookie)
+ if (cookie_size)
{
tree cookie;
@@ -2431,7 +2464,7 @@ build_new_1 (exp)
| (globally_qualified_p * LOOKUP_GLOBAL));
tree delete_node;
- if (use_cookie)
+ if (cookie_size)
/* Subtract the padding back out to get to the pointer returned
from operator new. */
delete_node = fold (build (MINUS_EXPR, TREE_TYPE (alloc_node),
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index e266938..468ba03b 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -3809,13 +3809,14 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
/* Otherwise, if we were avoiding committing until we knew
whether or not we had a pointer-to-member, we now know that
the expression is an ordinary reference to a qualified name. */
- if (qualifying_class && !processing_template_decl)
+ if (qualifying_class)
{
if (TREE_CODE (postfix_expression) == FIELD_DECL)
postfix_expression
= finish_non_static_data_member (postfix_expression,
qualifying_class);
- else if (BASELINK_P (postfix_expression))
+ else if (BASELINK_P (postfix_expression)
+ && !processing_template_decl)
{
tree fn;
tree fns;
@@ -11756,8 +11757,8 @@ cp_parser_class_head (cp_parser* parser,
}
else
{
- bool new_type_p;
tree class_type;
+ tree scope;
/* Given:
@@ -11780,14 +11781,25 @@ cp_parser_class_head (cp_parser* parser,
}
}
+ /* Figure out in what scope the declaration is being placed. */
+ scope = current_scope ();
+ if (!scope)
+ scope = current_namespace;
+ /* If that scope does not contain the scope in which the
+ class was originally declared, the program is invalid. */
+ if (scope && !is_ancestor (scope, CP_DECL_CONTEXT (type)))
+ {
+ error ("declaration of `%D' in `%D' which does not "
+ "enclose `%D'", type, scope, nested_name_specifier);
+ return NULL_TREE;
+ }
+
maybe_process_partial_specialization (TREE_TYPE (type));
class_type = current_class_type;
type = TREE_TYPE (handle_class_head (class_key,
nested_name_specifier,
type,
- attributes,
- /*defn_p=*/true,
- &new_type_p));
+ attributes));
if (type != error_mark_node)
{
if (!class_type && TYPE_CONTEXT (type))
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 27c6197..b409528 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,20 @@
+2003-03-08 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/9809
+ * g++.dg/parse/builtin1.C: New test.
+
+ PR c++/9982
+ * g++.dg/abi/cookie1.C: New test.
+ * g++.dg/abi/cookie2.C: Likewise.
+
+ PR c++/9524
+ * g++.dg/parse/field1.C: New test.
+
+ PR c++/9912
+ * g++.dg/parse/class1.C: New test.
+ * g++.dg/parse/namespace7.C: Likewise.
+ * g++.old-deja/g++.other/decl5.C: Remove XFAILs.
+
2003-03-07 Mark Mitchell <mark@codesourcery.com>
* g++.dg/init/ref4.C: New test.
diff --git a/gcc/testsuite/g++.dg/abi/cookie1.C b/gcc/testsuite/g++.dg/abi/cookie1.C
new file mode 100644
index 0000000..defc488
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/cookie1.C
@@ -0,0 +1,15 @@
+// { dg-options "-fabi-version=0" }
+
+void *operator new[](__SIZE_TYPE__, void *);
+
+struct A {
+ ~A(){}
+};
+
+int main()
+{
+ A * a = (A*) new char[20];
+ A * b = new(a) A[3];
+ if (a != b)
+ return 1;
+}
diff --git a/gcc/testsuite/g++.dg/abi/cookie2.C b/gcc/testsuite/g++.dg/abi/cookie2.C
new file mode 100644
index 0000000..dc18045
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/cookie2.C
@@ -0,0 +1,16 @@
+// { dg-options "-fabi-version=1" }
+
+void *operator new[](__SIZE_TYPE__, void *);
+
+struct A {
+ ~A(){}
+};
+
+int main()
+{
+ A * a = (A*) new char[20];
+ A * b = new(a) A[3];
+ // In the 3.2 ABI, a cookie was allocated in this case.
+ if (a == b)
+ return 1;
+}
diff --git a/gcc/testsuite/g++.dg/parse/builtin1.C b/gcc/testsuite/g++.dg/parse/builtin1.C
new file mode 100644
index 0000000..3b826bd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/builtin1.C
@@ -0,0 +1,16 @@
+namespace std {
+class Base {};
+}
+
+struct Derived : public std::Base {
+ operator const char*() const;
+ operator bool(void) const;
+};
+
+void log(const char* str);
+
+void nothing()
+{
+ Derived temp;
+ log(temp);
+}
diff --git a/gcc/testsuite/g++.dg/parse/class1.C b/gcc/testsuite/g++.dg/parse/class1.C
new file mode 100644
index 0000000..819c48d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/class1.C
@@ -0,0 +1,10 @@
+namespace N
+{
+ struct A;
+ int f() {
+ struct N::A { // { dg-error "" }
+ A() {}
+ };
+ return 0;
+ }
+}
diff --git a/gcc/testsuite/g++.dg/parse/namespace7.C b/gcc/testsuite/g++.dg/parse/namespace7.C
new file mode 100644
index 0000000..c8ac608
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/namespace7.C
@@ -0,0 +1,8 @@
+namespace O {
+ struct SO;
+ namespace I {
+ struct SI;
+ struct O::SO {}; // { dg-error "" }
+ }
+ struct I::SI {};
+}
diff --git a/gcc/testsuite/g++.dg/template/field1.C b/gcc/testsuite/g++.dg/template/field1.C
new file mode 100644
index 0000000..c61437b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/field1.C
@@ -0,0 +1,12 @@
+struct A {
+ void (*f)(void);
+};
+
+template< typename R >
+struct B : public A {
+ void g()
+ {
+ A::f();
+ }
+};
+template class B<bool>;
diff --git a/gcc/testsuite/g++.old-deja/g++.other/decl5.C b/gcc/testsuite/g++.old-deja/g++.other/decl5.C
index b46d57d..f384fe0 100644
--- a/gcc/testsuite/g++.old-deja/g++.other/decl5.C
+++ b/gcc/testsuite/g++.old-deja/g++.other/decl5.C
@@ -26,7 +26,7 @@ struct B {
struct A::fink { // ERROR - no such member
int m;
};
- struct A::Z { // ERROR - A::Z not a member of B XFAIL
+ struct A::Z { // ERROR - A::Z not a member of B
int m;
};
int m;
@@ -66,7 +66,7 @@ namespace NMS
int N::fn() { // ERROR - N::fn not a member of NMS
return 0;
}
- struct N::F { // ERROR - N::F not a member of NMS XFAIL
+ struct N::F { // ERROR - N::F not a member of NMS
int i;
};
}