39th Cygnus<->FSF merge

From-SVN: r7439
This commit is contained in:
Mike Stump 1994-06-03 21:42:31 +00:00
parent 5345f91a0b
commit a0a339271a
21 changed files with 1081 additions and 593 deletions

View File

@ -1,3 +1,289 @@
Fri Jun 3 02:10:56 1994 Jason Merrill (jason@deneb.cygnus.com)
* cvt.c (cp_convert): Replace constants with their values before
converting.
Thu Jun 2 03:53:30 1994 Jason Merrill (jason@deneb.cygnus.com)
* typeck2.c (build_x_arrow): Resolve OFFSET_REFs first.
Wed Jun 1 18:57:35 1994 Jason Merrill (jason@deneb.cygnus.com)
* typeck2.c (digest_init): Handle initializing a pmf with an
overloaded method.
* typeck.c (build_ptrmemfunc): Handle overloaded methods.
* decl.c (pushtag): Use build_decl to make TYPE_DECLs.
(xref_defn_tag): Ditto.
* pt.c (process_template_parm): Ditto.
(lookup_template_class): Ditto.
(push_template_decls): Ditto.
(instantiate_class_template): Ditto.
(create_nested_upt): Ditto.
* class.c (finish_struct): Don't try to set DECL_CLASS_CONTEXT on
TYPE_DECLs.
* typeck.c (convert_arguments): Make sure type is not NULL before
checking its TREE_CODE.
Wed Jun 1 17:40:39 1994 Mike Stump (mrs@cygnus.com)
* class.c (get_derived_offset): New routine.
* class.c (finish_base_struct): Make sure we set BINFO_VTABLE and
BINFO_VIRTUALS when we choose a new base class to inherit from.
* class.c (modify_one_vtable): Use get_derived_offset to get the
offset to the most base class subobject that we derived this binfo
from.
* class.c (finish_struct): Move code to calculate the
DECL_FIELD_BITPOS of the vfield up, as we need might need it for
new calls to get_derived_offset in modify_one_vtable.
Wed Jun 1 16:50:59 1994 Jason Merrill (jason@deneb.cygnus.com)
* init.c (build_member_call): Use build_pointer_type instead of
TYPE_POINTER_TO.
Wed Jun 1 11:11:15 1994 Brendan Kehoe (brendan@lisa.cygnus.com)
* decl.c (grokdeclarator): Make sure we have a DNAME set before we
try to use it in an error.
Wed Jun 1 09:48:49 1994 Mike Stump (mrs@cygnus.com)
* typeck.c (convert_arguments, convert_for_initialization): Don't
strip NOP_EXPRs, when we are converting to a reference.
Wed Jun 1 01:11:38 1994 Jason Merrill (jason@deneb.cygnus.com)
* typeck.c (build_modify_expr): Don't dereference references when
initializing them.
* decl2.c (grokfield): Don't check for grokdeclarator returning
error_mark_node any more.
* decl.c (grokfndecl): Return NULL_TREE instead of error_mark_node.
(start_method): Return void_type_node instead of error_mark_node.
* typeck.c (build_modify_expr): Resolve offset refs earlier.
Tue May 31 16:06:58 1994 Jason Merrill (jason@deneb.cygnus.com)
* call.c (build_method_call): Resolve OFFSET_REFs in the object.
* typeck.c (build_modify_expr): Dereference references before trying
to assign to them.
* call.c (build_method_call): Don't confuse type conversion
operators with constructors.
* typeck2.c (build_functional_cast): Just call build_c_cast if there
was only one parameter.
* method.c (build_typename_overload): Don't set
IDENTIFIER_GLOBAL_VALUE on these identifiers.
* decl.c (grok_op_properties): Warn about defining a type conversion
operator that converts to a base class (or reference to it).
* cvt.c (cp_convert): Don't try to use a type conversion operator
when converting to a base class.
(build_type_conversion_1): Don't call constructor_name_full on an
identifier.
* cp-tree.h (DERIVED_FROM_P): Should be self-explanatory.
* decl.c (start_decl): Don't complain that error_mark_node is an
incomplete type.
(finish_decl): Check for type == error_mark_node.
Mon May 30 23:38:55 1994 Jason Merrill (jason@deneb.cygnus.com)
* decl.c (start_function): Set DECL_DEFER_OUTPUT on implicit
instantiations and inline members.
* spew.c (yylex): Set looking_for_template if the next token is a '<'.
* lex.h: Declare looking_for_template.
* decl.c (lookup_name_real): Use looking_for_template to arbitrate
between type and template interpretations of an identifier.
Sat May 28 04:07:40 1994 Jason Merrill (jason@deneb.cygnus.com)
* pt.c (instantiate_template): Zero out p if we found a
specialization.
* decl.c (grokdeclarator): Elucidate warning.
(grokdeclarator): If pedantic AND -ansi, complain about long long.
Make explicit instantiation work reasonably. It is now appropriate
to deprecate the use of -fexternal-templates.
* pt.c (instantiate_template): Set DECL_TEMPLATE_SPECIALIZATION or
DECL_IMPLICIT_INSTANTIATION on fndecl as appropriate.
(end_template_instantiation): Reflect changes in USE_TEMPLATE
semantics.
(do_pending_expansions): if (!flag_implicit_templates) DECIDE(0);
(do_function_instantiation): Don't set EXPLICIT_INST if
flag_external_templates is set. Do set TREE_PUBLIC and DECL_EXTERN
appropriately otherwise.
(do_type_instantiation): Set interface info for class. Set
TREE_PUBLIC and DECL_EXTERN for methods. Do none of this if
flag_external_templates is set.
* parse.y: Reflect changes in USE_TEMPLATE semantics.
* decl2.c: New flag flag_implicit_templates determines whether or
not implicit instantiations get emitted. This flag currently
defaults to true, and must be true for -fexternal-templates to work.
(finish_file): Consider flag_implement_inlines when
setting DECL_EXTERNAL. Consider flag_implicit_templates when
deciding whether or not to emit a static copy.
* decl.c (start_function): Set TREE_PUBLIC and DECL_EXTERNAL
properly for template instantiations.
(start_method): Set DECL_IMPLICIT_INSTANTIATION on methods of a
template class.
* cp-tree.h (CLASSTYPE_USE_TEMPLATE): Change semantics.
(DECL_USE_TEMPLATE): Parallel macro for FUNCTION and VAR_DECLs.
(various others): Accessor macros for the above.
Fri May 27 13:57:40 1994 Jason Merrill (jason@deneb.cygnus.com)
* typeck.c (build_binary_op_nodefault): Division by constant zero is
an error.
Fri May 27 13:50:15 1994 Mike Stump (mrs@cygnus.com)
* class.c (override_one_vtable): Don't modify things we don't own.
Fri May 27 01:42:58 1994 Jason Merrill (jason@deneb.cygnus.com)
* decl.c (finish_decl): Don't postpone processing the initializer of
a decl with DECL_EXTERNAL set, and do call rest_of_compilation for a
PUBLIC const at toplevel.
(grokdeclarator): pedwarn about initializing non-const or
non-integral statics in the class body.
* decl.c (pushtag): Don't try to set DECL_CLASS_CONTEXT on a
TYPE_DECL.
* call.c (convert_harshness): Dereference reference on rhs before
proceeding, properly grok passing const things to non-const
references.
* typeck.c (build_unary_op): Soften error about taking the address
of main() to a pedwarn.
* lex.c (default_copy_constructor_body): Unambiguously specify base
classes (i.e. A((const class ::A&)_ctor_arg) ).
(default_assign_ref_body): Ditto.
Thu May 26 13:13:55 1994 Gerald Baumgartner (gb@mexican.cygnus.com)
* decl2.c (grokfield): Don't complain about local signature
method declaration without definition.
* call.c (convert_harshness): If `type' is a signature pointer
and `parmtype' is a pointer to a signature, just return 0. We
don't really convert in this case; it's a result of making the
`this' parameter of a signature method a signature pointer.
* call.c (build_method_call): Distinguish calling the default copy
constructor of a signature pointer/reference from a signature
member function call.
Thu May 26 12:56:25 1994 Jason Merrill (jason@deneb.cygnus.com)
* decl2.c (grokfield): Don't set TREE_PUBLIC on member function
declarations.
* decl.c (duplicate_decls): A previous function declaration as
static overrides a subsequent non-static definition.
(grokdeclarator): Don't set TREE_PUBLIC on inline method
declarations.
Wed May 25 14:36:38 1994 Jason Merrill (jason@deneb.cygnus.com)
* decl.c (grokdeclarator): Handle initialization of static const
members.
(finish_decl): Ditto.
* decl2.c (grokfield): Allow initialization of static const members
even when pedantic.
* decl2.c (grokfield): Deal with grokdeclarator returning
error_mark_node.
* decl.c (grok_ctor_properties): Return 0 for A(A) constructor.
(grokfndecl): Check the return value of grok_ctor_properties.
(start_method): Ditto.
* parse.y (absdcl): Expand type_quals inline.
Tue May 24 19:10:32 1994 Jason Merrill (jason@deneb.cygnus.com)
* decl.c (pushtag): Use IS_AGGR_TYPE rather than checking for a
RECORD_TYPE.
Tue May 24 18:09:16 1994 Per Bothner (bothner@kalessin.cygnus.com)
* cp-tree.h (VTABLE_NAME_FORMAT): If flag_vtable_thunks,
always use "__vt_%s".
* decl2.c (finish_vtable_vardecl): Don't consider abstract virtuals
when looking for a "sentinal" method (to decide on emitting vtables).
* decl2.c (finish_file): Scan all decls for thunks that need
to be emitted.
* decl2.c (finish_vtable_vardecl): Don't bother calling emit_thunk.
* method.c (make_thunk): Use a more meaningful label. If there
exists a matching top-level THUNK_DECL re-use it; otherwise
create a new THUNK_DECL (and declare it).
* method.c (emit_thunk): Make thunk external/public depending
on the underlying method.
Tue May 24 00:22:04 1994 Jason Merrill (jason@deneb.cygnus.com)
* pt.c (tsubst): Use lookup_name_nonclass to find guiding decls, not
lookup_name.
* call.c (build_overload_call_real): Don't immediately pick a
function which matches perfectly.
* decl.c (grokdeclarator): Use c_build_type_variant for arrays.
(grokdeclarator): Warn about, and throw away, cv-quals attached to a
reference (like 'int &const j').
* typeck.c (convert_arguments): Don't mess with i for methods.
* call.c (build_method_call): Pass the function decl to
convert_arguments.
* typeck.c (comp_ptr_ttypes_real): New function. Implements the
checking for which multi-level pointer conversions are allowed.
(comp_target_types): Call it.
(convert_for_assignment): Check const parity on the ultimate target
type, too. And make those warnings pedwarns.
Mon May 23 14:11:24 1994 Jason Merrill (jason@deneb.cygnus.com)
* error.c (dump_char): Use TARGET_* for character constants.
Mon May 23 13:03:03 1994 Brendan Kehoe (brendan@lisa.cygnus.com)
* tree.c (debug_no_list_hash): Make static.
* decl.c (decls_match): Say the types don't match if newdecl ends up
with a null type, after we've checked if olddecl does.
(pushdecl): Check if the decls themselves match before looking for
an extern redeclared as static, to avoid inappropriate and incorrect
warnings.
Fri May 20 14:04:34 1994 Jason Merrill (jason@deneb.cygnus.com)
* decl.c (grokdeclarator): Make warning about duplicate short, etc.
a pedwarn.
* typeck.c (build_c_cast): Casting to function or method type is an
error.
* class.c (finish_struct): Make warning for anonymous class with no
instances a pedwarn.
* Makefile.in (stamp-parse): Expect a s/r conflict.
* typeck.c (build_modify_expr): pedwarn about using a non-lvalue
cast as an lvalue.
Thu May 19 12:08:48 1994 Jason Merrill (jason@deneb.cygnus.com)
* cvt.c (type_promotes_to): Make sure bool promotes to int rather
@ -30,17 +316,6 @@ Wed May 18 14:27:06 1994 Jason Merrill (jason@deneb.cygnus.com)
* class.c (finish_struct): Allow bool bitfields.
Wed May 18 14:41:59 1994 Mike Stump (mrs@cygnus.com)
* class.c (finish_base_struct): Make sure we set BINFO_VTABLE and
BINFO_VIRTUALS when we choose a new base class to inherit from.
* class.c (modify_one_vtable): Use get_vfield_offset to get the
offset to the most base class subobject that we derived this binfo
from.
* class.c (finish_struct): Move code to calculate the
DECL_FIELD_BITPOS of the vfield up, as we need might need it for
new calls to get_vfield_offset in modify_one_vtable.
Wed May 18 12:35:27 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
* Make-lang.in (c++.install-man): Get g++.1 from $(srcdir)/cp.

View File

@ -41,6 +41,15 @@ CXX_FLAGS_TO_PASS = \
"CXXFLAGS=$(CXXFLAGS)" \
"CXX_FOR_TARGET=$(CXX_FOR_TARGET)"
# Actual names to use when installing a native compiler.
CXX_INSTALL_NAME = c++
GXX_INSTALL_NAME = g++
# Actual names to use when installing a cross-compiler.
CXX_CROSS_NAME = $(target)-c++
GXX_CROSS_NAME = $(target)-g++
# Define the names for selecting c++ in LANGUAGES.
# Note that it would be nice to move the dependency on g++
# into the C++ rule, but that needs a little bit of work
@ -90,17 +99,17 @@ c++.install-normal:
c++.install-common:
-if [ -f cc1plus ] ; then \
if [ -f g++-cross ] ; then \
rm -f $(bindir)/$(target)-g++; \
$(INSTALL_PROGRAM) g++-cross $(bindir)/$(target)-g++; \
chmod a+x $(bindir)/$(target)-g++; \
rm -f $(bindir)/$(target)-c++; \
ln $(bindir)/$(target)-g++ $(bindir)/$(target)-c++; \
rm -f $(bindir)/$(GXX_CROSS_NAME); \
$(INSTALL_PROGRAM) g++-cross $(bindir)/$(GXX_CROSS_NAME); \
chmod a+x $(bindir)/$(GXX_CROSS_NAME); \
rm -f $(bindir)/$(CXX_CROSS_NAME); \
ln $(bindir)/$(GXX_CROSS_NAME) $(bindir)/$(CXX_CROSS_NAME); \
else \
rm -f $(bindir)/g++; \
$(INSTALL_PROGRAM) g++ $(bindir)/g++; \
chmod a+x $(bindir)/g++; \
rm -f $(bindir)/c++; \
ln $(bindir)/g++ $(bindir)/c++; \
rm -f $(bindir)/$(GXX_INSTALL_NAME); \
$(INSTALL_PROGRAM) g++ $(bindir)/$(GXX_INSTALL_NAME); \
chmod a+x $(bindir)/$(GXX_INSTALL_NAME); \
rm -f $(bindir)/$(CXX_INSTALL_NAME); \
ln $(bindir)/$(GXX_INSTALL_NAME) $(bindir)/$(CXX_INSTALL_NAME); \
fi ; \
fi
@ -113,8 +122,10 @@ c++.install-man: $(srcdir)/cp/g++.1
else true; fi
c++.uninstall:
-rm -rf $(bindir)/g++ $(bindir)/c++
-rm -rf $(bindir)/$(target)-g++ $(bindir)/$(target)-c++
-rm -rf $(bindir)/$(CXX_INSTALL_NAME)
-rm -rf $(bindir)/$(CXX_CROSS_NAME)
-rm -rf $(bindir)/$(GXX_INSTALL_NAME)
-rm -rf $(bindir)/$(GXX_CROSS_NAME)
-rm -rf $(mandir)/g++$(manext)
# Clean hooks:

View File

@ -193,7 +193,7 @@ parse.o : $(srcdir)/parse.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h lex.h
`echo $(srcdir)/parse.c | sed 's,^\./,,'`
$(srcdir)/parse.c $(srcdir)/parse.h : $(srcdir)/parse.y
@echo expect 33 reduce/reduce conflicts.
@echo expect 1 shift/reduce confict and 33 reduce/reduce conflicts.
cd $(srcdir); $(BISON) $(BISONFLAGS) -d -o parse.c parse.y
cd $(srcdir); grep '^#define[ ]*YYEMPTY' parse.c >>parse.h

View File

@ -131,6 +131,13 @@ convert_harshness (type, parmtype, parm)
if (TYPE_PTRMEMFUNC_P (parmtype))
parmtype = TYPE_PTRMEMFUNC_FN_TYPE (parmtype);
if (TREE_CODE (parmtype) == REFERENCE_TYPE)
{
if (parm)
parm = convert_from_reference (parm);
parmtype = TREE_TYPE (parmtype);
}
codel = TREE_CODE (type);
coder = TREE_CODE (parmtype);
@ -474,196 +481,138 @@ convert_harshness (type, parmtype, parm)
}
}
/* C++: one of the types must be a reference type. */
{
tree ttl, ttr;
register tree intype = TYPE_MAIN_VARIANT (parmtype);
register enum tree_code form = TREE_CODE (intype);
int penalty = 0;
/* C++: Since the `this' parameter of a signature member function
is represented as a signature pointer to handle default implementations
correctly, we can have the case that `type' is a signature pointer
while `parmtype' is a pointer to a signature table. We don't really
do any conversions in this case, so just return 0. */
if (codel == REFERENCE_TYPE || coder == REFERENCE_TYPE)
{
ttl = TYPE_MAIN_VARIANT (type);
if (codel == RECORD_TYPE && coder == POINTER_TYPE
&& IS_SIGNATURE_POINTER (type) && IS_SIGNATURE (TREE_TYPE (parmtype)))
return ZERO_RETURN (h);
if (codel == REFERENCE_TYPE)
{
ttl = TREE_TYPE (ttl);
if (codel == REFERENCE_TYPE)
{
tree ttl, ttr;
int constp = parm ? TREE_READONLY (parm) : TYPE_READONLY (parmtype);
int volatilep = (parm ? TREE_THIS_VOLATILE (parm)
: TYPE_VOLATILE (parmtype));
register tree intype = TYPE_MAIN_VARIANT (parmtype);
register enum tree_code form = TREE_CODE (intype);
int penalty = 0;
/* When passing a non-const argument into a const reference,
dig it a little, so a non-const reference is preferred over
this one. (mrs) */
if (parm && TREE_READONLY (ttl) && ! TREE_READONLY (parm))
penalty = 2;
else
penalty = 0;
ttl = TREE_TYPE (type);
ttl = TYPE_MAIN_VARIANT (ttl);
/* When passing a non-const argument into a const reference (or vice
versa), dig it a little, so a non-const reference is preferred
over this one. (mrs) */
if (TYPE_READONLY (ttl) != constp
|| TYPE_VOLATILE (ttl) != volatilep)
penalty = 2;
else
penalty = 0;
if (form == OFFSET_TYPE)
{
intype = TREE_TYPE (intype);
form = TREE_CODE (intype);
}
ttl = TYPE_MAIN_VARIANT (ttl);
if (form == REFERENCE_TYPE)
{
intype = TYPE_MAIN_VARIANT (TREE_TYPE (intype));
if (form == OFFSET_TYPE)
{
intype = TREE_TYPE (intype);
form = TREE_CODE (intype);
}
if (ttl == intype)
return ZERO_RETURN (h);
penalty = 2;
}
else
{
/* Can reference be built up? */
if (ttl == intype && penalty == 0) {
/* Because the READONLY and VIRTUAL bits are not always in
the type, this extra check is necessary. The problem
should be fixed someplace else, and this extra code
removed.
if (ttl == intype && penalty == 0)
return ZERO_RETURN (h);
else
penalty = 2;
Also, if type if a reference, the readonly bits could
either be in the outer type (with reference) or on the
inner type (the thing being referenced). (mrs) */
if (parm
&& ((TREE_READONLY (parm)
&& ! (TYPE_READONLY (type)
|| (TREE_CODE (type) == REFERENCE_TYPE
&& TYPE_READONLY (TREE_TYPE (type)))))
|| (TREE_SIDE_EFFECTS (parm)
&& ! (TYPE_VOLATILE (type)
|| (TREE_CODE (type) == REFERENCE_TYPE
&& TYPE_VOLATILE (TREE_TYPE (type)))))))
penalty = 2;
else
return ZERO_RETURN (h);
}
else
penalty = 2;
}
}
else if (form == REFERENCE_TYPE)
{
if (parm)
{
tree tmp = convert_from_reference (parm);
intype = TYPE_MAIN_VARIANT (TREE_TYPE (tmp));
}
else
{
intype = parmtype;
do
intype = TREE_TYPE (intype);
while (TREE_CODE (intype) == REFERENCE_TYPE);
intype = TYPE_MAIN_VARIANT (intype);
}
if (TREE_UNSIGNED (ttl) ^ TREE_UNSIGNED (intype))
{
ttl = unsigned_type (ttl);
intype = unsigned_type (intype);
penalty += 2;
}
if (ttl == intype)
return ZERO_RETURN (h);
else
penalty = 2;
}
ttr = intype;
if (TREE_UNSIGNED (ttl) ^ TREE_UNSIGNED (intype))
{
ttl = unsigned_type (ttl);
intype = unsigned_type (intype);
penalty += 2;
}
/* If the initializer is not an lvalue, then it does not
matter if we make life easier for the programmer
by creating a temporary variable with which to
hold the result. */
if (parm && (INTEGRAL_CODE_P (coder)
|| coder == REAL_TYPE)
&& ! lvalue_p (parm))
{
h = convert_harshness (ttl, ttr, NULL_TREE);
if (penalty > 2 || h.code != 0)
h.code |= STD_CODE;
else
h.code |= TRIVIAL_CODE;
h.distance = 0;
return h;
}
ttr = intype;
/* If the initializer is not an lvalue, then it does not
matter if we make life easier for the programmer
by creating a temporary variable with which to
hold the result. */
if (parm && (INTEGRAL_CODE_P (coder)
|| coder == REAL_TYPE)
&& ! lvalue_p (parm))
{
h = convert_harshness (ttl, ttr, NULL_TREE);
if (penalty > 2 || h.code != 0)
h.code |= STD_CODE;
else
h.code |= TRIVIAL_CODE;
h.distance = 0;
return h;
}
if (ttl == ttr)
{
if (penalty > 2)
{
h.code = STD_CODE;
h.distance = 0;
}
else
{
h.code = TRIVIAL_CODE;
/* We set this here so that build_overload_call_real will be
able to see the penalty we found, rather than just looking
at a TRIVIAL_CODE with no other information. */
h.int_penalty = penalty;
}
return h;
}
/* Pointers to voids always convert for pointers. But
make them less natural than more specific matches. */
if (TREE_CODE (ttl) == POINTER_TYPE && TREE_CODE (ttr) == POINTER_TYPE)
{
if (TREE_TYPE (ttl) == void_type_node
|| TREE_TYPE (ttr) == void_type_node)
{
h.code = STD_CODE;
h.distance = 0;
return h;
}
}
if (parm && codel != REFERENCE_TYPE)
{
h = convert_harshness (ttl, ttr, NULL_TREE);
if (penalty == 2)
h.code |= QUAL_CODE;
else if (penalty == 4)
h.code |= STD_CODE;
h.distance = 0;
return h;
}
/* Here it does matter. If this conversion is from derived to base,
allow it. Otherwise, types must be compatible in the strong sense. */
if (TREE_CODE (ttl) == RECORD_TYPE && TREE_CODE (ttr) == RECORD_TYPE)
{
int b_or_d = get_base_distance (ttl, ttr, 0, 0);
if (b_or_d < 0)
{
b_or_d = get_base_distance (ttr, ttl, 0, 0);
if (b_or_d < 0)
return EVIL_RETURN (h);
h.distance = -b_or_d;
}
/* Say that this conversion is relatively painless.
If it turns out that there is a user-defined X(X&)
constructor, then that will be invoked, but that's
preferable to dealing with other user-defined conversions
that may produce surprising results. */
else
h.distance = b_or_d;
h.code = STD_CODE;
return h;
}
if (comp_target_types (ttl, intype, 1))
{
if (penalty)
if (ttl == ttr)
{
if (penalty > 2)
{
h.code = STD_CODE;
h.distance = 0;
return h;
}
}
}
h.distance = 0;
}
else
{
h.code = TRIVIAL_CODE;
/* We set this here so that build_overload_call_real will be
able to see the penalty we found, rather than just looking
at a TRIVIAL_CODE with no other information. */
h.int_penalty = penalty;
}
return h;
}
/* Pointers to voids always convert for pointers. But
make them less natural than more specific matches. */
if (TREE_CODE (ttl) == POINTER_TYPE && TREE_CODE (ttr) == POINTER_TYPE)
{
if (TREE_TYPE (ttl) == void_type_node
|| TREE_TYPE (ttr) == void_type_node)
{
h.code = STD_CODE;
h.distance = 0;
return h;
}
}
/* Here it does matter. If this conversion is from derived to base,
allow it. Otherwise, types must be compatible in the strong sense. */
if (TREE_CODE (ttl) == RECORD_TYPE && TREE_CODE (ttr) == RECORD_TYPE)
{
int b_or_d = get_base_distance (ttl, ttr, 0, 0);
if (b_or_d < 0)
{
b_or_d = get_base_distance (ttr, ttl, 0, 0);
if (b_or_d < 0)
return EVIL_RETURN (h);
h.distance = -b_or_d;
}
/* Say that this conversion is relatively painless.
If it turns out that there is a user-defined X(X&)
constructor, then that will be invoked, but that's
preferable to dealing with other user-defined conversions
that may produce surprising results. */
else
h.distance = b_or_d;
h.code = STD_CODE;
return h;
}
if (comp_target_types (ttl, intype, 1))
{
if (penalty)
h.code = STD_CODE;
h.distance = 0;
return h;
}
}
if (codel == RECORD_TYPE && coder == RECORD_TYPE)
{
int b_or_d = get_base_distance (type, parmtype, 0, 0);
@ -1789,6 +1738,9 @@ build_method_call (instance, name, parms, basetype_path, flags)
&& TREE_CODE (TREE_OPERAND (instance, 0)) == NOP_EXPR
&& TREE_OPERAND (TREE_OPERAND (instance, 0), 0) == error_mark_node);
if (TREE_CODE (instance) == OFFSET_REF)
instance = resolve_offset_ref (instance);
/* the base type of an instance variable is pointer to class */
basetype = TREE_TYPE (instance);
@ -1808,8 +1760,12 @@ build_method_call (instance, name, parms, basetype_path, flags)
if (! IS_AGGR_TYPE (basetype))
goto non_aggr_error;
if (IS_SIGNATURE_POINTER (basetype)
|| IS_SIGNATURE_REFERENCE (basetype))
/* If `instance' is a signature pointer/reference and `name' is
not a constructor, we are calling a signature member function.
In that case set the `basetype' to the signature type. */
if ((IS_SIGNATURE_POINTER (basetype)
|| IS_SIGNATURE_REFERENCE (basetype))
&& TYPE_IDENTIFIER (basetype) != name)
basetype = SIGNATURE_TYPE (basetype);
if ((IS_SIGNATURE (basetype)
@ -2001,8 +1957,9 @@ build_method_call (instance, name, parms, basetype_path, flags)
/* Look up function name in the structure type definition. */
if ((IDENTIFIER_HAS_TYPE_VALUE (name)
&& ! IDENTIFIER_OPNAME_P (name)
&& IS_AGGR_TYPE (IDENTIFIER_TYPE_VALUE (name))
&& TREE_CODE(IDENTIFIER_TYPE_VALUE (name)) != UNINSTANTIATED_P_TYPE)
&& TREE_CODE (IDENTIFIER_TYPE_VALUE (name)) != UNINSTANTIATED_P_TYPE)
|| name == constructor_name (basetype))
{
tree tmp = NULL_TREE;
@ -2494,11 +2451,9 @@ build_method_call (instance, name, parms, basetype_path, flags)
return error_mark_node;
}
/* We do not pass FUNCTION into `convert_arguments', because by
now everything should be ok. If not, then we have a serious error. */
if (DECL_STATIC_FUNCTION_P (function))
parms = convert_arguments (NULL_TREE, TYPE_ARG_TYPES (fntype),
TREE_CHAIN (parms), NULL_TREE, LOOKUP_NORMAL);
TREE_CHAIN (parms), function, LOOKUP_NORMAL);
else if (need_vtbl == unneeded)
{
int sub_flags = DECL_CONSTRUCTOR_P (function) ? flags : LOOKUP_NORMAL;
@ -2511,7 +2466,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
instance = build_indirect_ref (instance_ptr, NULL_PTR);
}
parms = tree_cons (NULL_TREE, instance_ptr,
convert_arguments (NULL_TREE, TREE_CHAIN (TYPE_ARG_TYPES (fntype)), TREE_CHAIN (parms), NULL_TREE, sub_flags));
convert_arguments (NULL_TREE, TREE_CHAIN (TYPE_ARG_TYPES (fntype)), TREE_CHAIN (parms), function, sub_flags));
}
else
{
@ -2559,7 +2514,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
instance = build_indirect_ref (instance_ptr, NULL_PTR);
}
parms = tree_cons (NULL_TREE, instance_ptr,
convert_arguments (NULL_TREE, TREE_CHAIN (TYPE_ARG_TYPES (fntype)), TREE_CHAIN (parms), NULL_TREE, LOOKUP_NORMAL));
convert_arguments (NULL_TREE, TREE_CHAIN (TYPE_ARG_TYPES (fntype)), TREE_CHAIN (parms), function, LOOKUP_NORMAL));
}
#if 0
@ -2861,18 +2816,6 @@ build_overload_call_real (fnname, parms, flags, final_cp, buildxxx)
if ((cp[0].h.code & EVIL_CODE) == 0)
{
cp[1].h.code = EVIL_CODE;
/* int_penalty is set by convert_harshness_ansi for cases
where we need to know about any penalties that would
otherwise make a TRIVIAL_CODE pass. */
if (final_cp
&& template_cost == 0
&& cp[0].h.code <= TRIVIAL_CODE
&& cp[0].h.int_penalty == 0)
{
final_cp[0].h = cp[0].h;
return function;
}
cp++;
}
}

