diff options
-rw-r--r-- | gcc/cp/ChangeLog | 16 | ||||
-rw-r--r-- | gcc/cp/call.c | 3 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 4 | ||||
-rw-r--r-- | gcc/cp/decl.c | 130 | ||||
-rw-r--r-- | gcc/cp/parse.y | 19 | ||||
-rw-r--r-- | gcc/cp/search.c | 44 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 27 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/crash1.C | 6 |
9 files changed, 161 insertions, 92 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index f9f55ea4865..bb028f6273f 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,19 @@ +2002-08-09 Mark Mitchell <mark@codesourcery.com> + + * call.c (standard_conversion): Use build_ptrmem_type. + * cp-tree.h (build_ptrmem_type): New function. + (adjust_result_of_qualified_name_lookup): Likewise. + * decl.c (grokvardecl): Do not look for OFFSET_TYPEs to indicate + static data members. + (build_ptrmem_type): New function. + (grokdeclarator): Do not use build_offset_type when encountering a + qualified name. + * parse.y (parse_finish_call_expr): Use + adjust_result_of_qualified_name_lookup. + * search.c (adjust_result_of_qualified_name_lookup): New function. + * typeck.c (qualify_type_recursive): Use TYPE_PTRMEM_* rather than + accessing OFFSET_TYPEs directly. + 2002-08-08 Mike Stump <mrs@apple.com> * call.c (add_builtin_candidate): legal -> valid, illegal -> invalid. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 00df003cffb..cbd7faf31a9 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -838,8 +838,7 @@ standard_conversion (to, from, expr) (TREE_TYPE (TREE_TYPE (from)), TREE_TYPE (TREE_TYPE (to))))) { - from = build_offset_type (tbase, TREE_TYPE (TREE_TYPE (from))); - from = build_pointer_type (from); + from = build_ptrmem_type (tbase, TREE_TYPE (TREE_TYPE (from))); conv = build_conv (PMEM_CONV, from, conv); } } diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 25b6e949d2d..44a52fc8e78 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -3682,6 +3682,7 @@ extern void expand_static_init PARAMS ((tree, tree)); extern tree start_handler_parms PARAMS ((tree, tree)); extern int complete_array_type PARAMS ((tree, tree, int)); extern tree build_ptrmemfunc_type PARAMS ((tree)); +extern tree build_ptrmem_type (tree, tree); /* the grokdeclarator prototype is in decl.h */ extern int parmlist_is_exprlist PARAMS ((tree)); extern int copy_fn_p PARAMS ((tree)); @@ -4056,7 +4057,8 @@ extern tree find_vbase_instance PARAMS ((tree, tree)); extern tree binfo_for_vbase PARAMS ((tree, tree)); extern tree binfo_via_virtual PARAMS ((tree, tree)); extern tree build_baselink (tree, tree, tree, tree); - +extern tree adjust_result_of_qualified_name_lookup + (tree, tree, tree); /* in semantics.c */ extern void init_cp_semantics PARAMS ((void)); extern tree finish_expr_stmt PARAMS ((tree)); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 15566e5f113..2a185148f51 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -9137,64 +9137,68 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals, return decl; } +/* Create a VAR_DECL named NAME with the indicated TYPE. + + If SCOPE is non-NULL, it is the class type or namespace containing + the variable. If SCOPE is NULL, the variable should is created in + the innermost enclosings scope. */ + static tree -grokvardecl (type, declarator, specbits_in, initialized, constp, in_namespace) +grokvardecl (type, name, specbits_in, initialized, constp, scope) tree type; - tree declarator; + tree name; RID_BIT_TYPE *specbits_in; int initialized; int constp; - tree in_namespace; + tree scope; { tree decl; RID_BIT_TYPE specbits; + my_friendly_assert (!name || TREE_CODE (name) == IDENTIFIER_NODE, + 20020808); + specbits = *specbits_in; - if (TREE_CODE (type) == OFFSET_TYPE) + /* Compute the scope in which to place the variable. */ + if (!scope) { - /* If you declare a static member so that it - can be initialized, the code will reach here. */ - tree basetype = TYPE_OFFSET_BASETYPE (type); - type = TREE_TYPE (type); - decl = build_lang_decl (VAR_DECL, declarator, type); - DECL_CONTEXT (decl) = basetype; - } + /* An explicit "extern" specifier indicates a namespace-scope + variable. */ + if (RIDBIT_SETP (RID_EXTERN, specbits)) + scope = current_namespace; + else if (!at_function_scope_p ()) + { + scope = current_scope (); + if (!scope) + scope = current_namespace; + } + } + + if (scope + && (/* If the variable is a namespace-scope variable declared in a + template, we need DECL_LANG_SPECIFIC. */ + (TREE_CODE (scope) == NAMESPACE_DECL && processing_template_decl) + /* Similarly for namespace-scope variables with language linkage + other than C++. */ + || (TREE_CODE (scope) == NAMESPACE_DECL + && current_lang_name != lang_name_cplusplus) + /* Similarly for static data members. */ + || TYPE_P (scope))) + decl = build_lang_decl (VAR_DECL, name, type); else - { - tree context; - - if (in_namespace) - context = in_namespace; - else if (namespace_bindings_p () || RIDBIT_SETP (RID_EXTERN, specbits)) - context = current_namespace; - else - context = NULL_TREE; - - /* For namespace-scope variables, declared in a template, we - need the full lang_decl. The same is true for - namespace-scope variables that do not have C++ language - linkage. */ - if (context - && (processing_template_decl - || current_lang_name != lang_name_cplusplus)) - decl = build_lang_decl (VAR_DECL, declarator, type); - else - decl = build_decl (VAR_DECL, declarator, type); - - if (context) - set_decl_namespace (decl, context, 0); + decl = build_decl (VAR_DECL, name, type); - context = DECL_CONTEXT (decl); - if (declarator && context && current_lang_name != lang_name_c) - /* We can't mangle lazily here because we don't have any - way to recover whether or not a variable was `extern - "C"' later. */ - mangle_decl (decl); - } + if (scope && TREE_CODE (scope) == NAMESPACE_DECL) + set_decl_namespace (decl, scope, 0); + else + DECL_CONTEXT (decl) = scope; - if (in_namespace) - set_decl_namespace (decl, in_namespace, 0); + if (name && scope && current_lang_name != lang_name_c) + /* We can't mangle lazily here because we don't have any + way to recover whether or not a variable was `extern + "C"' later. */ + mangle_decl (decl); if (RIDBIT_SETP (RID_EXTERN, specbits)) { @@ -9320,6 +9324,14 @@ build_ptrmemfunc_type (type) return t; } +/* Create and return a pointer to data member type. */ + +tree +build_ptrmem_type (tree class_type, tree member_type) +{ + return build_pointer_type (build_offset_type (class_type, member_type)); +} + /* DECL is a VAR_DECL defined in-class, whose TYPE is also given. Check to see that the definition is valid. Issue appropriate error messages. Return 1 if the definition is particularly bad, or 0 @@ -9811,6 +9823,12 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) tree attributes; + if (decl_context != NORMAL) + { + error ("variable declaration is not allowed here"); + return error_mark_node; + } + *next = TREE_OPERAND (decl, 0); init = CALL_DECLARATOR_PARMS (decl); @@ -9835,7 +9853,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) } else error ("invalid declarator"); - return 0; + return NULL_TREE; } innermost_code = TREE_CODE (decl); if (decl_context == FIELD && ctype == NULL_TREE) @@ -10580,7 +10598,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) /* Now figure out the structure of the declarator proper. Descend through it, creating more complex types, until we reach - the declared identifier (or NULL_TREE, in an absolute declarator). */ + the declared identifier (or NULL_TREE, in an abstract declarator). */ while (declarator && TREE_CODE (declarator) != IDENTIFIER_NODE && TREE_CODE (declarator) != TEMPLATE_ID_EXPR) @@ -10892,9 +10910,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) continue; } - if (TREE_CODE (type) == OFFSET_TYPE - && (TREE_CODE (TREE_TYPE (type)) == VOID_TYPE - || TREE_CODE (TREE_TYPE (type)) == REFERENCE_TYPE)) + if (ctype + && (TREE_CODE (type) == VOID_TYPE + || TREE_CODE (type) == REFERENCE_TYPE)) { error ("cannot declare pointer to `%#T' member", TREE_TYPE (type)); @@ -10917,6 +10935,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) } else if (TREE_CODE (type) == METHOD_TYPE) type = build_ptrmemfunc_type (build_pointer_type (type)); + else if (ctype) + type = build_ptrmem_type (ctype, type); else type = build_pointer_type (type); @@ -11102,7 +11122,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) ctype, name, current_class_type); return void_type_node; } - type = build_offset_type (ctype, type); } else { @@ -11121,14 +11140,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) if (declarator && TREE_CODE (declarator) == CALL_EXPR) /* In this case, we will deal with it later. */ ; - else - { - if (TREE_CODE (type) == FUNCTION_TYPE) - type = build_cplus_method_type (ctype, TREE_TYPE (type), - TYPE_ARG_TYPES (type)); - else - type = build_offset_type (ctype, type); - } + else if (TREE_CODE (type) == FUNCTION_TYPE) + type = build_cplus_method_type (ctype, TREE_TYPE (type), + TYPE_ARG_TYPES (type)); } } break; @@ -11846,7 +11860,7 @@ friend declaration requires class-key, i.e. `friend %#T'", decl = grokvardecl (type, declarator, &specbits, initialized, (type_quals & TYPE_QUAL_CONST) != 0, - in_namespace); + ctype ? ctype : in_namespace); bad_specifiers (decl, "variable", virtualp, quals != NULL_TREE, inlinep, friendp, raises != NULL_TREE); diff --git a/gcc/cp/parse.y b/gcc/cp/parse.y index 01181d73b4c..1134939f840 100644 --- a/gcc/cp/parse.y +++ b/gcc/cp/parse.y @@ -4156,22 +4156,9 @@ parse_finish_call_expr (tree fn, tree args, int koenig) BASELINK_FUNCTIONS (fn), template_args); } - if (BASELINK_P (fn) - && current_class_type - && DERIVED_FROM_P (scope, current_class_type)) - { - scope = lookup_base (current_class_type, scope, - ba_ignore | ba_quiet, NULL); - if (scope) - { - BASELINK_ACCESS_BINFO (fn) = scope; - BASELINK_BINFO (fn) - = lookup_base (scope, - BINFO_TYPE (BASELINK_BINFO (fn)), - ba_ignore | ba_quiet, - NULL); - } - } + if (current_class_type) + fn = (adjust_result_of_qualified_name_lookup + (fn, scope, current_class_type)); } } disallow_virtual = true; diff --git a/gcc/cp/search.c b/gcc/cp/search.c index 071a551fbe3..e4e8baa9ad2 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -1640,6 +1640,50 @@ lookup_fnfields_1 (type, name) return -1; } + +/* DECL is the result of a qualified name lookup. QUALIFYING_CLASS + was the class used to qualify the name. CONTEXT_CLASS is the class + corresponding to the object in which DECL will be used. Return a + possibly modified version of DECL that takes into account the + CONTEXT_CLASS. + + In particular, consider an expression like `B::m' in the context of + a derived class `D'. If `B::m' has been resolved to a BASELINK, + then the most derived class indicated by the BASELINK_BINFO will be + `B', not `D'. This function makes that adjustment. */ + +tree +adjust_result_of_qualified_name_lookup (tree decl, + tree qualifying_class, + tree context_class) +{ + my_friendly_assert (CLASS_TYPE_P (qualifying_class), 20020808); + my_friendly_assert (CLASS_TYPE_P (context_class), 20020808); + + if (BASELINK_P (decl) + && DERIVED_FROM_P (qualifying_class, context_class)) + { + tree base; + + /* Look for the QUALIFYING_CLASS as a base of the + CONTEXT_CLASS. If QUALIFYING_CLASS is ambiguous, we cannot + be sure yet than an error has occurred; perhaps the function + chosen by overload resolution will be static. */ + base = lookup_base (context_class, qualifying_class, + ba_ignore | ba_quiet, NULL); + if (base) + { + BASELINK_ACCESS_BINFO (decl) = base; + BASELINK_BINFO (decl) + = lookup_base (base, BINFO_TYPE (BASELINK_BINFO (decl)), + ba_ignore | ba_quiet, + NULL); + } + } + + return decl; +} + /* Walk the class hierarchy dominated by TYPE. FN is called for each type in the hierarchy, in a breadth-first preorder traversal. diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 09ecd66b4ad..f8bc3786358 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -203,28 +203,33 @@ qualify_type_recursive (t1, t2) if ((TYPE_PTR_P (t1) && TYPE_PTR_P (t2)) || (TYPE_PTRMEM_P (t1) && TYPE_PTRMEM_P (t2))) { - tree tt1 = TREE_TYPE (t1); - tree tt2 = TREE_TYPE (t2); + tree tt1; + tree tt2; tree b1; int type_quals; tree tgt; tree attributes = (*targetm.merge_type_attributes) (t1, t2); - if (TREE_CODE (tt1) == OFFSET_TYPE) + if (TYPE_PTRMEM_P (t1)) { - b1 = TYPE_OFFSET_BASETYPE (tt1); - tt1 = TREE_TYPE (tt1); - tt2 = TREE_TYPE (tt2); + b1 = TYPE_PTRMEM_CLASS_TYPE (t1); + tt1 = TYPE_PTRMEM_POINTED_TO_TYPE (t1); + tt2 = TYPE_PTRMEM_POINTED_TO_TYPE (t2); } else - b1 = NULL_TREE; + { + b1 = NULL_TREE; + tt1 = TREE_TYPE (t1); + tt2 = TREE_TYPE (t2); + } type_quals = (cp_type_quals (tt1) | cp_type_quals (tt2)); tgt = qualify_type_recursive (tt1, tt2); tgt = cp_build_qualified_type (tgt, type_quals); if (b1) - tgt = build_offset_type (b1, tgt); - t1 = build_pointer_type (tgt); + t1 = build_ptrmem_type (b1, tgt); + else + t1 = build_pointer_type (tgt); t1 = build_type_attribute_variant (t1, attributes); } return t1; @@ -4390,9 +4395,7 @@ unary_complex_lvalue (code, arg) return error_mark_node; } - type = build_offset_type (DECL_FIELD_CONTEXT (t), TREE_TYPE (t)); - type = build_pointer_type (type); - + type = build_ptrmem_type (DECL_FIELD_CONTEXT (t), TREE_TYPE (t)); t = make_ptrmem_cst (type, TREE_OPERAND (arg, 1)); return t; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 3e18dc1c340..c1bd99ba9e7 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2002-08-09 Mark Mitchell <mark@codesourcery.com> + + * g++.dg/template/crash1.C: New test. + 2002-08-08 Jakub Jelinek <jakub@redhat.com> * gcc.dg/tls/opt-2.c: New test. diff --git a/gcc/testsuite/g++.dg/template/crash1.C b/gcc/testsuite/g++.dg/template/crash1.C index 27e89641ac7..e3c83bcd22f 100644 --- a/gcc/testsuite/g++.dg/template/crash1.C +++ b/gcc/testsuite/g++.dg/template/crash1.C @@ -1,7 +1,7 @@ // { dg-do compile } -// Copyright (C) 2001 Free Software Foundation, Inc. -// Contributed by Nathan Sidwell 29 Dec 2001 <nathan@nathan@codesourcery.com> +// Copyright (C) 2001, 2002 Free Software Foundation, Inc. +// Contributed by Nathan Sidwell 29 Dec 2001 <nathan@codesourcery.com> // PR 5125. ICE @@ -13,5 +13,5 @@ class S template <class I> void S::Foo(int (*f)(TYPO&o) ) -{ // { dg-error "template definition of non-template|prototype" "" } +{ // { dg-error "template definition|variable declaration|prototype" "" } } |