2004-03-18 Mark Mitchell <mark@codesourcery.com>
+ * semantics.c (finish_pseudo_destructor_expr): Allow differing
+ cv-qualification between the type named by the
+ pseudo-destructor-name and the object-type.
+
+ * search.c (accessible_base_p): Handle non-proper bases.
+
+ * name-lookup.c (do_nonmember_using_decl): If a using declaration
+ refers to a single overloaded function, set the type of the
+ function.
+ * tree.c (lvalue_type): Simplify.
+ * typeck.c (type_unknown_p): Do not assume all OVERLOADs have an
+ unknown type.
+ (build_unary_op): Handle OVERLOADs with known types.
+
+ * decl.c (duplicate_decls): Do not destroy DECL_ARGUMENTS for
+ function templates.
+
+ * parser.c (cp_parser_postfix_expression): Handle the use of
+ "typename" in non-dependent contexts. Convert appropriately when
+ when using a qualified name after "->" or ".".
+
+ * call.c (conditional_conversion): Honor the requirement that some
+ conversions refer to the original object.
+
+2004-03-18 Mark Mitchell <mark@codesourcery.com>
+
* call.c (build_conditional_expr): Do not call force_rvalue for
operands of void_type when the conditional expression itself has
void type.
same cv-qualification as, or a greater cv-qualification than, the
cv-qualification of T1. If the conversion is applied, E1 is
changed to an rvalue of type T2 that still refers to the original
- source class object (or the appropriate subobject thereof).
-
- FIXME we can't express an rvalue that refers to the original object;
- we have to create a new one. */
+ source class object (or the appropriate subobject thereof). */
if (CLASS_TYPE_P (t1) && CLASS_TYPE_P (t2)
&& ((good_base = DERIVED_FROM_P (t2, t1)) || DERIVED_FROM_P (t1, t2)))
{
conv = build_identity_conv (t1, e1);
if (!same_type_p (TYPE_MAIN_VARIANT (t1),
TYPE_MAIN_VARIANT (t2)))
- {
- conv = build_conv (ck_base, t2, conv);
- conv->need_temporary_p = true;
- }
+ conv = build_conv (ck_base, t2, conv);
else
conv = build_conv (ck_rvalue, t2, conv);
return conv;
DECL_SOURCE_LOCATION (olddecl)
= DECL_SOURCE_LOCATION (DECL_TEMPLATE_RESULT (olddecl))
= DECL_SOURCE_LOCATION (newdecl);
+ if (DECL_FUNCTION_TEMPLATE_P (newdecl))
+ DECL_ARGUMENTS (DECL_TEMPLATE_RESULT (olddecl))
+ = DECL_ARGUMENTS (DECL_TEMPLATE_RESULT (newdecl));
}
if (DECL_FUNCTION_TEMPLATE_P (newdecl))
if (tmp1)
continue;
+ /* If we are adding to an existing OVERLOAD, then we no
+ longer know the type of the set of functions. */
+ if (*newval && TREE_CODE (*newval) == OVERLOAD)
+ TREE_TYPE (*newval) = unknown_type_node;
+ /* Add this new function to the set. */
*newval = build_overload (OVL_CURRENT (tmp), *newval);
+ /* If there is only one function, then we use its type. (A
+ using-declaration naming a single function can be used in
+ contexts where overload resolution cannot be
+ performed.) */
if (TREE_CODE (*newval) != OVERLOAD)
- *newval = ovl_cons (*newval, NULL_TREE);
+ {
+ *newval = ovl_cons (*newval, NULL_TREE);
+ TREE_TYPE (*newval) = TREE_TYPE (OVL_CURRENT (tmp));
+ }
OVL_USED (*newval) = 1;
}
}
/* If that didn't work, try an identifier. */
if (!cp_parser_parse_definitely (parser))
id = cp_parser_identifier (parser);
+ /* If we look up a template-id in a non-dependent qualifying
+ scope, there's no need to create a dependent type. */
+ if (TREE_CODE (id) == TYPE_DECL
+ && !dependent_type_p (parser->scope))
+ type = TREE_TYPE (id);
/* Create a TYPENAME_TYPE to represent the type to which the
functional cast is being performed. */
- type = make_typename_type (parser->scope, id,
- /*complain=*/1);
+ else
+ type = make_typename_type (parser->scope, id,
+ /*complain=*/1);
postfix_expression = cp_parser_functional_cast (parser, type);
}
parser->qualifying_scope = NULL_TREE;
parser->object_scope = NULL_TREE;
}
+ if (scope && name && BASELINK_P (name))
+ adjust_result_of_qualified_name_lookup
+ (name, BINFO_TYPE (BASELINK_BINFO (name)), scope);
postfix_expression
= finish_class_member_access_expr (postfix_expression, name);
}
}
/* Returns true if type BASE is accessible in T. (BASE is known to be
- a base class of T.) */
+ a (possibly non-proper) base class of T.) */
bool
accessible_base_p (tree t, tree base)
/* [class.access.base]
A base class is said to be accessible if an invented public
- member of the base class is accessible. */
+ member of the base class is accessible.
+
+ If BASE is a non-proper base, this condition is trivially
+ true. */
+ if (same_type_p (t, base))
+ return true;
/* Rather than inventing a public member, we use the implicit
public typedef created in the scope of every class. */
decl = TYPE_FIELDS (base);
return error_mark_node;
}
- if (!same_type_p (TREE_TYPE (object), destructor))
+ /* [expr.pseudo] says both:
+
+ The type designated by the pseudo-destructor-name shall be
+ the same as the object type.
+
+ and:
+
+ The cv-unqualified versions of the object type and of the
+ type designated by the pseudo-destructor-name shall be the
+ same type.
+
+ We implement the more generous second sentence, since that is
+ what most other compilers do. */
+ if (!same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (object),
+ destructor))
{
error ("`%E' is not of type `%T'", object, destructor);
return error_mark_node;
lvalue_type (tree arg)
{
tree type = TREE_TYPE (arg);
- if (TREE_CODE (arg) == OVERLOAD)
- type = unknown_type_node;
return type;
}
int
type_unknown_p (tree exp)
{
- return (TREE_CODE (exp) == OVERLOAD
- || TREE_CODE (exp) == TREE_LIST
+ return (TREE_CODE (exp) == TREE_LIST
|| TREE_TYPE (exp) == unknown_type_node);
}
if (! lvalue_p (arg) && pedantic)
pedwarn ("ISO C++ forbids taking the address of a cast to a non-lvalue expression");
break;
-
+
+ case OVERLOAD:
+ arg = OVL_CURRENT (arg);
+ break;
+
default:
break;
}
+2004-03-18 Mark Mitchell <mark@codesourcery.com>
+
+ * g++.dg/expr/dtor2.C: New test.
+
+ * g++.dg/lookup/anon4.C: New test.
+
+ * g++.dg/overload/using1.C: New test.
+
+ * g++.dg/template/lookup7.C: New test.
+
+ * g++.dg/template/typename6.C: New test.
+
+ * g++.dg/expr/cond6.C: New test.
+
2004-03-18 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* gcc.dg/torture/builtin-convert-1.c: Test more math builtins.
--- /dev/null
+// { dg-do "run" }
+
+extern "C" void abort ();
+
+struct B {
+ B() {}
+ B(const B& b) { abort (); }
+};
+
+struct D : public B {
+ D() {}
+ D(const D& d) : B() {}
+};
+
+D d;
+B b;
+
+D f() {
+ return d;
+}
+
+int main () {
+ b = (true ? f() : b);
+}
--- /dev/null
+typedef const int I;
+int i;
+
+void f() {
+ i.I::~I();
+}
--- /dev/null
+static union {
+ int i;
+};
+
+int *ip;
+
+void g() {
+ ip = &i;
+}
--- /dev/null
+void f();
+
+namespace N {
+ using ::f;
+}
+
+bool b;
+
+void g() {
+ b = N::f == ::f;
+}
--- /dev/null
+class S;
+
+template<class T>
+int f(T, S);
+
+class S {
+ template<class T>
+ friend int f(T t, S) { t; return 0; }
+};
--- /dev/null
+struct O {
+ template <typename T>
+ struct I {
+ I (int);
+ };
+};
+
+template <typename T>
+void f() {
+ typename ::O::I<int>(3);
+}