View File

@ -1123,6 +1123,24 @@ get_vfield_offset (binfo)
BINFO_OFFSET (binfo));
}
/* Get the offset to the start of the original binfo that we derived this
binfo from. */
tree get_derived_offset (binfo)
tree binfo;
{
tree offset1 = get_vfield_offset (TYPE_BINFO (BINFO_TYPE (binfo)));
tree offset2;
int i;
while (BINFO_BASETYPES (binfo)
&& (i=CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo))) != -1)
{
tree binfos = BINFO_BASETYPES (binfo);
binfo = TREE_VEC_ELT (binfos, i);
}
offset2 = get_vfield_offset (TYPE_BINFO (BINFO_TYPE (binfo)));
return size_binop (MINUS_EXPR, offset1, offset2);
}
/* If FOR_TYPE needs to reinitialize virtual function table pointers
for TYPE's sub-objects, add such reinitializations to BASE_INIT_LIST.
Returns BASE_INIT_LIST appropriately modified. */
@ -2171,8 +2189,13 @@ modify_one_vtable (binfo, t, fndecl, pfn)
/* Find the right offset for the this pointer based on the
base class we just found. We have to take into
consideration the virtual base class pointers that we
stick in before the virtual function table pointer. */
base_offset = get_vfield_offset (binfo);
stick in before the virtual function table pointer.
Also, we want just the delta bewteen the most base class
that we derived this vfield from and us. */
base_offset = size_binop (PLUS_EXPR,
get_derived_offset (binfo),
BINFO_OFFSET (binfo));
this_offset = size_binop (MINUS_EXPR, offset, base_offset);
/* Make sure we can modify the derived association with immunity. */
@ -2374,8 +2397,8 @@ override_one_vtable (binfo, old, t)
override_one_vtable (binfo, old, t);
return;
}
TREE_VALUE (virtuals) = TREE_VALUE (old_virtuals);
}
TREE_VALUE (virtuals) = TREE_VALUE (old_virtuals);
}
else
{
@ -2547,7 +2570,7 @@ finish_struct (t, list_of_fieldlists, warn_anon)
int ref_sans_init = 0;
int nonprivate_method = 0;
tree t_binfo = TYPE_BINFO (t);
tree access_decls = 0;
tree access_decls = NULL_TREE;
if (TREE_CODE (name) == TYPE_DECL)
{
@ -2578,7 +2601,7 @@ finish_struct (t, list_of_fieldlists, warn_anon)
}
if (warn_anon && code != UNION_TYPE && ANON_AGGRNAME_P (name))
warning ("anonymous class type not used to declare any objects");
pedwarn ("anonymous class type not used to declare any objects");
if (TYPE_SIZE (t))
{
@ -2599,7 +2622,7 @@ finish_struct (t, list_of_fieldlists, warn_anon)
/* If this type was previously laid out as a forward reference,
make sure we lay it out again. */
TYPE_SIZE (t) = 0;
TYPE_SIZE (t) = NULL_TREE;
CLASSTYPE_GOT_SEMICOLON (t) = 0;
/* A signature type will contain the fields of the signature table.
@ -3025,7 +3048,7 @@ finish_struct (t, list_of_fieldlists, warn_anon)
if (code == UNION_TYPE)
{
char * fie = 0;
char *fie = NULL;
if (TYPE_NEEDS_CONSTRUCTING (type))
fie = "constructor";
else if (TYPE_NEEDS_DESTRUCTOR (type))
@ -3252,9 +3275,9 @@ finish_struct (t, list_of_fieldlists, warn_anon)
if (DECL_NAME (TREE_VEC_ELT (method_vec, i)) == name)
{
cp_error ("cannot adjust access to `%#D' in `%#T'", fdecl, t);
cp_error_at ("because of local method `%#D' with same name",
cp_error_at (" because of local method `%#D' with same name",
TREE_VEC_ELT (method_vec, i));
fdecl = 0;
fdecl = NULL_TREE;
break;
}
@ -3265,8 +3288,8 @@ finish_struct (t, list_of_fieldlists, warn_anon)
if (DECL_NAME (tmp) == name)
{
cp_error ("cannot adjust access to `%#D' in `%#T'", fdecl, t);
cp_error_at ("because of local field `%#D' with same name", tmp);
fdecl = 0;
cp_error_at (" because of local field `%#D' with same name", tmp);
fdecl = NULL_TREE;
break;
}
@ -3315,7 +3338,7 @@ finish_struct (t, list_of_fieldlists, warn_anon)
}
else if (last_x)
{
my_friendly_assert (TREE_CHAIN (last_x) == 0, 175);
my_friendly_assert (TREE_CHAIN (last_x) == NULL_TREE, 175);
TREE_CHAIN (last_x) = vfield;
last_x = vfield;
}
@ -3378,7 +3401,7 @@ finish_struct (t, list_of_fieldlists, warn_anon)
moved into the type of this field, but nothing seems to break
by doing this. */
if (DECL_NAME (field) == 0
if (DECL_NAME (field) == NULL_TREE
&& TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
{
tree uelt = TYPE_FIELDS (TREE_TYPE (field));
@ -3405,7 +3428,7 @@ finish_struct (t, list_of_fieldlists, warn_anon)
TYPE_ALIGN (pseudo_basetype) = CLASSTYPE_ALIGN (t);
DECL_ALIGN (base_layout_decl) = TYPE_ALIGN (pseudo_basetype);
/* Don't re-use old size. */
DECL_SIZE (base_layout_decl) = 0;
DECL_SIZE (base_layout_decl) = NULL_TREE;
}
layout_type (t);
@ -3432,7 +3455,7 @@ finish_struct (t, list_of_fieldlists, warn_anon)
moved into the type of this field, but nothing seems to break
by doing this. */
if (DECL_NAME (field) == 0
if (DECL_NAME (field) == NULL_TREE
&& TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
{
tree uelt = TYPE_FIELDS (TREE_TYPE (field));
@ -3709,12 +3732,11 @@ finish_struct (t, list_of_fieldlists, warn_anon)
while (x)
{
#if 0 /* What's wrong with using the decl the type already has? */
tree tag = build_lang_decl (TYPE_DECL, TREE_PURPOSE (x), TREE_VALUE (x));
tree tag = build_decl (TYPE_DECL, TREE_PURPOSE (x), TREE_VALUE (x));
DECL_CONTEXT (tag) = t;
#else
tree tag = TYPE_NAME (TREE_VALUE (x));
#endif
DECL_CLASS_CONTEXT (tag) = t;
#ifdef DWARF_DEBUGGING_INFO
if (write_symbols == DWARF_DEBUG)
@ -3729,7 +3751,7 @@ finish_struct (t, list_of_fieldlists, warn_anon)
x = TREE_CHAIN (x);
last_x = chainon (last_x, tag);
}
if (TYPE_FIELDS (t) == 0)
if (TYPE_FIELDS (t) == NULL_TREE)
TYPE_FIELDS (t) = last_x;
CLASSTYPE_LOCAL_TYPEDECLS (t) = 1;
}
@ -4220,7 +4242,9 @@ popclass (modify)
{
if (CLASSTYPE_VTBL_PTR (current_class_type))
{
current_vtable_decl = lookup_name (DECL_NAME (CLASSTYPE_VTBL_PTR (current_class_type)), 0);
current_vtable_decl
= lookup_name (DECL_NAME (CLASSTYPE_VTBL_PTR (current_class_type)),
0);
if (current_vtable_decl)
current_vtable_decl = build_indirect_ref (current_vtable_decl,
NULL_PTR);
@ -4525,9 +4549,10 @@ instantiate_type (lhstype, rhs, complain)
{
if (complain)
{
cp_error ("cannot resolve overload to target type `%#T';", lhstype);
cp_error_at ("ambiguity between `%#D'", save_elem);
cp_error_at ("and `%#D', at least", elem);
cp_error ("cannot resolve overload to target type `%#T'",
lhstype);
cp_error_at (" ambiguity between `%#D'", save_elem);
cp_error_at (" and `%#D', at least", elem);
}
return error_mark_node;
}
@ -4547,9 +4572,9 @@ instantiate_type (lhstype, rhs, complain)
}
if (complain)
{
cp_error ("cannot resolve overload to target type `%#T';",
cp_error ("cannot resolve overload to target type `%#T'",
lhstype);
cp_error ("no suitable overload of function `%D' exists",
cp_error (" because no suitable overload of function `%D' exists",
TREE_PURPOSE (rhs));
}
return error_mark_node;
@ -4631,10 +4656,12 @@ instantiate_type (lhstype, rhs, complain)
case PLUS_EXPR:
case MINUS_EXPR:
case COMPOUND_EXPR:
TREE_OPERAND (rhs, 0) = instantiate_type (lhstype, TREE_OPERAND (rhs, 0), complain);
TREE_OPERAND (rhs, 0)
= instantiate_type (lhstype, TREE_OPERAND (rhs, 0), complain);
if (TREE_OPERAND (rhs, 0) == error_mark_node)
return error_mark_node;
TREE_OPERAND (rhs, 1) = instantiate_type (lhstype, TREE_OPERAND (rhs, 1), complain);
TREE_OPERAND (rhs, 1)
= instantiate_type (lhstype, TREE_OPERAND (rhs, 1), complain);
if (TREE_OPERAND (rhs, 1) == error_mark_node)
return error_mark_node;
@ -4701,10 +4728,12 @@ instantiate_type (lhstype, rhs, complain)
error ("not enough type information");
return error_mark_node;
}
TREE_OPERAND (rhs, 1) = instantiate_type (lhstype, TREE_OPERAND (rhs, 1), complain);
TREE_OPERAND (rhs, 1)
= instantiate_type (lhstype, TREE_OPERAND (rhs, 1), complain);
if (TREE_OPERAND (rhs, 1) == error_mark_node)
return error_mark_node;
TREE_OPERAND (rhs, 2) = instantiate_type (lhstype, TREE_OPERAND (rhs, 2), complain);
TREE_OPERAND (rhs, 2)
= instantiate_type (lhstype, TREE_OPERAND (rhs, 2), complain);
if (TREE_OPERAND (rhs, 2) == error_mark_node)
return error_mark_node;
@ -4712,7 +4741,8 @@ instantiate_type (lhstype, rhs, complain)
return rhs;
case MODIFY_EXPR:
TREE_OPERAND (rhs, 1) = instantiate_type (lhstype, TREE_OPERAND (rhs, 1), complain);
TREE_OPERAND (rhs, 1)
= instantiate_type (lhstype, TREE_OPERAND (rhs, 1), complain);
if (TREE_OPERAND (rhs, 1) == error_mark_node)
return error_mark_node;
@ -4730,8 +4760,8 @@ instantiate_type (lhstype, rhs, complain)
}
TREE_TYPE (rhs) = lhstype;
lhstype = TREE_TYPE (lhstype);
TREE_OPERAND (rhs, 0) = instantiate_type (lhstype, TREE_OPERAND (rhs, 0),
complain);
TREE_OPERAND (rhs, 0)
= instantiate_type (lhstype, TREE_OPERAND (rhs, 0), complain);
if (TREE_OPERAND (rhs, 0) == error_mark_node)
return error_mark_node;

View File

@ -362,6 +362,7 @@ enum languages { lang_c, lang_cplusplus };
#define UNIQUELY_DERIVED_FROM_P(PARENT, TYPE) (get_base_distance (PARENT, TYPE, 0, (tree *)0) >= 0)
#define ACCESSIBLY_DERIVED_FROM_P(PARENT, TYPE) (get_base_distance (PARENT, TYPE, -1, (tree *)0) >= 0)
#define ACCESSIBLY_UNIQUELY_DERIVED_P(PARENT, TYPE) (get_base_distance (PARENT, TYPE, 1, (tree *)0) >= 0)
#define DERIVED_FROM_P(PARENT, TYPE) (get_base_distance (PARENT, TYPE, 0, (tree *)0) != -1)
enum conversion_type { ptr_conv, constptr_conv, int_conv,
real_conv, last_conversion_type };
@ -497,8 +498,11 @@ struct lang_type
union tree_node *signature_reference_to;
};
/* Indicates whether a template should be (or has been) expanded for this
class definition. 0=do, 1=did, 2=don't, 3=didn't. */
/* Indicates whether or not (and how) a template was expanded for this class.
0=no information yet/non-template class
1=implicit template instantiation
2=explicit template specialization
3=explicit template instantiation */
#define CLASSTYPE_USE_TEMPLATE(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.use_template)
/* Fields used for storing information before the class is defined.
@ -931,7 +935,9 @@ struct lang_decl_flags
unsigned mutable_flag : 1;
unsigned is_default_implementation : 1;
unsigned saved_inline : 1;
unsigned dummy : 10;
unsigned use_template : 2;
unsigned dummy : 8;
tree access;
tree context;
@ -1101,7 +1107,7 @@ struct lang_decl
#if 0
/* Same, but tells if this field is private in current context. */
#define DECL_PRIVATE(NODE) NOTHING
#define DECL_PRIVATE(NODE) (DECL_LANG_FLAG_5 (NODE))
/* Same, but tells if this field is private in current context. */
#define DECL_PROTECTED(NODE) (DECL_LANG_FLAG_6 (NODE))
@ -1266,11 +1272,39 @@ struct lang_decl
#define DECL_TEMPLATE_RESULT(NODE) DECL_RESULT(NODE)
#define DECL_TEMPLATE_INSTANTIATIONS(NODE) DECL_VINDEX(NODE)
/* Macros for a DECL or TYPE generated from a template to indicate that it
was explicitly instantiated. */
#define DECL_EXPLICITLY_INSTANTIATED(NODE) (DECL_LANG_FLAG_5 (NODE))
#define CLASSTYPE_EXPLICITLY_INSTANTIATED(NODE) \
(DECL_EXPLICITLY_INSTANTIATED (TYPE_NAME (NODE)))
/* Indicates whether or not (and how) a template was expanded for this
FUNCTION_DECL or VAR_DECL.
0=normal declaration, e.g. int min (int, int);
1=implicit template instantiation
2=explicit template specialization, e.g. int min<int> (int, int);
3=explicit template instantiation, e.g. template int min<int> (int, int);
*/
#define DECL_USE_TEMPLATE(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.use_template)
#define DECL_TEMPLATE_INSTANTIATION(NODE) (DECL_USE_TEMPLATE (NODE) & 1)
#define CLASSTYPE_TEMPLATE_INSTANTIATION(NODE) \
(CLASSTYPE_USE_TEMPLATE (NODE) & 1)
#define DECL_TEMPLATE_SPECIALIZATION(NODE) (DECL_USE_TEMPLATE (NODE) == 2)
#define SET_DECL_TEMPLATE_SPECIALIZATION(NODE) (DECL_USE_TEMPLATE (NODE) = 2)
#define CLASSTYPE_TEMPLATE_SPECIALIZATION(NODE) \
(CLASSTYPE_USE_TEMPLATE (NODE) == 2)
#define SET_CLASSTYPE_TEMPLATE_SPECIALIZATION(NODE) \
(CLASSTYPE_USE_TEMPLATE (NODE) = 2)
#define DECL_IMPLICIT_INSTANTIATION(NODE) (DECL_USE_TEMPLATE (NODE) == 1)
#define SET_DECL_IMPLICIT_INSTANTIATION(NODE) (DECL_USE_TEMPLATE (NODE) = 1)
#define CLASSTYPE_IMPLICIT_INSTANTIATION(NODE) \
(CLASSTYPE_USE_TEMPLATE(NODE) == 1)
#define SET_CLASSTYPE_IMPLICIT_INSTANTIATION(NODE) \
(CLASSTYPE_USE_TEMPLATE(NODE) = 1)
#define DECL_EXPLICIT_INSTANTIATION(NODE) (DECL_USE_TEMPLATE (NODE) == 3)
#define SET_DECL_EXPLICIT_INSTANTIATION(NODE) (DECL_USE_TEMPLATE (NODE) = 3)
#define CLASSTYPE_EXPLICIT_INSTANTIATION(NODE) \
(CLASSTYPE_USE_TEMPLATE(NODE) == 3)
#define SET_CLASSTYPE_EXPLICIT_INSTANTIATION(NODE) \
(CLASSTYPE_USE_TEMPLATE(NODE) = 3)
#define THUNK_DELTA(DECL) ((DECL)->decl.frame_size.i)
@ -1309,6 +1343,7 @@ extern void check_function_format PROTO((tree, tree, tree));
/* Print an error message for invalid operands to arith operation CODE.
NOP_EXPR is used as a special case (see truthvalue_conversion). */
extern void binary_op_error PROTO((enum tree_code));
extern tree c_build_type_variant PROTO((tree, int, int));
extern void c_expand_expr_stmt PROTO((tree));
/* Validate the expression after `case' and apply default promotions. */
extern tree check_case_value PROTO((tree));
@ -1462,7 +1497,7 @@ extern int current_function_parms_stored;
#define AUTO_TEMP_NAME "_$tmp_"
#define AUTO_TEMP_FORMAT "_$tmp_%d"
#define VTABLE_BASE "$vb"
#define VTABLE_NAME_FORMAT (flag_vtable_thunks ? "_VT$%s" : "_vt$%s")
#define VTABLE_NAME_FORMAT (flag_vtable_thunks ? "__vt_%s" : "_vt$%s")
#define VFIELD_BASE "$vf"
#define VFIELD_NAME "_vptr$"
#define VFIELD_NAME_FORMAT "_vptr$%s"
@ -1484,7 +1519,7 @@ extern int current_function_parms_stored;
#define AUTO_TEMP_NAME "_.tmp_"
#define AUTO_TEMP_FORMAT "_.tmp_%d"
#define VTABLE_BASE ".vb"
#define VTABLE_NAME_FORMAT (flag_vtable_thunks ? "_VT.%s" : "_vt.%s")
#define VTABLE_NAME_FORMAT (flag_vtable_thunks ? "__vt_%s" : "_vt.%s")
#define VFIELD_BASE ".vf"
#define VFIELD_NAME "_vptr."
#define VFIELD_NAME_FORMAT "_vptr.%s"
@ -1513,7 +1548,7 @@ extern int current_function_parms_stored;
#define AUTO_TEMP_FORMAT "__tmp_%d"
#define VTABLE_BASE "__vtb"
#define VTABLE_NAME "__vt_"
#define VTABLE_NAME_FORMAT (flag_vtable_thunks ? "_VT_%s" : "_vt_%s")
#define VTABLE_NAME_FORMAT (flag_vtable_thunks ? "__vt_%s" : "_vt_%s")
#define VTABLE_NAME_P(ID_NODE) \
(!strncmp (IDENTIFIER_POINTER (ID_NODE), VTABLE_NAME, \
sizeof (VTABLE_NAME) - 1))
@ -1668,6 +1703,11 @@ extern int flag_gc;
extern int flag_dossier;
/* Nonzero means do emit exported implementations of functions even if
they can be inlined. */
extern int flag_implement_inlines;
/* Nonzero means templates obey #pragma interface and implementation. */
extern int flag_external_templates;
@ -1676,6 +1716,10 @@ extern int flag_external_templates;
extern int flag_alt_external_templates;
/* Nonzero means implicit template instantatiations are emitted. */
extern int flag_implicit_templates;
/* Current end of entries in the gc obstack for stack pointer variables. */
extern int current_function_obstack_index;
@ -1875,7 +1919,7 @@ extern tree lookup_name_current_level PROTO((tree));
extern void init_decl_processing PROTO((void));
/* skipped define_function */
extern void shadow_tag PROTO((tree));
extern void grok_ctor_properties PROTO((tree, tree));
extern int grok_ctor_properties PROTO((tree, tree));
extern tree groktypename PROTO((tree));
extern tree start_decl PROTO((tree, tree, int, tree));
extern void finish_decl PROTO((tree, tree, tree, int));

View File

@ -1226,6 +1226,9 @@ cp_convert (type, expr, convtype, flags)
else if (TREE_CODE (TREE_TYPE (e)) == REFERENCE_TYPE)
e = convert_from_reference (e);
if (TREE_READONLY_DECL_P (e))
e = decl_constant_value (e);
if (INTEGRAL_CODE_P (code))
{
tree intype = TREE_TYPE (expr);
@ -1332,8 +1335,12 @@ cp_convert (type, expr, convtype, flags)
{
tree binfo;
tree conversion = TYPE_HAS_CONVERSION (dtype)
? build_type_conversion (CONVERT_EXPR, type, e, 1) : NULL_TREE;
tree conversion;
if (! DERIVED_FROM_P (type, dtype) && TYPE_HAS_CONVERSION (dtype))
conversion = build_type_conversion (CONVERT_EXPR, type, e, 1);
else
conversion = NULL_TREE;
if (TYPE_HAS_CONSTRUCTOR (type))
{
@ -1493,8 +1500,7 @@ build_type_conversion_1 (xtype, basetype, expr, typename, for_sure)
else
flags = LOOKUP_NORMAL;
rval = build_method_call (first_arg, constructor_name_full (typename),
NULL_TREE, NULL_TREE, flags);
rval = build_method_call (first_arg, typename, NULL_TREE, NULL_TREE, flags);
if (rval == error_mark_node)
{
if (for_sure == 0)

View File

@ -410,11 +410,6 @@ extern int flag_short_double;
extern int flag_no_builtin;
/* Nonzero means do emit exported implementations of functions even if
they can be inlined. */
extern int flag_implement_inlines;
/* Nonzero means disable GNU extensions. */
extern int flag_ansi;
@ -1791,7 +1786,7 @@ pushtag (name, type, globalize)
{
/* Make nested declarations go into class-level scope. */
newdecl = 1;
d = build_lang_field_decl (TYPE_DECL, name, type);
d = build_decl (TYPE_DECL, name, type);
#ifdef DWARF_DEBUGGING_INFO
if (write_symbols == DWARF_DEBUG)
{
@ -1832,14 +1827,13 @@ pushtag (name, type, globalize)
}
/* else if (TYPE_SIZE (current_class_type) == NULL_TREE)
*/
else if (context && TREE_CODE (context) == RECORD_TYPE)
else if (context && IS_AGGR_TYPE (context))
{
/* Class-nested class. */
set_nested_typename (d, DECL_NESTED_TYPENAME (c_decl),
name, type);
/* This builds the links for classes nested in type scope. */
DECL_CONTEXT (d) = context;
DECL_CLASS_CONTEXT (d) = context;
}
TYPE_CONTEXT (type) = DECL_CONTEXT (d);
if (newdecl)
@ -2021,6 +2015,8 @@ decls_match (newdecl, olddecl)
types_match = TREE_TYPE (olddecl) == error_mark_node;
else if (TREE_TYPE (olddecl) == NULL_TREE)
types_match = TREE_TYPE (newdecl) == NULL_TREE;
else if (TREE_TYPE (newdecl) == NULL_TREE)
types_match = 0;
else
types_match = comptypes (TREE_TYPE (newdecl), TREE_TYPE (olddecl), 1);
}
@ -2441,18 +2437,7 @@ duplicate_decls (newdecl, olddecl)
TREE_STATIC (newdecl) = TREE_STATIC (olddecl);
DECL_EXTERNAL (newdecl) = DECL_EXTERNAL (olddecl);
/* For functions, static overrides non-static. */
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
TREE_PUBLIC (newdecl) &= TREE_PUBLIC (olddecl);
/* This is since we don't automatically
copy the attributes of NEWDECL into OLDDECL. */
TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
/* If this clears `static', clear it in the identifier too. */
if (! TREE_PUBLIC (olddecl))
TREE_PUBLIC (DECL_ASSEMBLER_NAME (olddecl)) = 0;
}
else
if (TREE_CODE (newdecl) != FUNCTION_DECL)
TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl);
}
else
@ -2464,7 +2449,20 @@ duplicate_decls (newdecl, olddecl)
&& TREE_READONLY (newdecl) && TREE_STATIC (newdecl)
&& ! DECL_THIS_EXTERN (newdecl))
TREE_PUBLIC (newdecl) = 0;
else if (TREE_CODE (newdecl) != FUNCTION_DECL)
TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
}
/* For functions, static overrides non-static. */
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
TREE_PUBLIC (newdecl) &= TREE_PUBLIC (olddecl);
/* This is since we don't automatically
copy the attributes of NEWDECL into OLDDECL. */
TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
/* If this clears `static', clear it in the identifier too. */
if (! TREE_PUBLIC (olddecl))
TREE_PUBLIC (DECL_ASSEMBLER_NAME (olddecl)) = 0;
}
/* If either decl says `inline', this fn is inline,
@ -2854,7 +2852,8 @@ pushdecl (x)
/* If new decl is `static' and an `extern' was seen previously,
warn about it. */
warn_extern_redeclared_static (x, t);
if (x != NULL_TREE && t != NULL_TREE && decls_match (x, t))
warn_extern_redeclared_static (x, t);
}
else
{
@ -3964,20 +3963,13 @@ lookup_name_real (name, prefer_type, nonclass)
done:
if (val)
{
/* Arbitrate between finding a TYPE_DECL and finding
other kinds of _DECLs. */
if (TREE_CODE (val) == TYPE_DECL || prefer_type < 0)
if ((TREE_CODE (val) == TEMPLATE_DECL && looking_for_template)
|| TREE_CODE (val) == TYPE_DECL || prefer_type <= 0)
return val;
if (IDENTIFIER_HAS_TYPE_VALUE (name))
{
register tree val_as_type = TYPE_NAME (IDENTIFIER_TYPE_VALUE (name));
return TYPE_NAME (IDENTIFIER_TYPE_VALUE (name));
if (val == val_as_type || prefer_type > 0)
return val_as_type;
return val;
}
if (TREE_TYPE (val) == error_mark_node)
return error_mark_node;
}
@ -5312,7 +5304,9 @@ start_decl (declarator, declspecs, initialized, raises)
default:
/* Don't allow initializations for incomplete types except for
arrays which might be completed by the initialization. */
if (TYPE_SIZE (type) != NULL_TREE)
if (type == error_mark_node)
; /* Don't complain again. */
else if (TYPE_SIZE (type) != NULL_TREE)
; /* A complete type is ok. */
else if (TREE_CODE (type) != ARRAY_TYPE)
{
@ -5768,7 +5762,8 @@ finish_decl (decl, init, asmspec_tree, need_pop)
TREE_TYPE (decl) = type = TREE_TYPE (init);
DECL_INITIAL (decl) = init = NULL_TREE;
}
if (IS_AGGR_TYPE (type) && DECL_NAME (decl))
if (type != error_mark_node
&& IS_AGGR_TYPE (type) && DECL_NAME (decl))
{
if (TREE_TYPE (DECL_NAME (decl)) && TREE_TYPE (decl) != type)
cp_warning ("shadowing previous type declaration of `%#D'", decl);
@ -5856,7 +5851,7 @@ finish_decl (decl, init, asmspec_tree, need_pop)
GNU_xref_decl (current_function_decl, decl);
if (TREE_CODE (decl) == FIELD_DECL || DECL_EXTERNAL (decl))
if (TREE_CODE (decl) == FIELD_DECL)
;
else if (TREE_CODE (decl) == CONST_DECL)
{
@ -5960,6 +5955,8 @@ finish_decl (decl, init, asmspec_tree, need_pop)
DECL_INITIAL (decl) = error_mark_node;
}
}
else if (DECL_EXTERNAL (decl))
;
else if (TREE_CODE_CLASS (TREE_CODE (type)) == 't'
&& (IS_AGGR_TYPE (type) || TYPE_NEEDS_CONSTRUCTING (type)))
{
@ -6185,11 +6182,11 @@ finish_decl (decl, init, asmspec_tree, need_pop)
store_expr (DECL_INITIAL (decl), DECL_RTL (decl), 0);
TREE_ASM_WRITTEN (decl) = 1;
}
else if (toplev)
else if (toplev && ! TREE_PUBLIC (decl))
{
/* If this is a static const, change its apparent linkage
if it belongs to a #pragma interface. */
if (TREE_STATIC (decl) && !interface_unknown)
if (!interface_unknown)
{
TREE_PUBLIC (decl) = 1;
DECL_EXTERNAL (decl) = interface_only;
@ -6681,7 +6678,9 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals,
grokclassfn (ctype, declarator, decl, flags, quals);
if (check)
check_classfn (ctype, declarator, decl);
grok_ctor_properties (ctype, decl);
if (! grok_ctor_properties (ctype, decl))
return NULL_TREE;
if (check == 0 && ! current_function_decl)
{
/* FIXME: this should only need to look at
@ -7393,18 +7392,15 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
{
if (i == (int) RID_LONG && RIDBIT_SETP (i, specbits))
{
#if 0
if (pedantic)
pedwarn ("duplicate `%s'", IDENTIFIER_POINTER (id));
else
#endif
if (longlong)
error ("`long long long' is too long for GCC");
if (pedantic && flag_ansi)
pedwarn ("duplicate `long'");
else if (longlong)
error ("`long long long' is too long for GCC");
else
longlong = 1;
}
else if (RIDBIT_SETP (i, specbits))
warning ("duplicate `%s'", IDENTIFIER_POINTER (id));
pedwarn ("duplicate `%s'", IDENTIFIER_POINTER (id));
RIDBIT_SET (i, specbits);
goto found;
}
@ -7619,7 +7615,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
warning ("duplicate `volatile'");
virtualp = RIDBIT_SETP (RID_VIRTUAL, specbits);
/* operators new and delete are implicitly static. */
if (RIDBIT_SETP (RID_STATIC, specbits))
staticp = 1 + (decl_context == FIELD);
@ -8049,8 +8044,13 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
else
{
if (flag_ansi)
cp_pedwarn ("ANSI C++ forbids variable-size array `%D'",
dname);
{
if (dname)
cp_pedwarn ("ANSI C++ forbids variable-size array `%D'",
dname);
else
cp_pedwarn ("ANSI C++ forbids variable-size array");
}
dont_grok_size:
itype =
build_binary_op (MINUS_EXPR, size, integer_one_node, 1);
@ -8070,8 +8070,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
type = build_cplus_array_type (type, itype);
if (constp || volatilep)
/* Should this be c_build_type_variant? -jason */
type = build_type_variant (type, constp, volatilep);
type = c_build_type_variant (type, constp, volatilep);
ctype = NULL_TREE;
}
@ -8383,9 +8382,18 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
}
}
if (constp > 1)
warning ("duplicate `const'");
pedwarn ("duplicate `const'");
if (volatilep > 1)
warning ("duplicate `volatile'");
pedwarn ("duplicate `volatile'");
if (TREE_CODE (declarator) == ADDR_EXPR
&& (constp || volatilep))
{
if (constp)
warning ("discarding `const' applied to a reference");
if (volatilep)
warning ("discarding `volatile' applied to a reference");
constp = volatilep = 0;
}
}
declarator = TREE_OPERAND (declarator, 0);
ctype = NULL_TREE;
@ -8841,7 +8849,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
/* Tell grokfndecl if it needs to set TREE_PUBLIC on the node. */
publicp = (RIDBIT_SETP (RID_EXTERN, specbits)
|| (ctype != NULL_TREE && funcdef_flag >= 0)
|| (ctype != NULL_TREE
&& funcdef_flag >= 0
&& RIDBIT_NOTSETP (RID_INLINE, specbits))
|| (friendp
&& ! funcdef_flag
&& RIDBIT_NOTSETP (RID_STATIC, specbits)
@ -8921,14 +8931,28 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
if (decl == NULL_TREE)
{
/* ANSI C++ June 5 1992 WP 9.2.2 and 9.4.2. A member-declarator
cannot have an initializer, and a static member declaration must
be defined elsewhere. */
if (initialized)
{
/* Motion 10 at San Diego: If a static const integral data
member is initialized with an integral constant
expression, the initializer may appear either in the
declaration (within the class), or in the definition,
but not both. If it appears in the class, the member is
a member constant. The file-scope definition is always
required. */
if (staticp)
error ("static member `%s' must be defined separately from its declaration",
IDENTIFIER_POINTER (declarator));
{
if (pedantic)
{
if (! constp)
cp_pedwarn ("ANSI C++ forbids in-class initialization of non-const static member `%D'",
declarator);
else if (! INTEGRAL_TYPE_P (type))
cp_pedwarn ("ANSI C++ forbids member constant `%D' of non-integral type `%T'", declarator, type);
}
}
/* Note that initialization of const members is prohibited
by the draft ANSI standard, though it appears to be in
common practice. 12.6.2: The argument list is used to
@ -8936,9 +8960,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
initializer list) is the only way to initialize
nonstatic const and reference members. */
else if (flag_ansi || ! constp)
pedwarn ("ANSI C++ forbids initialization of %s `%s'",
constp ? "const member" : "member",
IDENTIFIER_POINTER (declarator));
cp_pedwarn ("ANSI C++ forbids initialization of %s `%D'",
constp ? "const member" : "member", declarator);
}
if (staticp || (constp && initialized))
@ -8952,7 +8975,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
TREE_STATIC (decl) = 1;
/* In class context, static means public access. */
TREE_PUBLIC (decl) = 1;
DECL_EXTERNAL (decl) = !initialized;
DECL_EXTERNAL (decl) = !!staticp;
}
else
{
@ -9472,7 +9495,7 @@ grokparms (first_parm, funcdef_flag)
`grok_op_properties' takes notice of the various forms of
operator= which are defined, as well as what sorts of type conversion
may apply. Both functions take a FUNCTION_DECL as an argument. */
void
int
grok_ctor_properties (ctype, decl)
tree ctype, decl;
{
@ -9509,14 +9532,21 @@ grok_ctor_properties (ctype, decl)
{
if (TREE_CHAIN (parmtypes) != NULL_TREE
&& TREE_CHAIN (parmtypes) == void_list_node)
cp_error ("invalid constructor; you probably meant `%T (%T&)'",
ctype, ctype);
SET_IDENTIFIER_ERROR_LOCUS (DECL_NAME (decl), ctype);
TYPE_GETS_INIT_AGGR (ctype) = 1;
{
cp_error ("invalid constructor; you probably meant `%T (%T&)'",
ctype, ctype);
SET_IDENTIFIER_ERROR_LOCUS (DECL_NAME (decl), ctype);
return 0;
}
else
TYPE_GETS_INIT_AGGR (ctype) = 1;
}
else if (TREE_CODE (parmtype) == VOID_TYPE
|| TREE_PURPOSE (parmtypes) != NULL_TREE)
TYPE_HAS_DEFAULT_CONSTRUCTOR (ctype) = 1;
return 1;
}
/* An operator with this name can be either unary or binary. */
@ -9660,10 +9690,30 @@ grok_op_properties (decl, virtualp, friendp)
|| name == ansi_opname[(int) METHOD_CALL_EXPR])
return; /* no restrictions on args */
if (IDENTIFIER_TYPENAME_P (name)
&& TREE_CODE (TREE_TYPE (name)) == VOID_TYPE)
error ("void is not a valid type conversion operator");
if (IDENTIFIER_TYPENAME_P (name))
{
tree t = TREE_TYPE (name);
if (TREE_CODE (t) == VOID_TYPE)
pedwarn ("void is not a valid type conversion operator");
else if (! friendp)
{
int ref = (TREE_CODE (t) == REFERENCE_TYPE);
char *what = 0;
if (ref)
t = TYPE_MAIN_VARIANT (TREE_TYPE (t));
if (t == current_class_type)
what = "the same type";
else if (IS_AGGR_TYPE (t)
&& DERIVED_FROM_P (t, current_class_type))
what = "a base class";
if (what)
warning ("conversion to %s%s will never use a type conversion operator",
ref ? "a reference to " : "", what);
}
}
if (name == ansi_opname[(int) MODIFY_EXPR])
{
tree parmtype;
@ -9810,12 +9860,12 @@ xref_defn_tag (code_type_node, name, binfo)
#endif
#if 0
IDENTIFIER_LOCAL_VALUE (name) =
build_lang_decl (TYPE_DECL, ncp, NULL_TREE);
build_decl (TYPE_DECL, ncp, NULL_TREE);
#endif
rv = xref_tag (code_type_node, name, binfo, 0);
if (! ANON_AGGRNAME_P (name))
{
register tree type_decl = build_lang_decl (TYPE_DECL, ncp, rv);
register tree type_decl = build_decl (TYPE_DECL, ncp, rv);
#ifdef DWARF_DEBUGGING_INFO
/* Mark the TYPE_DECL node created just above as a gratuitous one
so that dwarfout.c will know not to generate a TAG_typedef DIE
@ -9875,10 +9925,10 @@ xref_tag (code_type_node, name, binfo, globalize)
/* If a cross reference is requested, look up the type
already defined for this tag and return it. */
if ((t = IDENTIFIER_TYPE_VALUE(name)))
{
if (TREE_CODE(t) != code) t = NULL_TREE;
}
t = IDENTIFIER_TYPE_VALUE (name);
if (t && TREE_CODE (t) != code)
t = NULL_TREE;
if (xref_next_defn)
{
/* If we know we are defining this tag, only look it up in this scope
@ -10694,15 +10744,29 @@ start_function (declspecs, declarator, raises, pre_parsed_p)
{
TREE_PUBLIC (decl1) = 1;
DECL_EXTERNAL (decl1)
= ((interface_only && !DECL_EXPLICITLY_INSTANTIATED (decl1))
= (interface_only
|| (DECL_INLINE (decl1) && ! flag_implement_inlines));
}
else if (DECL_EXPLICIT_INSTANTIATION (decl1))
{
TREE_PUBLIC (decl1) = 1;
DECL_EXTERNAL (decl1) = (DECL_INLINE (decl1)
&& ! flag_implement_inlines);
}
else
/* This is a definition, not a reference.
So normally clear DECL_EXTERNAL.
However, `extern inline' acts like a declaration except for
defining how to inline. So set DECL_EXTERNAL in that case. */
DECL_EXTERNAL (decl1) = current_extern_inline;
{
/* This is a definition, not a reference.
So normally clear DECL_EXTERNAL.
However, `extern inline' acts like a declaration except for
defining how to inline. So set DECL_EXTERNAL in that case. */
DECL_EXTERNAL (decl1) = current_extern_inline;
#if 0
DECL_DEFER_OUTPUT (decl1)
= (DECL_INLINE (decl1) && (DECL_IMPLICIT_INSTANTIATION (decl1)
|| DECL_FUNCTION_MEMBER_P (decl1)));
#endif
}
/* Record the decl so that the function name is defined.
If we already have a decl for this name, and it is a FUNCTION_DECL,
@ -11703,6 +11767,9 @@ start_method (declspecs, declarator, raises)
if (flag_default_inline)
DECL_INLINE (fndecl) = 1;
if (processing_template_defn)
SET_DECL_IMPLICIT_INSTANTIATION (fndecl);
/* We read in the parameters on the maybepermanent_obstack,
but we won't be getting back to them until after we
may have clobbered them. So the call to preserve_data
@ -11726,7 +11793,10 @@ start_method (declspecs, declarator, raises)
}
if (DECL_CONSTRUCTOR_P (fndecl))
grok_ctor_properties (current_class_type, fndecl);
{
if (! grok_ctor_properties (current_class_type, fndecl))
return void_type_node;
}
else if (IDENTIFIER_OPNAME_P (DECL_NAME (fndecl)))
grok_op_properties (fndecl, DECL_VIRTUAL_P (fndecl), 0);
}

View File

@ -116,6 +116,10 @@ int flag_external_templates = 0;
int flag_alt_external_templates = 0;
/* Nonzero means that implicit instantiations will be emitted if needed. */
int flag_implicit_templates = 1;
/* Nonzero means warn about implicit declarations. */
int warn_implicit = 1;
@ -352,6 +356,7 @@ static struct { char *string; int *variable; int on_value;} lang_f_options[] =
{"nonnull-objects", &flag_assume_nonnull_objects, 1},
{"implement-inlines", &flag_implement_inlines, 1},
{"external-templates", &flag_external_templates, 1},
{"implicit-templates", &flag_implicit_templates, 1},
{"huge-objects", &flag_huge_objects, 1},
{"conserve-space", &flag_conserve_space, 1},
{"vtable-thunks", &flag_vtable_thunks, 1},
@ -1181,7 +1186,7 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree)
value = grokdeclarator (declarator, declspecs, FIELD, init != 0, raises);
if (! value)
return NULL_TREE; /* friends went bad. */
return value; /* friend or constructor went bad. */
/* Pass friendly classes back. */
if (TREE_CODE (value) == VOID_TYPE)
@ -1236,21 +1241,13 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree)
grok_function_init (value, init);
init = NULL_TREE;
}
else if (pedantic)
{
#if 0
/* Already warned in grokdeclarator. */
if (DECL_NAME (value))
pedwarn ("ANSI C++ forbids initialization of member `%s'",
IDENTIFIER_POINTER (DECL_NAME (value)));
else
pedwarn ("ANSI C++ forbids initialization of fields");
#endif
init = NULL_TREE;
}
else if (pedantic && ! TREE_STATIC (value))
/* Already complained in grokdeclarator. */
init = NULL_TREE;
else
{
/* We allow initializers to become parameters to base initializers. */
/* We allow initializers to become parameters to base
initializers. */
if (TREE_CODE (init) == TREE_LIST)
{
if (TREE_CHAIN (init) == NULL_TREE)
@ -1352,8 +1349,6 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree)
}
if (TREE_CODE (value) == FUNCTION_DECL)
{
/* grokdeclarator defers setting this. */
TREE_PUBLIC (value) = 1;
if (DECL_CHAIN (value) != NULL_TREE)
{
/* Need a fresh node here so that we don't get circularity
@ -1368,7 +1363,7 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree)
if (DECL_FRIEND_P (value))
return void_type_node;
if (current_function_decl)
if (current_function_decl && ! IS_SIGNATURE (current_class_type))
cp_error ("method `%#D' of local class must be defined in class body",
value);
@ -2345,7 +2340,8 @@ finish_vtable_vardecl (prev, vars)
for (method = CLASSTYPE_METHODS (ctype); method != NULL_TREE;
method = DECL_NEXT_METHOD (method))
{
if (DECL_VINDEX (method) != NULL_TREE && !DECL_SAVED_INSNS (method))
if (DECL_VINDEX (method) != NULL_TREE && !DECL_SAVED_INSNS (method)
&& !DECL_ABSTRACT_VIRTUAL_P (method))
{
SET_CLASSTYPE_INTERFACE_KNOWN (ctype);
CLASSTYPE_INTERFACE_ONLY (ctype) = DECL_EXTERNAL (method);
@ -2376,20 +2372,6 @@ finish_vtable_vardecl (prev, vars)
mark_vtable_entries (vars);
if (TREE_TYPE (DECL_INITIAL (vars)) == 0)
store_init_value (vars, DECL_INITIAL (vars));
if (flag_vtable_thunks)
{
tree list = CONSTRUCTOR_ELTS (DECL_INITIAL (vars));
for (; list; list = TREE_CHAIN (list))
{
tree vfunc = TREE_VALUE (list);
if (TREE_CODE (vfunc) == ADDR_EXPR)
{
vfunc = TREE_OPERAND (vfunc, 0);
if (TREE_CODE (vfunc) == THUNK_DECL)
emit_thunk (vfunc);
}
}
}
#ifdef DWARF_DEBUGGING_INFO
if (write_symbols == DWARF_DEBUG)
@ -2737,6 +2719,12 @@ finish_file ()
walk_vtables ((void (*)())0, finish_vtable_vardecl);
for (vars = getdecls (); vars; vars = TREE_CHAIN (vars))
{
if (TREE_CODE (vars) == THUNK_DECL)
emit_thunk (vars);
}
/* Now write out inline functions which had their addresses taken
and which were not declared virtual and which were not declared
`extern inline'. */
@ -2752,12 +2740,16 @@ finish_file ()
if (CLASSTYPE_INTERFACE_KNOWN (ctype))
{
TREE_PUBLIC (decl) = 1;
DECL_EXTERNAL (decl) = CLASSTYPE_INTERFACE_ONLY (ctype);
DECL_EXTERNAL (decl)
= (CLASSTYPE_INTERFACE_ONLY (ctype)
|| (DECL_INLINE (decl) && ! flag_implement_inlines));
}
}
if (TREE_PUBLIC (decl) || TREE_ADDRESSABLE (decl))
{
if (DECL_EXTERNAL (decl))
if (DECL_EXTERNAL (decl)
|| (DECL_IMPLICIT_INSTANTIATION (decl)
&& ! flag_implicit_templates))
assemble_external (decl);
else
{

View File

@ -837,25 +837,25 @@ dump_char (c)
{
switch (c)
{
case '\n':
case TARGET_NEWLINE:
OB_PUTS ("\\n");
break;
case '\t':
case TARGET_TAB:
OB_PUTS ("\\t");
break;
case '\v':
case TARGET_VT:
OB_PUTS ("\\v");
break;
case '\b':
case TARGET_BS:
OB_PUTS ("\\b");
break;
case '\r':
case TARGET_CR:
OB_PUTS ("\\r");
break;
case '\f':
case TARGET_FF:
OB_PUTS ("\\f");
break;
case '\a':
case TARGET_BELL:
OB_PUTS ("\\a");
break;
case '\\':

View File

@ -1866,7 +1866,7 @@ build_member_call (cname, name, parmlist)
{
tree newtype = build_type_variant (type, TYPE_READONLY (oldtype),
TYPE_VOLATILE (oldtype));
decl = convert_force (TYPE_POINTER_TO (newtype), olddecl);
decl = convert_force (build_pointer_type (newtype), olddecl);
}
else
decl = olddecl;

View File

@ -1936,15 +1936,17 @@ default_assign_ref_body (bufp, lenp, type, fields)
name = TYPE_NESTED_NAME (btype);
s = IDENTIFIER_POINTER (name);
tneed = (2 * strlen (s)) + 33;
tneed = (2 * strlen (s)) + 42;
if (tgot < tneed)
{
tgot = tneed;
tbuf = (char *) alloca (tgot);
}
sprintf (tbuf, "%s::operator=((%s%s&)_ctor_arg);", s,
TYPE_READONLY (type) ? "const " : "", s);
sprintf (tbuf, "%s::operator=((%s%s ::%s&)_ctor_arg);", s,
TYPE_READONLY (type) ? "const " : "",
CLASSTYPE_DECLARED_CLASS (btype) ? "class" : "struct",
s);
obstack_grow (&body, tbuf, strlen (tbuf));
}
}
@ -2101,15 +2103,17 @@ default_copy_constructor_body (bufp, lenp, type, fields)
name = TYPE_NESTED_NAME (btype);
s = IDENTIFIER_POINTER (name);
tneed = (2 * strlen (s)) + 30;
tneed = (2 * strlen (s)) + 39;
if (tgot < tneed)
{
tgot = tneed;
tbuf = (char *) alloca (tgot);
}
sprintf (tbuf, "%c%s((%s%s&)_ctor_arg)", sep, s,
TYPE_READONLY (type) ? "const " : "", s);
sprintf (tbuf, "%c%s((%s%s ::%s&)_ctor_arg)", sep, s,
TYPE_READONLY (type) ? "const " : "",
CLASSTYPE_DECLARED_CLASS (btype) ? "class" : "struct",
s);
sep = ',';
obstack_grow (&prologue, tbuf, strlen (tbuf));
}

View File

@ -115,6 +115,7 @@ extern char *token_buffer; /* Pointer to token buffer. */
/* Back-door communication channel to the lexer. */
extern int looking_for_typename;
extern int looking_for_template;
/* Tell the lexer where to look for names. */
extern tree got_scope;

View File

@ -938,7 +938,9 @@ build_typename_overload (type)
build_overload_name (type, 0, 1);
id = get_identifier (obstack_base (&scratch_obstack));
IDENTIFIER_OPNAME_P (id) = 1;
#if 0
IDENTIFIER_GLOBAL_VALUE (id) = TYPE_NAME (type);
#endif
TREE_TYPE (id) = type;
return id;
}
@ -1676,8 +1678,9 @@ make_thunk (function, delta)
int delta;
{
char buffer[250];
tree thunk_fndecl;
tree thunk_fndecl, thunk_id;
tree thunk;
char *func_name;
static int thunk_number = 0;
tree func_decl;
if (TREE_CODE (function) != ADDR_EXPR)
@ -1685,14 +1688,26 @@ make_thunk (function, delta)
func_decl = TREE_OPERAND (function, 0);
if (TREE_CODE (func_decl) != FUNCTION_DECL)
abort ();
sprintf (buffer, "__thunk_%d_%d", -delta, thunk_number++);
thunk = build_decl (THUNK_DECL, get_identifier (buffer),
TREE_TYPE (func_decl));
DECL_RESULT (thunk)
= build_decl (RESULT_DECL, NULL_TREE, TREE_TYPE (vtable_entry_type));
make_function_rtl (thunk);
DECL_INITIAL (thunk) = function;
THUNK_DELTA (thunk) = delta;
func_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (func_decl));
sprintf (buffer, "__thunk_%d_%s", -delta, func_name);
thunk_id = get_identifier (buffer);
thunk = IDENTIFIER_GLOBAL_VALUE (thunk_id);
if (thunk && TREE_CODE (thunk) != THUNK_DECL)
{
error_with_decl ("implementation-reserved name `%s' used");
IDENTIFIER_GLOBAL_VALUE (thunk_id) = thunk = NULL_TREE;
}
if (thunk == NULL_TREE)
{
thunk = build_decl (THUNK_DECL, thunk_id, TREE_TYPE (func_decl));
DECL_RESULT (thunk)
= build_decl (RESULT_DECL, NULL_TREE, TREE_TYPE (vtable_entry_type));
make_function_rtl (thunk);
DECL_INITIAL (thunk) = function;
THUNK_DELTA (thunk) = delta;
/* So that finish_file can write out any thunks that need to be: */
pushdecl_top_level (thunk);
}
return thunk;
}
@ -1725,6 +1740,19 @@ emit_thunk (thunk_fndecl)
if (TREE_ASM_WRITTEN (thunk_fndecl))
return;
TREE_ASM_WRITTEN (thunk_fndecl) = 1;
if (TREE_PUBLIC (function))
{
TREE_PUBLIC (thunk_fndecl) = 1;
if (DECL_EXTERNAL (function))
{
DECL_EXTERNAL (thunk_fndecl) = 1;
assemble_external (thunk_fndecl);
return;
}
}
decl_printable_name = thunk_printable_name;
if (current_function_decl)
abort ();
@ -1833,8 +1861,6 @@ emit_thunk (thunk_fndecl)
expand_end_bindings (NULL, 1, 0);
poplevel (0, 0, 0);
TREE_ASM_WRITTEN (thunk_fndecl) = 1;
/* From now on, allocate rtl in current_obstack, not in saveable_obstack.
Note that that may have been done above, in save_for_inline_copying.
The call to resume_temporary_allocation near the end of this function
@ -1848,10 +1874,6 @@ emit_thunk (thunk_fndecl)
unshare_all_rtl (insns);
/* Instantiate all virtual registers. */
instantiate_virtual_regs (current_function_decl, get_insns ());
/* We are no longer anticipating cse in this function, at least. */
cse_not_expected = 1;

View File

@ -543,11 +543,12 @@ datadef:
&& TREE_PURPOSE (t) == NULL_TREE)
{
t = TREE_VALUE (t);
if (TREE_CODE (t) == RECORD_TYPE)
if (IS_AGGR_TYPE (t)
&& IDENTIFIER_TEMPLATE (TYPE_IDENTIFIER (t)))
{
if (CLASSTYPE_USE_TEMPLATE (t) == 0)
CLASSTYPE_USE_TEMPLATE (t) = 2;
else if (CLASSTYPE_USE_TEMPLATE (t) == 1)
SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (t);
else if (CLASSTYPE_TEMPLATE_INSTANTIATION (t))
error ("override declaration for already-expanded template");
}
}
@ -2914,14 +2915,18 @@ absdcl:
{ $$ = make_pointer_declarator ($2, $3); }
| '*' absdcl
{ $$ = make_pointer_declarator (NULL_TREE, $2); }
| '*' type_quals %prec EMPTY
| '*' nonempty_type_quals %prec EMPTY
{ $$ = make_pointer_declarator ($2, NULL_TREE); }
| '*' %prec EMPTY
{ $$ = make_pointer_declarator (NULL_TREE, NULL_TREE); }
| '&' nonempty_type_quals absdcl
{ $$ = make_reference_declarator ($2, $3); }
| '&' absdcl
{ $$ = make_reference_declarator (NULL_TREE, $2); }
| '&' type_quals %prec EMPTY
| '&' nonempty_type_quals %prec EMPTY
{ $$ = make_reference_declarator ($2, NULL_TREE); }
| '&' %prec EMPTY
{ $$ = make_reference_declarator (NULL_TREE, NULL_TREE); }
| ptr_to_mem type_quals %prec EMPTY
{ tree arg = make_pointer_declarator ($2, NULL_TREE);
$$ = build_parse_node (SCOPE_REF, $1, arg);

View File

@ -116,7 +116,7 @@ process_template_parm (list, next)
else
{
tree t = make_node (TEMPLATE_TYPE_PARM);
decl = build_lang_decl (TYPE_DECL, TREE_PURPOSE (parm), t);
decl = build_decl (TYPE_DECL, TREE_PURPOSE (parm), t);
TYPE_NAME (t) = decl;
TREE_VALUE (parm) = t;
}
@ -581,7 +581,7 @@ lookup_template_class (d1, arglist, in_decl)
tree t = make_lang_type (UNINSTANTIATED_P_TYPE);
tree d;
id = make_anon_name ();
d = build_lang_decl (TYPE_DECL, id, t);
d = build_decl (TYPE_DECL, id, t);
TYPE_NAME (t) = d;
TYPE_VALUES (t) = build_tree_list (template, arglist);
pushdecl_top_level (d);
@ -635,7 +635,7 @@ push_template_decls (parmlist, arglist, class_level)
}
decl = arg;
my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (decl)) == 't', 273);
decl = build_lang_decl (TYPE_DECL, parm, decl);
decl = build_decl (TYPE_DECL, parm, decl);
}
else
{
@ -987,7 +987,7 @@ instantiate_class_template (classname, setup_parse)
if (!TREE_TYPE (classname))
{
tree t = make_lang_type (RECORD_TYPE);
tree d = build_lang_decl (TYPE_DECL, classname, t);
tree d = build_decl (TYPE_DECL, classname, t);
DECL_NAME (d) = classname;
TYPE_NAME (t) = d;
pushdecl (d);
@ -1320,7 +1320,7 @@ tsubst (t, args, nargs, in_decl)
tree decls;
int got_it = 0;
decls = lookup_name (r, 0);
decls = lookup_name_nonclass (r);
if (decls == NULL_TREE)
/* no match */;
else if (TREE_CODE (decls) == TREE_LIST)
@ -1645,11 +1645,18 @@ instantiate_template (tmpl, targ_ptr)
DECL_ARGUMENTS (fndecl) = TREE_CHAIN (DECL_ARGUMENTS (fndecl));
}
t = DECL_TEMPLATE_INFO (tmpl);
/* If we have a preexisting version of this function, don't expand
the template version, use the other instead. */
t = DECL_TEMPLATE_INFO (tmpl);
if (t->text && !(DECL_INLINE (fndecl) && DECL_SAVED_INSNS (fndecl)))
if (DECL_INLINE (fndecl) && DECL_SAVED_INSNS (fndecl))
{
SET_DECL_TEMPLATE_SPECIALIZATION (fndecl);
p = (struct pending_inline *)0;
}
else if (t->text)
{
SET_DECL_IMPLICIT_INSTANTIATION (fndecl);
p = (struct pending_inline *) permalloc (sizeof (struct pending_inline));
p->parm_vec = t->parm_vec;
p->bindings = targs;
@ -1819,7 +1826,7 @@ end_template_instantiation (name)
my_friendly_assert (t != NULL_TREE
&& TREE_CODE_CLASS (TREE_CODE (t)) == 't',
287);
CLASSTYPE_USE_TEMPLATE (t) = 2;
SET_CLASSTYPE_IMPLICIT_INSTANTIATION (t);
/* Make methods of template classes static, unless
-fexternal-templates is given. */
if (!flag_external_templates)
@ -2227,8 +2234,10 @@ do_pending_expansions ()
if (TREE_ASM_WRITTEN (t))
DECIDE (0);
if (DECL_EXPLICITLY_INSTANTIATED (t))
if (DECL_EXPLICIT_INSTANTIATION (t))
DECIDE (1);
else if (! flag_implicit_templates)
DECIDE (0);
/* If it's a method, let the class type decide it.
@@ What if the method template is in a separate file?
@ -2357,7 +2366,12 @@ do_function_instantiation (declspecs, declarator)
if (! result)
cp_error ("no matching template for `%D' found", decl);
DECL_EXPLICITLY_INSTANTIATED (result) = 1;
if (flag_external_templates)
return;
SET_DECL_EXPLICIT_INSTANTIATION (result);
TREE_PUBLIC (result) = 1;
DECL_EXTERNAL (result) = DECL_INLINE (result) && ! flag_implement_inlines;
}
void
@ -2366,14 +2380,24 @@ do_type_instantiation (name)
{
tree t = TREE_TYPE (name);
CLASSTYPE_EXPLICITLY_INSTANTIATED (t) = 1;
if (flag_external_templates)
return;
SET_CLASSTYPE_EXPLICIT_INSTANTIATION (t);
CLASSTYPE_VTABLE_NEEDS_WRITING (t) = 1;
SET_CLASSTYPE_INTERFACE_KNOWN (t);
CLASSTYPE_INTERFACE_ONLY (t) = 0;
/* this should really be done by instantiate_member_templates */
{
tree method = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (t), 0);
for (; method; method = TREE_CHAIN (method))
DECL_EXPLICITLY_INSTANTIATED (method) = 1;
{
SET_DECL_EXPLICIT_INSTANTIATION (method);
TREE_PUBLIC (method) = 1;
DECL_EXTERNAL (method) = (DECL_INLINE (method)
&& ! flag_implement_inlines);
}
}
/* and data member templates, too */
@ -2384,7 +2408,7 @@ create_nested_upt (scope, name)
tree scope, name;
{
tree t = make_lang_type (UNINSTANTIATED_P_TYPE);
tree d = build_lang_decl (TYPE_DECL, name, t);
tree d = build_decl (TYPE_DECL, name, t);
TYPE_NAME (t) = d;
TYPE_VALUES (t) = TYPE_VALUES (scope);

View File

@ -512,8 +512,8 @@ build_signature_table_constructor (sig_ty, rhs)
{
if (! IS_DEFAULT_IMPLEMENTATION (sig_method))
{
cp_error ("class `%T' does not contain method `%s'",
rhstype, (int) IDENTIFIER_POINTER (sig_mname));
cp_error ("class `%T' does not contain method `%D'",
rhstype, sig_mname);
undo_casts (sig_ty);
return error_mark_node;
}

View File

@ -236,6 +236,7 @@ probe_obstack (h, obj, nlevels)
a typename (when it may be a local variable or a class variable).
Value is 0 if we treat this name in a default fashion. */
extern int looking_for_typename;
int looking_for_template;
extern struct obstack *current_obstack, *saveable_obstack;
tree got_scope;
@ -298,6 +299,8 @@ yylex()
if (nth_token (1)->yychar == SCOPE)
/* Don't interfere with the setting from an 'aggr' prefix. */
looking_for_typename++;
else if (nth_token (1)->yychar == '<')
looking_for_template = 1;
trrr = lookup_name (tmp_token.yylval.ttype, -2);
@ -334,6 +337,7 @@ yylex()
consume_token ();
if (looking_for_typename > 0)
looking_for_typename--;
looking_for_template = 0;
break;
case SCSPEC:

View File

@ -860,7 +860,7 @@ list_hash_add (hashcode, list)
This function frees the list you pass in if it is a duplicate. */
/* Set to 1 to debug without canonicalization. Never set by program. */
int debug_no_list_hash = 0;
static int debug_no_list_hash = 0;
tree
list_hash_canon (hashcode, list)

View File

@ -542,7 +542,9 @@ comp_array_types (cmp, t1, t2, strict)
2 : strict, except that if one type is a reference and
the other is not, compare the target type of the
reference to the type that's not a reference (ARM, p308).
This is used for checking for illegal overloading.
1 : strict (compared according to ANSI C)
This is used for checking whether two function decls match.
0 : <= (compared according to C++)
-1: <= or >= (relaxed)
@ -608,7 +610,7 @@ comptypes (type1, type2, strict)
if (TYPE_READONLY (t1) != TYPE_READONLY (t2))
return 0;
if (TREE_THIS_VOLATILE (t1) != TREE_THIS_VOLATILE (t2))
if (TYPE_VOLATILE (t1) != TYPE_VOLATILE (t2))
return 0;
/* Allow for two different type nodes which have essentially the same
@ -739,7 +741,13 @@ comp_target_types (ttl, ttr, nptrs)
return 0;
if (TREE_CODE (ttr) == POINTER_TYPE)
return comp_target_types (TREE_TYPE (ttl), TREE_TYPE (ttr), nptrs - 1);
{
if (TREE_CODE (TREE_TYPE (ttl)) == POINTER_TYPE
|| TREE_CODE (TREE_TYPE (ttl)) == ARRAY_TYPE)
return comp_ptr_ttypes (TREE_TYPE (ttl), TREE_TYPE (ttr));
else
return comp_target_types (TREE_TYPE (ttl), TREE_TYPE (ttr), nptrs - 1);
}
if (TREE_CODE (ttr) == REFERENCE_TYPE)
return comp_target_types (TREE_TYPE (ttl), TREE_TYPE (ttr), nptrs);
@ -2425,12 +2433,9 @@ convert_arguments (return_loc, typelist, values, fndecl, flags)
called_thing = "constructor";
else
called_thing = "member function";
i -= 1;
}
else
{
called_thing = "function";
}
called_thing = "function";
}
for (valtail = values, typetail = typelist;
@ -2510,7 +2515,8 @@ convert_arguments (return_loc, typelist, values, fndecl, flags)
/* build_c_cast puts on a NOP_EXPR to make the result not an lvalue.
Strip such NOP_EXPRs, since VAL is used in non-lvalue context. */
if (TREE_CODE (val) == NOP_EXPR
&& TREE_TYPE (val) == TREE_TYPE (TREE_OPERAND (val, 0)))
&& TREE_TYPE (val) == TREE_TYPE (TREE_OPERAND (val, 0))
&& (type == 0 || TREE_CODE (type) != REFERENCE_TYPE))
val = TREE_OPERAND (val, 0);
if ((type == 0 || TREE_CODE (type) != REFERENCE_TYPE)
@ -2886,6 +2892,17 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE)
&& (code1 == INTEGER_TYPE || code1 == REAL_TYPE))
{
if (TREE_CODE (op1) == INTEGER_CST && integer_zerop (op1))
{
error ("division by zero");
op1 = integer_one_node;
}
else if (TREE_CODE (op1) == REAL_CST && real_zerop (op1))
{
error ("division by zero");
op1 = build_real (TREE_TYPE (op1), dconst1);
}
if (!(code0 == INTEGER_TYPE && code1 == INTEGER_TYPE))
resultcode = RDIV_EXPR;
else
@ -2936,6 +2953,17 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
case TRUNC_MOD_EXPR:
case FLOOR_MOD_EXPR:
if (code1 == INTEGER_TYPE && integer_zerop (op1))
{
error ("division by zero");
op1 = integer_one_node;
}
else if (code1 == REAL_TYPE && real_zerop (op1))
{
error ("division by zero");
op1 = build_real (TREE_TYPE (op1), dconst1);
}
if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
{
/* Although it would be tempting to shorten always here, that loses
@ -4001,17 +4029,15 @@ build_unary_op (code, xarg, noconvert)
TREE_REFERENCE_EXPR (arg) = 1;
return arg;
}
else if (TREE_CODE (arg) == FUNCTION_DECL
else if (pedantic
&& TREE_CODE (arg) == FUNCTION_DECL
&& DECL_NAME (arg)
&& DECL_CONTEXT (arg) == NULL_TREE
&& IDENTIFIER_LENGTH (DECL_NAME (arg)) == 4
&& IDENTIFIER_POINTER (DECL_NAME (arg))[0] == 'm'
&& ! strcmp (IDENTIFIER_POINTER (DECL_NAME (arg)), "main"))
{
/* ARM $3.4 */
error ("attempt to take address of function `main'");
return error_mark_node;
}
/* ARM $3.4 */
pedwarn ("taking address of function `main'");
/* Let &* cancel out to simplify resulting code. */
if (TREE_CODE (arg) == INDIRECT_REF)
@ -4911,6 +4937,13 @@ build_c_cast (type, expr)
}
}
if (TREE_CODE (type) == FUNCTION_TYPE
|| TREE_CODE (type) == METHOD_TYPE)
{
cp_error ("casting to function type `%T'", type);
return error_mark_node;
}
if (IS_SIGNATURE (type))
{
error ("cast specifies signature type");
@ -5396,6 +5429,33 @@ build_modify_expr (lhs, modifycode, rhs)
}
}
if (TREE_CODE (lhs) == OFFSET_REF)
{
if (TREE_OPERAND (lhs, 0) == NULL_TREE)
{
/* Static class member? */
tree member = TREE_OPERAND (lhs, 1);
if (TREE_CODE (member) == VAR_DECL)
lhs = member;
else
{
compiler_error ("invalid static class member");
return error_mark_node;
}
}
else
lhs = resolve_offset_ref (lhs);
olhstype = lhstype = TREE_TYPE (lhs);
}
if (TREE_CODE (lhstype) == REFERENCE_TYPE
&& modifycode != INIT_EXPR)
{
lhs = convert_from_reference (lhs);
olhstype = lhstype = TREE_TYPE (lhs);
}
/* If a binary op has been requested, combine the old LHS value with the RHS
producing the value we should actually store into the LHS. */
@ -5413,9 +5473,6 @@ build_modify_expr (lhs, modifycode, rhs)
}
else if (modifycode == NOP_EXPR)
{
/* must deal with overloading of `operator=' here. */
if (TREE_CODE (lhstype) == REFERENCE_TYPE)
lhstype = TREE_TYPE (lhstype);
#if 1
/* `operator=' is not an inheritable operator. */
if (TYPE_LANG_SPECIFIC (lhstype) && TYPE_HAS_ASSIGNMENT (lhstype))
@ -5490,7 +5547,6 @@ build_modify_expr (lhs, modifycode, rhs)
newrhs = build_binary_op (modifycode, lhs, rhs, 1);
}
#if 0
/* Handle a cast used as an "lvalue".
We have already performed any binary operator using the value as cast.
Now convert the result to the cast type of the lhs,
@ -5515,6 +5571,9 @@ build_modify_expr (lhs, modifycode, rhs)
{
tree inner_lhs = TREE_OPERAND (lhs, 0);
tree result;
if (! lvalue_p (lhs) && pedantic)
pedwarn ("cast to non-reference type used as lvalue");
result = build_modify_expr (inner_lhs, NOP_EXPR,
convert (TREE_TYPE (inner_lhs),
convert (lhstype, newrhs)));
@ -5523,25 +5582,6 @@ build_modify_expr (lhs, modifycode, rhs)
return convert_force (TREE_TYPE (lhs), result);
}
}
#endif
if (TREE_CODE (lhs) == OFFSET_REF)
{
if (TREE_OPERAND (lhs, 0) == NULL_TREE)
{
/* Static class member? */
tree member = TREE_OPERAND (lhs, 1);
if (TREE_CODE (member) == VAR_DECL)
lhs = member;
else
{
compiler_error ("invalid static class member");
return error_mark_node;
}
}
else
lhs = resolve_offset_ref (lhs);
}
/* Now we have handled acceptable kinds of LHS that are not truly lvalues.
Reject anything strange now. */
@ -5576,7 +5616,18 @@ build_modify_expr (lhs, modifycode, rhs)
&& (TREE_CODE (lhstype) == INTEGER_TYPE
|| TREE_CODE (lhstype) == REAL_TYPE
|| TREE_CODE (lhstype) == ENUMERAL_TYPE))
lhstype = TREE_TYPE (get_unwidened (lhs, 0));
{
lhstype = TREE_TYPE (get_unwidened (lhs, 0));
/* If storing in a field that is in actuality a short or narrower
than one, we must store in the field in its actual type. */
if (lhstype != TREE_TYPE (lhs))
{
lhs = copy_node (lhs);
TREE_TYPE (lhs) = lhstype;
}
}
/* check to see if there is an assignment to `this' */
if (lhs == current_class_decl)
@ -5734,15 +5785,6 @@ build_modify_expr (lhs, modifycode, rhs)
#endif
}
/* If storing in a field that is in actuality a short or narrower than one,
we must store in the field in its actual type. */
if (lhstype != TREE_TYPE (lhs))
{
lhs = copy_node (lhs);
TREE_TYPE (lhs) = lhstype;
}
/* Convert new value to destination type. */
if (TREE_CODE (lhstype) == ARRAY_TYPE)
@ -6081,6 +6123,14 @@ build_ptrmemfunc (type, pfn, force)
return digest_init (TYPE_GET_PTRMEMFUNC_TYPE (type), u, (tree*)0);
}
if (TREE_CODE (pfn) == TREE_LIST)
{
pfn = instantiate_type (type, pfn, 1);
if (pfn == error_mark_node)
return error_mark_node;
pfn = build_unary_op (ADDR_EXPR, pfn, 0);
}
/* Allow pointer to member conversions here. */
delta = get_delta_difference (TYPE_METHOD_BASETYPE (TREE_TYPE (TREE_TYPE (pfn))),
TYPE_METHOD_BASETYPE (TREE_TYPE (type)),
@ -6399,45 +6449,63 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
}
else
{
int const_parity = TYPE_READONLY (type) ^ TYPE_READONLY (rhstype);
int volatile_parity = TYPE_VOLATILE (type) ^ TYPE_VOLATILE (rhstype);
int add_quals = 0, const_parity = 0, volatile_parity = 0;
int left_const = 1;
int unsigned_parity;
int nptrs = 0;
while (TREE_CODE (ttl) == POINTER_TYPE
&& TREE_CODE (ttr) == POINTER_TYPE)
/* This code is basically a duplicate of comp_ptr_ttypes_real. */
for (; ; ttl = TREE_TYPE (ttl), ttr = TREE_TYPE (ttr))
{
nptrs -= 1;
const_parity |= TYPE_READONLY (ttl) ^ TYPE_READONLY (ttr);
volatile_parity |= TYPE_VOLATILE (ttl) ^ TYPE_VOLATILE (ttr);
ttl = TREE_TYPE (ttl);
ttr = TREE_TYPE (ttr);
const_parity |= TYPE_READONLY (ttl) < TYPE_READONLY (ttr);
volatile_parity |= TYPE_VOLATILE (ttl) < TYPE_VOLATILE (ttr);
if (! left_const
&& (TYPE_READONLY (ttl) > TYPE_READONLY (ttr)
|| TYPE_VOLATILE (ttl) > TYPE_VOLATILE (ttr)))
add_quals = 1;
left_const &= TYPE_READONLY (ttl);
if (TREE_CODE (ttl) != POINTER_TYPE)
break;
}
unsigned_parity = TREE_UNSIGNED (ttl) - TREE_UNSIGNED (ttr);
if (unsigned_parity)
if (TREE_UNSIGNED (ttl))
ttr = unsigned_type (ttr);
else
ttl = unsigned_type (ttl);
{
if (TREE_UNSIGNED (ttl))
ttr = unsigned_type (ttr);
else
ttl = unsigned_type (ttl);
}
if (comp_target_types (ttl, ttr, nptrs))
{
if (add_quals)
{
if (fndecl)
cp_pedwarn ("passing `%T' as argument %P of `%D' adds cv-quals without intervening `const'",
rhstype, parmnum, fndecl);
else
cp_pedwarn ("%s to `%T' from `%T' adds cv-quals without intervening `const'",
errtype, type, rhstype);
}
if (const_parity)
{
if (fndecl)
cp_warning ("passing `%T' as argument %P of `%D' discards const",
cp_pedwarn ("passing `%T' as argument %P of `%D' discards const",
rhstype, parmnum, fndecl);
else
cp_warning ("%s to `%T' from `%T' discards const",
cp_pedwarn ("%s to `%T' from `%T' discards const",
errtype, type, rhstype);
}
if (volatile_parity)
{
if (fndecl)
cp_warning ("passing `%T' as argument %P of `%D' discards volatile",
cp_pedwarn ("passing `%T' as argument %P of `%D' discards volatile",
rhstype, parmnum, fndecl);
else
cp_warning ("%s to `%T' from `%T' discards volatile",
cp_pedwarn ("%s to `%T' from `%T' discards volatile",
errtype, type, rhstype);
}
if (unsigned_parity > 0)
@ -6591,7 +6659,8 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum)
/* build_c_cast puts on a NOP_EXPR to make the result not an lvalue.
Strip such NOP_EXPRs, since RHS is used in non-lvalue context. */
if (TREE_CODE (rhs) == NOP_EXPR
&& TREE_TYPE (rhs) == TREE_TYPE (TREE_OPERAND (rhs, 0)))
&& TREE_TYPE (rhs) == TREE_TYPE (TREE_OPERAND (rhs, 0))
&& codel != REFERENCE_TYPE)
rhs = TREE_OPERAND (rhs, 0);
if (rhs == error_mark_node
@ -7143,3 +7212,40 @@ c_expand_start_case (exp)
return exp;
}
/* CONSTP remembers whether or not all the intervening pointers in the `to'
type have been const. */
int
comp_ptr_ttypes_real (to, from, constp)
tree to, from;
int constp;
{
for (; ; to = TREE_TYPE (to), from = TREE_TYPE (from))
{
if (TREE_CODE (to) != TREE_CODE (from))
return 0;
if (TYPE_READONLY (from) > TYPE_READONLY (to)
|| TYPE_VOLATILE (from) > TYPE_VOLATILE (to))
return 0;
if (! constp
&& (TYPE_READONLY (to) > TYPE_READONLY (from)
|| TYPE_VOLATILE (to) > TYPE_READONLY (from)))
return 0;
constp &= TYPE_READONLY (to);
if (TREE_CODE (to) != POINTER_TYPE)
return comptypes (TYPE_MAIN_VARIANT (to), TYPE_MAIN_VARIANT (from), 1);
}
}
/* When comparing, say, char ** to char const **, this function takes the
'char *' and 'char const *'. Do not pass non-pointer types to this
function. */
int
comp_ptr_ttypes (to, from)
tree to, from;
{
return comp_ptr_ttypes_real (to, from, 1);
}

View File

@ -655,6 +655,7 @@ digest_init (type, init, tail)
&& ((TREE_CODE (init) == ADDR_EXPR
&& TREE_CODE (TREE_TYPE (init)) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (TREE_TYPE (init))) == METHOD_TYPE)
|| TREE_CODE (init) == TREE_LIST
|| integer_zerop (init)
|| (TREE_TYPE (init) && TYPE_PTRMEMFUNC_P (TREE_TYPE (init)))))
{
@ -1237,6 +1238,12 @@ build_x_arrow (datum)
if (type == error_mark_node)
return error_mark_node;
if (TREE_CODE (rval) == OFFSET_REF)
{
rval = resolve_offset_ref (datum);
type = TREE_TYPE (rval);
}
if (TREE_CODE (type) == REFERENCE_TYPE)
{
rval = convert_from_reference (rval);
@ -1268,7 +1275,6 @@ build_x_arrow (datum)
else
last_rval = default_conversion (rval);
more:
/* Signature pointers are not dereferenced. */
if (TYPE_LANG_SPECIFIC (TREE_TYPE (last_rval))
&& IS_SIGNATURE_POINTER (TREE_TYPE (last_rval)))
@ -1277,20 +1283,6 @@ build_x_arrow (datum)
if (TREE_CODE (TREE_TYPE (last_rval)) == POINTER_TYPE)
return build_indirect_ref (last_rval, NULL_PTR);
if (TREE_CODE (TREE_TYPE (last_rval)) == OFFSET_TYPE)
{
if (TREE_CODE (last_rval) == OFFSET_REF
&& TREE_STATIC (TREE_OPERAND (last_rval, 1)))
{
last_rval = TREE_OPERAND (last_rval, 1);
if (TREE_CODE (TREE_TYPE (last_rval)) == REFERENCE_TYPE)
last_rval = convert_from_reference (last_rval);
goto more;
}
compiler_error ("invalid member type in build_x_arrow");
return error_mark_node;
}
if (types_memoized)
error ("result of `operator->()' yields non-pointer result");
else
@ -1372,7 +1364,6 @@ build_functional_cast (exp, parms)
or a C cast in C++'s `functional' notation. */
tree type, name = NULL_TREE;
tree expr_as_ctor = NULL_TREE;
tree expr_as_conversion = NULL_TREE;
if (exp == error_mark_node || parms == error_mark_node)
return error_mark_node;
@ -1423,7 +1414,12 @@ build_functional_cast (exp, parms)
/* this must build a C cast */
if (parms == NULL_TREE)
return build1 (NOP_EXPR, type, integer_zero_node);
return build_c_cast (type, build_compound_expr (parms));
else if (TREE_CHAIN (parms) != NULL_TREE)
{
pedwarn ("initializer list being treated as compound expression");
parms = build_compound_expr (parms);
}
return build_c_cast (type, parms);
}
if (TYPE_SIZE (type) == NULL_TREE)
@ -1433,90 +1429,45 @@ build_functional_cast (exp, parms)
}
if (parms && TREE_CHAIN (parms) == NULL_TREE)
expr_as_conversion
= build_type_conversion (CONVERT_EXPR, type, TREE_VALUE (parms), 0);
if (! TYPE_HAS_CONSTRUCTOR (type) && parms != NULL_TREE)
{
char *msg = 0;
return build_c_cast (type, parms);
if (parms == NULL_TREE)
msg = "argument missing in cast to `%T' type";
else if (TREE_CHAIN (parms) == NULL_TREE)
{
if (expr_as_conversion == NULL_TREE)
msg = "conversion to type `%T' failed";
}
else msg = "type `%T' does not have a constructor";
expr_as_ctor = build_method_call (NULL_TREE, name, parms,
NULL_TREE, LOOKUP_NORMAL);
if (expr_as_conversion)
return expr_as_conversion;
if (expr_as_ctor == error_mark_node)
return error_mark_node;
cp_error (msg, type);
return error_mark_node;
}
if (current_function_decl)
return build_cplus_new (type, expr_as_ctor, 0);
{
int flags = LOOKUP_SPECULATIVELY|LOOKUP_NORMAL;
register tree parm = TREE_OPERAND (expr_as_ctor, 1);
if (parms && TREE_CHAIN (parms) == NULL_TREE)
flags |= LOOKUP_NO_CONVERSION;
expr_as_ctor = build_method_call (NULL_TREE, name, parms,
NULL_TREE, flags);
if (expr_as_ctor == error_mark_node)
return error_mark_node;
else if (expr_as_ctor)
{
if (expr_as_conversion && expr_as_conversion != error_mark_node)
{
/* ANSI C++ June 5 1992 WP 12.3.2.6.1 */
cp_error ("ambiguity between conversion to `%T' and constructor",
type);
return error_mark_node;
}
if (current_function_decl)
return build_cplus_new (type, expr_as_ctor, 0);
{
register tree parm = TREE_OPERAND (expr_as_ctor, 1);
/* Initializers for static variables and parameters have
to handle doing the initialization and cleanup themselves. */
my_friendly_assert (TREE_CODE (expr_as_ctor) == CALL_EXPR, 322);
/* Initializers for static variables and parameters have
to handle doing the initialization and cleanup themselves. */
my_friendly_assert (TREE_CODE (expr_as_ctor) == CALL_EXPR, 322);
#if 0
/* The following assertion fails in cases where we are initializing
a static member variable of a particular instance of a template
class with a call to a constructor of the given instance, as in:
TMPL<int> object = TMPL<int>();
Curiously, the assertion does not fail if we do the same thing
for a static member of a non-template class, as in:
T object = T();
I can't see why we should care here whether or not the initializer
expression involves a call to `new', so for the time being, it
seems best to just avoid doing this assertion. */
my_friendly_assert (TREE_CALLS_NEW (TREE_VALUE (parm)), 323);
/* The following assertion fails in cases where we are initializing
a static member variable of a particular instance of a template
class with a call to a constructor of the given instance, as in:
TMPL<int> object = TMPL<int>();
Curiously, the assertion does not fail if we do the same thing
for a static member of a non-template class, as in:
T object = T();
I can't see why we should care here whether or not the initializer
expression involves a call to `new', so for the time being, it
seems best to just avoid doing this assertion. */
my_friendly_assert (TREE_CALLS_NEW (TREE_VALUE (parm)), 323);
#endif
TREE_VALUE (parm) = NULL_TREE;
expr_as_ctor = build_indirect_ref (expr_as_ctor, NULL_PTR);
TREE_HAS_CONSTRUCTOR (expr_as_ctor) = 1;
}
return expr_as_ctor;
}
if (expr_as_conversion)
return expr_as_conversion;
cp_error ("no suitable conversion to `%T' exists", type);
return error_mark_node;
TREE_VALUE (parm) = NULL_TREE;
expr_as_ctor = build_indirect_ref (expr_as_ctor, NULL_PTR);
TREE_HAS_CONSTRUCTOR (expr_as_ctor) = 1;
}
return expr_as_ctor;
}
/* Return the character string for the name that encodes the