summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/cp/ChangeLog16
-rw-r--r--gcc/cp/call.c3
-rw-r--r--gcc/cp/cp-tree.h4
-rw-r--r--gcc/cp/decl.c130
-rw-r--r--gcc/cp/parse.y19
-rw-r--r--gcc/cp/search.c44
-rw-r--r--gcc/cp/typeck.c27
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/g++.dg/template/crash1.C6
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" "" }
}