diff options
author | Mark Mitchell <mark@codesourcery.com> | 2003-03-08 09:12:54 +0000 |
---|---|---|
committer | Mark Mitchell <mmitchel@gcc.gnu.org> | 2003-03-08 09:12:54 +0000 |
commit | 089d6ea74bea18d183968d655d7dd2c4e336ab03 (patch) | |
tree | 6b4defb4aeefb856b583b42ac040705d6ebed502 | |
parent | 6fef42173faf90a30b4fa0c565754173a74236b7 (diff) | |
download | gcc-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
-rw-r--r-- | gcc/cp/ChangeLog | 24 | ||||
-rw-r--r-- | gcc/cp/call.c | 5 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 3 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 98 | ||||
-rw-r--r-- | gcc/cp/init.c | 143 | ||||
-rw-r--r-- | gcc/cp/parser.c | 24 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 17 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/abi/cookie1.C | 15 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/abi/cookie2.C | 16 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/parse/builtin1.C | 16 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/parse/class1.C | 10 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/parse/namespace7.C | 8 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/field1.C | 12 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.other/decl5.C | 4 |
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; }; } |