aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog.apple-ppc392
-rw-r--r--gcc/cp/Make-lang.in28
-rw-r--r--gcc/cp/call.c63
-rw-r--r--gcc/cp/class.c211
-rw-r--r--gcc/cp/cp-objcp-common.c15
-rw-r--r--gcc/cp/cp-objcp-common.h16
-rw-r--r--gcc/cp/cp-tree.h54
-rw-r--r--gcc/cp/decl.c219
-rw-r--r--gcc/cp/decl2.c43
-rw-r--r--gcc/cp/init.c10
-rw-r--r--gcc/cp/lang-specs.h2
-rw-r--r--gcc/cp/lex.c52
-rw-r--r--gcc/cp/mangle.c15
-rw-r--r--gcc/cp/optimize.c189
-rw-r--r--gcc/cp/parser.c2245
-rw-r--r--gcc/cp/pt.c37
-rw-r--r--gcc/cp/semantics.c36
-rw-r--r--gcc/cp/tree.c4
-rw-r--r--gcc/cp/typeck.c301
-rw-r--r--gcc/cp/typeck2.c30
20 files changed, 3906 insertions, 56 deletions
diff --git a/gcc/cp/ChangeLog.apple-ppc b/gcc/cp/ChangeLog.apple-ppc
new file mode 100644
index 00000000000..6186b3cedd9
--- /dev/null
+++ b/gcc/cp/ChangeLog.apple-ppc
@@ -0,0 +1,392 @@
+2005-03-07 Devang Patel <dpatel@apple.com>
+
+ * class.c (tree-iterator.h): Include.
+
+2005-03-02 Robert Bowdidge <bowdidge@apple.com
+ Radar 4025293
+ * cp/typeck.c (convert_member_func_to_ptr) Ban casts from pointer-to-
+ member-function to pointer-to-function whenever the -fapple-kext flag
+ was passed to the compiler. Behavior changed between 3.3 and 4.0 in
+ incompatible ways, and the IOKit team wants all kexts to use a macro
+ that provides the correct (3.3) behavior.
+
+2005-02-21 Ziemowit Laski <zlaski@apple.com>
+
+ Radar 3809189
+ * typeck2.c (digest_init): Factor out Pascal-ness of string
+ initializer; allow NUL terminator to not fit into the array
+ being initialized.
+
+2005-02-18 Ziemowit Laski <zlaski@apple.com>
+
+ Radar 4011192
+ * parser.c (cp_parser_objc_try_catch_finally_statement): When
+ parsing '@finally' blocks, make sure the compound statement
+ winds up in a special STATEMENT_LIST instead of current scope.
+ (cp_parser_objc_synchronized_statement): Likewise for
+ '@synchronized' blocks.
+
+2005-02-17 Ziemowit Laski <zlaski@apple.com>
+
+ Radar 3635843, 3922342
+ * tree.c (lvalue_or_else): Do not emit warning if
+ '-Wno-non-lvalue-assign' has been specified.
+ * typeck.c (build_modify_expr): Call
+ objc_generate_write_barrier() if '-fobjc-gc' has been specified.
+
+2005-02-16 Fariborz Jahanian <fjahanian@apple.com>
+
+ Radar 3971074
+
+ * parser.c (cp_parser_cw_asm_statement): Pass lineno to cw_asm_stmt.
+
+2005-02-16 Fariborz Jahanian <fjahanian@apple.com>
+
+ Radar 3970655
+
+ * cp/parser.c (cw_build_identifier_string): New function.
+ (cp_parser_cw_identifier): Build the tree for a '.'identifier.
+ (cp_parser_cw_asm_postfix_expression): Some disambiguation case.
+
+2005-02-10 Ziemowit Laski <zlaski@apple.com>
+
+ Radar 3993052
+ * parser.c (cp_parser_objc_interstitial_code): New routine.
+ (cp_parser_objc_method_prototype_list): Call
+ cp_parser_objc_interstitial_code() instead of doing
+ non-ObjC++ parsing locally.
+ (cp_parser_objc_method_definition_list): Likewise.
+
+2005-02-10 Ziemowit Laski <zlaski@apple.com>
+
+ Radar 3982256
+ * cp-objcp-common.h (cxx_get_alias_set,
+ cxx_warn_unused_global_decl, cp_expr_size, cp_tree_size,
+ cp_var_mod_type_p, cxx_initialize_diagnostics,
+ cxx_types_compatible_p): Move prototypes ...
+ * cp-tree.h: ... here.
+
+2005-02-08 Ziemowit Laski <zlaski@apple.com>
+
+ Radar 3987120
+ * parser.c (cp_parser_objc_encode_expression): Call
+ 'complete_type (cp_parser_type_id ())' instead of
+ 'cp_parser_objc_typename ()' to retrieve argument type.
+
+2005-02-02 Ziemowit Laski <zlaski@apple.com>
+
+ Radar 3978104
+ * parser.c (cp_parser_objc_method_prototype_list): Allow stray
+ semicolons in between method signatures.
+
+2005-01-31 Ziemowit Laski <zlaski@apple.com>
+
+ Radar 3978168
+ * tree.c (lvalue_or_else): Allow certain non-lvalues
+ as arguments to '&', and print appropriate warning.
+
+2005-01-27 Ziemowit Laski <zlaski@apple.com>
+
+ Radar 3971244
+ * typeck.c (composite_pointer_type): Check for
+ ObjC subtype relations.
+
+2005-01-26 Matt Austern <austern@apple.com>
+
+ Radar 3972840
+ * call.c (build_over_call): Set type of function node correctly.
+ Type returned by build_vfn_ref_using_vtable is *not* what we
+ want.
+ * class.c (build_vfn_ref_using_vtable): Duplicate logic in
+ build_vfn_ref for setting attributes of vtable array ref node.
+
+2005-01-26 Devang Patel <dpatel@apple.com>
+
+ Radar 3971329
+ * parser.c (cp_parser_objc_method_definition_list): Parse extern
+ linkage specification.
+
+2005-01-24 Ziemowit Laski <zlaski@apple.com>
+
+ Radar 3968938
+ * parser.c (cp_parser_simple_type_specifier): After
+ constructing a protocol-qualified ObjC type, record
+ it in the DECL_SPECS structure.
+
+2005-01-23 Ziemowit Laski <zlaski@apple.com>
+
+ Radar 3961973
+ * cp-tree.h (lvalue_or_else): Change type of first parameter
+ from 'tree' to 'tree *'.
+ * tree.c (lvalue_or_else): Change first parameter from
+ 'tree' to 'tree *'; handle conditional lvalues in addition
+ to lvalue casts; when rewriting expressions, create a new
+ tree instead of clobbering an existing one.
+ * typeck.c (build_unary_op, build_modify_expr): Adjust
+ calls to lvalue_or_else().
+
+2005-01-19 Matt Austern <austern@apple.com>
+
+ Radar 3960754
+ * typeck.c (comptypes): Handle return code from objc_comptypes
+ correctly.
+
+2005-01-18 Mike Stump <mrs@apple.com>
+
+ Radar 3956093
+ * class.c (has_apple_kext_compatibility_attr_p): Avoid problems
+ when there are no base classes.
+
+2005-01-18 Ziemowit Laski <zlaski@apple.com>
+
+ * parser.c (cp_parser_cw_identifier): Reapply change
+ just reverted.
+
+2005-01-18 Ziemowit Laski <zlaski@apple.com>
+
+ * parser.c (cp_parser_cw_identifier): Revert change
+ from 2005-01-14.
+
+2005-01-17 Ziemowit Laski <zlaski@apple.com>
+
+ Radar 3955336
+ * parser.c (cp_parser_objc_message_receiver): Try parsing
+ receiver as an expression first; failing that, as a
+ nested type.
+
+2005-01-17 Ziemowit Laski <zlaski@apple.com>
+
+ Radar 3951689
+ * parser.c (cp_parser_objc_try_catch_finally_statement,
+ cp_parser_objc_synchronized_statement, cp_parser_objc_throw_statement
+ cp_parser_objc_statement): New functions.
+ (cp_parser_statement): Call cp_parser_objc_statement() to
+ parse Objective-C statements.
+
+2005-01-15 Geoffrey Keating <geoffk@apple.com>
+
+ * g++spec.c: Remove APPLE LOCAL changes involving
+ macosx_version_min_required.
+
+2005-01-14 Ziemowit Laski <zlaski@apple.com>
+
+ * parser.c (cp_parser_cw_identifier): Add a default:
+ to squash compiler warnings.
+
+2005-01-08 Ziemowit Laski <zlaski@apple.com>
+
+ Radar 3913725
+ * tree.c (lvalue_or_else): If expression is not an lvalue,
+ check if it is a cast of an lvalue; if so, and if the cast
+ involves POD types with identical size and aligment,
+ rewrite '(type)expr' into '*(type *)&expr' and allow the
+ result as an lvalue.
+
+2005-01-07 Devang Patel <dpatel@apple.com>
+
+ Radar 3943502
+ * parser.c (cp_parser_objc_defs_expression): New.
+ (cp_parser_member_declaration): Handle @defs.
+
+2005-01-06 Robert Bowdidge <bowdidge@apple.com>
+
+ Radar 3943783
+ * class.c: change has_apple_kext_compatibility_attr_p to use
+ BINFO_BASE_BINFO for walking class hierarchy.
+
+2005-01-06 Devang Patel <dpatel@apple.com>
+
+ Radar 3941766
+ * parser.c (cp_parser_objc_class_ivars): Add '}' check.
+
+2005-01-05 Mark Mitchell <mark@codesourcery.com>
+ Matt Austern <austern@apple.com>
+
+ Radar 3934803
+ PR c++/18369
+ * init.c (build_new_1): Handle parenthesized type-ids that name an
+ array type. Tidy.
+
+2004-12-20 Matt Austern <austern@apple.com>
+
+ Radar 3845716
+ PR c++/19044
+ * decl.c (make_rtl_for_nonlocal_decl): Use set_builtin_user_assembler_name
+
+2004-12-10 Ziemowit Laski <zlaski@apple.com>
+
+ Radar 3640156, 3877958
+ * decl.c (builtin_function_1): Do not require subsequent declarations
+ for AltiVec PIM builtins.
+
+2004-12-07 Mike Stump <mrs@apple.com>
+
+ Radar 3603833, 3896176, 3518821.
+ * parser.c (cp_parser_binary_expression): Add support for lines
+ that start with named operators such as and.
+ (cp_parser_cw_identifier): Move reused code from here to
+ cw_get_identifier.
+
+2004-11-17 Mike Stump <mrs@apple.com>
+
+ Radar 3860322
+ g++.dg/asm-block-3.C
+ * parser.c (cp_parser_cw_identifier): Handle C++ keywords like
+ and, or, xor in CW asm blocks.
+
+2004-11-14 Ziemowit Laski <zlaski@apple.com>
+
+ Radar 3877761
+ * parser.c (cp_parser_objc_class_ivars): Allow an optional
+ trailing semicolon, per existing usage.
+
+2004-11-10 Ziemowit Laski <zlaski@apple.com>
+
+ Radar 3761423
+ * typeck.c (finish_class_member_access_expr): Insert call to
+ objc_is_public() to check ObjC ivar access.
+
+2004-11-08 Ziemowit Laski <zlaski@apple.com>
+
+ Radar 3869280
+ * tree.c (lvalue_p_1): Determine lvalue-ness of CONST_DECLs the same
+ way as for VAR_DECLs.
+
+2004-11-03 Ziemowit Laski <zlaski@apple.com>
+
+ Radar 3863563 (fix from mainline)
+ * cp-lang.c (cxx_types_compatible_p): Remove prototype and definition.
+ (LANG_HOOKS_TYPES_COMPATIBLE_P): Move to cp-objcp-common.h.
+ * cp-objcp-common.c (cxx_types_compatible_p): Moved definition here
+ from cp-lang.c.
+ * cp-objcp-common.h (cxx_types_compatible_p): Moved prototype here
+ from cp-lang.c.
+ (LANG_HOOKS_TYPES_COMPATIBLE_P): Moved here from cp-lang.c.
+
+2004-11-01 Ziemowit Laski <zlaski@apple.com>
+
+ Radar 2810013
+ * parser.c (cp_parser_primary_expression): Perform instace variable
+ lookup in conjunction with C++ identifier expression lookup.
+ (cp_parser_postfix_expression): Moved instance variable lookup
+ to cp_parser_primary_expression().
+
+2004-10-21 Ziemowit Laski <zlaski@apple.com>
+
+ Radar 3540965
+ * parser.c (cp_parser_postfix_expression): Do not forget to parse
+ the rhs of a postfix expression when the lhs is an instance variable.
+
+2004-10-18 Robert Bowdidge <bowdidge@apple.com>
+
+ Radar 3843618
+ * gcc/cp/parser.c: Bring the change for PR/17829 over from mainline
+ so that Finder_FE will build again.
+
+2004-10-13 Ziemowit Laski <zlaski@apple.com>
+
+ Radar 3677258
+ * cp-tree.h (struct lang_identifier): Add 'interface_value' field.
+
+2004-09-14 Andrew Pinski <apinski@apple.com>
+
+ Rest of Radar 3753405
+ * cp-tree.h (enum cp_decl_sepcs): Add ds_cw_asm.
+ * decl.c (grokdeclarator): Rename cw_asm_specbit to cw_asm_p to mirror
+ the other specbits.
+ Access specbits for cw_asm.
+ Add "asm" to decl_specs_names.
+ Remove MERGE FIXME comment.
+ * parser.c (cp_parser_decl_specifier_seq, <case RID_ASM>): Mirror the
+ other decl spec bits.
+
+2004-08-22 Andrew Pinski <apinski@apple.com>
+
+ Revert:
+ 2004-08-22 Andrew Pinski <apinski@apple.com>
+ PR c++/14029
+ * typeck.c (build_unary_op): Use &a.b if the foldded lowered
+ expression is not constant.
+
+2004-08-22 Andrew Pinski <apinski@apple.com>
+
+ PR c++/14029
+ * typeck.c (build_unary_op): Use &a.b if the foldded lowered
+ expression is not constant.
+
+2004-08-10 Devang Patel <dpatel@apple.com>
+
+ Remove Symbol Separation.
+ Radar 3555440. Reviewed by Mike Stump.
+ * decl2.c (finish_file): Do not write context.
+
+2004-08-08 Andrew Pinski <apinski@apple.com>
+
+ * cp/lex.c (cxx_init): Remove APPLE LOCAL for setting -gused
+ by default as it is handled in CC1_SPECs now.
+
+2004-08-03 Stan Shebs <shebs@apple.com>
+
+ Support for CodeWarrior-style assembly language blocks and
+ functions. Radar 3368707.
+ * cp-tree.h (cw_asm_cp_build_component_ref): Declare.
+ * decl.c (grokdeclarator): Recognize asm keyword, set flag
+ on function decl if seen.
+ * parser.c (cp_lexer_get_preprocessor_token): Allow @-tokens
+ if doing asm.
+ (cp_parser_primary_expression): Recognize @-tokens in asm,
+ replace with @-identifier (which will become a label) later.
+ (cp_parser_unary_expression): Call asm-specific postfix
+ expression handler.
+ (cp_parser_compound_statement): Handle asm compound statements
+ specially.
+ (cp_parser_statement_seq_opt): Handle statement sequences in
+ asm blocks specially.
+ (cp_parser_simple_declaration): Leave instead of erroring out
+ if apparent asm opcode is seen.
+ (cp_parser_decl_specifier_seq,
+ cp_parser_storage_class_specifier_opt): Accept RID_ASM as a specifier.
+ (cp_parser_asm_definition): Detect asm blocks and handle.
+ (cp_parser_cw_asm_compound_statement,
+ cp_parser_cw_asm_declaration_seq_opt, cp_parser_cw_asm_line_seq_opt,
+ cp_parser_cw_asm_line, cp_parser_cw_asm_statement_seq_opt,
+ cp_parser_cw_asm_statement, cp_parser_cw_asm_operands,
+ cp_parser_cw_asm_operand, cp_parser_cw_asm_postfix_expression,
+ cw_asm_typename_or_reserved): New functions.
+ semantics.c (finish_id_expression): Handle register names
+ and labels in asm blocks specially.
+ * typeck.c (cw_asm_cp_build_component_ref): New function.
+
+2004-08-01 Devang Patel <dpatel@apple.com>
+
+ Re-implement -fwritable-strings support.
+ Radar : 3699482
+
+ * decl.c (cxx_init_decl_processing): Check flag_writable_strings.
+
+2004-08-01 Geoffrey Keating <geoffk@apple.com>
+
+ * decl.c (grokdeclarator): Don't call warn_about_long_double.
+
+2004-06-08 Fariborz Jahanian <fjahanian@apple.com>
+
+ * decl2.c (maybe_emit_vtables, get_guard):
+ Remove all APPLE LOCAL coalescing codes.
+ (import_export_decl): Remove all APPLE LOCAL coalescing codes,
+ except for one call to comdat_linkage.
+
+2004-06-08 Fariborz Jahanian <fjahanian@apple.com>
+
+ * decl2.c (maybe_emit_vtables, import_export_decl, get_guard):
+ Resore various APPLE LOCAL coalescing codes.
+
+2004-06-07 Fariborz Jahanian <fjahanian@apple.com>
+
+ * decl2.c (maybe_emit_vtables, import_export_decl, get_guard):
+ Remove various APPLE LOCAL coalescing codes.
+
+2004-04-02 Ziemowit Laski <zlaski@apple.com>
+
+ Remove APPLE LOCAL AltiVec code whenever possible; merge in
+ AltiVec/VECTOR_TYPE-handling code from mainline.
+
diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in
index 00075b30a9f..6347afc19f7 100644
--- a/gcc/cp/Make-lang.in
+++ b/gcc/cp/Make-lang.in
@@ -70,6 +70,15 @@ g++-cross$(exeext): g++$(exeext)
-rm -f g++-cross$(exeext)
cp g++$(exeext) g++-cross$(exeext)
+# APPLE LOCAL begin order files --ilr
+ifeq ($(ORDER_FILES),yes)
+CC1PLUS_ORDER_FLAGS = `if [ -f $(srcdir)/../order-files/cc1plus.order ]; then \
+ echo -sectorder __TEXT __text $(srcdir)/../order-files/cc1plus.order -e start ; fi`
+else
+CC1PLUS_ORDER_FLAGS =
+endif
+# APPLE LOCAL end order files --ilr
+
# The compiler itself.
# Shared with C front end:
CXX_C_OBJS = attribs.o c-common.o c-format.o c-pragma.o c-semantics.o c-lex.o \
@@ -91,9 +100,12 @@ CXX_OBJS = cp/cp-lang.o stub-objc.o $(CXX_AND_OBJCXX_OBJS)
# Use strict warnings for this front end.
cp-warn = $(STRICT_WARN)
+# APPLE LOCAL begin order files --ilr
cc1plus$(exeext): $(CXX_OBJS) $(BACKEND) $(LIBDEPS)
$(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ \
- $(CXX_OBJS) $(BACKEND) $(LIBS)
+ $(CXX_OBJS) $(BACKEND) $(LIBS) \
+ $(CC1PLUS_ORDER_FLAGS)
+# APPLE LOCAL end order files --ilr
# Special build rules.
$(srcdir)/cp/cfns.h: $(srcdir)/cp/cfns.gperf
@@ -253,16 +265,20 @@ cp/method.o: cp/method.c $(CXX_TREE_H) $(TM_H) toplev.h $(RTL_H) $(EXPR_H) \
$(TM_P_H) $(TARGET_H) gt-cp-method.h
cp/cvt.o: cp/cvt.c $(CXX_TREE_H) $(TM_H) cp/decl.h flags.h toplev.h convert.h
cp/search.o: cp/search.c $(CXX_TREE_H) $(TM_H) flags.h toplev.h $(RTL_H)
+# APPLE LOCAL begin Objective-C++
cp/tree.o: cp/tree.c $(CXX_TREE_H) $(TM_H) flags.h toplev.h $(RTL_H) \
- insn-config.h integrate.h tree-inline.h real.h gt-cp-tree.h $(TARGET_H)
+ insn-config.h integrate.h tree-inline.h real.h gt-cp-tree.h $(TARGET_H) debug.h
+# APPLE LOCAL end Objective-C++
cp/ptree.o: cp/ptree.c $(CXX_TREE_H) $(TM_H)
cp/rtti.o: cp/rtti.c $(CXX_TREE_H) $(TM_H) flags.h toplev.h convert.h
cp/except.o: cp/except.c $(CXX_TREE_H) $(TM_H) flags.h $(RTL_H) except.h toplev.h \
cp/cfns.h $(EXPR_H) libfuncs.h tree-inline.h
cp/expr.o: cp/expr.c $(CXX_TREE_H) $(TM_H) $(RTL_H) flags.h $(EXPR_H) toplev.h \
except.h $(TM_P_H)
-cp/pt.o: cp/pt.c $(CXX_TREE_H) $(TM_H) cp/decl.h \
- toplev.h $(RTL_H) except.h tree-inline.h pointer-set.h gt-cp-pt.h
+# APPLE LOCAL begin Objective-C++
+cp/pt.o: cp/pt.c $(CXX_TREE_H) $(TM_H) cp/decl.h cp/cp-objcp-common.h \
+ toplev.h $(RTL_H) except.h tree-inline.h pointer-set.h gt-cp-pt.h c-common.h
+# APPLE LOCAL end Objective-C++
cp/error.o: cp/error.c $(CXX_TREE_H) $(TM_H) toplev.h $(DIAGNOSTIC_H) \
flags.h real.h $(LANGHOOKS_DEF_H) $(CXX_PRETTY_PRINT_H)
cp/repo.o: cp/repo.c $(CXX_TREE_H) $(TM_H) toplev.h diagnostic.h \
@@ -276,8 +292,10 @@ cp/optimize.o: cp/optimize.c $(CXX_TREE_H) $(TM_H) rtl.h integrate.h insn-config
cp/mangle.o: cp/mangle.c $(CXX_TREE_H) $(TM_H) toplev.h real.h gt-cp-mangle.h \
$(TARGET_H) $(TM_P_H)
+# APPLE LOCAL begin Objective-C++
cp/parser.o: cp/parser.c $(CXX_TREE_H) $(TM_H) diagnostic.h gt-cp-parser.h \
- output.h
+ output.h c-common.h
+# APPLE LOCAL end Objective-C++
cp/cp-gimplify.o: cp/cp-gimplify.c $(CXX_TREE_H) toplev.h c-common.h \
$(TM_H) coretypes.h pointer-set.h
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 4655430a2bd..13bbf4caf52 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -4079,6 +4079,36 @@ enforce_access (tree basetype_path, tree decl)
return true;
}
+/* APPLE LOCAL begin direct-binding-refs 20020224 --turly */
+
+/* Should we *really* call a constructor for the object whose reference type
+ we want? If we have a user conversion function which returns the ref
+ type directly, there's no need to call the object's constructor as we
+ can bind directly (dcl.init.ref.)
+
+ These must be exactly the same types. */
+
+static int really_call_constructor_p (tree, tree, tree);
+static int
+really_call_constructor_p (tree expr, tree convfn, tree totype)
+{
+ /* TEMPORARILY DISABLING THIS "FIX" NOW WE HAVE A SOURCE WORKAROUND. */
+ /* However, we'll leave the code here pending input from the FSF
+ on this issue. */
+
+ if (0 /* && ! NEED_TEMPORARY_P (convfn) Watch out! this macro is undefined */
+ && TREE_CODE (expr) == INDIRECT_REF
+ && TREE_CODE (TREE_TYPE (convfn)) == METHOD_TYPE
+ && TREE_CODE (TREE_TYPE (TREE_TYPE (convfn))) == REFERENCE_TYPE
+ && TREE_CODE (TREE_TYPE (TREE_TYPE (TREE_TYPE (convfn)))) == RECORD_TYPE
+ && TREE_TYPE (TREE_TYPE (TREE_TYPE (convfn))) == totype
+ && TREE_TYPE (expr) == totype)
+ return 0;
+
+ return 1;
+}
+/* APPLE LOCAL end direct-binding-refs 20020224 --turly */
+
/* Check that a callable constructor to initialize a temporary of
TYPE from an EXPR exists. */
@@ -4246,6 +4276,8 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
If the target is a class, that means call a ctor. */
if (IS_AGGR_TYPE (totype)
+ /* APPLE LOCAL direct-binding-refs 20020224 --turly */
+ && really_call_constructor_p (expr, convfn, totype)
&& (inner >= 0 || !lvalue_p (expr)))
{
expr = (build_temp
@@ -4904,7 +4936,11 @@ build_over_call (struct z_candidate *cand, int flags)
mark_used (fn);
- if (DECL_VINDEX (fn) && (flags & LOOKUP_NONVIRTUAL) == 0)
+ /* APPLE LOCAL begin KEXT indirect-virtual-calls --sts */
+ if (DECL_VINDEX (fn)
+ && (flag_apple_kext
+ || (flags & LOOKUP_NONVIRTUAL) == 0))
+ /* APPLE LOCAL end KEXT indirect-virtual-calls --sts */
{
tree t, *p = &TREE_VALUE (converted_args);
tree binfo = lookup_base (TREE_TYPE (TREE_TYPE (*p)),
@@ -4918,6 +4954,31 @@ build_over_call (struct z_candidate *cand, int flags)
t = build_pointer_type (TREE_TYPE (fn));
if (DECL_CONTEXT (fn) && TYPE_JAVA_INTERFACE (DECL_CONTEXT (fn)))
fn = build_java_interface_fn_ref (fn, *p);
+ /* APPLE LOCAL begin KEXT indirect-virtual-calls --sts */
+ /* If this is not really supposed to be a virtual call, find the
+ vtable corresponding to the correct type, and use it. */
+ else if (flags & LOOKUP_NONVIRTUAL) {
+ tree call_site_type = TREE_TYPE (cand->access_path);
+ tree fn_class_type = DECL_CLASS_CONTEXT (fn);
+
+ gcc_assert (call_site_type != NULL &&
+ fn_class_type != NULL &&
+ AGGREGATE_TYPE_P (call_site_type) &&
+ AGGREGATE_TYPE_P (fn_class_type));
+ gcc_assert (lookup_base(TYPE_MAIN_VARIANT (call_site_type),
+ TYPE_MAIN_VARIANT (fn_class_type),
+ ba_any | ba_quiet,
+ NULL) != NULL);
+
+ if (BINFO_N_BASE_BINFOS (TYPE_BINFO (call_site_type)) > 1
+ || CLASSTYPE_VBASECLASSES (call_site_type))
+ error ("indirect virtual calls are invalid for a type that uses multiple or virtual inheritance");
+
+ fn = (build_vfn_ref_using_vtable
+ (BINFO_VTABLE (TYPE_BINFO (call_site_type)),
+ DECL_VINDEX (fn)));
+ }
+ /* APPLE LOCAL end KEXT indirect-virtual-calls --sts */
else
fn = build_vfn_ref (*p, DECL_VINDEX (fn));
TREE_TYPE (fn) = t;
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index ae73f522121..1a3cee35a49 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -35,6 +35,8 @@ Boston, MA 02111-1307, USA. */
#include "toplev.h"
#include "target.h"
#include "convert.h"
+/* APPLE LOCAL KEXT */
+#include "tree-iterator.h"
/* The number of nested classes being processed. If we are not in the
scope of any class, this is zero. */
@@ -214,6 +216,10 @@ int n_compute_conversion_costs = 0;
int n_inner_fields_searched = 0;
#endif
+/* APPLE LOCAL begin Macintosh alignment 2002-5-24 --ff */
+extern int darwin_align_is_first_member_of_class;
+/* APPLE LOCAL end Macintosh alignment 2002-5-24 --ff */
+
/* Convert to or from a base subobject. EXPR is an expression of type
`A' or `A*', an expression of type `B' or `B*' is returned. To
convert A to a base B, CODE is PLUS_EXPR and BINFO is the binfo for
@@ -578,6 +584,12 @@ build_vtbl_ref_1 (tree instance, tree idx)
assemble_external (vtbl);
+ /* APPLE LOCAL begin KEXT double destructor */
+#ifdef ADJUST_VTABLE_INDEX
+ ADJUST_VTABLE_INDEX (idx, vtbl);
+#endif
+ /* APPLE LOCAL end KEXT double destructor */
+
aref = build_array_ref (vtbl, idx);
TREE_CONSTANT (aref) |= TREE_CONSTANT (vtbl) && TREE_CONSTANT (idx);
TREE_INVARIANT (aref) = TREE_CONSTANT (aref);
@@ -615,6 +627,32 @@ build_vfn_ref (tree instance_ptr, tree idx)
return aref;
}
+/* APPLE LOCAL begin KEXT indirect-virtual-calls --sts */
+/* Given a VTBL and an IDX, return an expression for the function
+ pointer located at the indicated index. BASETYPE is the static
+ type of the object containing the vtable. */
+
+tree
+build_vfn_ref_using_vtable (tree vtbl, tree idx)
+{
+ tree aref;
+
+ vtbl = unshare_expr (vtbl);
+ assemble_external (vtbl);
+
+ /* APPLE LOCAL KEXT double destructor */
+#ifdef ADJUST_VTABLE_INDEX
+ ADJUST_VTABLE_INDEX (idx, vtbl);
+#endif
+
+ aref = build_array_ref (vtbl, idx);
+ TREE_CONSTANT (aref) |= TREE_CONSTANT (vtbl) && TREE_CONSTANT (idx);
+ TREE_INVARIANT (aref) = TREE_CONSTANT (aref);
+
+ return aref;
+}
+/* APPLE LOCAL end KEXT indirect-virtual-calls --sts */
+
/* Return the name of the virtual function table (as an IDENTIFIER_NODE)
for the given TYPE. */
@@ -1734,9 +1772,21 @@ layout_vtable_decl (tree binfo, int n)
{
tree atype;
tree vtable;
+ /* APPLE LOCAL begin KEXT terminated-vtables */
+ int n_entries;
+
+ n_entries = n;
+
+ /* Enlarge suggested vtable size by one entry; it will be filled
+ with a zero word. Darwin kernel dynamic-driver loader looks
+ for this value to find vtable ends for patching. */
+ if (flag_apple_kext)
+ n_entries += 1;
+ /* APPLE LOCAL end KEXT terminated-vtables */
atype = build_cplus_array_type (vtable_entry_type,
- build_index_type (size_int (n - 1)));
+ /* APPLE LOCAL KEXT terminated-vtables */
+ build_index_type (size_int (n_entries - 1)));
layout_type (atype);
/* We may have to grow the vtable. */
@@ -3848,9 +3898,18 @@ clone_function_decl (tree fn, int update_method_vec_p)
if (update_method_vec_p)
add_method (DECL_CONTEXT (clone), clone);
}
- clone = build_clone (fn, complete_dtor_identifier);
- if (update_method_vec_p)
- add_method (DECL_CONTEXT (clone), clone);
+
+ /* APPLE LOCAL begin KEXT double destructor */
+ /* Don't use the complete dtor. */
+ if (! flag_apple_kext
+ || ! has_apple_kext_compatibility_attr_p (DECL_CONTEXT (fn)))
+ {
+ clone = build_clone (fn, complete_dtor_identifier);
+ if (update_method_vec_p)
+ add_method (DECL_CONTEXT (clone), clone);
+ }
+ /* APPLE LOCAL end KEXT double destructor */
+
clone = build_clone (fn, base_dtor_identifier);
if (update_method_vec_p)
add_method (DECL_CONTEXT (clone), clone);
@@ -4546,6 +4605,13 @@ layout_class_type (tree t, tree *virtuals_p)
NULL, NULL);
build_base_fields (rli, empty_base_offsets, next_field);
+ /* APPLE LOCAL begin Macintosh alignment 2002-5-24 --ff */
+ /* Turn on this flag until the first real member of the class is
+ laid out. (Enums and such things declared in the class do not
+ count.) */
+ darwin_align_is_first_member_of_class = 1;
+ /* APPLE LOCAL end Macintosh alignment 2002-5-24 --ff */
+
/* Layout the non-static data members. */
for (field = non_static_data_members; field; field = TREE_CHAIN (field))
{
@@ -4664,6 +4730,12 @@ layout_class_type (tree t, tree *virtuals_p)
layout_nonempty_base_or_field (rli, field, NULL_TREE,
empty_base_offsets);
+ /* APPLE LOCAL begin Macintosh alignment 2002-5-24 --ff */
+ /* When we reach here we have laid out the first real member of
+ the class. */
+ darwin_align_is_first_member_of_class = 0;
+ /* APPLE LOCAL end Macintosh alignment 2002-5-24 --ff */
+
/* Remember the location of any empty classes in FIELD. */
if (abi_version_at_least (2))
record_subobject_offsets (TREE_TYPE (field),
@@ -4717,6 +4789,12 @@ layout_class_type (tree t, tree *virtuals_p)
last_field_was_bitfield = DECL_C_BIT_FIELD (field);
}
+ /* APPLE LOCAL begin Macintosh alignment 2002-5-24 --ff */
+ /* Make sure the flag is turned off in cases where there were no
+ real members in the class. */
+ darwin_align_is_first_member_of_class = 0;
+
+ /* APPLE LOCAL end Macintosh alignment 2002-5-24 --ff */
if (abi_version_at_least (2) && !integer_zerop (rli->bitpos))
{
/* Make sure that we are on a byte boundary so that the size of
@@ -7069,6 +7147,19 @@ dfs_accumulate_vtbl_inits (tree binfo,
index = size_binop (MULT_EXPR,
TYPE_SIZE_UNIT (vtable_entry_type),
index);
+ /* APPLE LOCAL begin KEXT double destructor */
+#ifdef VPTR_INITIALIZER_ADJUSTMENT
+ /* Subtract VPTR_INITIALIZER_ADJUSTMENT from INDEX. */
+ if (flag_apple_kext && !ctor_vtbl_p && ! BINFO_PRIMARY_P (binfo)
+ && TREE_CODE (index) == INTEGER_CST
+ && TREE_INT_CST_LOW (index) >= VPTR_INITIALIZER_ADJUSTMENT
+ && TREE_INT_CST_HIGH (index) == 0)
+ index = fold (build (MINUS_EXPR,
+ TREE_TYPE (index), index,
+ size_int (VPTR_INITIALIZER_ADJUSTMENT)));
+#endif
+ /* APPLE LOCAL end KEXT double destructor */
+
vtbl = build2 (PLUS_EXPR, TREE_TYPE (vtbl), vtbl, index);
}
@@ -7715,4 +7806,116 @@ cp_fold_obj_type_ref (tree ref, tree known_type)
return build_address (fndecl);
}
+/* APPLE LOCAL begin KEXT double destructor */
+/* Return whether CLASS or any of its primary ancestors have the
+ "apple_kext_compatibility" attribute, in which case the
+ non-deleting destructor is not emitted. Only single
+ inheritance heirarchies can have this tag. */
+int
+has_apple_kext_compatibility_attr_p (tree class)
+{
+ while (class != NULL)
+ {
+ tree base_binfo;
+
+ if (TREE_CODE (class) == ARRAY_TYPE)
+ {
+ class = TREE_TYPE (class);
+ continue;
+ }
+
+ if (BINFO_N_BASE_BINFOS (TYPE_BINFO (class)) > 1)
+ return 0;
+
+ if (lookup_attribute ("apple_kext_compatibility",
+ TYPE_ATTRIBUTES (class)))
+ return 1;
+
+ /* If there are no more base classes, we're done. */
+ if (BINFO_N_BASE_BINFOS (TYPE_BINFO (class)) < 1)
+ break;
+
+ base_binfo = BINFO_BASE_BINFO (TYPE_BINFO (class), 0);
+ if (base_binfo
+ && ! BINFO_VIRTUAL_P (base_binfo))
+ class = BINFO_TYPE (base_binfo);
+ else
+ break;
+ }
+
+ return 0;
+}
+
+/* Walk through a function body and return true if nothing in there
+ would cause us to generate code. */
+static int
+compound_body_is_empty_p (tree t)
+{
+ while (t && t != error_mark_node)
+ {
+ enum tree_code tc = TREE_CODE (t);
+ if (tc == BIND_EXPR)
+ {
+ if (BIND_EXPR_VARS (t) == 0
+ && compound_body_is_empty_p (BIND_EXPR_BODY (t)))
+ t = TREE_CHAIN (t);
+ else
+ return 0;
+ }
+ else if (tc == STATEMENT_LIST)
+ {
+ tree_stmt_iterator iter;
+
+ for (iter = tsi_start (t); !tsi_end_p (iter); tsi_next (&iter))
+ if (! compound_body_is_empty_p (tsi_stmt (iter)))
+ return 0;
+ return 1;
+ }
+ else
+ return 0;
+ }
+ /* We hit the end of the body function without seeing anything. */
+ return 1;
+}
+
+/* TRUE if we have an operator delete which is empty (i.e., NO CODE!) */
+int
+has_empty_operator_delete_p (tree class)
+{
+ if (! class)
+ return 0;
+
+ if (BINFO_N_BASE_BINFOS (TYPE_BINFO (class)) > 1)
+ return 0;
+
+ if (TYPE_GETS_DELETE (class))
+ {
+ tree f = lookup_fnfields (TYPE_BINFO (class),
+ ansi_opname (DELETE_EXPR), 0);
+
+ if (f == error_mark_node)
+ return 0;
+
+ if (BASELINK_P (f))
+ f = BASELINK_FUNCTIONS (f);
+
+ if (OVL_CURRENT (f))
+ {
+ f = OVL_CURRENT (f);
+
+ /* We've overridden TREE_SIDE_EFFECTS for C++ operator deletes
+ to mean that the function is empty. */
+ if (TREE_SIDE_EFFECTS (f))
+ return 1;
+
+ /* Otherwise, it could be an inline but empty function. */
+ if (DECL_SAVED_TREE (f))
+ return compound_body_is_empty_p (DECL_SAVED_TREE (f));
+ }
+ }
+
+ return 0;
+}
+/* APPLE LOCAL end KEXT double destructor */
+
#include "gt-cp-class.h"
diff --git a/gcc/cp/cp-objcp-common.c b/gcc/cp/cp-objcp-common.c
index d43c159c01f..9605aebb950 100644
--- a/gcc/cp/cp-objcp-common.c
+++ b/gcc/cp/cp-objcp-common.c
@@ -202,3 +202,18 @@ has_c_linkage (tree decl)
{
return DECL_EXTERN_C_P (decl);
}
+
+/* APPLE LOCAL begin kext identify vtables */
+/* Return true if t is a vtable. In kexts (only) these may
+ be overridden by other modules, so we can't do the
+ normal optimizations we do on initialized const objects. */
+int
+cp_vtable_p (tree t)
+{
+ if (TREE_CODE (t) == VAR_DECL
+ && TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE
+ && TREE_TYPE (TREE_TYPE (t)) == vtable_entry_type)
+ return 1;
+ return 0;
+}
+/* APPLE LOCAL end kext identify vtables */
diff --git a/gcc/cp/cp-objcp-common.h b/gcc/cp/cp-objcp-common.h
index 7a2a2343b7c..9623a3abf5e 100644
--- a/gcc/cp/cp-objcp-common.h
+++ b/gcc/cp/cp-objcp-common.h
@@ -22,15 +22,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#ifndef GCC_CP_OBJCP_COMMON
#define GCC_CP_OBJCP_COMMON
-/* In cp/cp-objcp-common.c. */
-
-extern HOST_WIDE_INT cxx_get_alias_set (tree);
-extern bool cxx_warn_unused_global_decl (tree);
-extern tree cp_expr_size (tree);
-extern size_t cp_tree_size (enum tree_code);
-extern bool cp_var_mod_type_p (tree, tree);
-extern void cxx_initialize_diagnostics (struct diagnostic_context *);
-extern int cxx_types_compatible_p (tree, tree);
+/* APPLE LOCAL Objective-C++ */
+/* Function prototypes for cp/cp-objcp-common.c moved to cp/cp-tree.h. */
/* In cp/cp-lang.c and objcp/objcp-lang.c. */
@@ -162,4 +155,9 @@ extern tree objcp_tsubst_copy_and_build (tree, tree, tsubst_flags_t,
#undef LANG_HOOKS_GIMPLIFY_EXPR
#define LANG_HOOKS_GIMPLIFY_EXPR cp_gimplify_expr
+/* APPLE LOCAL begin kext identify vtables */
+#undef LANG_HOOKS_VTABLE_P
+#define LANG_HOOKS_VTABLE_P cp_vtable_p
+/* APPLE LOCAL end kext identify vtables */
+
#endif /* GCC_CP_OBJCP_COMMON */
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index bd5d0eca14d..4cf47a85fa7 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -194,6 +194,9 @@ struct lang_identifier GTY(())
cxx_binding *namespace_bindings;
cxx_binding *bindings;
tree class_template_info;
+ /* APPLE LOCAL begin objc speedup --dpatel */
+ tree interface_value; /* ObjC interface, if any */
+ /* APPLE LOCAL end objc speedup --dpatel */
tree label_value;
};
@@ -522,6 +525,12 @@ enum cp_tree_index
CPTI_KEYED_CLASSES,
+ /* APPLE LOCAL begin KEXT 2.95-ptmf-compatibility --turly */
+ CPTI_DELTA2_IDENTIFIER,
+ CPTI_INDEX_IDENTIFIER,
+ CPTI_PFN_OR_DELTA2_IDENTIFIER,
+ /* APPLE LOCAL end KEXT 2.95-ptmf-compatibility --turly */
+
CPTI_MAX
};
@@ -592,6 +601,12 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
#define deleting_dtor_identifier cp_global_trees[CPTI_DELETING_DTOR_IDENTIFIER]
#define delta_identifier cp_global_trees[CPTI_DELTA_IDENTIFIER]
#define in_charge_identifier cp_global_trees[CPTI_IN_CHARGE_IDENTIFIER]
+ /* APPLE LOCAL begin KEXT 2.95-ptmf-compatibility --turly */
+#define delta2_identifier cp_global_trees[CPTI_DELTA2_IDENTIFIER]
+#define index_identifier cp_global_trees[CPTI_INDEX_IDENTIFIER]
+#define pfn_or_delta2_identifier cp_global_trees[CPTI_PFN_OR_DELTA2_IDENTIFIER]
+ /* APPLE LOCAL end KEXT 2.95-ptmf-compatibility --turly */
+
/* The name of the parameter that contains a pointer to the VTT to use
for this subobject constructor or destructor. */
#define vtt_parm_identifier cp_global_trees[CPTI_VTT_PARM_IDENTIFIER]
@@ -2521,8 +2536,13 @@ struct lang_decl GTY(())
/* Get the POINTER_TYPE to the METHOD_TYPE associated with this
pointer to member function. TYPE_PTRMEMFUNC_P _must_ be true,
before using this macro. */
-#define TYPE_PTRMEMFUNC_FN_TYPE(NODE) \
- (TREE_TYPE (TYPE_FIELDS (NODE)))
+/* APPLE LOCAL begin KEXT 2.95-ptmf-compatibility --turly */
+#define TYPE_PTRMEMFUNC_FN_TYPE(NODE) \
+ *((flag_apple_kext) ? \
+ &(TREE_TYPE (TYPE_FIELDS (TREE_TYPE (TREE_CHAIN ( \
+ TREE_CHAIN (TYPE_FIELDS (NODE))))))) : \
+ &(TREE_TYPE (TYPE_FIELDS (NODE)))) \
+/* APPLE LOCAL end KEXT 2.95-ptmf-compatibility --turly */
/* Returns `A' for a type like `int (A::*)(double)' */
#define TYPE_PTRMEMFUNC_OBJECT_TYPE(NODE) \
@@ -3517,6 +3537,8 @@ typedef enum cp_decl_spec {
ds_typedef,
ds_complex,
ds_thread,
+ /* APPLE LOCAL CW asm blocks. */
+ ds_cw_asm,
ds_last
} cp_decl_spec;
@@ -3723,6 +3745,8 @@ extern void note_name_declared_in_class (tree, tree);
extern tree get_vtbl_decl_for_binfo (tree);
extern tree get_vtt_name (tree);
extern tree get_primary_binfo (tree);
+/* APPLE LOCAL KEXT indirect-virtual-calls --sts */
+extern tree build_vfn_ref_using_vtable (tree, tree);
extern void debug_class (tree);
extern void debug_thunks (tree);
extern tree cp_fold_obj_type_ref (tree, tree);
@@ -4104,6 +4128,8 @@ extern void pop_to_parent_deferring_access_checks (void);
extern void perform_deferred_access_checks (void);
extern void perform_or_defer_access_check (tree, tree);
extern void init_cp_semantics (void);
+/* APPLE LOCAL Objective-C++ */
+extern tree do_poplevel (tree);
extern void add_decl_expr (tree);
extern tree finish_expr_stmt (tree);
extern tree begin_if_stmt (void);
@@ -4370,10 +4396,34 @@ extern tree mangle_ref_init_variable (tree);
/* in dump.c */
extern bool cp_dump_tree (void *, tree);
+/* APPLE LOCAL begin Objective-C */
+/* In cp/cp-objcp-common.c. */
+
+extern HOST_WIDE_INT cxx_get_alias_set (tree);
+extern bool cxx_warn_unused_global_decl (tree);
+extern tree cp_expr_size (tree);
+extern size_t cp_tree_size (enum tree_code);
+extern bool cp_var_mod_type_p (tree, tree);
+extern void cxx_initialize_diagnostics (struct diagnostic_context *);
+extern int cxx_types_compatible_p (tree, tree);
+/* APPLE LOCAL end Objective-C */
+
+/* APPLE LOCAL begin KEXT double destructor */
+extern int has_apple_kext_compatibility_attr_p PARAMS ((tree));
+extern int has_empty_operator_delete_p PARAMS ((tree));
+/* APPLE LOCAL end KEXT double destructor */
+
+/* APPLE LOCAL kext identify vtables */
+extern int cp_vtable_p (tree);
+
/* in cp-simplify.c */
extern int cp_gimplify_expr (tree *, tree *, tree *);
extern void cp_genericize (tree);
+/* APPLE LOCAL begin CW asm blocks */
+extern tree cw_asm_cp_build_component_ref (tree, tree);
+/* APPLE LOCAL end CW asm blocks */
+
/* -- end of C++ */
/* In order for the format checking to accept the C++ frontend
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 48f8d8c55fd..9400a8b4576 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -229,10 +229,17 @@ int function_depth;
with __attribute__((deprecated)). An object declared as
__attribute__((deprecated)) suppresses warnings of uses of other
deprecated items. */
+/* APPLE LOCAL begin "unavailable" attribute (radar 2809697) */
+/* An object declared as __attribute__((unavailable)) suppresses
+ any reports of being declared with unavailable or deprecated
+ items. */
+/* APPLE LOCAL end "unavailable" attribute (radar 2809697) */
enum deprecated_states {
DEPRECATED_NORMAL,
DEPRECATED_SUPPRESS
+ /* APPLE LOCAL "unavailable" attribute (radar 2809697) */
+ , DEPRECATED_UNAVAILABLE_SUPPRESS
};
static enum deprecated_states deprecated_state = DEPRECATED_NORMAL;
@@ -2846,6 +2853,45 @@ initialize_predefined_identifiers (void)
if (pid->ctor_or_dtor_p)
IDENTIFIER_CTOR_OR_DTOR_P (*pid->node) = 1;
}
+ /* APPLE LOCAL begin KEXT 2.95-ptmf-compatibility --turly */
+ if (flag_apple_kext)
+ {
+ /* This is snarfed from the 2.95 cp-tree.h. The mechanism is
+ completely different from gcc3 (see cp-tree.h, and read the
+ comment just above 'enum ptrmemfunc_vbit_where_t'. Sigh.
+
+ A 2.95 pointer-to-function member type looks like:
+
+ struct {
+ short __delta;
+ short __index;
+ union {
+ P __pfn;
+ short __delta2;
+ } __pfn_or_delta2;
+ };
+
+ where P is a POINTER_TYPE to a METHOD_TYPE appropriate for the
+ pointer to member. The fields are used as follows:
+
+ If __INDEX is -1, then the function to call is non-virtual, and
+ is located at the address given by __PFN.
+
+ If __INDEX is zero, then this a NULL pointer-to-member.
+
+ Otherwise, the function to call is virtual. Then, __DELTA2 gives
+ the offset from an instance of the object to the virtual function
+ table, and __INDEX - 1 is the index into the vtable to use to
+ find the function.
+
+ The value to use for the THIS parameter is the address of the
+ object plus __DELTA. */
+
+ delta2_identifier = get_identifier ("__delta2");
+ index_identifier = get_identifier ("__index");
+ pfn_or_delta2_identifier = get_identifier ("__pfn_or_delta2");
+ }
+ /* APPLE LOCAL end KEXT 2.95-ptmf-compatibility --turly */
}
/* Create the predefined scalar types of C,
@@ -2930,6 +2976,11 @@ cxx_init_decl_processing (void)
record_builtin_type (RID_MAX, NULL, string_type_node);
#endif
+ /* APPLE LOCAL begin KEXT 2.95-ptmf-compatibility --turly */
+ if (flag_apple_kext)
+ delta_type_node = short_integer_type_node;
+ else
+ /* APPLE LOCAL end KEXT 2.95-ptmf-compatibility --turly */
delta_type_node = ptrdiff_type_node;
vtable_index_type = ptrdiff_type_node;
@@ -3037,6 +3088,13 @@ cxx_init_decl_processing (void)
/* Show we use EH for cleanups. */
if (flag_exceptions)
using_eh_for_cleanups ();
+
+ /* APPLE LOCAL begin fwritable strings. */
+ /* Maintain consistency. Perhaps we should just complain if they
+ say -fwritable-strings? */
+ if (flag_writable_strings)
+ flag_const_strings = 0;
+ /* APPLE LOCAL end fwritable strings. */
}
/* Generate an initializer for a function naming variable from
@@ -3150,8 +3208,18 @@ builtin_function_1 (const char* name,
/* Warn if a function in the namespace for users
is used without an occasion to consider it declared. */
- if (name[0] != '_' || name[1] != '_')
+ /* APPLE LOCAL begin AltiVec */
+ if ((name[0] != '_' || name[1] != '_')
+#ifdef TARGET_POWERPC
+ /* AltiVec PIM builtins, even though they do not begin with
+ underscores, need not be declared either. */
+ && !(class == BUILT_IN_MD
+ && code >= ALTIVEC_PIM__FIRST
+ && code <= ALTIVEC_PIM__LAST)
+#endif /* TARGET_POWERPC */
+ )
DECL_ANTICIPATED (decl) = 1;
+ /* APPLE LOCAL end AltiVec */
/* Possibly apply some default attributes to this built-in function. */
if (attrs)
@@ -3188,7 +3256,10 @@ builtin_function (const char* name,
{
/* All builtins that don't begin with an '_' should additionally
go in the 'std' namespace. */
- if (name[0] != '_')
+ /* APPLE LOCAL begin alloca not in std */
+ /* Don't use `std' namespace for alloca. */
+ if (name[0] != '_' && strcmp (name, "alloca"))
+ /* APPLE LOCAL end alloca not in std */
{
push_namespace (std_identifier);
builtin_function_1 (name, type, std_node, code, cl, libname, attrs);
@@ -3566,6 +3637,8 @@ start_decl (const cp_declarator *declarator,
tree decl;
tree type, tem;
tree context;
+ /* APPLE LOCAL "unavailable" attribute (radar 2809697) */
+ tree a;
*pushed_scope_p = NULL_TREE;
@@ -3576,10 +3649,34 @@ start_decl (const cp_declarator *declarator,
have_extern_spec = false;
}
- /* An object declared as __attribute__((deprecated)) suppresses
- warnings of uses of other deprecated items. */
+ /* APPLE LOCAL begin "unavailable" attribute (radar 2809697) */
+ /* An object declared as __attribute__((unavailable)) suppresses
+ any reports of being declared with unavailable or deprecated
+ items. An object declared as __attribute__((deprecated))
+ suppresses warnings of uses of other deprecated items. */
+#ifdef A_LESS_INEFFICENT_WAY /* which I really don't want to do! */
if (lookup_attribute ("deprecated", attributes))
deprecated_state = DEPRECATED_SUPPRESS;
+ else if (lookup_attribute ("unavailable", attributes))
+ deprecated_state = DEPRECATED_UNAVAILABLE_SUPPRESS;
+#else /* a more efficient way doing what lookup_attribute would do */
+ for (a = attributes; a; a = TREE_CHAIN (a))
+ {
+ tree name = TREE_PURPOSE (a);
+ if (TREE_CODE (name) == IDENTIFIER_NODE)
+ if (is_attribute_p ("deprecated", name))
+ {
+ deprecated_state = DEPRECATED_SUPPRESS;
+ break;
+ }
+ if (is_attribute_p ("unavailable", name))
+ {
+ deprecated_state = DEPRECATED_UNAVAILABLE_SUPPRESS;
+ break;
+ }
+ }
+#endif
+ /* APPLE LOCAL end "unavailable" attribute (radar 2809697) */
attributes = chainon (attributes, prefix_attributes);
@@ -4610,7 +4707,19 @@ make_rtl_for_nonlocal_decl (tree decl, tree init, const char* asmspec)
&& DECL_IMPLICIT_INSTANTIATION (decl))
defer_p = 1;
- /* If we're not deferring, go ahead and assemble the variable. */
+
+ /* APPLE LOCAL begin static const members 20020110 --turly */
+ /* Static const members which require runtime initialisation should
+ not be placed in readonly memory. Avoid this by temporarily
+ whacking the TREE_READONLY bit. */
+ if (!defer_p && init != NULL_TREE && TREE_READONLY (decl) && toplev)
+ {
+ TREE_READONLY (decl) = 0;
+ rest_of_decl_compilation (decl, toplev, at_eof);
+ TREE_READONLY (decl) = 1;
+ }
+ else
+ /* APPLE LOCAL end static const members 20020110 --turly */
if (!defer_p)
rest_of_decl_compilation (decl, toplev, at_eof);
}
@@ -5994,6 +6103,37 @@ build_ptrmemfunc_type (tree type)
unqualified_variant
= build_ptrmemfunc_type (TYPE_MAIN_VARIANT (type));
+ /* APPLE LOCAL begin KEXT 2.95-ptmf-compatibility --turly */
+ if (flag_apple_kext)
+ {
+ tree u = make_aggr_type (UNION_TYPE);
+ SET_IS_AGGR_TYPE (u, 0);
+ xref_basetypes (u, NULL_TREE);
+ fields = build_decl (FIELD_DECL, delta2_identifier, delta_type_node);
+ TREE_CHAIN (fields)
+ = build_decl (FIELD_DECL, pfn_identifier, type);
+ finish_builtin_struct (u, "__ptrmemfunc_type", fields, ptr_type_node);
+ TYPE_NAME (u) = NULL_TREE;
+
+ t = make_aggr_type (RECORD_TYPE);
+ xref_basetypes (t, NULL_TREE);
+
+ /* Let the front-end know this is a pointer to member function... */
+ TYPE_PTRMEMFUNC_FLAG (t) = 1;
+ /* ... and not really an aggregate. */
+ SET_IS_AGGR_TYPE (t, 0);
+
+ fields = build_decl (FIELD_DECL, pfn_or_delta2_identifier, u);
+ TREE_CHAIN (fields) =
+ build_decl (FIELD_DECL, index_identifier, delta_type_node);
+ TREE_CHAIN (TREE_CHAIN (fields)) =
+ build_decl (FIELD_DECL, delta_identifier, delta_type_node);
+ finish_builtin_struct (t, "__ptrmemfunc_type", fields, ptr_type_node);
+ }
+ else
+ {
+ /* APPLE LOCAL end KEXT 2.95-ptmf-compatibility --turly */
+
t = make_aggr_type (RECORD_TYPE);
xref_basetypes (t, NULL_TREE);
@@ -6010,6 +6150,8 @@ build_ptrmemfunc_type (tree type)
fields = field;
finish_builtin_struct (t, "__ptrmemfunc_type", fields, ptr_type_node);
+ /* APPLE LOCAL KEXT 2.95-ptmf-compatibility --turly */
+ }
/* Zap out the name so that the back-end will give us the debugging
information for this anonymous RECORD_TYPE. */
@@ -6491,6 +6633,8 @@ grokdeclarator (const cp_declarator *declarator,
cp_decl_spec ds;
cp_storage_class storage_class;
bool unsigned_p, signed_p, short_p, long_p, thread_p;
+ /* APPLE LOCAL CW asm blocks */
+ bool cw_asm_p;
bool type_was_error_mark_node = false;
signed_p = declspecs->specs[(int)ds_signed];
@@ -6498,6 +6642,8 @@ grokdeclarator (const cp_declarator *declarator,
short_p = declspecs->specs[(int)ds_short];
long_p = declspecs->specs[(int)ds_long];
thread_p = declspecs->specs[(int)ds_thread];
+ /* APPLE LOCAL CW asm blocks */
+ cw_asm_p = declspecs->specs[(int)ds_cw_asm];
if (decl_context == FUNCDEF)
funcdef_flag = 1, decl_context = NORMAL;
@@ -6696,6 +6842,19 @@ grokdeclarator (const cp_declarator *declarator,
type = NULL_TREE;
type_was_error_mark_node = true;
}
+
+ /* APPLE LOCAL begin unavailable attribute (radar 2809697) --bowdidge */
+ /* If the entire declaration is itself tagged as unavailable then
+ suppress reports of unavailable/deprecated items. If the
+ entire declaration is tagged as only deprecated we still
+ report unavailable uses. */
+ if (type && TREE_DEPRECATED (type) && TREE_UNAVAILABLE (type))
+ {
+ if (deprecated_state != DEPRECATED_UNAVAILABLE_SUPPRESS)
+ warn_deprecated_use (type);
+ }
+ else
+ /* APPLE LOCAL end unavailable attribute (radar 2809697) --bowdidge */
/* If the entire declaration is itself tagged as deprecated then
suppress reports of deprecated items. */
if (type && TREE_DEPRECATED (type)
@@ -6752,6 +6911,8 @@ grokdeclarator (const cp_declarator *declarator,
"typedef",
"__complex",
"__thread"
+ /* APPLE LOCAL CW asm blocks. */
+ , "asm"
};
error ("duplicate %qs", decl_spec_names[(int)ds]);
}
@@ -8199,6 +8360,21 @@ grokdeclarator (const cp_declarator *declarator,
else if (storage_class == sc_static)
DECL_THIS_STATIC (decl) = 1;
+ /* APPLE LOCAL begin CW asm blocks */
+ if (cw_asm_p)
+ {
+ /* Record that this is a decl of a CW-style asm function. */
+ if (flag_cw_asm_blocks)
+ {
+ DECL_CW_ASM_FUNCTION (decl) = 1;
+ DECL_CW_ASM_NORETURN (decl) = 0;
+ DECL_CW_ASM_FRAME_SIZE (decl) = -2;
+ }
+ else
+ error ("asm functions not enabled, use `-fasm-blocks'");
+ }
+ /* APPLE LOCAL end CW asm blocks */
+
/* Record constancy and volatility. There's no need to do this
when processing a template; we'll do this for the instantiated
declaration based on the type of DECL. */
@@ -10173,6 +10349,17 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
DECL_CONTEXT (cdtor_label) = current_function_decl;
}
+ /* APPLE LOCAL begin CW asm blocks */
+ /* If this was a function declared as an assembly function, change
+ the state to expect to see C++ decls, possibly followed by assembly
+ code. */
+ if (DECL_CW_ASM_FUNCTION (current_function_decl))
+ {
+ cw_asm_state = cw_asm_decls;
+ cw_asm_in_decl = 0;
+ }
+ /* APPLE LOCAL end CW asm blocks */
+
start_fname_decls ();
store_parm_decls (current_function_parms);
@@ -10938,6 +11125,25 @@ cxx_maybe_build_cleanup (tree decl)
tree rval;
bool has_vbases = (TREE_CODE (type) == RECORD_TYPE
&& CLASSTYPE_VBASECLASSES (type));
+ /* APPLE LOCAL begin KEXT double destructor */
+ special_function_kind dtor = sfk_complete_destructor;
+ if (flag_apple_kext
+ && has_apple_kext_compatibility_attr_p (type))
+ {
+ /* If we have a trivial operator delete (), we can go ahead and
+ just use the deleting destructor, sfk_deleting_destructor. */
+
+ if (! has_empty_operator_delete_p (type) || pedantic)
+ {
+ cp_warning_at ("'%D' is an instance of a class which does "
+ "not allow global or stack-based objects; it "
+ "does not have an empty `operator delete', and "
+ "so it will ** NOT ** be destructed.", decl);
+ return NULL_TREE;
+ }
+ dtor = sfk_deleting_destructor;
+ }
+ /* APPLE LOCAL end KEXT double destructor */
if (TREE_CODE (type) == ARRAY_TYPE)
rval = decl;
@@ -10952,7 +11158,8 @@ cxx_maybe_build_cleanup (tree decl)
flags |= LOOKUP_NONVIRTUAL;
rval = build_delete (TREE_TYPE (rval), rval,
- sfk_complete_destructor, flags, 0);
+ /* APPLE LOCAL KEXT double destructor */
+ dtor, flags, 0);
return rval;
}
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index c7b04150e8f..0330c912659 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -2069,6 +2069,14 @@ start_objects (int method_type, int initp)
DECL_GLOBAL_DTOR_P (current_function_decl) = 1;
DECL_LANG_SPECIFIC (current_function_decl)->decl_flags.u2sel = 1;
+ /* APPLE LOCAL begin static structors in __StaticInit section */
+#ifdef STATIC_INIT_SECTION
+ if ( ! flag_apple_kext)
+ DECL_SECTION_NAME (current_function_decl) =
+ build_string (strlen (STATIC_INIT_SECTION), STATIC_INIT_SECTION);
+#endif
+ /* APPLE LOCAL end static structors in __StaticInit section */
+
body = begin_compound_stmt (BCS_FN_BODY);
/* We cannot allow these functions to be elided, even if they do not
@@ -2175,6 +2183,14 @@ start_static_storage_duration_function (unsigned count)
TREE_PUBLIC (ssdf_decl) = 0;
DECL_ARTIFICIAL (ssdf_decl) = 1;
+ /* APPLE LOCAL begin static structors in __StaticInit section */
+#ifdef STATIC_INIT_SECTION
+ if ( ! flag_apple_kext)
+ DECL_SECTION_NAME (ssdf_decl) = build_string (strlen (STATIC_INIT_SECTION),
+ STATIC_INIT_SECTION);
+#endif
+ /* APPLE LOCAL end static structors in __StaticInit section */
+
/* Put this function in the list of functions to be called from the
static constructors and destructors. */
if (!ssdf_decls)
@@ -2569,6 +2585,17 @@ generate_ctor_or_dtor_function (bool constructor_p, int priority,
global constructors and destructors. */
body = NULL_TREE;
+ /* APPLE LOCAL begin Objective-C++ */
+ /* For Objective-C++, we may need to initialize metadata found in this module.
+ This must be done _before_ any other static initializations. */
+ if (c_dialect_objc () && (priority == DEFAULT_INIT_PRIORITY)
+ && constructor_p && objc_static_init_needed_p ())
+ {
+ body = start_objects (function_key, priority);
+ static_ctors = objc_generate_static_init_call (static_ctors);
+ }
+ /* APPLE LOCAL end Objective-C++ */
+
/* Call the static storage duration function with appropriate
arguments. */
if (ssdf_decls)
@@ -2943,6 +2970,22 @@ cp_finish_file (void)
back end. */
if (DECL_NOT_REALLY_EXTERN (decl) && decl_needed_p (decl))
DECL_EXTERNAL (decl) = 0;
+ /* APPLE LOCAL begin write used class statics 20020226 --turly */
+#ifdef MACHOPIC_VAR_REFERRED_TO_P
+ else
+ if (TREE_USED (decl) && DECL_INITIAL (decl) != 0
+ && DECL_INITIAL (decl) != error_mark_node
+ && TREE_CODE (DECL_INITIAL (decl)) != CONSTRUCTOR
+ && DECL_EXTERNAL (decl)
+ && MACHOPIC_VAR_REFERRED_TO_P (IDENTIFIER_POINTER (
+ DECL_ASSEMBLER_NAME (decl))))
+ {
+ /* Force a local copy of this decl to be written. */
+ DECL_EXTERNAL (decl) = 0;
+ TREE_PUBLIC (decl) = 0;
+ }
+#endif
+ /* APPLE LOCAL end write used class statics 20020226 --turly */
}
if (pending_statics
&& wrapup_global_declarations (&VARRAY_TREE (pending_statics, 0),
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 4ad5e62c4ac..ebac6d77df4 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -2837,6 +2837,16 @@ build_delete (tree type, tree addr, special_function_kind auto_delete,
build_op_delete_call (DELETE_EXPR, addr, cxx_sizeof_nowarn (type),
/*global_p=*/false, NULL_TREE);
}
+ /* APPLE LOCAL begin KEXT double destructor --matt 20020501 */
+ /* If we're compiling a class in kext compatibility mode we
+ don't have a non-deleting destructor, so we unconditionally
+ generate a reference to the deleting variety. */
+ if (flag_apple_kext && has_apple_kext_compatibility_attr_p (type))
+ {
+ gcc_assert (auto_delete != sfk_base_destructor);
+ auto_delete = sfk_deleting_destructor;
+ }
+ /* APPLE LOCAL end KEXT double destructor --matt 20020501 */
expr = build_dtor_call (build_indirect_ref (addr, NULL),
auto_delete, flags);
diff --git a/gcc/cp/lang-specs.h b/gcc/cp/lang-specs.h
index 9adda3d5edd..74f6e7d8171 100644
--- a/gcc/cp/lang-specs.h
+++ b/gcc/cp/lang-specs.h
@@ -47,6 +47,8 @@ Boston, MA 02111-1307, USA. */
CPLUSPLUS_CPP_SPEC, 0, 0},
{"@c++",
"%{E|M|MM:cc1plus -E %(cpp_options) %2 %(cpp_debug_options)}\
+ "/* APPLE LOCAL prohibit -arch with -E and -S */"\
+ %{E|S:%{@:%e-E and -S are not allowed with multiple -arch flags}}\
%{!E:%{!M:%{!MM:\
%{save-temps|no-integrated-cpp:cc1plus -E\
%(cpp_options) %2 -o %{save-temps:%b.ii} %{!save-temps:%g.ii} \n}\
diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c
index 6074fef9ea1..97dcb87afed 100644
--- a/gcc/cp/lex.c
+++ b/gcc/cp/lex.c
@@ -175,6 +175,8 @@ struct resword
_true_. */
#define D_EXT 0x01 /* GCC extension */
#define D_ASM 0x02 /* in C99, but has a switch to turn it off */
+/* APPLE LOCAL Objective-C++ */
+#define D_OBJC 0x08 /* Objective C++ only */
CONSTRAINT(ridbits_fit, RID_LAST_MODIFIER < sizeof(unsigned long) * CHAR_BIT);
@@ -203,6 +205,8 @@ static const struct resword reswords[] =
{ "__inline__", RID_INLINE, 0 },
{ "__label__", RID_LABEL, 0 },
{ "__null", RID_NULL, 0 },
+ /* APPLE LOCAL private extern */
+ { "__private_extern__", RID_PRIVATE_EXTERN, 0 },
{ "__real", RID_REALPART, 0 },
{ "__real__", RID_REALPART, 0 },
{ "__restrict", RID_RESTRICT, 0 },
@@ -279,6 +283,33 @@ static const struct resword reswords[] =
{ "wchar_t", RID_WCHAR, 0 },
{ "while", RID_WHILE, 0 },
+ /* APPLE LOCAL begin Objective-C++ */
+ /* The remaining keywords are specific to Objective-C++. NB:
+ All of them will remain _disabled_, since they are context-
+ sensitive. */
+
+ /* These ObjC keywords are recognized only immediately after
+ an '@'. NB: The following C++ keywords double as
+ ObjC keywords in this context: RID_CLASS, RID_PRIVATE,
+ RID_PROTECTED, RID_PUBLIC, RID_THROW, RID_TRY and RID_CATCH. */
+ { "compatibility_alias", RID_AT_ALIAS, D_OBJC },
+ { "defs", RID_AT_DEFS, D_OBJC },
+ { "encode", RID_AT_ENCODE, D_OBJC },
+ { "end", RID_AT_END, D_OBJC },
+ { "implementation", RID_AT_IMPLEMENTATION, D_OBJC },
+ { "interface", RID_AT_INTERFACE, D_OBJC },
+ { "protocol", RID_AT_PROTOCOL, D_OBJC },
+ { "selector", RID_AT_SELECTOR, D_OBJC },
+ { "finally", RID_AT_FINALLY, D_OBJC },
+ { "synchronized", RID_AT_SYNCHRONIZED, D_OBJC },
+ /* These are recognized only in protocol-qualifier context. */
+ { "bycopy", RID_BYCOPY, D_OBJC },
+ { "byref", RID_BYREF, D_OBJC },
+ { "in", RID_IN, D_OBJC },
+ { "inout", RID_INOUT, D_OBJC },
+ { "oneway", RID_ONEWAY, D_OBJC },
+ { "out", RID_OUT, D_OBJC },
+ /* APPLE LOCAL end Objective-C++ */
};
void
@@ -287,6 +318,8 @@ init_reswords (void)
unsigned int i;
tree id;
int mask = ((flag_no_asm ? D_ASM : 0)
+ /* APPLE LOCAL Objective-C++ */
+ | D_OBJC
| (flag_no_gnu_keywords ? D_EXT : 0));
ridpointers = ggc_calloc ((int) RID_MAX, sizeof (tree));
@@ -298,6 +331,25 @@ init_reswords (void)
if (! (reswords[i].disable & mask))
C_IS_RESERVED_WORD (id) = 1;
}
+
+ /* APPLE LOCAL begin private extern Radar 2872481 --ilr */
+ /* For C++ there is always a -D__private_extern__=extern on the
+ command line. However, if -fpreprocessed was specified then
+ macros are not expanded so the -D is meaningless. But this
+ replacement is required for C++. There for we have to "pretend"
+ that '__private_extern__' is 'extern' and we can do this simply by
+ making the rid code for '__private_extern__' be the same as for
+ extern. Note, we probably could always do this here since
+ '__private_extern__' is always to be treated like 'extern' for
+ c++. But we'll be conservative and only do it when -fpreprocessed
+ is specified and depend on the macro substitution in all other
+ cases. */
+ if (flag_preprocessed)
+ {
+ id = get_identifier ("__private_extern__");
+ C_RID_CODE (id) = RID_EXTERN;
+ }
+ /* APPLE LOCAL end private extern Radar 2872481 --ilr */
}
static void
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index eb9f8f075a2..14dced860aa 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -1367,15 +1367,19 @@ write_identifier (const char *identifier)
Currently, allocating constructors are never used.
- We also need to provide mangled names for the maybe-in-charge
- constructor, so we treat it here too. mangle_decl_string will
- append *INTERNAL* to that, to make sure we never emit it. */
+ APPLE LOCAL decloning
+ Deleted comment. */
static void
write_special_name_constructor (const tree ctor)
{
if (DECL_BASE_CONSTRUCTOR_P (ctor))
write_string ("C2");
+ /* APPLE LOCAL begin decloning */
+ /* This is the old-style "[unified]" constructor. */
+ else if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (ctor))
+ write_string ("C4");
+ /* APPLE LOCAL end decloning */
else
{
gcc_assert (DECL_COMPLETE_CONSTRUCTOR_P (ctor)
@@ -1406,6 +1410,11 @@ write_special_name_destructor (const tree dtor)
write_string ("D0");
else if (DECL_BASE_DESTRUCTOR_P (dtor))
write_string ("D2");
+ /* APPLE LOCAL begin decloning */
+ else if (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (dtor))
+ /* This is the old-style "[unified]" destructor. */
+ write_string ("D4");
+ /* APPLE LOCAL end decloning */
else
{
gcc_assert (DECL_COMPLETE_DESTRUCTOR_P (dtor)
diff --git a/gcc/cp/optimize.c b/gcc/cp/optimize.c
index 7ccfaffbf0d..26193fc39e8 100644
--- a/gcc/cp/optimize.c
+++ b/gcc/cp/optimize.c
@@ -46,6 +46,10 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
/* Prototypes. */
static void update_cloned_parm (tree, tree);
+/* APPLE LOCAL begin structor thunks */
+static int maybe_alias_body (tree fn, tree clone);
+static int maybe_thunk_body (tree fn);
+/* APPLE LOCAL end structor thunks */
/* CLONED_PARM is a copy of CLONE, generated for a cloned constructor
or destructor. Update it to ensure that the source-position for
@@ -70,6 +74,165 @@ update_cloned_parm (tree parm, tree cloned_parm)
DECL_SOURCE_LOCATION (cloned_parm) = DECL_SOURCE_LOCATION (parm);
}
+/* APPLE LOCAL begin structor thunks */
+/* FN is a constructor or destructor, and there are FUNCTION_DECLs cloned from it nearby.
+ If the clone and the original funciton have identical parameter lists,
+ it is a fully-degenerate (does absolutely nothing) thunk.
+ Make the clone an alias for the original function label. */
+static int
+maybe_alias_body (tree fn ATTRIBUTE_UNUSED, tree clone ATTRIBUTE_UNUSED)
+{
+ extern FILE *asm_out_file ATTRIBUTE_UNUSED;
+
+#ifdef ASM_MAYBE_ALIAS_BODY
+ ASM_MAYBE_ALIAS_BODY (asm_out_file, fn, clone);
+#endif
+ return 0;
+}
+
+/* FN is a constructor or destructor, and there are FUNCTION_DECLs
+ cloned from it nearby. Instead of cloning this body, leave it
+ alone and create tiny one-call bodies for the cloned
+ FUNCTION_DECLs. These clones are sibcall candidates, and their
+ resulting code will be very thunk-esque. */
+static int
+maybe_thunk_body (tree fn)
+{
+ tree call, clone, expr_stmt, fn_parm, fn_parm_typelist, last_arg, start;
+ int parmno, vtt_parmno;
+
+ if (flag_apple_kext || flag_clone_structors)
+ return 0;
+
+ /* If we've already seen this structor, avoid re-processing it. */
+ if (TREE_ASM_WRITTEN (fn))
+ return 1;
+
+ /* If function accepts variable arguments, give up. */
+ last_arg = tree_last (TYPE_ARG_TYPES (TREE_TYPE (fn)));
+ if ( ! VOID_TYPE_P (TREE_VALUE (last_arg)))
+ return 0;
+
+ /* If constructor expects vector (AltiVec) arguments, give up. */
+ for (fn_parm = DECL_ARGUMENTS( fn); fn_parm; fn_parm = TREE_CHAIN (fn_parm))
+ if (TREE_CODE (fn_parm) == VECTOR_TYPE)
+ return 0;
+
+ /* If we don't see a clone, nothing to do. */
+ clone = TREE_CHAIN (fn);
+ if (!clone || ! DECL_CLONED_FUNCTION_P (clone))
+ return 0;
+
+ /* This is only a win if there are two or more clones. */
+ if ( ! TREE_CHAIN (clone))
+ return 0;
+
+ /* Only thunk-ify non-trivial structors. */
+ if (DECL_ESTIMATED_INSNS (fn) < 5)
+ return 0;
+
+ /* If we got this far, we've decided to turn the clones into thunks. */
+
+ /* We're going to generate code for fn, so it is no longer "abstract." */
+ /* APPLE LOCAL begin fix -gused debug info (radar 3271957 3262497) */
+ /* Leave 'abstract' bit set for unified constructs and destructors when
+ -gused is used. */
+ if (!(flag_debug_only_used_symbols
+ && DECL_DESTRUCTOR_P (fn)
+ && DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fn))
+ && !(flag_debug_only_used_symbols
+ && DECL_CONSTRUCTOR_P (fn)
+ && DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (fn))
+ )
+ DECL_ABSTRACT (fn) = 0;
+ /* APPLE LOCAL end */
+
+ /* Find the vtt_parm, if present. */
+ for (vtt_parmno = -1, parmno = 0, fn_parm = DECL_ARGUMENTS (fn);
+ fn_parm;
+ ++parmno, fn_parm = TREE_CHAIN (fn_parm))
+ {
+ if (DECL_ARTIFICIAL (fn_parm) && DECL_NAME (fn_parm) == vtt_parm_identifier)
+ {
+ vtt_parmno = parmno; /* Compensate for removed in_charge parameter. */
+ break;
+ }
+ }
+
+ /* We know that any clones immediately follow FN in the TYPE_METHODS
+ list. */
+ for (clone = start = TREE_CHAIN (fn);
+ clone && DECL_CLONED_FUNCTION_P (clone);
+ clone = TREE_CHAIN (clone))
+ {
+ tree clone_parm, parmlist;
+
+ /* If the clone and original parmlists are identical, turn the clone into an alias. */
+ if (maybe_alias_body (fn, clone))
+ continue;
+
+ /* If we've already generated a body for this clone, avoid duplicating it.
+ (Is it possible for a clone-list to grow after we first see it?) */
+ if (DECL_SAVED_TREE (clone) || TREE_ASM_WRITTEN (clone))
+ continue;
+
+ /* Start processing the function. */
+ push_to_top_level ();
+ start_preparsed_function (clone, NULL_TREE, SF_PRE_PARSED);
+
+ /* Walk parameter lists together, creating parameter list for call to original function. */
+ for (parmno = 0,
+ parmlist = NULL,
+ fn_parm = DECL_ARGUMENTS (fn),
+ fn_parm_typelist = TYPE_ARG_TYPES (TREE_TYPE (fn)),
+ clone_parm = DECL_ARGUMENTS (clone);
+ fn_parm;
+ ++parmno,
+ fn_parm = TREE_CHAIN (fn_parm))
+ {
+ if (parmno == vtt_parmno && ! DECL_HAS_VTT_PARM_P (clone))
+ {
+ tree typed_null_pointer_node = copy_node (null_pointer_node);
+ gcc_assert (fn_parm_typelist);
+ /* Clobber actual parameter with formal parameter type. */
+ TREE_TYPE (typed_null_pointer_node) = TREE_VALUE (fn_parm_typelist);
+ parmlist = tree_cons (NULL, typed_null_pointer_node, parmlist);
+ }
+ else if (parmno == 1 && DECL_HAS_IN_CHARGE_PARM_P (fn))
+ {
+ tree in_charge = copy_node (in_charge_arg_for_name (DECL_NAME (clone)));
+ parmlist = tree_cons (NULL, in_charge, parmlist);
+ }
+ /* Map other parameters to their equivalents in the cloned
+ function. */
+ else
+ {
+ gcc_assert (clone_parm);
+ DECL_ABSTRACT_ORIGIN (clone_parm) = NULL;
+ parmlist = tree_cons (NULL, clone_parm, parmlist);
+ clone_parm = TREE_CHAIN (clone_parm);
+ }
+ if (fn_parm_typelist)
+ fn_parm_typelist = TREE_CHAIN (fn_parm_typelist);
+ }
+
+ /* We built this list backwards; fix now. */
+ parmlist = nreverse (parmlist);
+ mark_used (fn);
+ call = build_function_call (fn, parmlist);
+ expr_stmt = build_stmt (EXPR_STMT, call);
+ add_stmt (expr_stmt);
+
+ /* Now, expand this function into RTL, if appropriate. */
+ finish_function (0);
+ DECL_ABSTRACT_ORIGIN (clone) = NULL;
+ expand_body (clone);
+ pop_from_top_level ();
+ }
+ return 1;
+}
+/* APPLE LOCAL end structor thunks */
+
/* FN is a function that has a complete body. Clone the body as
necessary. Returns nonzero if there's no longer any need to
process the main body. */
@@ -94,8 +257,8 @@ maybe_clone_body (tree fn)
{
tree parm;
tree clone_parm;
- int parmno;
- splay_tree decl_map;
+ /* APPLE LOCAL structor thunks */
+ /* Delete some local variables. */
/* Update CLONE's source position information to match FN's. */
DECL_SOURCE_LOCATION (clone) = DECL_SOURCE_LOCATION (fn);
@@ -130,6 +293,28 @@ maybe_clone_body (tree fn)
parm = TREE_CHAIN (parm), clone_parm = TREE_CHAIN (clone_parm))
/* Update this parameter. */
update_cloned_parm (parm, clone_parm);
+ /* APPLE LOCAL structor thunks */
+ }
+
+ /* APPLE LOCAL begin structor thunks */
+ /* If we decide to turn clones into thunks, they will branch to fn.
+ Must have original function available to call. */
+ if (maybe_thunk_body (fn))
+ return 0;
+ /* APPLE LOCAL end structor thunks */
+
+ /* APPLE LOCAL begin structor thunks */
+ /* We know that any clones immediately follow FN in the TYPE_METHODS
+ list. */
+ for (clone = TREE_CHAIN (fn);
+ clone && DECL_CLONED_FUNCTION_P (clone);
+ clone = TREE_CHAIN (clone))
+ {
+ tree parm;
+ tree clone_parm;
+ int parmno;
+ splay_tree decl_map;
+ /* APPLE LOCAL end structor thunks */
/* Start processing the function. */
start_preparsed_function (clone, NULL_TREE, SF_PRE_PARSED);
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index f38f6fbc78f..abdec2e4c88 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -36,6 +36,10 @@
#include "toplev.h"
#include "output.h"
#include "target.h"
+/* APPLE LOCAL Objective-C++ */
+#include "c-common.h"
+/* APPLE LOCAL pascal strings */
+#include "../../libcpp/internal.h"
/* The lexer. */
@@ -405,6 +409,25 @@ cp_lexer_get_preprocessor_token (cp_lexer *lexer ATTRIBUTE_UNUSED ,
mapped to `const'. */
token->value = ridpointers[token->keyword];
}
+ /* APPLE LOCAL begin Objective-C++ */
+ /* Handle Objective-C++ keywords. */
+ else if (token->type == CPP_AT_NAME)
+ {
+ token->type = CPP_KEYWORD;
+ switch (C_RID_CODE (token->value))
+ {
+ /* Map 'class' to '@class', 'private' to '@private', etc. */
+ case RID_CLASS: token->keyword = RID_AT_CLASS; break;
+ case RID_PRIVATE: token->keyword = RID_AT_PRIVATE; break;
+ case RID_PROTECTED: token->keyword = RID_AT_PROTECTED; break;
+ case RID_PUBLIC: token->keyword = RID_AT_PUBLIC; break;
+ case RID_THROW: token->keyword = RID_AT_THROW; break;
+ case RID_TRY: token->keyword = RID_AT_TRY; break;
+ case RID_CATCH: token->keyword = RID_AT_CATCH; break;
+ default: token->keyword = C_RID_CODE (token->value);
+ }
+ }
+ /* APPLE LOCAL end Objective-C++ */
else
token->keyword = RID_MAX;
}
@@ -1638,6 +1661,81 @@ static bool cp_parser_extension_opt
static void cp_parser_label_declaration
(cp_parser *);
+/* APPLE LOCAL begin Objective-C++ */
+/* Objective-C++ Productions */
+
+static tree cp_parser_objc_message_receiver
+ (cp_parser *);
+static tree cp_parser_objc_message_args
+ (cp_parser *);
+static tree cp_parser_objc_message_expression
+ (cp_parser *);
+static tree cp_parser_objc_encode_expression
+ (cp_parser *);
+static tree cp_parser_objc_defs_expression
+ (cp_parser *);
+static tree cp_parser_objc_protocol_expression
+ (cp_parser *);
+static tree cp_parser_objc_selector_expression
+ (cp_parser *);
+static tree cp_parser_objc_expression
+ (cp_parser *);
+static void cp_parser_objc_visibility_spec
+ (cp_parser *);
+static void cp_parser_objc_method_type
+ (cp_parser *);
+static tree cp_parser_objc_protocol_qualifiers
+ (cp_parser *);
+static tree cp_parser_objc_typename
+ (cp_parser *);
+static bool cp_parser_objc_selector_p
+ (enum cpp_ttype);
+static tree cp_parser_objc_selector
+ (cp_parser *);
+static tree cp_parser_objc_method_keyword_params
+ (cp_parser *);
+static tree cp_parser_objc_method_tail_params_opt
+ (cp_parser *);
+static void cp_parser_objc_interstitial_code
+ (cp_parser *);
+static tree cp_parser_objc_method_signature
+ (cp_parser *);
+static void cp_parser_objc_method_prototype_list
+ (cp_parser *);
+static void cp_parser_objc_method_definition_list
+ (cp_parser *);
+static void cp_parser_objc_class_ivars
+ (cp_parser *);
+static tree cp_parser_objc_identifier_list
+ (cp_parser *);
+static void cp_parser_objc_alias_declaration
+ (cp_parser *);
+static void cp_parser_objc_class_declaration
+ (cp_parser *);
+static void cp_parser_objc_protocol_declaration
+ (cp_parser *);
+static tree cp_parser_objc_protocol_refs_opt
+ (cp_parser *);
+static void cp_parser_objc_superclass_or_category
+ (cp_parser *, tree *, tree *);
+static void cp_parser_objc_class_interface
+ (cp_parser *);
+static void cp_parser_objc_class_implementation
+ (cp_parser *);
+static void cp_parser_objc_end_implementation
+ (cp_parser *);
+static void cp_parser_objc_declaration
+ (cp_parser *);
+static tree cp_parser_objc_try_catch_finally_statement
+ (cp_parser *);
+static tree cp_parser_objc_synchronized_statement
+ (cp_parser *);
+static tree cp_parser_objc_throw_statement
+ (cp_parser *);
+static tree cp_parser_objc_statement
+ (cp_parser *);
+/* APPLE LOCAL end Objective-C++ */
+
/* Utility Routines */
static tree cp_parser_lookup_name
@@ -1763,6 +1861,33 @@ static bool cp_parser_is_keyword
static tree cp_parser_make_typename_type
(cp_parser *, tree, tree);
+/* APPLE LOCAL begin CW asm blocks */
+static tree cp_parser_cw_asm_compound_statement
+ (cp_parser *);
+static void cp_parser_cw_asm_declaration_seq_opt
+ (cp_parser *);
+static void cp_parser_cw_asm_line_seq_opt
+ (cp_parser *);
+static void cp_parser_cw_asm_line
+ (cp_parser *);
+static void cp_parser_cw_asm_statement_seq_opt
+ (cp_parser *);
+static void cp_parser_cw_asm_statement
+ (cp_parser *);
+static tree cp_parser_cw_asm_operands
+ (cp_parser *);
+static tree cp_parser_cw_asm_operand
+ (cp_parser *);
+static tree cp_parser_cw_asm_postfix_expression
+ (cp_parser *, bool);
+static tree cp_parser_cw_identifier_or_number
+ (cp_parser* parser);
+static tree cw_build_identifier_string
+ (cp_parser* parser, const char* str);
+static tree cp_parser_cw_asm_relative_branch
+ (cp_parser *parser);
+/* APPLE LOCAL end CW asm blocks */
+
/* Returns nonzero if we are parsing tentatively. */
static inline bool
@@ -2474,6 +2599,8 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok)
{
tree value;
bool wide = false;
+ /* APPLE LOCAL pascal strings */
+ bool pascal_p = false;
size_t count;
struct obstack str_ob;
cpp_string str, istr, *strs;
@@ -2498,6 +2625,11 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok)
count = 1;
if (tok->type == CPP_WSTRING)
wide = true;
+ /* APPLE LOCAL begin pascal strings */
+ else if (CPP_OPTION (parse_in, pascal_strings)
+ && str.text[1] == '\\' && str.text[2] == 'p')
+ pascal_p = true;
+ /* APPLE LOCAL end pascal strings */
strs = &str;
}
@@ -2514,6 +2646,11 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok)
str.len = TREE_STRING_LENGTH (tok->value);
if (tok->type == CPP_WSTRING)
wide = true;
+ /* APPLE LOCAL begin pascal strings */
+ else if (count == 1 && CPP_OPTION (parse_in, pascal_strings)
+ && str.text[1] == '\\' && str.text[2] == 'p')
+ pascal_p = true;
+ /* APPLE LOCAL end pascal strings */
obstack_grow (&str_ob, &str, sizeof (cpp_string));
@@ -2530,13 +2667,23 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok)
wide = false;
}
+ /* APPLE LOCAL begin pascal strings */
+ if (wide)
+ pascal_p = false;
+ /* APPLE LOCAL end pascal strings */
+
if ((translate ? cpp_interpret_string : cpp_interpret_string_notranslate)
- (parse_in, strs, count, &istr, wide))
+ /* APPLE LOCAL pascal strings */
+ (parse_in, strs, count, &istr, wide, pascal_p))
{
value = build_string (istr.len, (char *)istr.text);
free ((void *)istr.text);
- TREE_TYPE (value) = wide ? wchar_array_type_node : char_array_type_node;
+ /* APPLE LOCAL begin pascal strings */
+ TREE_TYPE (value) = wide ? wchar_array_type_node
+ : pascal_p ? pascal_string_type_node
+ : char_array_type_node;
+ /* APPLE LOCAL end pascal strings */
value = fix_string_type (value);
}
else
@@ -2637,6 +2784,13 @@ cp_parser_translation_unit (cp_parser* parser)
( compound-statement )
__builtin_va_arg ( assignment-expression , type-id )
+ APPLE LOCAL begin Objective-C++
+ Objective-C++ Extension:
+
+ primary-expression:
+ objc-expression
+ APPLE LOCAL end Objective-C++
+
literal:
__null
@@ -2658,6 +2812,8 @@ cp_parser_primary_expression (cp_parser *parser,
tree *qualifying_class)
{
cp_token *token;
+ /* APPLE LOCAL CW asm blocks */
+ int atsignhack = 0;
/* Assume the primary expression is not an id-expression. */
*idk = CP_ID_KIND_NONE;
@@ -2863,11 +3019,27 @@ cp_parser_primary_expression (cp_parser *parser,
case RID_OFFSETOF:
return cp_parser_builtin_offsetof (parser);
+ /* APPLE LOCAL begin Objective-C++ */
+ /* Objective-C++ expressions. */
+ case RID_AT_ENCODE:
+ case RID_AT_PROTOCOL:
+ case RID_AT_SELECTOR:
+ return cp_parser_objc_expression (parser);
+ /* APPLE LOCAL end Objective-C++ */
+
default:
cp_parser_error (parser, "expected primary-expression");
return error_mark_node;
}
+ /* APPLE LOCAL begin CW asm blocks */
+ case CPP_ATSIGN:
+ /* Recognize @-labels and handle them specially later. */
+ cp_lexer_consume_token (parser->lexer);
+ atsignhack = 1;
+ token = cp_lexer_peek_token (parser->lexer);
+ /* APPLE LOCAL end CW asm blocks */
+
/* An id-expression can start with either an identifier, a
`::' as the beginning of a qualified-id, or the "operator"
keyword. */
@@ -2888,6 +3060,11 @@ cp_parser_primary_expression (cp_parser *parser,
/*check_dependency_p=*/true,
/*template_p=*/NULL,
/*declarator_p=*/false);
+ /* APPLE LOCAL begin CW asm blocks */
+ /* Replace the id with an id prefixed with @. */
+ if (atsignhack)
+ id_expression = prepend_char_identifier (id_expression, '@');
+ /* APPLE LOCAL end CW asm blocks */
if (id_expression == error_mark_node)
return error_mark_node;
/* If we have a template-id, then no further lookup is
@@ -2911,6 +3088,13 @@ cp_parser_primary_expression (cp_parser *parser,
been issued. */
if (ambiguous_p)
return error_mark_node;
+
+ /* APPLE LOCAL begin Objective-C++ */
+ /* In Objective-C++, an instance variable (ivar) may be preferred
+ to whatever cp_parser_lookup_name() found. */
+ decl = objc_lookup_ivar (decl, id_expression);
+ /* APPLE LOCAL end Objective-C++ */
+
/* If name lookup gives us a SCOPE_REF, then the
qualifying scope was dependent. Just propagate the
name. */
@@ -2961,6 +3145,13 @@ cp_parser_primary_expression (cp_parser *parser,
/* Anything else is an error. */
default:
+ /* APPLE LOCAL begin Objective-C++ */
+ /* ...unless we have an Objective-C++ message or string literal, that is. */
+ if (c_dialect_objc ()
+ && (token->type == CPP_OPEN_SQUARE || token->type == CPP_OBJC_STRING))
+ return cp_parser_objc_expression (parser);
+ /* APPLE LOCAL end Objective-C++ */
+
cp_parser_error (parser, "expected primary-expression");
return error_mark_node;
}
@@ -3319,6 +3510,22 @@ cp_parser_unqualified_id (cp_parser* parser,
return build_nt (BIT_NOT_EXPR, TREE_TYPE (type_decl));
}
+ /* APPLE LOCAL begin CW asm blocks C++ */
+ case CPP_NUMBER:
+ {
+ if (flag_cw_asm_blocks
+ && TREE_CODE (token->value) == INTEGER_CST)
+ {
+ char buf[60];
+
+ sprintf (buf, HOST_WIDE_INT_PRINT_UNSIGNED, tree_low_cst (token->value, 0));
+ cp_lexer_consume_token (parser->lexer);
+ return get_identifier (buf);
+ }
+ goto bad;
+ }
+ /* APPLE LOCAL end CW asm blocks C++ */
+
case CPP_KEYWORD:
if (token->keyword == RID_OPERATOR)
{
@@ -3347,6 +3554,8 @@ cp_parser_unqualified_id (cp_parser* parser,
/* Fall through. */
default:
+ /* APPLE LOCAL CW asm blocks C++ */
+ bad:
cp_parser_error (parser, "expected unqualified-id");
return error_mark_node;
}
@@ -3961,7 +4170,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p)
{
/* Warn the user that a compound literal is not
allowed in standard C++. */
- if (pedantic)
+ /* APPLE LOCAL Altivec initializers 3068233 */
+ if (pedantic && TREE_CODE (type) != VECTOR_TYPE)
pedwarn ("ISO C++ forbids compound-literals");
/* Form the representation of the compound-literal. */
postfix_expression
@@ -4645,8 +4855,13 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p)
switch (keyword)
{
- case RID_ALIGNOF:
+ /* APPLE LOCAL begin CW asm blocks */
case RID_SIZEOF:
+ if (cw_asm_block)
+ break;
+
+ case RID_ALIGNOF:
+ /* APPLE LOCAL end CW asm blocks */
{
tree operand;
enum tree_code op;
@@ -4800,6 +5015,14 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p)
return expression;
}
+ /* APPLE LOCAL begin CW asm blocks */
+ /* Postfix expressions in CW asm are more restricted and handled
+ quite differently, so diverge from the usual expression
+ precedence sequence here. */
+ if (cw_asm_block)
+ return cp_parser_cw_asm_postfix_expression (parser, address_p);
+ /* APPLE LOCAL end CW asm blocks */
+
return cp_parser_postfix_expression (parser, address_p, cast_p);
}
@@ -5394,6 +5617,14 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p)
token = cp_lexer_peek_token (parser->lexer);
new_prec = TOKEN_PRECEDENCE (token);
+ /* APPLE LOCAL begin CW asm blocks */
+ if (flag_cw_asm_blocks && cw_asm_block)
+ {
+ if ((token->flags & BOL) != 0)
+ new_prec = PREC_NOT_OPERATOR;
+ }
+ /* APPLE LOCAL end CW asm blocks */
+
/* Popping an entry off the stack means we completed a subexpression:
- either we found a token which is not an operator (`>' where it is not
an operator, or prec == PREC_NOT_OPERATOR), in which case popping
@@ -5424,6 +5655,15 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p)
cases such as 3 + 4 + 5 or 3 * 4 + 5. */
token = cp_lexer_peek_token (parser->lexer);
lookahead_prec = TOKEN_PRECEDENCE (token);
+
+ /* APPLE LOCAL begin CW asm blocks */
+ if (flag_cw_asm_blocks && cw_asm_block)
+ {
+ if ((token->flags & BOL) != 0)
+ lookahead_prec = PREC_NOT_OPERATOR;
+ }
+ /* APPLE LOCAL end CW asm blocks */
+
if (lookahead_prec > new_prec)
{
/* ... and prepare to parse the RHS of the new, higher priority
@@ -5454,6 +5694,15 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p)
lhs = sp->lhs;
}
+ /* APPLE LOCAL begin CW asm blocks */
+ if (cw_asm_block && TREE_CODE (rhs) == COMPOUND_EXPR)
+ {
+ gcc_assert (TREE_CODE (TREE_OPERAND (rhs, 1)) == IDENTIFIER_NODE);
+ lhs = build_x_binary_op (tree_type, lhs, TREE_OPERAND (rhs, 0), &overloaded_p);
+ lhs = cw_asm_build_register_offset (lhs, TREE_OPERAND (rhs, 1));
+ return lhs;
+ }
+ /* APPLE LOCAL end CW asm blocks */
overloaded_p = false;
lhs = build_x_binary_op (tree_type, lhs, rhs, &overloaded_p);
@@ -5925,6 +6174,17 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr)
statement = cp_parser_jump_statement (parser);
break;
+ /* APPLE LOCAL begin Objective-C++ */
+ /* Objective-C++ exception-handling constructs. */
+ case RID_AT_TRY:
+ case RID_AT_CATCH:
+ case RID_AT_FINALLY:
+ case RID_AT_SYNCHRONIZED:
+ case RID_AT_THROW:
+ statement = cp_parser_objc_statement (parser);
+ break;
+ /* APPLE LOCAL end Objective-C++ */
+
case RID_TRY:
statement = cp_parser_try_block (parser);
break;
@@ -6122,6 +6382,23 @@ cp_parser_compound_statement (cp_parser *parser, tree in_statement_expr,
return error_mark_node;
/* Begin the compound-statement. */
compound_stmt = begin_compound_stmt (in_try ? BCS_TRY_BLOCK : 0);
+ /* APPLE LOCAL begin CW asm blocks */
+ /* Maybe this is the body of an asm function, which has asm lines
+ following the decls. */
+ if (cw_asm_state >= cw_asm_decls)
+ {
+ cw_asm_in_decl = 1;
+ cp_parser_cw_asm_declaration_seq_opt (parser);
+ cw_asm_in_decl = 0;
+ cw_asm_state = cw_asm_asm;
+ cw_asm_block = 1;
+ clear_cw_asm_labels ();
+ cp_parser_cw_asm_line_seq_opt (parser);
+ cw_asm_state = cw_asm_none;
+ cw_asm_block = 0;
+ }
+ else
+ /* APPLE LOCAL end CW asm blocks */
/* Parse an (optional) statement-seq. */
cp_parser_statement_seq_opt (parser, in_statement_expr);
/* Finish the compound-statement. */
@@ -6132,6 +6409,16 @@ cp_parser_compound_statement (cp_parser *parser, tree in_statement_expr,
return compound_stmt;
}
+/* APPLE LOCAL begin CW asm blocks */
+static bool
+cp_lexer_cw_bol (cp_lexer* lexer)
+{
+ cp_token *token = cp_lexer_peek_token (lexer);
+
+ return (token->flags & BOL) != 0;
+}
+/* APPLE LOCAL end CW asm blocks */
+
/* Parse an (optional) statement-seq.
statement-seq:
@@ -6151,6 +6438,14 @@ cp_parser_statement_seq_opt (cp_parser* parser, tree in_statement_expr)
/* Parse the statement. */
cp_parser_statement (parser, in_statement_expr);
+
+ /* APPLE LOCAL begin CW asm blocks */
+ if (flag_cw_asm_blocks
+ && cw_asm_state >= cw_asm_decls
+ && (cp_lexer_cw_bol (parser->lexer)
+ || cp_lexer_next_token_is (parser->lexer, CPP_NAME)))
+ break;
+ /* APPLE LOCAL end CW asm blocks */
}
}
@@ -6826,6 +7121,11 @@ cp_parser_declaration (cp_parser* parser)
/* An unnamed namespace definition. */
|| token2.type == CPP_OPEN_BRACE))
cp_parser_namespace_definition (parser);
+ /* APPLE LOCAL begin Objective-C++ */
+ /* Objective-C++ declaration/definition. */
+ else if (c_dialect_objc () && OBJC_IS_AT_KEYWORD (token1.keyword))
+ cp_parser_objc_declaration (parser);
+ /* APPLE LOCAL end Objective-C++ */
/* We must have either a block declaration or a function
definition. */
else
@@ -6965,6 +7265,13 @@ cp_parser_simple_declaration (cp_parser* parser,
if (!function_definition_allowed_p
&& !decl_specifiers.any_specifiers_p)
{
+ /* APPLE LOCAL begin CW asm blocks */
+ /* We might have seen an asm opcode, and it's time to switch to
+ asm instruction handling. */
+ if (flag_cw_asm_blocks && cw_asm_state >= cw_asm_decls)
+ return;
+ /* APPLE LOCAL end CW asm blocks */
+
cp_parser_error (parser, "expected declaration");
goto done;
}
@@ -7079,6 +7386,11 @@ cp_parser_simple_declaration (cp_parser* parser,
/* Consume the `;'. */
cp_parser_require (parser, CPP_SEMICOLON, "`;'");
+ /* APPLE LOCAL begin CW asm blocks */
+ if (flag_cw_asm_blocks)
+ cw_asm_in_decl = 0;
+ /* APPLE LOCAL end CW asm blocks */
+
done:
pop_deferring_access_checks ();
}
@@ -7234,6 +7546,15 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
++decl_specs->specs[(int) ds_thread];
break;
+ /* APPLE LOCAL begin CW asm blocks */
+ /* If we ever get here, we must be in CW asm mode. */
+ case RID_ASM:
+ /* Consume the token. */
+ cp_lexer_consume_token (parser->lexer);
+ ++decl_specs->specs[(int) ds_cw_asm];
+ break;
+ /* APPLE LOCAL end CW asm blocks */
+
default:
/* We did not yet find a decl-specifier yet. */
found_decl_spec = false;
@@ -7355,6 +7676,10 @@ cp_parser_storage_class_specifier_opt (cp_parser* parser)
case RID_EXTERN:
case RID_MUTABLE:
case RID_THREAD:
+ /* APPLE LOCAL begin CW asm blocks */
+ /* If we ever get here, we must be in CW asm mode. */
+ case RID_ASM:
+ /* APPLE LOCAL end CW asm blocks */
/* Consume the token. */
return cp_lexer_consume_token (parser->lexer)->value;
@@ -9562,7 +9887,28 @@ cp_parser_simple_type_specifier (cp_parser* parser,
followed by a "<". That usually indicates that the user thought
that the type was a template. */
if (type && type != error_mark_node)
- cp_parser_check_for_invalid_template_id (parser, TREE_TYPE (type));
+ /* APPLE LOCAL begin Objective-C++ */
+ {
+ /* As a last-ditch effort, see if TYPE is an Objective-C type.
+ If it is, then the '<'...'>' enclose protocol names rather than
+ template arguments, and so everything is fine. */
+ if (c_dialect_objc ()
+ && (objc_is_id (type) || objc_is_class_name (type)))
+ {
+ tree protos = cp_parser_objc_protocol_refs_opt (parser);
+ tree qual_type = objc_get_protocol_qualified_type (type, protos);
+
+ /* Clobber the "unqualified" type previously entered into
+ DECL_SPECS with the new, improved protocol-qualifed version. */
+ if (decl_specs)
+ decl_specs->type = qual_type;
+
+ return qual_type;
+ }
+
+ cp_parser_check_for_invalid_template_id (parser, TREE_TYPE (type));
+ }
+ /* APPLE LOCAL end Objective-C++ */
return type;
}
@@ -9608,6 +9954,19 @@ cp_parser_type_name (cp_parser* parser)
/* Look up the type-name. */
type_decl = cp_parser_lookup_name_simple (parser, identifier);
+
+ /* APPLE LOCAL begin Objective-C++ */
+ if (TREE_CODE (type_decl) != TYPE_DECL
+ && (objc_is_id (identifier) || objc_is_class_name (identifier)))
+ {
+ /* See if this is an Objective-C type. */
+ tree protos = cp_parser_objc_protocol_refs_opt (parser);
+ tree type = objc_get_protocol_qualified_type (identifier, protos);
+ if (type)
+ type_decl = TYPE_NAME (type);
+ }
+ /* APPLE LOCAL end Objective-C++ */
+
/* Issue an error if we did not find a type-name. */
if (TREE_CODE (type_decl) != TYPE_DECL)
{
@@ -10326,6 +10685,8 @@ cp_parser_using_directive (cp_parser* parser)
asm-definition:
asm ( string-literal ) ;
+ APPLE LOCAL CW asm blocks
+ asm { asm-line [opt] }
GNU Extension:
@@ -10349,6 +10710,27 @@ cp_parser_asm_definition (cp_parser* parser)
bool volatile_p = false;
bool extended_p = false;
+ /* APPLE LOCAL begin CW asm blocks */
+ cp_token *nextup;
+ /* Detect when a leading `asm' is actually a spec of an asm function
+ rather than an asm statement or block. */
+ if (flag_cw_asm_blocks)
+ {
+ nextup = cp_lexer_peek_nth_token (parser->lexer, 2);
+ if (!((nextup->type == CPP_OPEN_PAREN)
+ || (nextup->keyword == RID_VOLATILE
+ && cp_lexer_peek_nth_token (parser->lexer, 3)->type == CPP_OPEN_PAREN)
+ || (nextup->type == CPP_OPEN_BRACE)))
+ {
+ /* An asm function - we'll treat the `asm' as if it were a
+ storage class spec, which will eventually affect function
+ body parsing. */
+ cp_parser_simple_declaration (parser, true);
+ return;
+ }
+ }
+ /* APPLE LOCAL end CW asm blocks */
+
/* Look for the `asm' keyword. */
cp_parser_require_keyword (parser, RID_ASM, "`asm'");
/* See if the next token is `volatile'. */
@@ -10360,6 +10742,21 @@ cp_parser_asm_definition (cp_parser* parser)
/* Consume the token. */
cp_lexer_consume_token (parser->lexer);
}
+ /* APPLE LOCAL begin CW asm blocks */
+ /* A CW-style asm block is introduced by an open brace. */
+ if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
+ {
+ if (flag_cw_asm_blocks)
+ {
+ cp_parser_cw_asm_compound_statement (parser);
+ }
+ else
+ {
+ error ("asm blocks not enabled, use `-fasm-blocks'");
+ }
+ return;
+ }
+ /* APPLE LOCAL end CW asm blocks */
/* Look for the opening `('. */
if (!cp_parser_require (parser, CPP_OPEN_PAREN, "`('"))
return;
@@ -11693,7 +12090,11 @@ cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error)
/* Peek at the next token. */
if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN)
- || cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
+ /* APPLE LOCAL begin Objective-C++ */
+ || cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS)
+ || cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)
+ || cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
+ /* APPLE LOCAL end Objective-C++ */
/* The parameter-declaration-list is complete. */
break;
else if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
@@ -13027,6 +13428,24 @@ cp_parser_member_declaration (cp_parser* parser)
return;
}
+ /* APPLE LOCAL begin Objective-C++ */
+ /* Check for @defs. */
+ if (cp_lexer_next_token_is_keyword (parser->lexer, RID_AT_DEFS))
+ {
+ tree ivar, member;
+ tree ivar_chains = cp_parser_objc_defs_expression (parser);
+ ivar = ivar_chains;
+ while (ivar)
+ {
+ member = ivar;
+ ivar = TREE_CHAIN (member);
+ TREE_CHAIN (member) = NULL_TREE;
+ finish_member_declaration (member);
+ }
+ return;
+ }
+ /* APPLE LOCAL end Objective-C++ */
+
/* Parse the decl-specifier-seq. */
cp_parser_decl_specifier_seq (parser,
CP_PARSER_FLAGS_OPTIONAL,
@@ -15991,6 +16410,1820 @@ cp_parser_allow_gnu_extensions_p (cp_parser* parser)
return parser->allow_gnu_extensions_p;
}
+/* APPLE LOCAL begin CW asm blocks */
+
+/* This is the section of CW-asm-specific parsing functions. */
+
+static tree
+cp_parser_cw_asm_compound_statement (cp_parser *parser)
+{
+ tree compound_stmt;
+
+ cw_asm_state = cw_asm_asm;
+ cw_asm_block = 1;
+ cw_asm_at_bol = 1;
+ clear_cw_asm_labels ();
+ if (!cp_parser_require (parser, CPP_OPEN_BRACE, "`{'"))
+ return error_mark_node;
+ /* Begin the compound-statement. */
+ compound_stmt = begin_compound_stmt (/*has_no_scope=*/false);
+ /* Parse an (optional) statement-seq. */
+ cp_parser_cw_asm_line_seq_opt (parser);
+ /* Finish the compound-statement. */
+ finish_compound_stmt (compound_stmt);
+ /* Consume the `}'. */
+ cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'");
+ /* We're done with the block of asm. */
+ cw_asm_block = 0;
+ cw_asm_state = cw_asm_none;
+ return compound_stmt;
+}
+
+static void
+cp_parser_cw_asm_declaration_seq_opt (cp_parser* parser)
+{
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
+
+ if (token->type == CPP_NAME
+ && !cw_asm_typename_or_reserved (token->value))
+ return;
+
+ /* Scan declarations until there aren't any more. */
+ while (true)
+ {
+ /* If we're looking at a `}', then we've run out of statements. */
+ if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE)
+ || cp_lexer_next_token_is (parser->lexer, CPP_EOF))
+ break;
+
+ /* Parse a declaration. */
+ cp_parser_simple_declaration (parser, false);
+
+ /* CPP_PRAGMA is a #pragma inside a function body, which
+ constitutes a declaration all its own. */
+ if (token->type == CPP_PRAGMA)
+ cp_lexer_handle_pragma (parser->lexer);
+
+ if (cw_asm_state >= cw_asm_decls
+ && (cp_lexer_cw_bol (parser->lexer)
+ || cp_lexer_next_token_is (parser->lexer, CPP_NAME)))
+ break;
+ }
+}
+
+/* Parse an (optional) line-seq.
+
+ line-seq:
+ line
+ line-seq [opt] line */
+
+static void
+cp_parser_cw_asm_line_seq_opt (cp_parser* parser)
+{
+ /* Scan lines of asm until there aren't any more. */
+ while (true)
+ {
+ /* If we're looking at a `}', then we've run out of lines. */
+ if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE)
+ || cp_lexer_next_token_is (parser->lexer, CPP_EOF))
+ break;
+
+ /* Parse the line. */
+ cp_parser_cw_asm_line (parser);
+ }
+}
+
+static void
+cp_parser_cw_asm_line (cp_parser* parser)
+{
+ cp_parser_cw_asm_statement_seq_opt (parser);
+}
+
+static void
+cp_parser_cw_asm_statement_seq_opt (cp_parser* parser)
+{
+ /* Scan statements until there aren't any more. */
+ while (true)
+ {
+ if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE)
+ || cp_lexer_next_token_is (parser->lexer, CPP_EOF))
+ break;
+
+ /* Semicolons divide up individual statements. */
+ if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
+ cp_lexer_consume_token (parser->lexer);
+
+ /* Parse a single statement. */
+ cp_parser_cw_asm_statement (parser);
+
+ /* We parse at most, one line. */
+ if (cp_lexer_cw_bol (parser->lexer))
+ break;
+
+ if (!(cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE)
+ || cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)))
+ {
+ cp_parser_error (parser, "expected `;' or `}' or end-of-line");
+ }
+ }
+}
+
+/* Build an identifier comprising the string passed and the
+ next token. */
+
+static tree
+cw_build_identifier_string (cp_parser* parser, const char* str)
+{
+ char *buf;
+ int len;
+ tree id;
+
+ id = cp_parser_cw_identifier_or_number (parser);
+ len = strlen (str);
+ buf = (char *) alloca (IDENTIFIER_LENGTH (id) + len + 1);
+ memcpy (buf, str, len);
+ memcpy (buf+len, IDENTIFIER_POINTER (id), IDENTIFIER_LENGTH (id));
+ buf[IDENTIFIER_LENGTH (id) + len] = 0;
+ return get_identifier (buf);
+}
+
+/* Parse a CW asm identifier. Returns an IDENTIFIER_NODE representing
+ the identifier. The CW asm identifieriers include [.+-] as part of
+ the identifier. */
+
+static tree
+cp_parser_cw_identifier (cp_parser* parser)
+{
+ cp_token *token;
+ tree t;
+ const char *str = "";
+
+ /* We have to accept certain keywords. */
+ token = cp_lexer_peek_token (parser->lexer);
+ if (token->flags & NAMED_OP)
+ {
+ const char *s = 0;
+ switch (token->type) {
+ case CPP_AND_AND: s="and"; break;
+ case CPP_AND_EQ: s="and_eq"; break;
+ case CPP_AND: s="bitand"; break;
+ case CPP_OR: s="bitor"; break;
+ case CPP_COMPL: s="compl"; break;
+ case CPP_NOT: s="not"; break;
+ case CPP_NOT_EQ: s="not_eq"; break;
+ case CPP_OR_OR: s="or"; break;
+ case CPP_OR_EQ: s="or_eq"; break;
+ case CPP_XOR: s="xor"; break;
+ case CPP_XOR_EQ: s="xor_eq"; break;
+ default: break;
+ }
+
+ /* The above list is the entire list of named operators. We
+ can't fail to translate the name. See operator_array in
+ libcpp/init.c. */
+ gcc_assert (s != 0);
+ cp_lexer_consume_token (parser->lexer);
+ t = get_identifier (s);
+ }
+ else
+ if (token->type == CPP_DOT)
+ {
+ /* .align */
+ cp_lexer_consume_token (parser->lexer);
+ t = cw_build_identifier_string (parser, ".");
+ }
+ else
+ t = cp_parser_identifier (parser);
+
+ if (t == error_mark_node)
+ return t;
+
+ token = cp_lexer_peek_token (parser->lexer);
+
+ switch (token->type)
+ {
+ case CPP_DOT:
+ str = ".";
+ break;
+ case CPP_PLUS:
+ str = "+";
+ break;
+ case CPP_MINUS:
+ str = "-";
+ break;
+ case CPP_PLUS_PLUS:
+ str = "++";
+ break;
+ case CPP_MINUS_MINUS:
+ str = "--";
+ break;
+ default:
+ return t;
+ }
+
+ /* If there was whitespace between the identifier and the [.+-]
+ character, then that character can't be part of the
+ identifier. */
+ if (token->flags & PREV_WHITE)
+ return t;
+
+ cp_lexer_consume_token (parser->lexer);
+
+ return cw_get_identifier (t, str);
+}
+
+static tree
+cp_parser_cw_identifier_or_number (cp_parser* parser)
+{
+ cp_token *token;
+
+ token = cp_lexer_peek_token (parser->lexer);
+ if (token->type == CPP_NUMBER
+ && TREE_CODE (token->value) == INTEGER_CST)
+ {
+ char buf[60];
+
+ sprintf (buf, HOST_WIDE_INT_PRINT_UNSIGNED, tree_low_cst (token->value, 0));
+ cp_lexer_consume_token (parser->lexer);
+ return get_identifier (buf);
+ }
+
+ return cp_parser_identifier (parser);
+}
+
+static void
+cp_parser_cw_asm_statement (cp_parser* parser)
+{
+ tree aname, scspec, anothername, operands;
+
+ /* Keep sucking labels from the front of the statement until a
+ non-label is seen. */
+ while (true)
+ {
+ if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)
+ || cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE)
+ || cp_lexer_next_token_is (parser->lexer, CPP_EOF))
+ break;
+
+ if (cp_lexer_next_token_is (parser->lexer, CPP_PRAGMA))
+ {
+ cp_lexer_handle_pragma (parser->lexer);
+ }
+ else if (cp_lexer_next_token_is (parser->lexer, CPP_ATSIGN))
+ {
+ cp_lexer_consume_token (parser->lexer);
+ aname = cp_parser_cw_identifier_or_number (parser);
+ /* Optional ':' after a label. */
+ if (cp_lexer_next_token_is (parser->lexer, CPP_COLON))
+ cp_lexer_consume_token (parser->lexer);
+ cw_asm_label (aname, 1);
+ }
+ else
+ {
+ aname = cp_parser_cw_identifier (parser);
+ if (cp_lexer_next_token_is (parser->lexer, CPP_COLON))
+ {
+ cp_lexer_consume_token (parser->lexer);
+ cw_asm_label (aname, 0);
+ }
+ else
+ {
+ scspec = cp_parser_storage_class_specifier_opt (parser);
+ if (scspec)
+ {
+ anothername = cp_parser_cw_asm_operand (parser);
+ cw_asm_entry (aname, scspec, anothername);
+ }
+ else
+ {
+ cw_asm_in_operands = 1;
+ operands = cp_parser_cw_asm_operands (parser);
+ cw_asm_stmt (aname, operands, input_line);
+ }
+ break;
+ }
+ }
+
+ if (cp_lexer_cw_bol (parser->lexer))
+ break;
+ }
+}
+
+tree
+cp_parser_cw_asm_operands (cp_parser *parser)
+{
+ tree operands = NULL_TREE, operand;
+
+ while (true)
+ {
+ /* If we're looking at the end of the line, then we've run out of operands. */
+ if (cp_lexer_cw_bol (parser->lexer)
+ || cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)
+ || cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE)
+ || cp_lexer_next_token_is (parser->lexer, CPP_EOF))
+ break;
+
+ operand = cp_parser_cw_asm_operand (parser);
+
+ if (operand)
+ {
+ operands = chainon (operands, build_tree_list (NULL_TREE, operand));
+ if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+ cp_lexer_consume_token (parser->lexer);
+ }
+ else
+ {
+ return error_mark_node;
+ }
+ }
+
+ return operands;
+}
+
+tree
+cp_parser_cw_asm_operand (cp_parser *parser)
+{
+ tree operand;
+
+ /* Jump into the usual operand precedence stack. */
+ operand = cp_parser_binary_expression (parser, false);
+
+ return operand;
+}
+
+/* Need to handle case of relative branch using: .[+|-]number
+ syntax */
+static tree
+cp_parser_cw_asm_relative_branch (cp_parser *parser)
+{
+ cp_token *token;
+ token = cp_lexer_peek_nth_token (parser->lexer, 2);
+ if (token->type == CPP_PLUS || token->type == CPP_MINUS)
+ {
+ const char *str = (token->type == CPP_PLUS) ? ".+" : ".-";
+ /* consume '.' */
+ cp_lexer_consume_token (parser->lexer);
+ /* consume '-' or '+' */
+ cp_lexer_consume_token (parser->lexer);
+ return cw_build_identifier_string (parser, str);
+ }
+ return error_mark_node;
+}
+
+/* Parse a CW asm-style postfix-expression.
+
+ postfix-expression:
+ primary-expression
+ postfix-expression [ expression ]
+ postfix-expression ( expression-list [opt] )
+ simple-type-specifier ( expression-list [opt] )
+ postfix-expression . template [opt] id-expression
+ postfix-expression -> template [opt] id-expression
+ postfix-expression . pseudo-destructor-name
+ postfix-expression -> pseudo-destructor-name
+ typeid ( expression )
+ typeid ( type-id )
+
+ GNU Extension:
+
+ postfix-expression:
+ ( type-id ) { initializer-list , [opt] }
+
+ This extension is a GNU version of the C99 compound-literal
+ construct. (The C99 grammar uses `type-name' instead of `type-id',
+ but they are essentially the same concept.)
+
+ If ADDRESS_P is true, the postfix expression is the operand of the
+ `&' operator.
+
+ Returns a representation of the expression. */
+
+static tree
+cp_parser_cw_asm_postfix_expression (cp_parser *parser, bool address_p)
+{
+ bool for_offsetof = false;
+ cp_token *token;
+ enum rid keyword;
+ cp_id_kind idk = CP_ID_KIND_NONE;
+ tree postfix_expression = NULL_TREE;
+ /* Non-NULL only if the current postfix-expression can be used to
+ form a pointer-to-member. In that case, QUALIFYING_CLASS is the
+ class used to qualify the member. */
+ tree qualifying_class = NULL_TREE;
+
+ /* Peek at the next token. */
+ token = cp_lexer_peek_token (parser->lexer);
+ /* Some of the productions are determined by keywords. */
+ keyword = token->keyword;
+ switch (keyword)
+ {
+ /* APPLE LOCAL begin CW asm blocks */
+ case RID_SIZEOF:
+ {
+ tree operand;
+ /* Consume the token. */
+ cp_lexer_consume_token (parser->lexer);
+ /* Parse the operand. */
+ operand = cp_parser_sizeof_operand (parser, keyword);
+ postfix_expression = cxx_sizeof_or_alignof_type (operand, SIZEOF_EXPR, true);
+ break;
+ }
+ /* APPLE LOCAL end CW asm blocks */
+
+ default:
+ {
+ tree type;
+
+ /* If the next thing is a simple-type-specifier, we may be
+ looking at a functional cast. We could also be looking at
+ an id-expression. So, we try the functional cast, and if
+ that doesn't work we fall back to the primary-expression. */
+ cp_parser_parse_tentatively (parser);
+ /* Look for the simple-type-specifier. */
+ type = cp_parser_simple_type_specifier (parser,
+ CP_PARSER_FLAGS_NONE,
+ /*identifier_p=*/false);
+ /* Parse the cast itself. */
+ if (!cp_parser_error_occurred (parser))
+ postfix_expression
+ = cp_parser_functional_cast (parser, type);
+ /* If that worked, we're done. */
+ if (cp_parser_parse_definitely (parser))
+ break;
+
+ if (token->type == CPP_DOT)
+ {
+ postfix_expression = cp_parser_cw_asm_relative_branch (parser);
+ if (postfix_expression != error_mark_node)
+ break;
+ }
+
+ /* If the functional-cast didn't work out, try a
+ compound-literal. */
+ if (cp_parser_allow_gnu_extensions_p (parser)
+ && cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
+ {
+ tree initializer_list = NULL_TREE;
+ bool saved_in_type_id_in_expr_p;
+
+ cp_parser_parse_tentatively (parser);
+ /* Consume the `('. */
+ cp_lexer_consume_token (parser->lexer);
+ /* Parse the type. */
+ saved_in_type_id_in_expr_p = parser->in_type_id_in_expr_p;
+ parser->in_type_id_in_expr_p = true;
+ type = cp_parser_type_id (parser);
+ parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p;
+ /* Look for the `)'. */
+ cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+ /* Look for the `{'. */
+ cp_parser_require (parser, CPP_OPEN_BRACE, "`{'");
+ /* If things aren't going well, there's no need to
+ keep going. */
+ if (!cp_parser_error_occurred (parser))
+ {
+ bool non_constant_p;
+ /* Parse the initializer-list. */
+ initializer_list
+ = cp_parser_initializer_list (parser, &non_constant_p);
+ /* Allow a trailing `,'. */
+ if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+ cp_lexer_consume_token (parser->lexer);
+ /* Look for the final `}'. */
+ cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'");
+ }
+ /* If that worked, we're definitely looking at a
+ compound-literal expression. */
+ if (cp_parser_parse_definitely (parser))
+ {
+ /* Warn the user that a compound literal is not
+ allowed in standard C++. */
+ if (pedantic)
+ pedwarn ("ISO C++ forbids compound-literals");
+ /* Form the representation of the compound-literal. */
+ postfix_expression
+ = finish_compound_literal (type, initializer_list);
+ break;
+ }
+ }
+
+ /* It must be a primary-expression. */
+ postfix_expression = cp_parser_primary_expression (parser,
+ false,
+ &idk,
+ &qualifying_class);
+ }
+ break;
+ }
+
+ /* If we were avoiding committing to the processing of a
+ qualified-id until we knew whether or not we had a
+ pointer-to-member, we now know. */
+ if (qualifying_class)
+ {
+ bool done;
+
+ /* Peek at the next token. */
+ token = cp_lexer_peek_token (parser->lexer);
+ done = (token->type != CPP_OPEN_SQUARE
+ && token->type != CPP_OPEN_PAREN
+ && token->type != CPP_DOT
+ && token->type != CPP_DEREF
+ && token->type != CPP_PLUS_PLUS
+ && token->type != CPP_MINUS_MINUS);
+
+ postfix_expression = finish_qualified_id_expr (qualifying_class,
+ postfix_expression,
+ done,
+ address_p);
+ if (done)
+ return postfix_expression;
+ }
+
+ /* Keep looping until the postfix-expression is complete. */
+ while (true)
+ {
+ if (idk == CP_ID_KIND_UNQUALIFIED
+ && TREE_CODE (postfix_expression) == IDENTIFIER_NODE
+ && cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_PAREN))
+ /* It is not a Koenig lookup function call. */
+ postfix_expression
+ = unqualified_name_lookup_error (postfix_expression);
+
+ /* Peek at the next token. */
+ token = cp_lexer_peek_token (parser->lexer);
+
+ switch (token->type)
+ {
+ case CPP_OPEN_SQUARE:
+ /* postfix-expression [ expression ] */
+ {
+ tree index;
+
+ /* Consume the `[' token. */
+ cp_lexer_consume_token (parser->lexer);
+ /* Parse the index expression. */
+ index = cp_parser_expression (parser, false);
+ /* Look for the closing `]'. */
+ cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'");
+
+ /* Build the ARRAY_REF. */
+ postfix_expression
+ = grok_array_decl (postfix_expression, index);
+ idk = CP_ID_KIND_NONE;
+ /* Array references are not permitted in
+ constant-expressions. */
+ if (cp_parser_non_integral_constant_expression
+ (parser, "an array reference"))
+ postfix_expression = error_mark_node;
+ }
+ break;
+
+ case CPP_OPEN_PAREN:
+ /* postfix-expression ( expression ) */
+ {
+ tree expr;
+
+ cp_lexer_consume_token (parser->lexer);
+ expr = cp_parser_binary_expression (parser, false);
+
+ if (expr == error_mark_node)
+ {
+ postfix_expression = error_mark_node;
+ break;
+ }
+
+ postfix_expression =
+ cw_asm_build_register_offset (postfix_expression, expr);
+
+ cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+
+ /* The POSTFIX_EXPRESSION is certainly no longer an id. */
+ idk = CP_ID_KIND_NONE;
+ }
+ break;
+
+ case CPP_DOT:
+ /* Disambiguation of asm's last operand followed by a '.'.
+ This happens when an asm instruction is followed by a
+ directive, such as .align. Bail out early. */
+ if (TREE_CODE (postfix_expression) == INTEGER_CST
+ || TREE_CODE (postfix_expression) == IDENTIFIER_NODE
+ || TREE_CODE (postfix_expression) == COMPOUND_EXPR)
+ return postfix_expression;
+
+ case CPP_DEREF:
+ /* postfix-expression . template [opt] id-expression
+ postfix-expression . pseudo-destructor-name
+ postfix-expression -> template [opt] id-expression
+ postfix-expression -> pseudo-destructor-name */
+ {
+ tree name;
+ bool dependent_p;
+ bool template_p;
+ tree scope = NULL_TREE;
+ enum cpp_ttype token_type = token->type;
+
+ /* If this is a `->' operator, dereference the pointer. */
+ if (token->type == CPP_DEREF)
+ postfix_expression = build_x_arrow (postfix_expression);
+ /* Check to see whether or not the expression is
+ type-dependent. */
+ dependent_p = type_dependent_expression_p (postfix_expression);
+ /* The identifier following the `->' or `.' is not
+ qualified. */
+ parser->scope = NULL_TREE;
+ parser->qualifying_scope = NULL_TREE;
+ parser->object_scope = NULL_TREE;
+ idk = CP_ID_KIND_NONE;
+ /* Enter the scope corresponding to the type of the object
+ given by the POSTFIX_EXPRESSION. */
+ if (!dependent_p
+ && TREE_TYPE (postfix_expression) != NULL_TREE)
+ {
+ scope = TREE_TYPE (postfix_expression);
+ /* According to the standard, no expression should
+ ever have reference type. Unfortunately, we do not
+ currently match the standard in this respect in
+ that our internal representation of an expression
+ may have reference type even when the standard says
+ it does not. Therefore, we have to manually obtain
+ the underlying type here. */
+ scope = non_reference (scope);
+ /* The type of the POSTFIX_EXPRESSION must be
+ complete. */
+ scope = complete_type_or_else (scope, NULL_TREE);
+ /* Let the name lookup machinery know that we are
+ processing a class member access expression. */
+ parser->context->object_type = scope;
+ /* If something went wrong, we want to be able to
+ discern that case, as opposed to the case where
+ there was no SCOPE due to the type of expression
+ being dependent. */
+ if (!scope)
+ scope = error_mark_node;
+ /* If the SCOPE was erroneous, make the various
+ semantic analysis functions exit quickly -- and
+ without issuing additional error messages. */
+ if (scope == error_mark_node)
+ postfix_expression = error_mark_node;
+ }
+
+ /* Consume the `.' or `->' operator. */
+ cp_lexer_consume_token (parser->lexer);
+ /* If the SCOPE is not a scalar type, we are looking at an
+ ordinary class member access expression, rather than a
+ pseudo-destructor-name. */
+ if (!scope || !SCALAR_TYPE_P (scope))
+ {
+ template_p = cp_parser_optional_template_keyword (parser);
+ /* Parse the id-expression. */
+ name = cp_parser_id_expression (parser,
+ template_p,
+ /*check_dependency_p=*/true,
+ /*template_p=*/NULL,
+ /*declarator_p=*/false);
+ /* In general, build a SCOPE_REF if the member name is
+ qualified. However, if the name was not dependent
+ and has already been resolved; there is no need to
+ build the SCOPE_REF. For example;
+
+ struct X { void f(); };
+ template <typename T> void f(T* t) { t->X::f(); }
+
+ Even though "t" is dependent, "X::f" is not and has
+ been resolved to a BASELINK; there is no need to
+ include scope information. */
+
+ /* But we do need to remember that there was an explicit
+ scope for virtual function calls. */
+ if (parser->scope)
+ idk = CP_ID_KIND_QUALIFIED;
+
+ if (name != error_mark_node
+ && !BASELINK_P (name)
+ && parser->scope)
+ {
+ name = build_nt (SCOPE_REF, parser->scope, name);
+ parser->scope = NULL_TREE;
+ 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
+ = cw_asm_cp_build_component_ref (postfix_expression, name);
+ }
+ /* Otherwise, try the pseudo-destructor-name production. */
+ else
+ {
+ tree s = NULL_TREE;
+ tree type;
+
+ /* Parse the pseudo-destructor-name. */
+ cp_parser_pseudo_destructor_name (parser, &s, &type);
+ /* Form the call. */
+ postfix_expression
+ = finish_pseudo_destructor_expr (postfix_expression,
+ s, TREE_TYPE (type));
+ }
+
+ /* We no longer need to look up names in the scope of the
+ object on the left-hand side of the `.' or `->'
+ operator. */
+ parser->context->object_type = NULL_TREE;
+
+ /* Outside of offsetof, these operators may not appear in
+ constant-expressions. */
+ if (!for_offsetof
+ && (cp_parser_non_integral_constant_expression
+ (parser, token_type == CPP_DEREF ? "'->'" : "`.'")))
+ postfix_expression = error_mark_node;
+ }
+ break;
+
+ default:
+ return postfix_expression;
+ }
+ }
+
+ /* We should never get here. */
+ abort ();
+ return error_mark_node;
+}
+
+int
+cw_asm_typename_or_reserved (tree value)
+{
+ return (C_IS_RESERVED_WORD (value));
+}
+/* APPLE LOCAL end CW asm blocks */
+
+/* APPLE LOCAL begin Objective-C++ */
+/* Objective-C++ Productions */
+
+
+/* Parse an Objective-C expression, which feeds into a primary-expression
+ above.
+
+ objc-expression:
+ objc-message-expression
+ objc-string-literal
+ objc-encode-expression
+ objc-protocol-expression
+ objc-selector-expression
+
+ Returns a tree representation of the expression. */
+
+static tree
+cp_parser_objc_expression (cp_parser* parser)
+{
+ /* Try to figure out what kind of declaration is present. */
+ cp_token *kwd = cp_lexer_peek_token (parser->lexer);
+
+ switch (kwd->type)
+ {
+ case CPP_OPEN_SQUARE:
+ return cp_parser_objc_message_expression (parser);
+
+ case CPP_OBJC_STRING:
+ kwd = cp_lexer_consume_token (parser->lexer);
+ return objc_build_string_object (kwd->value);
+
+ case CPP_KEYWORD:
+ switch (kwd->keyword)
+ {
+ case RID_AT_ENCODE:
+ return cp_parser_objc_encode_expression (parser);
+
+ case RID_AT_PROTOCOL:
+ return cp_parser_objc_protocol_expression (parser);
+
+ case RID_AT_SELECTOR:
+ return cp_parser_objc_selector_expression (parser);
+
+ default:
+ break;
+ }
+ default:
+ error ("misplaced `@%D' Objective-C++ construct", kwd->value);
+ cp_parser_skip_to_end_of_block_or_statement (parser);
+ }
+
+ return error_mark_node;
+}
+
+/* Parse an Objective-C message expression.
+
+ objc-message-expression:
+ [ objc-message-receiver objc-message-args ]
+
+ Returns a representation of an Objective-C message. */
+
+static tree
+cp_parser_objc_message_expression (cp_parser* parser)
+{
+ tree receiver, messageargs;
+
+ cp_lexer_consume_token (parser->lexer); /* Eat '['. */
+ receiver = cp_parser_objc_message_receiver (parser);
+ messageargs = cp_parser_objc_message_args (parser);
+ cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'");
+
+ return objc_build_message_expr (build_tree_list (receiver, messageargs));
+}
+
+/* Parse an objc-message-receiver.
+
+ objc-message-receiver:
+ type-name
+ expression
+
+ Returns a representation of the type or expression. */
+
+static tree
+cp_parser_objc_message_receiver (cp_parser* parser)
+{
+ tree rcv;
+ bool class_scope_p, template_p;
+
+ /* An Objective-C message receiver may be either (1) a type
+ or (2) an expression. */
+ cp_parser_parse_tentatively (parser);
+ rcv = cp_parser_expression (parser, false);
+
+ if (cp_parser_parse_definitely (parser))
+ return rcv;
+
+ /* Look for the optional `::' operator. */
+ cp_parser_global_scope_opt (parser, false);
+ /* Look for the nested-name-specifier. */
+ cp_parser_nested_name_specifier_opt (parser,
+ /*typename_keyword_p=*/true,
+ /*check_dependency_p=*/true,
+ /*type_p=*/true,
+ /*is_declaration=*/true);
+ class_scope_p = (parser->scope && TYPE_P (parser->scope));
+ template_p = class_scope_p && cp_parser_optional_template_keyword (parser);
+ /* Finally, look for the class-name. */
+ rcv = cp_parser_class_name (parser,
+ class_scope_p,
+ template_p,
+ /*type_p=*/true,
+ /*check_dependency_p=*/true,
+ /*class_head_p=*/false,
+ /*is_declaration=*/true);
+
+ return objc_get_class_reference (rcv);
+}
+
+/* Parse the arguments and selectors comprising an Objective-C message.
+
+ objc-message-args:
+ objc-selector
+ objc-selector-args
+ objc-selector-args , objc-comma-args
+
+ objc-selector-args:
+ objc-selector [opt] : assignment-expression
+ objc-selector-args objc-selector [opt] : assignment-expression
+
+ objc-comma-args:
+ assignment-expression
+ objc-comma-args , assignment-expression
+
+ Returns a TREE_LIST, with TREE_PURPOSE containing a list of
+ selector arguments and TREE_VALUE containing a list of comma
+ arguments. */
+
+static tree
+cp_parser_objc_message_args (cp_parser* parser)
+{
+ tree sel_args = NULL_TREE, addl_args = NULL_TREE;
+ bool maybe_unary_selector_p = true;
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
+
+ while (cp_parser_objc_selector_p (token->type) || token->type == CPP_COLON)
+ {
+ tree selector = NULL_TREE, arg;
+
+ if (token->type != CPP_COLON)
+ selector = cp_parser_objc_selector (parser);
+
+ /* Detect if we have a unary selector. */
+ if (maybe_unary_selector_p
+ && cp_lexer_next_token_is_not (parser->lexer, CPP_COLON))
+ return build_tree_list (selector, NULL_TREE);
+
+ maybe_unary_selector_p = false;
+ cp_parser_require (parser, CPP_COLON, "`:'");
+ arg = cp_parser_assignment_expression (parser, false);
+
+ sel_args
+ = chainon (sel_args,
+ build_tree_list (selector, arg));
+
+ token = cp_lexer_peek_token (parser->lexer);
+ }
+
+ /* Handle non-selector arguments, if any. */
+ while (token->type == CPP_COMMA)
+ {
+ tree arg;
+
+ cp_lexer_consume_token (parser->lexer);
+ arg = cp_parser_assignment_expression (parser, false);
+
+ addl_args
+ = chainon (addl_args,
+ build_tree_list (NULL_TREE, arg));
+
+ token = cp_lexer_peek_token (parser->lexer);
+ }
+
+ return build_tree_list (sel_args, addl_args);
+}
+
+/* Parse an Objective-C encode expression.
+
+ objc-encode-expression:
+ @encode objc-typename
+
+ Returns an encoded representation of the type argument. */
+
+static tree
+cp_parser_objc_encode_expression (cp_parser* parser)
+{
+ tree type;
+
+ cp_lexer_consume_token (parser->lexer); /* Eat '@encode'. */
+ cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+ type = complete_type (cp_parser_type_id (parser));
+ cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+
+ if (!type)
+ {
+ error ("`@encode' must specify a type as an argument");
+ return error_mark_node;
+ }
+
+ return objc_build_encode_expr (type);
+}
+
+/* Parse an Objective-C @defs expression. */
+
+static tree
+cp_parser_objc_defs_expression (cp_parser *parser)
+{
+ tree name;
+
+ cp_lexer_consume_token (parser->lexer); /* Eat '@defs'. */
+ cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+ name = cp_parser_identifier (parser);
+ cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+
+ return objc_get_class_ivars (name);
+}
+
+/* Parse an Objective-C protocol expression.
+
+ objc-protocol-expression:
+ @protocol ( identifier )
+
+ Returns a representation of the protocol expression. */
+
+static tree
+cp_parser_objc_protocol_expression (cp_parser* parser)
+{
+ tree proto;
+
+ cp_lexer_consume_token (parser->lexer); /* Eat '@protocol'. */
+ cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+ proto = cp_parser_identifier (parser);
+ cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+
+ return objc_build_protocol_expr (proto);
+}
+
+/* Parse an Objective-C selector expression.
+
+ objc-selector-expression:
+ @selector ( objc-method-signature )
+
+ objc-method-signature:
+ objc-selector
+ objc-selector-seq
+
+ objc-selector-seq:
+ objc-selector :
+ objc-selector-seq objc-selector :
+
+ Returns a representation of the method selector. */
+
+static tree
+cp_parser_objc_selector_expression (cp_parser* parser)
+{
+ tree sel_seq = NULL_TREE;
+ bool maybe_unary_selector_p = true;
+ cp_token *token;
+
+ cp_lexer_consume_token (parser->lexer); /* Eat '@selector'. */
+ cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+ token = cp_lexer_peek_token (parser->lexer);
+
+ while (cp_parser_objc_selector_p (token->type) || token->type == CPP_COLON)
+ {
+ tree selector = NULL_TREE;
+
+ if (token->type != CPP_COLON)
+ selector = cp_parser_objc_selector (parser);
+
+ /* Detect if we have a unary selector. */
+ if (maybe_unary_selector_p
+ && cp_lexer_next_token_is_not (parser->lexer, CPP_COLON))
+ {
+ sel_seq = selector;
+ goto finish_selector;
+ }
+
+ maybe_unary_selector_p = false;
+ cp_parser_require (parser, CPP_COLON, "`:'");
+
+ sel_seq
+ = chainon (sel_seq,
+ build_tree_list (selector, NULL_TREE));
+
+ token = cp_lexer_peek_token (parser->lexer);
+ }
+
+ finish_selector:
+ cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+
+ return objc_build_selector_expr (sel_seq);
+}
+
+/* Parse a list of identifiers.
+
+ objc-identifier-list:
+ identifier
+ objc-identifier-list , identifier
+
+ Returns a TREE_LIST of identifier nodes. */
+
+static tree
+cp_parser_objc_identifier_list (cp_parser* parser)
+{
+ tree list = build_tree_list (NULL_TREE, cp_parser_identifier (parser));
+ cp_token *sep = cp_lexer_peek_token (parser->lexer);
+
+ while (sep->type == CPP_COMMA)
+ {
+ cp_lexer_consume_token (parser->lexer); /* Eat ','. */
+ list = chainon (list,
+ build_tree_list (NULL_TREE,
+ cp_parser_identifier (parser)));
+ sep = cp_lexer_peek_token (parser->lexer);
+ }
+
+ return list;
+}
+
+/* Parse an Objective-C alias declaration.
+
+ objc-alias-declaration:
+ @compatibility_alias identifier identifier ;
+
+ This function registers the alias mapping with the Objective-C front-end.
+ It returns nothing. */
+
+static void
+cp_parser_objc_alias_declaration (cp_parser* parser)
+{
+ tree alias, orig;
+
+ cp_lexer_consume_token (parser->lexer); /* Eat '@compatibility_alias'. */
+ alias = cp_parser_identifier (parser);
+ orig = cp_parser_identifier (parser);
+ objc_declare_alias (alias, orig);
+ cp_parser_consume_semicolon_at_end_of_statement (parser);
+}
+
+/* Parse an Objective-C class forward-declaration.
+
+ objc-class-declaration:
+ @class objc-identifier-list ;
+
+ The function registers the forward declarations with the Objective-C
+ front-end. It returns nothing. */
+
+static void
+cp_parser_objc_class_declaration (cp_parser* parser)
+{
+ cp_lexer_consume_token (parser->lexer); /* Eat '@class'. */
+ objc_declare_class (cp_parser_objc_identifier_list (parser));
+ cp_parser_consume_semicolon_at_end_of_statement (parser);
+}
+
+/* Parse a list of Objective-C protocol references.
+
+ objc-protocol-refs-opt:
+ objc-protocol-refs [opt]
+
+ objc-protocol-refs:
+ < objc-identifier-list >
+
+ Returns a TREE_LIST of identifiers, if any. */
+
+static tree
+cp_parser_objc_protocol_refs_opt (cp_parser* parser)
+{
+ tree protorefs = NULL_TREE;
+
+ if(cp_lexer_next_token_is (parser->lexer, CPP_LESS))
+ {
+ cp_lexer_consume_token (parser->lexer); /* Eat '<'. */
+ protorefs = cp_parser_objc_identifier_list (parser);
+ cp_parser_require (parser, CPP_GREATER, "`>'");
+ }
+
+ return protorefs;
+}
+
+static void
+cp_parser_objc_visibility_spec (cp_parser* parser)
+{
+ cp_token *vis = cp_lexer_peek_token (parser->lexer);
+
+ switch (vis->keyword)
+ {
+ case RID_AT_PRIVATE:
+ objc_set_visibility (2);
+ break;
+ case RID_AT_PROTECTED:
+ objc_set_visibility (0);
+ break;
+ case RID_AT_PUBLIC:
+ objc_set_visibility (1);
+ break;
+ default:
+ return;
+ }
+
+ /* Eat '@private'/'@protected'/'@public'. */
+ cp_lexer_consume_token (parser->lexer);
+}
+
+static void
+cp_parser_objc_method_type (cp_parser* parser)
+{
+ objc_set_method_type
+ (cp_lexer_consume_token (parser->lexer)->type == CPP_PLUS
+ ? PLUS_EXPR
+ : MINUS_EXPR);
+}
+
+static tree
+cp_parser_objc_protocol_qualifiers (cp_parser* parser)
+{
+ tree quals = NULL_TREE, node;
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
+
+ node = token->value;
+
+ while (node && TREE_CODE (node) == IDENTIFIER_NODE
+ && (node == ridpointers [(int) RID_IN]
+ || node == ridpointers [(int) RID_OUT]
+ || node == ridpointers [(int) RID_INOUT]
+ || node == ridpointers [(int) RID_BYCOPY]
+ || node == ridpointers [(int) RID_BYREF]
+ || node == ridpointers [(int) RID_ONEWAY]))
+ {
+ quals = tree_cons (NULL_TREE, node, quals);
+ cp_lexer_consume_token (parser->lexer);
+ token = cp_lexer_peek_token (parser->lexer);
+ node = token->value;
+ }
+
+ return quals;
+}
+
+static tree
+cp_parser_objc_typename (cp_parser* parser)
+{
+ tree typename = NULL_TREE;
+
+ if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
+ {
+ tree proto_quals, cp_type = NULL_TREE;
+
+ cp_lexer_consume_token (parser->lexer); /* Eat '('. */
+ proto_quals = cp_parser_objc_protocol_qualifiers (parser);
+
+ /* An ObjC type name may consist of just protocol qualifiers, in which
+ case the type shall default to 'id'. */
+ if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN))
+ cp_type = cp_parser_type_id (parser);
+
+ cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+ typename = build_tree_list (proto_quals, cp_type);
+ }
+
+ return typename;
+}
+
+static bool
+cp_parser_objc_selector_p (enum cpp_ttype type)
+{
+ return (type == CPP_NAME || type == CPP_KEYWORD
+ || type == CPP_AND_AND || type == CPP_AND_EQ || type == CPP_AND
+ || type == CPP_OR || type == CPP_COMPL || type == CPP_NOT
+ || type == CPP_NOT_EQ || type == CPP_OR_OR || type == CPP_OR_EQ
+ || type == CPP_XOR || type == CPP_XOR_EQ);
+}
+
+static tree
+cp_parser_objc_selector (cp_parser* parser)
+{
+ cp_token *token = cp_lexer_consume_token (parser->lexer);
+
+ if (!cp_parser_objc_selector_p (token->type))
+ {
+ error ("invalid Objective-C++ selector name");
+ return error_mark_node;
+ }
+
+ /* C++ operator names are allowed to appear in ObjC selectors. */
+ switch (token->type)
+ {
+ case CPP_AND_AND: return get_identifier ("and");
+ case CPP_AND_EQ: return get_identifier ("and_eq");
+ case CPP_AND: return get_identifier ("bitand");
+ case CPP_OR: return get_identifier ("bitor");
+ case CPP_COMPL: return get_identifier ("compl");
+ case CPP_NOT: return get_identifier ("not");
+ case CPP_NOT_EQ: return get_identifier ("not_eq");
+ case CPP_OR_OR: return get_identifier ("or");
+ case CPP_OR_EQ: return get_identifier ("or_eq");
+ case CPP_XOR: return get_identifier ("xor");
+ case CPP_XOR_EQ: return get_identifier ("xor_eq");
+ default: return token->value;
+ }
+}
+
+static tree
+cp_parser_objc_method_keyword_params (cp_parser* parser)
+{
+ tree params = NULL_TREE;
+ bool maybe_unary_selector_p = true;
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
+
+ while (cp_parser_objc_selector_p (token->type) || token->type == CPP_COLON)
+ {
+ tree selector = NULL_TREE, typename, identifier;
+
+ if (token->type != CPP_COLON)
+ selector = cp_parser_objc_selector (parser);
+
+ /* Detect if we have a unary selector. */
+ if (maybe_unary_selector_p
+ && cp_lexer_next_token_is_not (parser->lexer, CPP_COLON))
+ return selector;
+
+ maybe_unary_selector_p = false;
+ cp_parser_require (parser, CPP_COLON, "`:'");
+ typename = cp_parser_objc_typename (parser);
+ identifier = cp_parser_identifier (parser);
+
+ params
+ = chainon (params,
+ objc_build_keyword_decl (selector,
+ typename,
+ identifier));
+
+ token = cp_lexer_peek_token (parser->lexer);
+ }
+
+ return params;
+}
+
+static tree
+cp_parser_objc_method_tail_params_opt (cp_parser* parser)
+{
+ tree params = make_node (TREE_LIST);
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
+
+ TREE_OVERFLOW (params) = 0; /* Initially, assume no ellipsis. */
+
+ while (token->type == CPP_COMMA)
+ {
+ cp_parameter_declarator *parmdecl;
+ tree parm;
+
+ cp_lexer_consume_token (parser->lexer); /* Eat ','. */
+ token = cp_lexer_peek_token (parser->lexer);
+
+ if (token->type == CPP_ELLIPSIS)
+ {
+ cp_lexer_consume_token (parser->lexer); /* Eat '...'. */
+ TREE_OVERFLOW (params) = 1;
+ break;
+ }
+
+ parmdecl = cp_parser_parameter_declaration (parser, false, NULL);
+ parm = grokdeclarator (parmdecl->declarator,
+ &parmdecl->decl_specifiers,
+ PARM, /*initialized=*/0,
+ /*attrlist=*/NULL);
+
+ chainon (params, build_tree_list (NULL_TREE, parm));
+ token = cp_lexer_peek_token (parser->lexer);
+ }
+
+ return params;
+}
+
+static void
+cp_parser_objc_interstitial_code (cp_parser* parser)
+{
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
+
+ /* If the next token is `extern' and the following token is a string
+ literal, then we have a linkage specification. */
+ if (token->keyword == RID_EXTERN
+ && cp_parser_is_string_literal (cp_lexer_peek_nth_token (parser->lexer, 2)))
+ cp_parser_linkage_specification (parser);
+ /* Handle #pragma, if any. */
+ else if (token->type == CPP_PRAGMA)
+ cp_lexer_handle_pragma (parser->lexer);
+ /* Allow stray semicolons. */
+ else if (token->type == CPP_SEMICOLON)
+ cp_lexer_consume_token (parser->lexer);
+ /* Finally, try to parse a block-declaration, or a function-definition. */
+ else
+ cp_parser_block_declaration (parser, /*statement_p=*/false);
+}
+
+static tree
+cp_parser_objc_method_signature (cp_parser* parser)
+{
+ tree rettype, kwdparms, optparms;
+
+ cp_parser_objc_method_type (parser);
+ rettype = cp_parser_objc_typename (parser);
+ kwdparms = cp_parser_objc_method_keyword_params (parser);
+ optparms = cp_parser_objc_method_tail_params_opt (parser);
+
+ return objc_build_method_signature (rettype, kwdparms, optparms);
+}
+
+static void
+cp_parser_objc_method_prototype_list (cp_parser* parser)
+{
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
+
+ while (token->keyword != RID_AT_END)
+ {
+ if (token->type == CPP_PLUS || token->type == CPP_MINUS)
+ {
+ objc_add_method_declaration
+ (cp_parser_objc_method_signature (parser));
+ cp_parser_consume_semicolon_at_end_of_statement (parser);
+ }
+ else
+ /* Allow for interspersed non-ObjC++ code. */
+ cp_parser_objc_interstitial_code (parser);
+
+ token = cp_lexer_peek_token (parser->lexer);
+ }
+
+ cp_lexer_consume_token (parser->lexer); /* Eat '@end'. */
+ objc_finish_interface ();
+}
+
+static void
+cp_parser_objc_method_definition_list (cp_parser* parser)
+{
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
+
+ while (token->keyword != RID_AT_END)
+ {
+ tree meth;
+
+ if (token->type == CPP_PLUS || token->type == CPP_MINUS)
+ {
+ push_deferring_access_checks (dk_deferred);
+ objc_start_method_definition
+ (cp_parser_objc_method_signature (parser));
+
+ /* For historical reasons, we accept an optional semicolon. */
+ if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
+ cp_lexer_consume_token (parser->lexer);
+
+ perform_deferred_access_checks ();
+ stop_deferring_access_checks ();
+ meth = cp_parser_function_definition_after_declarator (parser,
+ false);
+ pop_deferring_access_checks ();
+ objc_finish_method_definition (meth);
+ }
+ else
+ /* Allow for interspersed non-ObjC++ code. */
+ cp_parser_objc_interstitial_code (parser);
+
+ token = cp_lexer_peek_token (parser->lexer);
+ }
+
+ cp_lexer_consume_token (parser->lexer); /* Eat '@end'. */
+ objc_finish_implementation ();
+}
+
+static void
+cp_parser_objc_class_ivars (cp_parser* parser)
+{
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
+
+ if (token->type != CPP_OPEN_BRACE)
+ return; /* No ivars specified. */
+
+ cp_lexer_consume_token (parser->lexer); /* Eat '{'. */
+ token = cp_lexer_peek_token (parser->lexer);
+
+ while (token->type != CPP_CLOSE_BRACE)
+ {
+ cp_decl_specifier_seq declspecs;
+ int decl_class_or_enum_p;
+ tree prefix_attributes;
+
+ cp_parser_objc_visibility_spec (parser);
+
+ if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE))
+ break;
+
+ cp_parser_decl_specifier_seq (parser,
+ CP_PARSER_FLAGS_OPTIONAL,
+ &declspecs,
+ &decl_class_or_enum_p);
+ prefix_attributes = declspecs.attributes;
+ declspecs.attributes = NULL_TREE;
+
+ /* Keep going until we hit the `;' at the end of the
+ declaration. */
+ while (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
+ {
+ tree width = NULL_TREE, attributes, first_attribute, decl;
+ cp_declarator *declarator = NULL;
+ int ctor_dtor_or_conv_p;
+
+ /* Check for a (possibly unnamed) bitfield declaration. */
+ token = cp_lexer_peek_token (parser->lexer);
+ if (token->type == CPP_COLON)
+ goto eat_colon;
+
+ if (token->type == CPP_NAME
+ && (cp_lexer_peek_nth_token (parser->lexer, 2)->type
+ == CPP_COLON))
+ {
+ /* Get the name of the bitfield. */
+ declarator = make_id_declarator (NULL_TREE,
+ cp_parser_identifier (parser));
+
+ eat_colon:
+ cp_lexer_consume_token (parser->lexer); /* Eat ':'. */
+ /* Get the width of the bitfield. */
+ width
+ = cp_parser_constant_expression (parser,
+ /*allow_non_constant=*/false,
+ NULL);
+ }
+ else
+ {
+ /* Parse the declarator. */
+ declarator
+ = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
+ &ctor_dtor_or_conv_p,
+ /*parenthesized_p=*/NULL,
+ /*member_p=*/false);
+ }
+
+ /* Look for attributes that apply to the ivar. */
+ attributes = cp_parser_attributes_opt (parser);
+ /* Remember which attributes are prefix attributes and
+ which are not. */
+ first_attribute = attributes;
+ /* Combine the attributes. */
+ attributes = chainon (prefix_attributes, attributes);
+
+ if (width)
+ {
+ /* Create the bitfield declaration. */
+ decl = grokbitfield (declarator, &declspecs, width);
+ cplus_decl_attributes (&decl, attributes, /*flags=*/0);
+ }
+ else
+ decl = grokfield (declarator, &declspecs, NULL_TREE,
+ NULL_TREE, attributes);
+
+ /* Add the instance variable. */
+ objc_add_instance_variable (decl);
+
+ /* Reset PREFIX_ATTRIBUTES. */
+ while (attributes && TREE_CHAIN (attributes) != first_attribute)
+ attributes = TREE_CHAIN (attributes);
+ if (attributes)
+ TREE_CHAIN (attributes) = NULL_TREE;
+
+ token = cp_lexer_peek_token (parser->lexer);
+
+ if (token->type == CPP_COMMA)
+ {
+ cp_lexer_consume_token (parser->lexer); /* Eat ','. */
+ continue;
+ }
+ break;
+ }
+
+ cp_parser_consume_semicolon_at_end_of_statement (parser);
+ token = cp_lexer_peek_token (parser->lexer);
+ }
+
+ cp_lexer_consume_token (parser->lexer); /* Eat '}'. */
+ /* For historical reasons, we accept an optional semicolon. */
+ if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
+ cp_lexer_consume_token (parser->lexer);
+}
+
+static void
+cp_parser_objc_protocol_declaration (cp_parser* parser)
+{
+ tree proto, protorefs;
+ cp_token *tok;
+
+ cp_lexer_consume_token (parser->lexer); /* Eat '@protocol'. */
+ if (cp_lexer_next_token_is_not (parser->lexer, CPP_NAME))
+ {
+ error ("identifier expected after `@protocol'");
+ goto finish;
+ }
+
+ /* See if we have a foward declaration or a definition. */
+ tok = cp_lexer_peek_nth_token (parser->lexer, 2);
+
+ /* Try a forward declaration first. */
+ if (tok->type == CPP_COMMA || tok->type == CPP_SEMICOLON)
+ {
+ objc_declare_protocols (cp_parser_objc_identifier_list (parser));
+ finish:
+ cp_parser_consume_semicolon_at_end_of_statement (parser);
+ }
+
+ /* Ok, we got a full-fledged definition (or at least should). */
+ else
+ {
+ proto = cp_parser_identifier (parser);
+ protorefs = cp_parser_objc_protocol_refs_opt (parser);
+ objc_start_protocol (proto, protorefs);
+ cp_parser_objc_method_prototype_list (parser);
+ }
+}
+
+static void
+cp_parser_objc_superclass_or_category (cp_parser *parser, tree *super,
+ tree *categ)
+{
+ cp_token *next = cp_lexer_peek_token (parser->lexer);
+
+ *super = *categ = NULL_TREE;
+ if (next->type == CPP_COLON)
+ {
+ cp_lexer_consume_token (parser->lexer); /* Eat ':'. */
+ *super = cp_parser_identifier (parser);
+ }
+ else if (next->type == CPP_OPEN_PAREN)
+ {
+ cp_lexer_consume_token (parser->lexer); /* Eat '('. */
+ *categ = cp_parser_identifier (parser);
+ cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+ }
+}
+
+static void
+cp_parser_objc_class_interface (cp_parser* parser)
+{
+ tree name, super, categ, protos;
+
+ cp_lexer_consume_token (parser->lexer); /* Eat '@interface'. */
+ name = cp_parser_identifier (parser);
+ cp_parser_objc_superclass_or_category (parser, &super, &categ);
+ protos = cp_parser_objc_protocol_refs_opt (parser);
+
+ /* We have either a class or a category on our hands. */
+ if (categ)
+ objc_start_category_interface (name, categ, protos);
+ else
+ {
+ objc_start_class_interface (name, super, protos);
+ /* Handle instance variable declarations, if any. */
+ cp_parser_objc_class_ivars (parser);
+ objc_continue_interface ();
+ }
+
+ cp_parser_objc_method_prototype_list (parser);
+}
+
+static void
+cp_parser_objc_class_implementation (cp_parser* parser)
+{
+ tree name, super, categ;
+
+ cp_lexer_consume_token (parser->lexer); /* Eat '@implementation'. */
+ name = cp_parser_identifier (parser);
+ cp_parser_objc_superclass_or_category (parser, &super, &categ);
+
+ /* We have either a class or a category on our hands. */
+ if (categ)
+ objc_start_category_implementation (name, categ);
+ else
+ {
+ objc_start_class_implementation (name, super);
+ /* Handle instance variable declarations, if any. */
+ cp_parser_objc_class_ivars (parser);
+ objc_continue_implementation ();
+ }
+
+ cp_parser_objc_method_definition_list (parser);
+}
+
+static void
+cp_parser_objc_end_implementation (cp_parser* parser)
+{
+ cp_lexer_consume_token (parser->lexer); /* Eat '@end'. */
+ objc_finish_implementation ();
+}
+
+static void
+cp_parser_objc_declaration (cp_parser* parser)
+{
+ /* Try to figure out what kind of declaration is present. */
+ cp_token *kwd = cp_lexer_peek_token (parser->lexer);
+
+ switch (kwd->keyword)
+ {
+ case RID_AT_ALIAS:
+ cp_parser_objc_alias_declaration (parser);
+ break;
+ case RID_AT_CLASS:
+ cp_parser_objc_class_declaration (parser);
+ break;
+ case RID_AT_PROTOCOL:
+ cp_parser_objc_protocol_declaration (parser);
+ break;
+ case RID_AT_INTERFACE:
+ cp_parser_objc_class_interface (parser);
+ break;
+ case RID_AT_IMPLEMENTATION:
+ cp_parser_objc_class_implementation (parser);
+ break;
+ case RID_AT_END:
+ cp_parser_objc_end_implementation (parser);
+ break;
+ default:
+ error ("misplaced `@%D' Objective-C++ construct", kwd->value);
+ cp_parser_skip_to_end_of_block_or_statement (parser);
+ }
+}
+
+/* Parse an Objective-C try-catch-finally statement.
+
+ objc-try-catch-finally-stmt:
+ @try compound-statement objc-catch-clause-seq [opt]
+ objc-finally-clause [opt]
+
+ objc-catch-clause-seq:
+ objc-catch-clause objc-catch-clause-seq [opt]
+
+ objc-catch-clause:
+ @catch ( exception-declaration ) compound-statement
+
+ objc-finally-clause
+ @finally compound-statement
+
+ Returns NULL_TREE. */
+
+static tree
+cp_parser_objc_try_catch_finally_statement (cp_parser *parser) {
+ location_t location;
+ tree stmt;
+
+ cp_parser_require_keyword (parser, RID_AT_TRY, "`@try'");
+ location = cp_lexer_peek_token (parser->lexer)->location;
+ /* NB: The @try block needs to be wrapped in its own STATEMENT_LIST
+ node, lest it get absorbed into the surrounding block. */
+ stmt = push_stmt_list ();
+ cp_parser_compound_statement (parser, NULL, false);
+ objc_begin_try_stmt (location, pop_stmt_list (stmt));
+
+ while (cp_lexer_next_token_is_keyword (parser->lexer, RID_AT_CATCH))
+ {
+ cp_parameter_declarator *parmdecl;
+ tree parm;
+
+ cp_lexer_consume_token (parser->lexer);
+ cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+ parmdecl = cp_parser_parameter_declaration (parser, false, NULL);
+ parm = grokdeclarator (parmdecl->declarator,
+ &parmdecl->decl_specifiers,
+ PARM, /*initialized=*/0,
+ /*attrlist=*/NULL);
+ cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+ objc_begin_catch_clause (parm);
+ cp_parser_compound_statement (parser, NULL, false);
+ objc_finish_catch_clause ();
+ }
+
+ if (cp_lexer_next_token_is_keyword (parser->lexer, RID_AT_FINALLY))
+ {
+ cp_lexer_consume_token (parser->lexer);
+ location = cp_lexer_peek_token (parser->lexer)->location;
+ /* NB: The @finally block needs to be wrapped in its own STATEMENT_LIST
+ node, lest it get absorbed into the surrounding block. */
+ stmt = push_stmt_list ();
+ cp_parser_compound_statement (parser, NULL, false);
+ objc_build_finally_clause (location, pop_stmt_list (stmt));
+ }
+
+ return objc_finish_try_stmt ();
+}
+
+/* Parse an Objective-C synchronized statement.
+
+ objc-synchronized-stmt:
+ @synchronized ( expression ) compound-statement
+
+ Returns NULL_TREE. */
+
+static tree
+cp_parser_objc_synchronized_statement (cp_parser *parser) {
+ location_t location;
+ tree lock, stmt;
+
+ cp_parser_require_keyword (parser, RID_AT_SYNCHRONIZED, "`@synchronized'");
+
+ location = cp_lexer_peek_token (parser->lexer)->location;
+ cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+ lock = cp_parser_expression (parser, false);
+ cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+
+ /* NB: The @synchronized block needs to be wrapped in its own STATEMENT_LIST
+ node, lest it get absorbed into the surrounding block. */
+ stmt = push_stmt_list ();
+ cp_parser_compound_statement (parser, NULL, false);
+
+ return objc_build_synchronized (location, lock, pop_stmt_list (stmt));
+}
+
+/* Parse an Objective-C throw statement.
+
+ objc-throw-stmt:
+ @throw assignment-expression [opt] ;
+
+ Returns a constructed '@throw' statement. */
+
+static tree
+cp_parser_objc_throw_statement (cp_parser *parser) {
+ tree expr = NULL_TREE;
+
+ cp_parser_require_keyword (parser, RID_AT_THROW, "`@throw'");
+
+ if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
+ expr = cp_parser_assignment_expression (parser, false);
+
+ cp_parser_consume_semicolon_at_end_of_statement (parser);
+
+ return objc_build_throw_stmt (expr);
+}
+
+static tree
+cp_parser_objc_statement (cp_parser * parser) {
+ /* Try to figure out what kind of declaration is present. */
+ cp_token *kwd = cp_lexer_peek_token (parser->lexer);
+
+ switch (kwd->keyword)
+ {
+ case RID_AT_TRY:
+ return cp_parser_objc_try_catch_finally_statement (parser);
+ case RID_AT_SYNCHRONIZED:
+ return cp_parser_objc_synchronized_statement (parser);
+ case RID_AT_THROW:
+ return cp_parser_objc_throw_statement (parser);
+ default:
+ error ("misplaced `@%D' Objective-C++ construct", kwd->value);
+ cp_parser_skip_to_end_of_block_or_statement (parser);
+ }
+
+ return error_mark_node;
+}
+/* APPLE LOCAL end Objective-C++ */
/* The parser. */
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 7025deff788..089a57d7d27 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -34,7 +34,11 @@ Boston, MA 02111-1307, USA. */
#include "tree.h"
#include "pointer-set.h"
#include "flags.h"
+/* APPLE LOCAL Objective-C++ */
+#include "c-common.h"
#include "cp-tree.h"
+/* APPLE LOCAL Objective-C++ */
+#include "cp-objcp-common.h"
#include "tree-inline.h"
#include "decl.h"
#include "output.h"
@@ -4012,7 +4016,26 @@ template_args_equal (tree ot, tree nt)
/* For member templates */
return TREE_CODE (ot) == TREE_VEC && comp_template_args (ot, nt);
else if (TYPE_P (nt))
- return TYPE_P (ot) && same_type_p (ot, nt);
+ /* APPLE LOCAL begin Objective-C++ */
+ {
+ int c1, c2;
+
+ if (!TYPE_P (ot))
+ return 0;
+
+ /* We must handle ObjC types specially because they may differ
+ only in protocol qualifications (e.g., 'NSObject *' vs.
+ 'NSObject <Foo> *') that must be taken into account here.
+ See also cp/typeck.c:build_c_cast(), where a similar problem
+ arises. We must call objc_comptypes() twice, since its
+ comparisons are _not_ symmetric. */
+ if ((c1 = objc_comptypes (ot, nt, 0)) >= 0
+ && (c2 = objc_comptypes (nt, ot, 0)) >= 0)
+ return (c1 && c2);
+
+ return same_type_p (ot, nt);
+ }
+ /* APPLE LOCAL end Objective-C++ */
else if (TREE_CODE (ot) == TREE_VEC || TYPE_P (ot))
return 0;
else
@@ -8839,6 +8862,18 @@ tsubst_copy_and_build (tree t,
return t;
default:
+ /* APPLE LOCAL begin Objective-C++ */
+ /* Handle Objective-C++ constructs, if appropriate. */
+ {
+ tree subst
+ = objcp_tsubst_copy_and_build (t, args, complain,
+ in_decl, /*function_p=*/false);
+
+ if (subst)
+ return subst;
+ }
+ /* APPLE LOCAL end Objective-C++ */
+
return tsubst_copy (t, args, complain, in_decl);
}
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index ebc213d7812..7f573e1f4a2 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -401,7 +401,8 @@ anon_aggr_type_p (tree node)
/* Finish a scope. */
-static tree
+/* APPLE LOCAL Objective-C++ */
+tree
do_poplevel (tree stmt_list)
{
tree block = NULL;
@@ -1166,7 +1167,8 @@ finish_asm_stmt (int volatile_p, tree string, tree output_operands,
otherwise we'll get an error. Gross, but ... */
STRIP_NOPS (operand);
- if (!lvalue_or_else (operand, lv_asm))
+ /* APPLE LOCAL non-lvalue assign */
+ if (!lvalue_or_else (&operand, lv_asm))
operand = error_mark_node;
constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t)));
@@ -2441,6 +2443,27 @@ finish_id_expression (tree id_expression,
if (decl == error_mark_node)
{
/* Name lookup failed. */
+ /* APPLE LOCAL begin CW asm blocks */
+ /* CW assembly has automagical handling of register names.
+ It's also handy to assume undeclared names as labels,
+ although it would be better to have a second pass and
+ complain about names in the block that are not
+ labels. */
+ if (cw_asm_block)
+ {
+ tree new_id;
+ if ((new_id = cw_asm_reg_name (id_expression)))
+ return new_id;
+#ifdef CW_ASM_SPECIAL_LABEL
+ if ((new_id = CW_ASM_SPECIAL_LABEL (id_expression)))
+ return new_id;
+#endif
+ /* Assume undeclared symbols are labels. */
+ new_id = get_cw_asm_label (id_expression);
+ return new_id;
+ }
+ /* APPLE LOCAL end CW asm blocks */
+
if (scope
&& (!TYPE_P (scope)
|| (!dependent_type_p (scope)
@@ -2485,6 +2508,15 @@ finish_id_expression (tree id_expression,
*error_msg = "missing template arguments";
return error_mark_node;
}
+ /* APPLE LOCAL begin CW asm blocks */
+ /* Accept raw type decls, which will be used in offset-getting
+ expressions like "type.field(r3)". */
+ else if (TREE_CODE (decl) == TYPE_DECL && cw_asm_block)
+ {
+ *idk = CP_ID_KIND_NONE;
+ return decl;
+ }
+ /* APPLE LOCAL end CW asm blocks */
else if (TREE_CODE (decl) == TYPE_DECL
|| TREE_CODE (decl) == NAMESPACE_DECL)
{
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 8a264d7afa9..e4fd013abd6 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -33,6 +33,8 @@ Boston, MA 02111-1307, USA. */
#include "insn-config.h"
#include "integrate.h"
#include "tree-inline.h"
+/* APPLE LOCAL Objective-C++ */
+#include "debug.h"
#include "target.h"
static tree bot_manip (tree *, int *, void *);
@@ -111,6 +113,8 @@ lvalue_p_1 (tree ref,
case STRING_CST:
return clk_ordinary;
+ /* APPLE LOCAL Objective-C++ */
+ case CONST_DECL:
case VAR_DECL:
if (TREE_READONLY (ref) && ! TREE_STATIC (ref)
&& DECL_LANG_SPECIFIC (ref)
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index e0dc1ebdb49..8b754b1682d 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -530,10 +530,16 @@ composite_pointer_type (tree t1, tree t2, tree arg1, tree arg2,
class1 = TREE_TYPE (t1);
class2 = TREE_TYPE (t2);
- if (DERIVED_FROM_P (class1, class2))
+ /* APPLE LOCAL begin Objective-C++ */
+ if (DERIVED_FROM_P (class1, class2) ||
+ (c_dialect_objc () && objc_comptypes (class1, class2, 0) == 1))
+ /* APPLE LOCAL end Objective-C++ */
t2 = (build_pointer_type
(cp_build_qualified_type (class1, TYPE_QUALS (class2))));
- else if (DERIVED_FROM_P (class2, class1))
+ /* APPLE LOCAL begin Objective-C++ */
+ else if (DERIVED_FROM_P (class2, class1) ||
+ (c_dialect_objc () && objc_comptypes (class2, class1, 0) == 1))
+ /* APPLE LOCAL end Objective-C++ */
t1 = (build_pointer_type
(cp_build_qualified_type (class2, TYPE_QUALS (class1))));
else
@@ -1847,6 +1853,12 @@ finish_class_member_access_expr (tree object, tree name)
if (object == error_mark_node || name == error_mark_node)
return error_mark_node;
+ /* APPLE LOCAL begin Objective-C++ */
+ /* If OBJECT is an ObjC class instance, we must obey ObjC access rules. */
+ if (!objc_is_public (object, name))
+ return error_mark_node;
+ /* APPLE LOCAL end Objective-C++ */
+
object_type = TREE_TYPE (object);
if (processing_template_decl)
@@ -2006,6 +2018,8 @@ build_ptrmemfunc_access_expr (tree ptrmem, tree member_name)
routine directly because it expects the object to be of class
type. */
ptrmem_type = TREE_TYPE (ptrmem);
+ /* APPLE LOCAL KEXT 2.95-ptmf-compatibility --turly */
+ if (!flag_apple_kext)
gcc_assert (TYPE_PTRMEMFUNC_P (ptrmem_type));
member = lookup_member (ptrmem_type, member_name, /*protect=*/0,
/*want_type=*/false);
@@ -2289,7 +2303,10 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function)
if (TYPE_PTRMEMFUNC_P (TREE_TYPE (function)))
{
- tree idx, delta, e1, e2, e3, vtbl, basetype;
+ /* APPLE LOCAL begin KEXT 2.95-ptmf-compatibility --turly */
+ tree idx, delta, e1, e2, e3, vtbl = vtbl, basetype;
+ tree delta2 = delta2;
+ /* APPLE LOCAL end KEXT 2.95-ptmf-compatibility --turly */
tree fntype = TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (function));
tree instance_ptr = *instance_ptrptr;
@@ -2321,6 +2338,17 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function)
/* Start by extracting all the information from the PMF itself. */
e3 = pfn_from_ptrmemfunc (function);
delta = build_ptrmemfunc_access_expr (function, delta_identifier);
+
+ /* APPLE LOCAL begin KEXT 2.95-ptmf-compatibility --turly */
+ if (flag_apple_kext)
+ {
+ idx = build_ptrmemfunc_access_expr (function, index_identifier);
+ idx = save_expr (default_conversion (idx));
+ e1 = cp_build_binary_op (GE_EXPR, idx, integer_zero_node);
+ }
+ else
+ {
+ /* APPLE LOCAL end KEXT 2.95-ptmf-compatibility --turly */
idx = build1 (NOP_EXPR, vtable_index_type, e3);
switch (TARGET_PTRMEMFUNC_VBIT_LOCATION)
{
@@ -2338,6 +2366,19 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function)
gcc_unreachable ();
}
+ /* APPLE LOCAL begin KEXT 2.95-ptmf-compatibility --turly */
+ }
+ /* DELTA2 is the amount by which to adjust the `this' pointer
+ to find the vtbl. */
+ if (flag_apple_kext)
+ {
+ delta2 = build_ptrmemfunc_access_expr (function,
+ pfn_or_delta2_identifier);
+ delta2 = build_ptrmemfunc_access_expr (delta2,
+ delta2_identifier);
+ }
+ /* APPLE LOCAL end KEXT 2.95-ptmf-compatibility --turly */
+
/* Convert down to the right base before using the instance. First
use the type... */
basetype = TYPE_METHOD_BASETYPE (TREE_TYPE (fntype));
@@ -2346,6 +2387,14 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function)
instance_ptr = build_base_path (PLUS_EXPR, instance_ptr, basetype, 1);
if (instance_ptr == error_mark_node)
return error_mark_node;
+
+ /* APPLE LOCAL begin KEXT 2.95-ptmf-compatibility --turly */
+ if (flag_apple_kext)
+ /* Next extract the vtable pointer from the object. */
+ vtbl = build (PLUS_EXPR,build_pointer_type (vtbl_ptr_type_node),
+ instance_ptr, cp_convert (ptrdiff_type_node, delta2));
+ /* APPLE LOCAL end KEXT 2.95-ptmf-compatibility --turly */
+
/* ...and then the delta in the PMF. */
instance_ptr = build2 (PLUS_EXPR, TREE_TYPE (instance_ptr),
instance_ptr, delta);
@@ -2353,11 +2402,22 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function)
/* Hand back the adjusted 'this' argument to our caller. */
*instance_ptrptr = instance_ptr;
+ /* APPLE LOCAL KEXT 2.95-ptmf-compatibility --turly */
+ if (!flag_apple_kext)
/* Next extract the vtable pointer from the object. */
vtbl = build1 (NOP_EXPR, build_pointer_type (vtbl_ptr_type_node),
instance_ptr);
vtbl = build_indirect_ref (vtbl, NULL);
+ /* APPLE LOCAL begin KEXT 2.95-ptmf-compatibility --turly */
+ /* 2.95-style indices are off by one. */
+ if (flag_apple_kext)
+ {
+ idx = cp_build_binary_op (MINUS_EXPR, idx, integer_one_node);
+ idx = cp_build_binary_op (LSHIFT_EXPR, idx, integer_two_node);
+ }
+ /* APPLE LOCAL end KEXT 2.95-ptmf-compatibility --turly */
+
/* Finally, extract the function pointer from the vtable. */
e2 = fold (build2 (PLUS_EXPR, TREE_TYPE (vtbl), vtbl, idx));
e2 = build_indirect_ref (e2, NULL);
@@ -2653,6 +2713,13 @@ build_x_binary_op (enum tree_code code, tree arg1, tree arg2,
tree orig_arg2;
tree expr;
+ /* APPLE LOCAL begin CW asm blocks */
+ if (cw_asm_block
+ && (TREE_CODE (arg1) == IDENTIFIER_NODE
+ || TREE_CODE (arg2) == IDENTIFIER_NODE))
+ return error_mark_node;
+ /* APPLE LOCAL end CW asm blocks */
+
orig_arg1 = arg1;
orig_arg2 = arg2;
@@ -3016,6 +3083,13 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
}
else if (TYPE_PTRMEMFUNC_P (type0) && null_ptr_cst_p (op1))
{
+ /* APPLE LOCAL begin KEXT 2.95-ptmf-compatibility --turly */
+ /* Shouldn't we use INDEX here rather than PFN? This seems to
+ work fine, though... */
+ if (flag_apple_kext)
+ op0 = build_ptrmemfunc_access_expr (op0, index_identifier);
+ else
+ /* APPLE LOCAL end KEXT 2.95-ptmf-compatibility --turly */
op0 = build_ptrmemfunc_access_expr (op0, pfn_identifier);
op1 = cp_convert (TREE_TYPE (op0), integer_zero_node);
result_type = TREE_TYPE (op0);
@@ -3910,9 +3984,12 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert)
}
/* Complain about anything else that is not a true lvalue. */
- if (!lvalue_or_else (arg, ((code == PREINCREMENT_EXPR
- || code == POSTINCREMENT_EXPR)
- ? lv_increment : lv_decrement)))
+ /* APPLE LOCAL begin non-lvalue assign */
+ if (!lvalue_or_else (&arg, ((code == PREINCREMENT_EXPR
+ || code == POSTINCREMENT_EXPR)
+ ? lv_increment
+ : lv_decrement)))
+ /* APPLE LOCAL end non-lvalue assign */
return error_mark_node;
/* Forbid using -- on `bool'. */
@@ -4056,7 +4133,8 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert)
is an error. */
else if (TREE_CODE (argtype) != FUNCTION_TYPE
&& TREE_CODE (argtype) != METHOD_TYPE
- && !lvalue_or_else (arg, lv_addressof))
+ /* APPLE LOCAL non-lvalue assign */
+ && !lvalue_or_else (&arg, lv_addressof))
return error_mark_node;
if (argtype != error_mark_node)
@@ -4429,8 +4507,12 @@ build_x_compound_expr (tree op1, tree op2)
tree
build_compound_expr (tree lhs, tree rhs)
{
- lhs = convert_to_void (lhs, "left-hand operand of comma");
-
+ /* APPLE LOCAL begin AltiVec */
+ lhs = convert_to_void (lhs, targetm.cast_expr_as_vector_init
+ ? NULL
+ : "left-hand operand of comma");
+ /* APPLE LOCAL end AltiVec */
+
if (lhs == error_mark_node || rhs == error_mark_node)
return error_mark_node;
@@ -4739,6 +4821,13 @@ build_static_cast (tree type, tree expr)
if (type == error_mark_node || expr == error_mark_node)
return error_mark_node;
+ /* APPLE LOCAL begin AltiVec */
+ /* If we are casting to a vector type, treat the expression as a vector
+ initializer if this target supports it. */
+ if (TREE_CODE (type) == VECTOR_TYPE && targetm.cast_expr_as_vector_init)
+ return vector_constructor_from_expr (expr, type);
+ /* APPLE LOCAL end AltiVec */
+
if (processing_template_decl)
{
expr = build_min (STATIC_CAST_EXPR, type, expr);
@@ -4779,6 +4868,20 @@ convert_member_func_to_ptr (tree type, tree expr)
gcc_assert (TYPE_PTRMEMFUNC_P (intype)
|| TREE_CODE (intype) == METHOD_TYPE);
+ /* APPLE LOCAL begin kext ptmf casts --bowdidge*/
+ /* Beginning in gcc-4.0, casts from pointer-to-member-function to pointer-to-
+ function should always be done with the OSMemberFunctionCast() to guarantee
+ the 2.95 behavior. Casts the "old fashioned way" should be flagged as
+ errors so developers won't have kexts that silently use the new
+ ptmf->pmf behavior and get a different function than 3.3. */
+
+ if (flag_apple_kext)
+ {
+ error ("converting from `%T' to `%T' in a kext. Use OSMemberFunctionCast() instead.", intype, type);
+ return error_mark_node;
+ }
+ /* APPLE LOCAL end kext ptmf casts */
+
if (pedantic || warn_pmf2ptr)
pedwarn ("converting from %qT to %qT", intype, type);
@@ -4937,6 +5040,14 @@ build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p,
error ("invalid cast from type %qT to type %qT", intype, type);
return error_mark_node;
}
+
+ /* APPLE LOCAL begin don't sign-extend pointers cast to integers */
+ if (TREE_CODE (type) == INTEGER_TYPE
+ && TREE_CODE (intype) == POINTER_TYPE
+ && TYPE_PRECISION (type) > TYPE_PRECISION (intype)
+ && TYPE_UNSIGNED (type))
+ expr = cp_convert (c_common_type_for_size (POINTER_SIZE, 1), expr);
+ /* APPLE LOCAL end don't sign-extend pointers cast to integers */
return cp_convert (type, expr);
}
@@ -4947,6 +5058,13 @@ build_reinterpret_cast (tree type, tree expr)
if (type == error_mark_node || expr == error_mark_node)
return error_mark_node;
+ /* APPLE LOCAL begin AltiVec */
+ /* If we are casting to a vector type, treat the expression as a vector
+ initializer if this target supports it. */
+ if (TREE_CODE (type) == VECTOR_TYPE && targetm.cast_expr_as_vector_init)
+ return vector_constructor_from_expr (expr, type);
+ /* APPLE LOCAL end AltiVec */
+
if (processing_template_decl)
{
tree t = build_min (REINTERPRET_CAST_EXPR, type, expr);
@@ -5112,6 +5230,15 @@ build_c_cast (tree type, tree expr)
return convert_from_reference (t);
}
+ /* APPLE LOCAL begin AltiVec */
+ /* If we are casting to a vector type, treat the expression as a vector
+ initializer if this target supports it. */
+ if (TREE_CODE (type) == VECTOR_TYPE
+ && targetm.cast_expr_as_vector_init
+ && !IS_AGGR_TYPE (TREE_TYPE(expr)))
+ return vector_constructor_from_expr (expr, type);
+ /* APPLE LOCAL end AltiVec */
+
/* Casts to a (pointer to a) specific ObjC class (or 'id' or
'Class') should always be retained, because this information aids
in method lookup. */
@@ -5252,7 +5379,8 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
case MAX_EXPR:
/* MIN_EXPR and MAX_EXPR are currently only permitted as lvalues,
when neither operand has side-effects. */
- if (!lvalue_or_else (lhs, lv_assign))
+ /* APPLE LOCAL non-lvalue assign */
+ if (!lvalue_or_else (&lhs, lv_assign))
return error_mark_node;
gcc_assert (!TREE_SIDE_EFFECTS (TREE_OPERAND (lhs, 0))
@@ -5280,7 +5408,8 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
/* Check this here to avoid odd errors when trying to convert
a throw to the type of the COND_EXPR. */
- if (!lvalue_or_else (lhs, lv_assign))
+ /* APPLE LOCAL non-lvalue assign */
+ if (!lvalue_or_else (&lhs, lv_assign))
return error_mark_node;
cond = build_conditional_expr
@@ -5374,7 +5503,8 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
}
/* The left-hand side must be an lvalue. */
- if (!lvalue_or_else (lhs, lv_assign))
+ /* APPLE LOCAL non-lvalue assign */
+ if (!lvalue_or_else (&lhs, lv_assign))
return error_mark_node;
/* Warn about modifying something that is `const'. Don't warn if
@@ -5476,6 +5606,16 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
if (newrhs == error_mark_node)
return error_mark_node;
+ /* APPLE LOCAL begin ObjC GC */
+ if (c_dialect_objc () && flag_objc_gc)
+ {
+ result = objc_generate_write_barrier (lhs, modifycode, newrhs);
+
+ if (result)
+ return result;
+ }
+ /* APPLE LOCAL end ObjC GC */
+
result = build2 (modifycode == NOP_EXPR ? MODIFY_EXPR : INIT_EXPR,
lhstype, lhs, newrhs);
@@ -5603,6 +5743,114 @@ build_ptrmemfunc1 (tree type, tree delta, tree pfn)
tree delta_field;
tree pfn_field;
+ /* APPLE LOCAL begin KEXT 2.95-ptmf-compatibility --turly */
+ if (flag_apple_kext)
+ {
+ /* Ooo-err, Missus. Cons up a 2.95-style ptmf struct given
+ gcc3-style inputs! Recall:
+
+ struct ptmf2 { struct ptmf3 {
+ short __delta; __P __pfn;
+ short __index; ptrdiff_t __delta;
+ union { }
+ __P __pfn;
+ short __delta2;
+ }
+ }
+
+ Won't this be fun. Much of this is snarfed from 2.95.
+ Note that the __delta2 val, if required, will always be __delta. */
+
+ tree subtype, pfn_or_delta2_field, idx, idx_field, delta2_field;
+ tree delta2 = integer_zero_node;
+ int ixval = 0;
+ int allconstant = 0, allsimple = 0, allinvariant = 0;
+
+ delta_field = TYPE_FIELDS (type);
+ idx_field = TREE_CHAIN (delta_field);
+ pfn_or_delta2_field = TREE_CHAIN (idx_field);
+ subtype = TREE_TYPE (pfn_or_delta2_field);
+ pfn_field = TYPE_FIELDS (subtype);
+ delta2_field = TREE_CHAIN (pfn_field);
+
+ if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_pfn)
+ {
+ /* If the low bit of PFN is set, the virtual index is PFN >> 1.
+ Else it's nonvirtual. */
+ allconstant = TREE_CONSTANT (pfn);
+ allinvariant = TREE_INVARIANT (pfn);
+ allsimple = !! initializer_constant_valid_p (pfn, TREE_TYPE (pfn));
+ if (TREE_CODE (pfn) == INTEGER_CST && (TREE_INT_CST_LOW (pfn) & 1))
+ {
+ /* It's a virtual function. PFN is the vt offset + 1. */
+
+ int vt_entry_sz = 4;
+ tree vt_entry_sz_tree = TYPE_SIZE_UNIT (vtable_entry_type);
+ if (TREE_CODE (vt_entry_sz_tree) == INTEGER_CST)
+ vt_entry_sz = TREE_INT_CST_LOW (vt_entry_sz_tree);
+
+ ixval = (TREE_INT_CST_LOW (pfn) - 1);
+ ixval /= vt_entry_sz;
+
+ /* Now add 2 for that spadgey VPTR index hack, plus one because
+ 2.95 indices are offset by 1. */
+ ixval += 2 + 1;
+
+ /* __delta2 is the same as __delta. */
+ u = tree_cons (delta2_field, delta, NULL_TREE);
+ }
+ else
+ if (TREE_CODE (pfn) == INTEGER_CST && TREE_INT_CST_LOW (pfn) == 0)
+ {
+ /* NULL pfn. Just zero out everything. */
+ ixval = 0;
+ pfn = integer_zero_node;
+ delta = integer_zero_node;
+ u = tree_cons (pfn_field, pfn, NULL_TREE);
+ }
+ else
+ {
+ ixval = -1; /* -1 ==> PFN is the pointer */
+ u = tree_cons (pfn_field, pfn, NULL_TREE);
+ }
+ }
+ else /* Low bit of DELTA is set if we're virtual. */
+ {
+ /* Don't know how to do this yet. Much like the above, probably. */
+ abort ();
+ allconstant = TREE_CONSTANT (delta);
+ allinvariant = TREE_INVARIANT (delta);
+ allsimple = !! initializer_constant_valid_p (delta,
+ TREE_TYPE (delta));
+
+ u = tree_cons (delta2_field, delta2, NULL_TREE);
+ }
+
+ delta = convert_and_check (delta_type_node, delta);
+ idx = convert_and_check (delta_type_node, ssize_int (ixval));
+
+ u = build_constructor (subtype, u);
+ TREE_CONSTANT (u) = allconstant;
+ TREE_INVARIANT (u) = allinvariant;
+ TREE_STATIC (u) = allconstant && allsimple;
+
+ allconstant = allconstant && TREE_CONSTANT (delta) && TREE_CONSTANT (idx);
+ allinvariant = allinvariant && TREE_INVARIANT (delta) && TREE_INVARIANT (idx);
+ allsimple = allsimple
+ && initializer_constant_valid_p (delta, TREE_TYPE (delta))
+ && initializer_constant_valid_p (idx, TREE_TYPE (idx));
+
+ u = tree_cons (delta_field, delta,
+ tree_cons (idx_field, idx,
+ tree_cons (pfn_or_delta2_field, u, NULL_TREE)));
+ u = build_constructor (type, u);
+ TREE_CONSTANT (u) = allconstant;
+ TREE_INVARIANT (u) = allinvariant;
+ TREE_STATIC (u) = allconstant && allsimple;
+ return u;
+ }
+ /* APPLE LOCAL end KEXT 2.95-ptmf-compatibility --turly */
+
/* Pull the FIELD_DECLs out of the type. */
pfn_field = TYPE_FIELDS (type);
delta_field = TREE_CHAIN (pfn_field);
@@ -5794,6 +6042,22 @@ expand_ptrmemfunc_cst (tree cst, tree *delta, tree *pfn)
tree
pfn_from_ptrmemfunc (tree t)
{
+ /* APPLE LOCAL begin KEXT 2.95-ptmf-compatibility --turly */
+ if (flag_apple_kext)
+ {
+ if (TREE_CODE (t) == PTRMEM_CST)
+ {
+ tree fn = PTRMEM_CST_MEMBER (t);
+ if (!DECL_VIRTUAL_P (fn))
+ return convert (TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (t)),
+ build_addr_func (fn));
+ }
+
+ t = build_ptrmemfunc_access_expr (t, pfn_or_delta2_identifier);
+ return build_ptrmemfunc_access_expr (t, pfn_identifier);
+ }
+ /* APPLE LOCAL end KEXT 2.95-ptmf-compatibility --turly */
+
if (TREE_CODE (t) == PTRMEM_CST)
{
tree delta;
@@ -6500,3 +6764,16 @@ non_reference (tree t)
t = TREE_TYPE (t);
return t;
}
+
+/* APPLE LOCAL begin CW asm blocks */
+tree
+cw_asm_cp_build_component_ref (tree datum, tree component)
+{
+ tree expr = finish_class_member_access_expr (datum, component);
+ /* If this is not a real component reference, extract the field
+ decl, which includes the numeric offset we'll use later. */
+ if (TREE_CODE (datum) == TYPE_DECL)
+ expr = TREE_OPERAND (expr, 1);
+ return expr;
+}
+/* APPLE LOCAL end CW asm blocks */
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index 8017af3dd25..db097f4d5a5 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -695,16 +695,26 @@ digest_init (tree type, tree init, tree* tail)
|| (element && TREE_CODE (element) == STRING_CST)))
{
tree string = element ? element : init;
+ /* APPLE LOCAL begin pascal strings */
+ bool pascal_p
+ = (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (string)))
+ == unsigned_char_type_node);
+ /* APPLE LOCAL end pascal strings */
if ((TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (string)))
!= char_type_node)
+ /* APPLE LOCAL pascal strings */
+ && !pascal_p
&& TYPE_PRECISION (typ1) == BITS_PER_UNIT)
{
error ("char-array initialized from wide string");
return error_mark_node;
}
- if ((TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (string)))
+ /* APPLE LOCAL begin pascal strings */
+ if (((TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (string)))
== char_type_node)
+ || pascal_p)
+ /* APPLE LOCAL end pascal strings */
&& TYPE_PRECISION (typ1) != BITS_PER_UNIT)
{
error ("int-array initialized from non-wide string");
@@ -721,7 +731,13 @@ digest_init (tree type, tree init, tree* tail)
because it's ok to ignore the terminating null char that is
counted in the length of the constant, but in C++ this would
be invalid. */
- if (size < TREE_STRING_LENGTH (string))
+ /* APPLE LOCAL begin pascal strings */
+ /* For Pascal strings, though, ignoring the terminating NUL
+ is still cool. */
+ if (size < (pascal_p
+ ? TREE_STRING_LENGTH (string) - 1
+ : TREE_STRING_LENGTH (string)))
+ /* APPLE LOCAL end pascal strings */
pedwarn ("initializer-string for array of chars is too long");
}
return string;
@@ -789,7 +805,15 @@ digest_init (tree type, tree init, tree* tail)
return process_init_constructor (type, 0, tail);
}
- if (code != ARRAY_TYPE)
+ /* APPLE LOCAL begin AltiVec */
+ if (code == VECTOR_TYPE
+ && TREE_CODE (init) == CONSTRUCTOR
+ && TREE_CODE (TREE_TYPE (init)) == VECTOR_TYPE
+ && vector_types_convertible_p (TREE_TYPE (init), type)
+ && TREE_CONSTANT (init))
+ return build_vector (type, CONSTRUCTOR_ELTS (init));
+ else if (code != ARRAY_TYPE)
+ /* APPLE LOCAL end AltiVec */
{
int flags = LOOKUP_NORMAL;
/* Initialization from { } is copy-initialization. */