diff options
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog.apple-ppc | 392 | ||||
-rw-r--r-- | gcc/cp/Make-lang.in | 28 | ||||
-rw-r--r-- | gcc/cp/call.c | 63 | ||||
-rw-r--r-- | gcc/cp/class.c | 211 | ||||
-rw-r--r-- | gcc/cp/cp-objcp-common.c | 15 | ||||
-rw-r--r-- | gcc/cp/cp-objcp-common.h | 16 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 54 | ||||
-rw-r--r-- | gcc/cp/decl.c | 219 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 43 | ||||
-rw-r--r-- | gcc/cp/init.c | 10 | ||||
-rw-r--r-- | gcc/cp/lang-specs.h | 2 | ||||
-rw-r--r-- | gcc/cp/lex.c | 52 | ||||
-rw-r--r-- | gcc/cp/mangle.c | 15 | ||||
-rw-r--r-- | gcc/cp/optimize.c | 189 | ||||
-rw-r--r-- | gcc/cp/parser.c | 2245 | ||||
-rw-r--r-- | gcc/cp/pt.c | 37 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 36 | ||||
-rw-r--r-- | gcc/cp/tree.c | 4 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 301 | ||||
-rw-r--r-- | gcc/cp/typeck2.c | 30 |
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. */ |