-2011-02-13 Mike Stump <mikestump@comcast.net>
-
- * config/t-darwin (build/slashify1): Harden against rebuilds.
- (config/darwin.h.rebuild): Harden against parallel builds.
- * config/slashify.c: Nix parms to quite the build.
-
2011-02-13 Ralf Wildenhues <Ralf.Wildenhues@gmx.de>
* configure: Regenerate.
-2011-02-12 Mike Stump <mikestump@comcast.net>
-
- * config/t-darwin (build/slashify): Allow others to reuse easier.
-
-2011-02-12 Mike Stump <mikestump@comcast.net>
-
- * config/darwin.h: Make pretty.
- * config/t-darwin (config/darwin.h.rebuild): Add.
- (build/slashify): Add.
- * config/slashify.c: Add.
-
2011-02-12 Joseph Myers <joseph@codesourcery.com>
PR driver/45731
2011-02-12 Iain Sandoe <iains@gcc.gnu.org>
* config/darwin.c (darwin_override_options): Add a hunk missed
- from the commit of r168571. Trim comment line lengths and
+ from the commit of r168571. Trim comment line lengths and
correct indents of the preceding block.
2011-02-12 Iain Sandoe <iains@gcc.gnu.org>
/* True if pragma ms_struct is in effect. */
extern GTY(()) int darwin_ms_struct;
-#define DRIVER_SELF_SPECS @(
- "%{gfull:-g -fno-eliminate-unused-debug-symbols} %<gfull",
- "%{gused:-g -feliminate-unused-debug-symbols} %<gused",
- "%{fapple-kext|mkernel:-static}",
- "%{shared:-Zdynamiclib} %<shared"@)
-
-#define DARWIN_CC1_SPEC @(
- "%{findirect-virtual-calls: -fapple-kext} %<findirect-virtual-calls "
- "%{fterminated-vtables: -fapple-kext} %<fterminated-vtables "
- "%<filelist* %<framework*"@)
-
-#define SUBSUBTARGET_OVERRIDE_OPTIONS @(
- do {
- darwin_override_options ();
- } while (0)@)
-
-#define SUBTARGET_C_COMMON_OVERRIDE_OPTIONS @(
- do {
- /* Sort out ObjC exceptions: If the runtime is NeXT we default to
- sjlj for m32 only. */
- if (!global_options_set.x_flag_objc_sjlj_exceptions)
- global_options.x_flag_objc_sjlj_exceptions
- = flag_next_runtime && !TARGET_64BIT;
- if (flag_mkernel || flag_apple_kext)
- {
- if (flag_use_cxa_atexit == 2)
- flag_use_cxa_atexit = 0;
- /* kexts should always be built without the coalesced sections
- because the kernel loader doesn't grok such sections. */
- flag_weak = 0;
- /* No RTTI in kexts. */
- flag_rtti = 0;
- }
- } while (0)@)
+#define DRIVER_SELF_SPECS \
+ "%{gfull:-g -fno-eliminate-unused-debug-symbols} %<gfull", \
+ "%{gused:-g -feliminate-unused-debug-symbols} %<gused", \
+ "%{fapple-kext|mkernel:-static}", \
+ "%{shared:-Zdynamiclib} %<shared"
+
+#define DARWIN_CC1_SPEC \
+ "%{findirect-virtual-calls: -fapple-kext} %<findirect-virtual-calls " \
+ "%{fterminated-vtables: -fapple-kext} %<fterminated-vtables " \
+ "%<filelist* %<framework*"
+
+#define SUBSUBTARGET_OVERRIDE_OPTIONS \
+ do { \
+ darwin_override_options (); \
+ } while (0)
+
+#define SUBTARGET_C_COMMON_OVERRIDE_OPTIONS do { \
+ /* Sort out ObjC exceptions: If the runtime is NeXT we default to \
+ sjlj for m32 only. */ \
+ if (!global_options_set.x_flag_objc_sjlj_exceptions) \
+ global_options.x_flag_objc_sjlj_exceptions = \
+ flag_next_runtime && !TARGET_64BIT; \
+ if (flag_mkernel || flag_apple_kext) \
+ { \
+ if (flag_use_cxa_atexit == 2) \
+ flag_use_cxa_atexit = 0; \
+ /* kexts should always be built without the coalesced sections \
+ because the kernel loader doesn't grok such sections. */ \
+ flag_weak = 0; \
+ /* No RTTI in kexts. */ \
+ flag_rtti = 0; \
+ } \
+ } while (0)
/* Machine dependent cpp options. Don't add more options here, add
them to darwin_cpp_builtins in darwin-c.c. */
#undef CPP_SPEC
-#define CPP_SPEC "%{static:%{!dynamic:-D__STATIC__}}%{!static:-D__DYNAMIC__}" @(
- " %{pthread:-D_REENTRANT}"@)
+#define CPP_SPEC "%{static:%{!dynamic:-D__STATIC__}}%{!static:-D__DYNAMIC__}" \
+ " %{pthread:-D_REENTRANT}"
/* This is mostly a clone of the standard LINK_COMMAND_SPEC, plus
precomp, libtool, and fat build additions.
specifying the handling of options understood by generic Unix
linkers, and for positional arguments like libraries. */
-#define LINK_COMMAND_SPEC_A @(
- "%{!fdump=*:%{!fsyntax-only:%{!c:%{!M:%{!MM:%{!E:%{!S:
- %(linker)
- %{flto*:%<fcompare-debug*}
- %{flto*}
- %l %X %{s} %{t} %{Z} %{u*}
- %{e*} %{r}
- %{o*}%{!o:-o a.out}
- %{!nostdlib:%{!nostartfiles:%S}}
- %{L*} %(link_libgcc) %o %{fprofile-arcs|fprofile-generate*|coverage:-lgcov}
- %{fopenmp|ftree-parallelize-loops=*:
- %{static|static-libgcc|static-libstdc++|static-libgfortran: libgomp.a%s; : -lgomp } }
- %{!nostdlib:%{!nodefaultlibs:
- %(link_ssp) %(link_gcc_c_sequence)
- }}
- %{!nostdlib:%{!nostartfiles:%E}} %{T*} %{F*} }}}}}}}"@)
+#define LINK_COMMAND_SPEC_A \
+ "%{!fdump=*:%{!fsyntax-only:%{!c:%{!M:%{!MM:%{!E:%{!S:\
+ %(linker) \
+ %{flto*:%<fcompare-debug*} \
+ %{flto*} \
+ %l %X %{s} %{t} %{Z} %{u*} \
+ %{e*} %{r} \
+ %{o*}%{!o:-o a.out} \
+ %{!nostdlib:%{!nostartfiles:%S}} \
+ %{L*} %(link_libgcc) %o %{fprofile-arcs|fprofile-generate*|coverage:-lgcov} \
+ %{fopenmp|ftree-parallelize-loops=*: \
+ %{static|static-libgcc|static-libstdc++|static-libgfortran: libgomp.a%s; : -lgomp } } \
+ %{!nostdlib:%{!nodefaultlibs:\
+ %(link_ssp) %(link_gcc_c_sequence)\
+ }}\
+ %{!nostdlib:%{!nostartfiles:%E}} %{T*} %{F*} }}}}}}}"
#define DSYMUTIL "\ndsymutil"
-#define DSYMUTIL_SPEC @(
- "%{!fdump=*:%{!fsyntax-only:%{!c:%{!M:%{!MM:%{!E:%{!S:
- %{v}
- %{gdwarf-2:%{!gstabs*:%{!g0: -idsym}}}
- %{.c|.cc|.C|.cpp|.cp|.c++|.cxx|.CPP|.m|.mm:
- %{gdwarf-2:%{!gstabs*:%{!g0: -dsym}}}}}}}}}}}"@)
+#define DSYMUTIL_SPEC \
+ "%{!fdump=*:%{!fsyntax-only:%{!c:%{!M:%{!MM:%{!E:%{!S:\
+ %{v} \
+ %{gdwarf-2:%{!gstabs*:%{!g0: -idsym}}}\
+ %{.c|.cc|.C|.cpp|.cp|.c++|.cxx|.CPP|.m|.mm: \
+ %{gdwarf-2:%{!gstabs*:%{!g0: -dsym}}}}}}}}}}}"
#define LINK_COMMAND_SPEC LINK_COMMAND_SPEC_A DSYMUTIL_SPEC
#define LINK_GCC_C_SEQUENCE_SPEC "%G %L"
#ifdef TARGET_SYSTEM_ROOT
-#define LINK_SYSROOT_SPEC @(
- "%{isysroot*:-syslibroot %*;:-syslibroot " TARGET_SYSTEM_ROOT "}"@)
+#define LINK_SYSROOT_SPEC \
+ "%{isysroot*:-syslibroot %*;:-syslibroot " TARGET_SYSTEM_ROOT "}"
#else
#define LINK_SYSROOT_SPEC "%{isysroot*:-syslibroot %*}"
#endif
'Z' and 'no' prefixes). Note that options taking arguments may appear
multiple times on a command line with different arguments each time,
so put a * after their names so all of them get passed. */
-#define LINK_SPEC @(
- "%{static}%{!static:-dynamic}
- %:remove-outfile(-ldl)
- %:remove-outfile(-lm)
- %:remove-outfile(-lpthread)
- %{fgnu-runtime: %{static|static-libgcc:
- %:replace-outfile(-lobjc libobjc-gnu.a%s);
- :%:replace-outfile(-lobjc -lobjc-gnu ) } }
- %{static|static-libgcc|static-libgfortran:%:replace-outfile(-lgfortran libgfortran.a%s)}
- %{static|static-libgcc|static-libstdc++|static-libgfortran:%:replace-outfile(-lgomp libgomp.a%s)}
- %{static|static-libgcc|static-libstdc++:%:replace-outfile(-lstdc++ libstdc++.a%s)}
- %{!Zdynamiclib:
- %{Zforce_cpusubtype_ALL:-arch %(darwin_arch) -force_cpusubtype_ALL}
- %{!Zforce_cpusubtype_ALL:-arch %(darwin_subarch)}
- %{Zbundle:-bundle}
- %{Zbundle_loader*:-bundle_loader %*}
- %{client_name*}
- %{compatibility_version*:%e-compatibility_version only allowed with -dynamiclib
-}
- %{current_version*:%e-current_version only allowed with -dynamiclib}
- %{Zforce_flat_namespace:-force_flat_namespace}
- %{Zinstall_name*:%e-install_name only allowed with -dynamiclib}
- %{keep_private_externs}
- %{private_bundle}
- }
- %{Zdynamiclib: -dylib
- %{Zbundle:%e-bundle not allowed with -dynamiclib}
- %{Zbundle_loader*:%e-bundle_loader not allowed with -dynamiclib}
- %{client_name*:%e-client_name not allowed with -dynamiclib}
- %{compatibility_version*:-dylib_compatibility_version %*}
- %{current_version*:-dylib_current_version %*}
- %{Zforce_cpusubtype_ALL:-arch %(darwin_arch)}
- %{!Zforce_cpusubtype_ALL: -arch %(darwin_subarch)}
- %{Zforce_flat_namespace:%e-force_flat_namespace not allowed with -dynamiclib}
- %{Zinstall_name*:-dylib_install_name %*}
- %{keep_private_externs:%e-keep_private_externs not allowed with -dynamiclib}
- %{private_bundle:%e-private_bundle not allowed with -dynamiclib}
- }
- %{Zall_load:-all_load}
- %{Zallowable_client*:-allowable_client %*}
- %{Zbind_at_load:-bind_at_load}
- %{Zarch_errors_fatal:-arch_errors_fatal}
- %{Zdead_strip:-dead_strip}
- %{Zno_dead_strip_inits_and_terms:-no_dead_strip_inits_and_terms}
- %{Zdylib_file*:-dylib_file %*}
- %{Zdynamic:-dynamic}
- %{Zexported_symbols_list*:-exported_symbols_list %*}
- %{Zflat_namespace:-flat_namespace}
- %{headerpad_max_install_names}
- %{Zimage_base*:-image_base %*}
- %{Zinit*:-init %*}
- %{!mmacosx-version-min=*:-macosx_version_min %(darwin_minversion)}
- %{mmacosx-version-min=*:-macosx_version_min %*}
- %{nomultidefs}
- %{Zmulti_module:-multi_module} %{Zsingle_module:-single_module}
- %{Zmultiply_defined*:-multiply_defined %*}
- %{!Zmultiply_defined*:%{shared-libgcc:
- %:version-compare(< 10.5 mmacosx-version-min= -multiply_defined)
- %:version-compare(< 10.5 mmacosx-version-min= suppress)}}
- %{Zmultiplydefinedunused*:-multiply_defined_unused %*}
- %{fpie:-pie}
- %{prebind} %{noprebind} %{nofixprebinding} %{prebind_all_twolevel_modules}
- %{read_only_relocs}
- %{sectcreate*} %{sectorder*} %{seg1addr*} %{segprot*}
- %{Zsegaddr*:-segaddr %*}
- %{Zsegs_read_only_addr*:-segs_read_only_addr %*}
- %{Zsegs_read_write_addr*:-segs_read_write_addr %*}
- %{Zseg_addr_table*: -seg_addr_table %*}
- %{Zfn_seg_addr_table_filename*:-seg_addr_table_filename %*}
- %{sub_library*} %{sub_umbrella*}
- " LINK_SYSROOT_SPEC "
- %{twolevel_namespace} %{twolevel_namespace_hints}
- %{Zumbrella*: -umbrella %*}
- %{undefined*}
- %{Zunexported_symbols_list*:-unexported_symbols_list %*}
- %{Zweak_reference_mismatches*:-weak_reference_mismatches %*}
- %{!Zweak_reference_mismatches*:-weak_reference_mismatches non-weak}
- %{X}
- %{y*}
- %{w}
- %{pagezero_size*} %{segs_read_*} %{seglinkedit} %{noseglinkedit}
- %{sectalign*} %{sectobjectsymbols*} %{segcreate*} %{whyload}
- %{whatsloaded} %{dylinker_install_name*}
- %{dylinker} %{Mach} "@)
+#define LINK_SPEC \
+ "%{static}%{!static:-dynamic} \
+ %:remove-outfile(-ldl) \
+ %:remove-outfile(-lm) \
+ %:remove-outfile(-lpthread) \
+ %{fgnu-runtime: %{static|static-libgcc: \
+ %:replace-outfile(-lobjc libobjc-gnu.a%s); \
+ :%:replace-outfile(-lobjc -lobjc-gnu ) } }\
+ %{static|static-libgcc|static-libgfortran:%:replace-outfile(-lgfortran libgfortran.a%s)}\
+ %{static|static-libgcc|static-libstdc++|static-libgfortran:%:replace-outfile(-lgomp libgomp.a%s)}\
+ %{static|static-libgcc|static-libstdc++:%:replace-outfile(-lstdc++ libstdc++.a%s)}\
+ %{!Zdynamiclib: \
+ %{Zforce_cpusubtype_ALL:-arch %(darwin_arch) -force_cpusubtype_ALL} \
+ %{!Zforce_cpusubtype_ALL:-arch %(darwin_subarch)} \
+ %{Zbundle:-bundle} \
+ %{Zbundle_loader*:-bundle_loader %*} \
+ %{client_name*} \
+ %{compatibility_version*:%e-compatibility_version only allowed with -dynamiclib\
+} \
+ %{current_version*:%e-current_version only allowed with -dynamiclib} \
+ %{Zforce_flat_namespace:-force_flat_namespace} \
+ %{Zinstall_name*:%e-install_name only allowed with -dynamiclib} \
+ %{keep_private_externs} \
+ %{private_bundle} \
+ } \
+ %{Zdynamiclib: -dylib \
+ %{Zbundle:%e-bundle not allowed with -dynamiclib} \
+ %{Zbundle_loader*:%e-bundle_loader not allowed with -dynamiclib} \
+ %{client_name*:%e-client_name not allowed with -dynamiclib} \
+ %{compatibility_version*:-dylib_compatibility_version %*} \
+ %{current_version*:-dylib_current_version %*} \
+ %{Zforce_cpusubtype_ALL:-arch %(darwin_arch)} \
+ %{!Zforce_cpusubtype_ALL: -arch %(darwin_subarch)} \
+ %{Zforce_flat_namespace:%e-force_flat_namespace not allowed with -dynamiclib} \
+ %{Zinstall_name*:-dylib_install_name %*} \
+ %{keep_private_externs:%e-keep_private_externs not allowed with -dynamiclib} \
+ %{private_bundle:%e-private_bundle not allowed with -dynamiclib} \
+ } \
+ %{Zall_load:-all_load} \
+ %{Zallowable_client*:-allowable_client %*} \
+ %{Zbind_at_load:-bind_at_load} \
+ %{Zarch_errors_fatal:-arch_errors_fatal} \
+ %{Zdead_strip:-dead_strip} \
+ %{Zno_dead_strip_inits_and_terms:-no_dead_strip_inits_and_terms} \
+ %{Zdylib_file*:-dylib_file %*} \
+ %{Zdynamic:-dynamic}\
+ %{Zexported_symbols_list*:-exported_symbols_list %*} \
+ %{Zflat_namespace:-flat_namespace} \
+ %{headerpad_max_install_names} \
+ %{Zimage_base*:-image_base %*} \
+ %{Zinit*:-init %*} \
+ %{!mmacosx-version-min=*:-macosx_version_min %(darwin_minversion)} \
+ %{mmacosx-version-min=*:-macosx_version_min %*} \
+ %{nomultidefs} \
+ %{Zmulti_module:-multi_module} %{Zsingle_module:-single_module} \
+ %{Zmultiply_defined*:-multiply_defined %*} \
+ %{!Zmultiply_defined*:%{shared-libgcc: \
+ %:version-compare(< 10.5 mmacosx-version-min= -multiply_defined) \
+ %:version-compare(< 10.5 mmacosx-version-min= suppress)}} \
+ %{Zmultiplydefinedunused*:-multiply_defined_unused %*} \
+ %{fpie:-pie} \
+ %{prebind} %{noprebind} %{nofixprebinding} %{prebind_all_twolevel_modules} \
+ %{read_only_relocs} \
+ %{sectcreate*} %{sectorder*} %{seg1addr*} %{segprot*} \
+ %{Zsegaddr*:-segaddr %*} \
+ %{Zsegs_read_only_addr*:-segs_read_only_addr %*} \
+ %{Zsegs_read_write_addr*:-segs_read_write_addr %*} \
+ %{Zseg_addr_table*: -seg_addr_table %*} \
+ %{Zfn_seg_addr_table_filename*:-seg_addr_table_filename %*} \
+ %{sub_library*} %{sub_umbrella*} \
+ " LINK_SYSROOT_SPEC " \
+ %{twolevel_namespace} %{twolevel_namespace_hints} \
+ %{Zumbrella*: -umbrella %*} \
+ %{undefined*} \
+ %{Zunexported_symbols_list*:-unexported_symbols_list %*} \
+ %{Zweak_reference_mismatches*:-weak_reference_mismatches %*} \
+ %{!Zweak_reference_mismatches*:-weak_reference_mismatches non-weak} \
+ %{X} \
+ %{y*} \
+ %{w} \
+ %{pagezero_size*} %{segs_read_*} %{seglinkedit} %{noseglinkedit} \
+ %{sectalign*} %{sectobjectsymbols*} %{segcreate*} %{whyload} \
+ %{whatsloaded} %{dylinker_install_name*} \
+ %{dylinker} %{Mach} "
/* Machine dependent libraries. */
If it is linked against, it has to be before -lgcc, because it may
need symbols from -lgcc. */
#undef REAL_LIBGCC_SPEC
-#define REAL_LIBGCC_SPEC @(
- "%{static-libgcc|static: -lgcc_eh -lgcc;
- shared-libgcc|fexceptions|fgnu-runtime:
- %:version-compare(!> 10.5 mmacosx-version-min= -lgcc_s.10.4)
- %:version-compare(>< 10.5 10.6 mmacosx-version-min= -lgcc_s.10.5)
- %:version-compare(!> 10.5 mmacosx-version-min= -lgcc_ext.10.4)
- %:version-compare(>= 10.5 mmacosx-version-min= -lgcc_ext.10.5)
- -lgcc ;
- :%:version-compare(>< 10.3.9 10.5 mmacosx-version-min= -lgcc_s.10.4)
- %:version-compare(>< 10.5 10.6 mmacosx-version-min= -lgcc_s.10.5)
- %:version-compare(!> 10.5 mmacosx-version-min= -lgcc_ext.10.4)
- %:version-compare(>= 10.5 mmacosx-version-min= -lgcc_ext.10.5)
- -lgcc }"@)
+#define REAL_LIBGCC_SPEC \
+ "%{static-libgcc|static: -lgcc_eh -lgcc; \
+ shared-libgcc|fexceptions|fgnu-runtime: \
+ %:version-compare(!> 10.5 mmacosx-version-min= -lgcc_s.10.4) \
+ %:version-compare(>< 10.5 10.6 mmacosx-version-min= -lgcc_s.10.5) \
+ %:version-compare(!> 10.5 mmacosx-version-min= -lgcc_ext.10.4) \
+ %:version-compare(>= 10.5 mmacosx-version-min= -lgcc_ext.10.5) \
+ -lgcc ; \
+ :%:version-compare(>< 10.3.9 10.5 mmacosx-version-min= -lgcc_s.10.4) \
+ %:version-compare(>< 10.5 10.6 mmacosx-version-min= -lgcc_s.10.5) \
+ %:version-compare(!> 10.5 mmacosx-version-min= -lgcc_ext.10.4) \
+ %:version-compare(>= 10.5 mmacosx-version-min= -lgcc_ext.10.5) \
+ -lgcc }"
/* We specify crt0.o as -lcrt0.o so that ld will search the library path.
powerpc program built. */
#undef STARTFILE_SPEC
-#define STARTFILE_SPEC @(
- "%{Zdynamiclib: %(darwin_dylib1) }
- %{!Zdynamiclib:%{Zbundle:%{!static:-lbundle1.o}}
- %{!Zbundle:%{pg:%{static:-lgcrt0.o}
- %{!static:%{object:-lgcrt0.o}
- %{!object:%{preload:-lgcrt0.o}
- %{!preload:-lgcrt1.o %(darwin_crt2)}}}}
- %{!pg:%{static:-lcrt0.o}
- %{!static:%{object:-lcrt0.o}
- %{!object:%{preload:-lcrt0.o}
- %{!preload: %(darwin_crt1)
- %(darwin_crt2)}}}}}}
- %{shared-libgcc:%:version-compare(< 10.5 mmacosx-version-min= crt3.o%s)}"@)
+#define STARTFILE_SPEC \
+ "%{Zdynamiclib: %(darwin_dylib1) } \
+ %{!Zdynamiclib:%{Zbundle:%{!static:-lbundle1.o}} \
+ %{!Zbundle:%{pg:%{static:-lgcrt0.o} \
+ %{!static:%{object:-lgcrt0.o} \
+ %{!object:%{preload:-lgcrt0.o} \
+ %{!preload:-lgcrt1.o %(darwin_crt2)}}}} \
+ %{!pg:%{static:-lcrt0.o} \
+ %{!static:%{object:-lcrt0.o} \
+ %{!object:%{preload:-lcrt0.o} \
+ %{!preload: %(darwin_crt1) \
+ %(darwin_crt2)}}}}}} \
+ %{shared-libgcc:%:version-compare(< 10.5 mmacosx-version-min= crt3.o%s)}"
/* The native Darwin linker doesn't necessarily place files in the order
that they're specified on the link line. Thus, it is pointless
to put anything in ENDFILE_SPEC. */
/* #define ENDFILE_SPEC "" */
-#define DARWIN_EXTRA_SPECS @(
- { "darwin_crt1", DARWIN_CRT1_SPEC },
- { "darwin_dylib1", DARWIN_DYLIB1_SPEC },
- { "darwin_minversion", DARWIN_MINVERSION_SPEC },@)
+#define DARWIN_EXTRA_SPECS \
+ { "darwin_crt1", DARWIN_CRT1_SPEC }, \
+ { "darwin_dylib1", DARWIN_DYLIB1_SPEC }, \
+ { "darwin_minversion", DARWIN_MINVERSION_SPEC },
-#define DARWIN_DYLIB1_SPEC @(
- "%:version-compare(!> 10.5 mmacosx-version-min= -ldylib1.o)
- %:version-compare(>= 10.5 mmacosx-version-min= -ldylib1.10.5.o)"@)
+#define DARWIN_DYLIB1_SPEC \
+ "%:version-compare(!> 10.5 mmacosx-version-min= -ldylib1.o) \
+ %:version-compare(>= 10.5 mmacosx-version-min= -ldylib1.10.5.o)"
-#define DARWIN_CRT1_SPEC @(
- "%:version-compare(!> 10.5 mmacosx-version-min= -lcrt1.o)
- %:version-compare(>= 10.5 mmacosx-version-min= -lcrt1.10.5.o)"@)
+#define DARWIN_CRT1_SPEC \
+ "%:version-compare(!> 10.5 mmacosx-version-min= -lcrt1.o) \
+ %:version-compare(>= 10.5 mmacosx-version-min= -lcrt1.10.5.o)"
/* Default Darwin ASM_SPEC, very simple. */
-#define ASM_SPEC "-arch %(darwin_arch) @(
- %{Zforce_cpusubtype_ALL:-force_cpusubtype_ALL}
- %{static}"@)
+#define ASM_SPEC "-arch %(darwin_arch) \
+ %{Zforce_cpusubtype_ALL:-force_cpusubtype_ALL} \
+ %{static}"
/* We still allow output of STABS. */
coalesced sections. Weak aliases (or any other kind of aliases) are
not supported. Weak symbols that aren't visible outside the .s file
are not supported. */
-#define ASM_WEAKEN_DECL(FILE, DECL, NAME, ALIAS) @(
- do {
- if (ALIAS)
- {
- warning (0, "alias definitions not supported in Mach-O; ignored");
- break;
- }
-
- if (! DECL_EXTERNAL (DECL) && TREE_PUBLIC (DECL))
- targetm.asm_out.globalize_label (FILE, NAME);
- if (DECL_EXTERNAL (DECL))
- fputs ("\t.weak_reference ", FILE);
- else if (lookup_attribute ("weak_import", DECL_ATTRIBUTES (DECL)))
- break;
- else if (TREE_PUBLIC (DECL))
- fputs ("\t.weak_definition ", FILE);
- else
- break;
- assemble_name (FILE, NAME);
- fputc ('\n', FILE);
- } while (0)@)
+#define ASM_WEAKEN_DECL(FILE, DECL, NAME, ALIAS) \
+ do { \
+ if (ALIAS) \
+ { \
+ warning (0, "alias definitions not supported in Mach-O; ignored"); \
+ break; \
+ } \
+ \
+ if (! DECL_EXTERNAL (DECL) && TREE_PUBLIC (DECL)) \
+ targetm.asm_out.globalize_label (FILE, NAME); \
+ if (DECL_EXTERNAL (DECL)) \
+ fputs ("\t.weak_reference ", FILE); \
+ else if (lookup_attribute ("weak_import", DECL_ATTRIBUTES (DECL))) \
+ break; \
+ else if (TREE_PUBLIC (DECL)) \
+ fputs ("\t.weak_definition ", FILE); \
+ else \
+ break; \
+ assemble_name (FILE, NAME); \
+ fputc ('\n', FILE); \
+ } while (0)
/* Darwin has the pthread routines in libSystem, which every program
links to, so there's no need for weak-ness for that. */
#undef TARGET_ASM_LTO_END
#define TARGET_ASM_LTO_END darwin_asm_lto_end
-#define ASM_OUTPUT_SKIP(FILE,SIZE) @(
- fprintf (FILE, "\t.space "HOST_WIDE_INT_PRINT_UNSIGNED"\n", SIZE)@)
+#define ASM_OUTPUT_SKIP(FILE,SIZE) \
+ fprintf (FILE, "\t.space "HOST_WIDE_INT_PRINT_UNSIGNED"\n", SIZE)
/* Give ObjC methods pretty symbol names. */
#undef OBJC_GEN_METHOD_LABEL
-#define OBJC_GEN_METHOD_LABEL(BUF,IS_INST,CLASS_NAME,CAT_NAME,SEL_NAME,NUM) @(
- do { if (CAT_NAME)
- sprintf (BUF, "%c[%s(%s) %s]", (IS_INST) ? '-' : '+',
- (CLASS_NAME), (CAT_NAME), (SEL_NAME));
- else
- sprintf (BUF, "%c[%s %s]", (IS_INST) ? '-' : '+',
- (CLASS_NAME), (SEL_NAME));
- } while (0)@)
+#define OBJC_GEN_METHOD_LABEL(BUF,IS_INST,CLASS_NAME,CAT_NAME,SEL_NAME,NUM) \
+ do { if (CAT_NAME) \
+ sprintf (BUF, "%c[%s(%s) %s]", (IS_INST) ? '-' : '+', \
+ (CLASS_NAME), (CAT_NAME), (SEL_NAME)); \
+ else \
+ sprintf (BUF, "%c[%s %s]", (IS_INST) ? '-' : '+', \
+ (CLASS_NAME), (SEL_NAME)); \
+ } while (0)
#undef ASM_DECLARE_OBJECT_NAME
-#define ASM_DECLARE_OBJECT_NAME(FILE, NAME, DECL) @(
- darwin_asm_declare_object_name ((FILE), (NAME), (DECL))@)
+#define ASM_DECLARE_OBJECT_NAME(FILE, NAME, DECL) \
+ darwin_asm_declare_object_name ((FILE), (NAME), (DECL))
/* The RTTI data (e.g., __ti4name) is common and public (and static),
but it does need to be referenced via indirect PIC data pointers.
that the name *is* defined in this module, so it doesn't need to
make them indirect. */
-#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) @(
- do {
- const char *xname = NAME;
- if (GET_CODE (XEXP (DECL_RTL (DECL), 0)) != SYMBOL_REF)
- xname = IDENTIFIER_POINTER (DECL_NAME (DECL));
- if (! DECL_WEAK (DECL)
- && ((TREE_STATIC (DECL)
- && (!DECL_COMMON (DECL) || !TREE_PUBLIC (DECL)))
- || DECL_INITIAL (DECL)))
- machopic_define_symbol (DECL_RTL (DECL));
- if ((TREE_STATIC (DECL)
- && (!DECL_COMMON (DECL) || !TREE_PUBLIC (DECL)))
- || DECL_INITIAL (DECL))
- (* targetm.encode_section_info) (DECL, DECL_RTL (DECL), false);
- ASM_OUTPUT_FUNCTION_LABEL (FILE, xname, DECL);
- } while (0)@)
+#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \
+ do { \
+ const char *xname = NAME; \
+ if (GET_CODE (XEXP (DECL_RTL (DECL), 0)) != SYMBOL_REF) \
+ xname = IDENTIFIER_POINTER (DECL_NAME (DECL)); \
+ if (! DECL_WEAK (DECL) \
+ && ((TREE_STATIC (DECL) \
+ && (!DECL_COMMON (DECL) || !TREE_PUBLIC (DECL))) \
+ || DECL_INITIAL (DECL))) \
+ machopic_define_symbol (DECL_RTL (DECL)); \
+ if ((TREE_STATIC (DECL) \
+ && (!DECL_COMMON (DECL) || !TREE_PUBLIC (DECL))) \
+ || DECL_INITIAL (DECL)) \
+ (* targetm.encode_section_info) (DECL, DECL_RTL (DECL), false); \
+ ASM_OUTPUT_FUNCTION_LABEL (FILE, xname, DECL); \
+ } while (0)
#undef TARGET_ASM_DECLARE_CONSTANT_NAME
#define TARGET_ASM_DECLARE_CONSTANT_NAME darwin_asm_declare_constant_name
/* Wrap new method names in quotes so the assembler doesn't gag.
- Make Objective-C internal symbols local and in doing this, we need
+ Make Objective-C internal symbols local and in doing this, we need
to accommodate the name mangling done by c++ on file scope locals. */
int darwin_label_is_anonymous_local_objc_name (const char *name);
#undef ASM_OUTPUT_LABELREF
-#define ASM_OUTPUT_LABELREF(FILE,NAME) @(
- do {
- const char *xname = (NAME);
- if (! strcmp (xname, MACHOPIC_FUNCTION_BASE_NAME))
- machopic_output_function_base_name(FILE);
- else if (xname[0] == '&' || xname[0] == '*')
- {
- int len = strlen (xname);
- if (len > 6 && !strcmp ("$stub", xname + len - 5))
- machopic_validate_stub_or_non_lazy_ptr (xname);
- else if (len > 7 && !strcmp ("$stub\"", xname + len - 6))
- machopic_validate_stub_or_non_lazy_ptr (xname);
- else if (len > 14 && !strcmp ("$non_lazy_ptr", xname + len - 13))
- machopic_validate_stub_or_non_lazy_ptr (xname);
- else if (len > 15 && !strcmp ("$non_lazy_ptr\"", xname + len - 14))
- machopic_validate_stub_or_non_lazy_ptr (xname);
- if (xname[1] != '"' && name_needs_quotes (&xname[1]))
- fprintf (FILE, "\"%s\"", &xname[1]);
- else
- fputs (&xname[1], FILE);
- }
- else if (xname[0] == '+' || xname[0] == '-')
- fprintf (FILE, "\"%s\"", xname);
- else if (darwin_label_is_anonymous_local_objc_name (xname))
- fprintf (FILE, "L%s", xname);
- else if (!strncmp (xname, ".objc_class_name_", 17))
- fprintf (FILE, "%s", xname);
- else if (xname[0] != '"' && name_needs_quotes (xname))
- fprintf (FILE, "\"%s\"", xname);
- else
- asm_fprintf (FILE, "%U%s", xname);
- } while (0)@)
+#define ASM_OUTPUT_LABELREF(FILE,NAME) \
+ do { \
+ const char *xname = (NAME); \
+ if (! strcmp (xname, MACHOPIC_FUNCTION_BASE_NAME)) \
+ machopic_output_function_base_name(FILE); \
+ else if (xname[0] == '&' || xname[0] == '*') \
+ { \
+ int len = strlen (xname); \
+ if (len > 6 && !strcmp ("$stub", xname + len - 5)) \
+ machopic_validate_stub_or_non_lazy_ptr (xname); \
+ else if (len > 7 && !strcmp ("$stub\"", xname + len - 6)) \
+ machopic_validate_stub_or_non_lazy_ptr (xname); \
+ else if (len > 14 && !strcmp ("$non_lazy_ptr", xname + len - 13)) \
+ machopic_validate_stub_or_non_lazy_ptr (xname); \
+ else if (len > 15 && !strcmp ("$non_lazy_ptr\"", xname + len - 14)) \
+ machopic_validate_stub_or_non_lazy_ptr (xname); \
+ if (xname[1] != '"' && name_needs_quotes (&xname[1])) \
+ fprintf (FILE, "\"%s\"", &xname[1]); \
+ else \
+ fputs (&xname[1], FILE); \
+ } \
+ else if (xname[0] == '+' || xname[0] == '-') \
+ fprintf (FILE, "\"%s\"", xname); \
+ else if (darwin_label_is_anonymous_local_objc_name (xname)) \
+ fprintf (FILE, "L%s", xname); \
+ else if (!strncmp (xname, ".objc_class_name_", 17)) \
+ fprintf (FILE, "%s", xname); \
+ else if (xname[0] != '"' && name_needs_quotes (xname)) \
+ fprintf (FILE, "\"%s\"", xname); \
+ else \
+ asm_fprintf (FILE, "%U%s", xname); \
+ } while (0)
/* Output before executable code. */
#undef TEXT_SECTION_ASM_OP
#define ALIGN_ASM_OP ".align"
#undef ASM_OUTPUT_ALIGN
-#define ASM_OUTPUT_ALIGN(FILE,LOG) @(
- if ((LOG) != 0)
- fprintf (FILE, "\t%s\t%d\n", ALIGN_ASM_OP, (LOG))@)
+#define ASM_OUTPUT_ALIGN(FILE,LOG) \
+ if ((LOG) != 0) \
+ fprintf (FILE, "\t%s\t%d\n", ALIGN_ASM_OP, (LOG))
/* The maximum alignment which the object file format can support in
bits. For Mach-O, this is 2^15 bytes. */
#define L2_MAX_OFILE_ALIGNMENT 15
/* These are the three variants that emit referenced blank space. */
-#define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) @(
- darwin_output_aligned_bss ((FILE), (DECL), (NAME), (SIZE), (ALIGN))@)
+#define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \
+ darwin_output_aligned_bss ((FILE), (DECL), (NAME), (SIZE), (ALIGN))
#undef ASM_OUTPUT_ALIGNED_DECL_LOCAL
-#define ASM_OUTPUT_ALIGNED_DECL_LOCAL(FILE, DECL, NAME, SIZE, ALIGN) @(
- darwin_asm_output_aligned_decl_local
- ((FILE), (DECL), (NAME), (SIZE), (ALIGN))@)
+#define ASM_OUTPUT_ALIGNED_DECL_LOCAL(FILE, DECL, NAME, SIZE, ALIGN) \
+ darwin_asm_output_aligned_decl_local \
+ ((FILE), (DECL), (NAME), (SIZE), (ALIGN))
#undef ASM_OUTPUT_ALIGNED_DECL_COMMON
-#define ASM_OUTPUT_ALIGNED_DECL_COMMON(FILE, DECL, NAME, SIZE, ALIGN) @(
- darwin_asm_output_aligned_decl_common
- ((FILE), (DECL), (NAME), (SIZE), (ALIGN))@)
+#define ASM_OUTPUT_ALIGNED_DECL_COMMON(FILE, DECL, NAME, SIZE, ALIGN) \
+ darwin_asm_output_aligned_decl_common \
+ ((FILE), (DECL), (NAME), (SIZE), (ALIGN))
/* The generic version, archs should over-ride where required. */
#define MACHOPIC_NL_SYMBOL_PTR_SECTION ".non_lazy_symbol_pointer"
#define TARGET_ASM_FUNCTION_SECTION darwin_function_section
#undef TARGET_ASM_FUNCTION_SWITCHED_TEXT_SECTIONS
-#define TARGET_ASM_FUNCTION_SWITCHED_TEXT_SECTIONS @(
- darwin_function_switched_text_sections@)
+#define TARGET_ASM_FUNCTION_SWITCHED_TEXT_SECTIONS \
+ darwin_function_switched_text_sections
#undef TARGET_ASM_SELECT_RTX_SECTION
#define TARGET_ASM_SELECT_RTX_SECTION machopic_select_rtx_section
#define TARGET_ASM_RELOC_RW_MASK machopic_reloc_rw_mask
-#define ASM_DECLARE_UNRESOLVED_REFERENCE(FILE,NAME) @(
- do {
- if (FILE) {
- if (MACHOPIC_INDIRECT)
- fprintf (FILE, "\t.lazy_reference ");
- else
- fprintf (FILE, "\t.reference ");
- assemble_name (FILE, NAME);
- fprintf (FILE, "\n");
- }
- } while (0)@)
-
-#define ASM_DECLARE_CLASS_REFERENCE(FILE,NAME) @(
- do {
- if (FILE) {
- fprintf (FILE, "\t");
- assemble_name (FILE, NAME);
- fprintf (FILE, "=0\n");
- (*targetm.asm_out.globalize_label) (FILE, NAME);
- }
- } while (0)@)
+#define ASM_DECLARE_UNRESOLVED_REFERENCE(FILE,NAME) \
+ do { \
+ if (FILE) { \
+ if (MACHOPIC_INDIRECT) \
+ fprintf (FILE, "\t.lazy_reference "); \
+ else \
+ fprintf (FILE, "\t.reference "); \
+ assemble_name (FILE, NAME); \
+ fprintf (FILE, "\n"); \
+ } \
+ } while (0)
+
+#define ASM_DECLARE_CLASS_REFERENCE(FILE,NAME) \
+ do { \
+ if (FILE) { \
+ fprintf (FILE, "\t"); \
+ assemble_name (FILE, NAME); \
+ fprintf (FILE, "=0\n"); \
+ (*targetm.asm_out.globalize_label) (FILE, NAME); \
+ } \
+ } while (0)
/* Globalizing directive for a label. */
#define GLOBAL_ASM_OP "\t.globl "
#define TARGET_ASM_ASSEMBLE_VISIBILITY darwin_assemble_visibility
/* Extra attributes for Darwin. */
-#define SUBTARGET_ATTRIBUTE_TABLE @(
- /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
- { "apple_kext_compatibility", 0, 0, false, true, false,
- darwin_handle_kext_attribute },
- { "weak_import", 0, 0, true, false, false,
- darwin_handle_weak_import_attribute }@)
+#define SUBTARGET_ATTRIBUTE_TABLE \
+ /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */ \
+ { "apple_kext_compatibility", 0, 0, false, true, false, \
+ darwin_handle_kext_attribute }, \
+ { "weak_import", 0, 0, true, false, false, \
+ darwin_handle_weak_import_attribute }
#undef ASM_GENERATE_INTERNAL_LABEL
-#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) @(
- sprintf (LABEL, "*%s%ld", PREFIX, (long)(NUM))@)
+#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \
+ sprintf (LABEL, "*%s%ld", PREFIX, (long)(NUM))
#undef TARGET_ASM_MARK_DECL_PRESERVED
#define TARGET_ASM_MARK_DECL_PRESERVED darwin_mark_decl_preserved
#undef TARGET_STRIP_NAME_ENCODING
#define TARGET_STRIP_NAME_ENCODING default_strip_name_encoding
-#define GEN_BINDER_NAME_FOR_STUB(BUF,STUB,STUB_LENGTH) @(
- do {
- const char *const stub_ = (STUB);
- char *buffer_ = (BUF);
- strcpy (buffer_, stub_);
- if (stub_[0] == '"')
- {
- strcpy (buffer_ + (STUB_LENGTH) - 1, "_binder\"");
- }
- else
- {
- strcpy (buffer_ + (STUB_LENGTH), "_binder");
- }
- } while (0)@)
-
-#define GEN_SYMBOL_NAME_FOR_SYMBOL(BUF,SYMBOL,SYMBOL_LENGTH) @(
- do {
- const char *const symbol_ = (SYMBOL);
- char *buffer_ = (BUF);
- if (name_needs_quotes (symbol_) && symbol_[0] != '"')
- {
- sprintf (buffer_, "\"%s\"", symbol_);
- }
- else
- {
- strcpy (buffer_, symbol_);
- }
- } while (0)@)
+#define GEN_BINDER_NAME_FOR_STUB(BUF,STUB,STUB_LENGTH) \
+ do { \
+ const char *const stub_ = (STUB); \
+ char *buffer_ = (BUF); \
+ strcpy (buffer_, stub_); \
+ if (stub_[0] == '"') \
+ { \
+ strcpy (buffer_ + (STUB_LENGTH) - 1, "_binder\""); \
+ } \
+ else \
+ { \
+ strcpy (buffer_ + (STUB_LENGTH), "_binder"); \
+ } \
+ } while (0)
+
+#define GEN_SYMBOL_NAME_FOR_SYMBOL(BUF,SYMBOL,SYMBOL_LENGTH) \
+ do { \
+ const char *const symbol_ = (SYMBOL); \
+ char *buffer_ = (BUF); \
+ if (name_needs_quotes (symbol_) && symbol_[0] != '"') \
+ { \
+ sprintf (buffer_, "\"%s\"", symbol_); \
+ } \
+ else \
+ { \
+ strcpy (buffer_, symbol_); \
+ } \
+ } while (0)
/* Given a symbol name string, create the lazy pointer version
of the symbol name. */
-#define GEN_LAZY_PTR_NAME_FOR_SYMBOL(BUF,SYMBOL,SYMBOL_LENGTH) @(
- do {
- const char *symbol_ = (SYMBOL);
- char *buffer_ = (BUF);
- if (symbol_[0] == '"')
- {
- strcpy (buffer_, "\"L");
- strcpy (buffer_ + 2, symbol_ + 1);
- strcpy (buffer_ + (SYMBOL_LENGTH), "$lazy_ptr\"");
- }
- else if (name_needs_quotes (symbol_))
- {
- strcpy (buffer_, "\"L");
- strcpy (buffer_ + 2, symbol_);
- strcpy (buffer_ + (SYMBOL_LENGTH) + 2, "$lazy_ptr\"");
- }
- else
- {
- strcpy (buffer_, "L");
- strcpy (buffer_ + 1, symbol_);
- strcpy (buffer_ + (SYMBOL_LENGTH) + 1, "$lazy_ptr");
- }
- } while (0)@)
+#define GEN_LAZY_PTR_NAME_FOR_SYMBOL(BUF,SYMBOL,SYMBOL_LENGTH) \
+ do { \
+ const char *symbol_ = (SYMBOL); \
+ char *buffer_ = (BUF); \
+ if (symbol_[0] == '"') \
+ { \
+ strcpy (buffer_, "\"L"); \
+ strcpy (buffer_ + 2, symbol_ + 1); \
+ strcpy (buffer_ + (SYMBOL_LENGTH), "$lazy_ptr\""); \
+ } \
+ else if (name_needs_quotes (symbol_)) \
+ { \
+ strcpy (buffer_, "\"L"); \
+ strcpy (buffer_ + 2, symbol_); \
+ strcpy (buffer_ + (SYMBOL_LENGTH) + 2, "$lazy_ptr\""); \
+ } \
+ else \
+ { \
+ strcpy (buffer_, "L"); \
+ strcpy (buffer_ + 1, symbol_); \
+ strcpy (buffer_ + (SYMBOL_LENGTH) + 1, "$lazy_ptr"); \
+ } \
+ } while (0)
#define EH_FRAME_SECTION_NAME "__TEXT"
#define EH_FRAME_SECTION_ATTR ",coalesced,no_toc+strip_static_syms+live_support"
#define JCR_SECTION_NAME "__DATA,jcr,regular,no_dead_strip"
#undef ASM_PREFERRED_EH_DATA_FORMAT
-#define ASM_PREFERRED_EH_DATA_FORMAT(CODE,GLOBAL) @(
- (((CODE) == 2 && (GLOBAL) == 1)
- ? (DW_EH_PE_pcrel | DW_EH_PE_indirect | DW_EH_PE_sdata4) :
- ((CODE) == 1 || (GLOBAL) == 0) ? DW_EH_PE_pcrel : DW_EH_PE_absptr)@)
+#define ASM_PREFERRED_EH_DATA_FORMAT(CODE,GLOBAL) \
+ (((CODE) == 2 && (GLOBAL) == 1) \
+ ? (DW_EH_PE_pcrel | DW_EH_PE_indirect | DW_EH_PE_sdata4) : \
+ ((CODE) == 1 || (GLOBAL) == 0) ? DW_EH_PE_pcrel : DW_EH_PE_absptr)
-#define ASM_OUTPUT_DWARF_DELTA(FILE,SIZE,LABEL1,LABEL2) @(
- darwin_asm_output_dwarf_delta (FILE, SIZE, LABEL1, LABEL2)@)
+#define ASM_OUTPUT_DWARF_DELTA(FILE,SIZE,LABEL1,LABEL2) \
+ darwin_asm_output_dwarf_delta (FILE, SIZE, LABEL1, LABEL2)
-#define ASM_OUTPUT_DWARF_OFFSET(FILE,SIZE,LABEL,BASE) @(
- darwin_asm_output_dwarf_offset (FILE, SIZE, LABEL, BASE)@)
+#define ASM_OUTPUT_DWARF_OFFSET(FILE,SIZE,LABEL,BASE) \
+ darwin_asm_output_dwarf_offset (FILE, SIZE, LABEL, BASE)
-#define ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX(ASM_OUT_FILE, ENCODING, SIZE, ADDR, DONE) @(
- if (ENCODING == ASM_PREFERRED_EH_DATA_FORMAT (2, 1)) {
- darwin_non_lazy_pcrel (ASM_OUT_FILE, ADDR);
- goto DONE;
- }@)
+#define ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX(ASM_OUT_FILE, ENCODING, SIZE, ADDR, DONE) \
+ if (ENCODING == ASM_PREFERRED_EH_DATA_FORMAT (2, 1)) { \
+ darwin_non_lazy_pcrel (ASM_OUT_FILE, ADDR); \
+ goto DONE; \
+ }
/* Experimentally, putting jump tables in text is faster on SPEC.
Also this is needed for correctness for coalesced functions. */
#undef TARGET_ASM_NAMED_SECTION
#define TARGET_ASM_NAMED_SECTION darwin_asm_named_section
-#define DARWIN_REGISTER_TARGET_PRAGMAS() @(
- do {
- if (!flag_preprocess_only)
- cpp_register_pragma (parse_in, NULL, "mark",
- darwin_pragma_ignore, false);
- c_register_pragma (0, "options", darwin_pragma_options);
- c_register_pragma (0, "segment", darwin_pragma_ignore);
- c_register_pragma (0, "unused", darwin_pragma_unused);
- c_register_pragma (0, "ms_struct", darwin_pragma_ms_struct);
- } while (0)@)
+#define DARWIN_REGISTER_TARGET_PRAGMAS() \
+ do { \
+ if (!flag_preprocess_only) \
+ cpp_register_pragma (parse_in, NULL, "mark", \
+ darwin_pragma_ignore, false); \
+ c_register_pragma (0, "options", darwin_pragma_options); \
+ c_register_pragma (0, "segment", darwin_pragma_ignore); \
+ c_register_pragma (0, "unused", darwin_pragma_unused); \
+ c_register_pragma (0, "ms_struct", darwin_pragma_ms_struct); \
+ } while (0)
#undef ASM_APP_ON
#define ASM_APP_ON ""
#undef GOMP_SELF_SPECS
#define GOMP_SELF_SPECS ""
-/* Darwin disables section anchors by default.
+/* Darwin disables section anchors by default.
They should be enabled per arch where support exists in that arch. */
#define TARGET_ASM_OUTPUT_ANCHOR NULL
#define DARWIN_SECTION_ANCHORS 0
considered dangerous for library calls to send messages to
stdout/stderr. */
-#define ENABLE_EXECUTE_STACK @(
- extern void __enable_execute_stack (void *);
-
- void
- __enable_execute_stack (void *addr)
- {
- extern int mprotect (void *, size_t, int);
- extern int getpagesize (void);
- static int size;
- static long mask;
-
- char *page, *end;
-
- if (size == 0)
- {
- size = getpagesize();
- mask = ~((long) size - 1);
- }
-
- page = (char *) (((long) addr) & mask);
- end = (char *) ((((long) (addr + (TARGET_64BIT ? 48 : 40))) & mask) + size);
-
- /* 7 == PROT_READ | PROT_WRITE | PROT_EXEC */
- (void) mprotect (page, end - page, 7);
- }@)
+#define ENABLE_EXECUTE_STACK \
+extern void __enable_execute_stack (void *); \
+void \
+__enable_execute_stack (void *addr) \
+{ \
+ extern int mprotect (void *, size_t, int); \
+ extern int getpagesize (void); \
+ static int size; \
+ static long mask; \
+ \
+ char *page, *end; \
+ \
+ if (size == 0) \
+ { \
+ size = getpagesize(); \
+ mask = ~((long) size - 1); \
+ } \
+ \
+ page = (char *) (((long) addr) & mask); \
+ end = (char *) ((((long) (addr + (TARGET_64BIT ? 48 : 40))) & mask) + size); \
+ \
+ /* 7 == PROT_READ | PROT_WRITE | PROT_EXEC */ \
+ (void) mprotect (page, end - page, 7); \
+}
/* For Apple KEXTs, we make the constructors return this to match gcc
2.95. */
/* We have target-specific builtins. */
#define TARGET_FOLD_BUILTIN darwin_fold_builtin
-#define TARGET_OBJC_CONSTRUCT_STRING_OBJECT @(
- darwin_objc_construct_string@)
+#define TARGET_OBJC_CONSTRUCT_STRING_OBJECT \
+ darwin_objc_construct_string
-#define TARGET_STRING_OBJECT_REF_TYPE_P @(
- darwin_cfstring_ref_p@)
+#define TARGET_STRING_OBJECT_REF_TYPE_P \
+ darwin_cfstring_ref_p
#define TARGET_N_FORMAT_TYPES 1
#define TARGET_FORMAT_TYPES darwin_additional_format_types
-#define TARGET_CHECK_STRING_OBJECT_FORMAT_ARG @(
- darwin_check_cfstring_format_arg@)
+#define TARGET_CHECK_STRING_OBJECT_FORMAT_ARG \
+ darwin_check_cfstring_format_arg
#define TARGET_HAS_TARGETCM 1
#ifndef USED_FOR_TARGET
extern void darwin_driver_init (unsigned int *,struct cl_decoded_option **);
-#define GCC_DRIVER_HOST_INITIALIZATION @(
- darwin_driver_init (&decoded_options_count, &decoded_options)@)
+#define GCC_DRIVER_HOST_INITIALIZATION \
+ darwin_driver_init (&decoded_options_count, &decoded_options)
#endif
/* The Apple assembler and linker do not support constructor priorities. */
+++ /dev/null
-/* Generate a slashified version of the input
- Copyright (C) 2011
- Free Software Foundation, Inc.
- Contributed by Mike Stump <mikestump@comcast.net>
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 3, or (at your option) any later
-version.
-
-GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
-
-
-/* This is a small utility to slashify a source file so that one never
- needs to stare at backslashes. */
-
-#include <stdio.h>
-
-extern int main (void);
-
-int main (void) {
- int c,c1;
- int saw_start = 0;
- while ((c=getchar ()) != EOF) {
- if (c != '@') {
- if (saw_start && c == '\n') {
- putchar ('\\');
- }
- putchar (c);
- continue;
- }
- c1=getchar();
- if (c1 == EOF) {
- putchar (c);
- return 0;
- }
- if (!saw_start && c1 == '(') {
- saw_start = 1;
- } else if (saw_start && c1 == ')') {
- saw_start = 0;
- } else {
- putchar (c);
- putchar (c1);
- }
- }
- return 0;
-}
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
-build/slashify1: $(srcdir)/config/slashify.c
- $(COMPILER_FOR_BUILD) $(BUILD_COMPILERFLAGS) $(BUILD_CPPFLAGS) $(srcdir)/config/slashify.c -o $@
-
-$(srcdir)/config/darwin.h: config/darwin.h.rebuild
-
-config/darwin.h.rebuild: build/slashify1
- @$(mkinstalldirs) config
- @if [ ! -e $(srcdir)/config/darwin.h \
- -o $(srcdir)/config/darwin.h -nt config/darwin.h ]; then \
- cp $(srcdir)/config/darwin-sections.def \
- config/darwin-sections.def && \
- build/slashify1 < $(srcdir)/config/darwin.h >config/darwin.h; \
- fi
-
darwin.o: $(srcdir)/config/darwin.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TM_H) $(RTL_H) $(REGS_H) hard-reg-set.h $(REAL_H) insn-config.h \
conditions.h insn-flags.h output.h insn-attr.h flags.h $(TREE_H) expr.h \
-2011-02-13 Mike Stump <mikestump@comcast.net>
-
- * parser.c (cp_parser_primary_expression): Add arguments to all the plugins.
- * lex.c: Plugify.
- * Make-lang.in (objcp/plugin/lex.h): Likewise.
- (build/slashify): Harden against rebuilds.
- (objcp/plugin/parser.h): Harden against parallel builds.
-
- * Make-lang.in (cp/parser.o): Move c-family/c-objc.h dependancy
- down.
-
-2011-02-12 Mike Stump <mikestump@comcast.net>
-
- * Make-lang.in (build/slashify): Plugify Objective-C++.
- (cp/parser.o): Likewise.
- (objcp/plugin/parser.h): Likewise.
- * parser.c (cp_parser_token_starts_cast_expression): Likewise.
-
2011-02-09 Jason Merrill <jason@redhat.com>
* decl.c (cp_make_fname_decl): Set DECL_THIS_STATIC at toplevel.
CXX_PRETTY_PRINT_H = cp/cxx-pretty-print.h $(C_PRETTY_PRINT_H)
cp/lex.o: cp/lex.c $(CXX_TREE_H) $(TM_H) $(FLAGS_H) \
- $(C_PRAGMA_H) output.h input.h cp/operators.def $(TM_P_H)
+ $(C_PRAGMA_H) output.h input.h cp/operators.def $(TM_P_H) \
+ c-family/c-objc.h
cp/cp-lang.o: cp/cp-lang.c $(CXX_TREE_H) $(TM_H) debug.h langhooks.h \
$(LANGHOOKS_DEF_H) $(C_COMMON_H) gtype-cp.h gt-cp-cp-lang.h \
cp/cp-objcp-common.h $(EXPR_H) $(TARGET_H)
cp/mangle.o: cp/mangle.c $(CXX_TREE_H) $(TM_H) $(REAL_H) \
gt-cp-mangle.h $(TARGET_H) $(TM_P_H) $(CGRAPH_H)
cp/parser.o: cp/parser.c $(CXX_TREE_H) $(TM_H) $(DIAGNOSTIC_CORE_H) \
- gt-cp-parser.h output.h $(TARGET_H) $(PLUGIN_H) intl.h
+ gt-cp-parser.h output.h $(TARGET_H) $(PLUGIN_H) intl.h \
+ c-family/c-objc.h
cp/cp-gimplify.o: cp/cp-gimplify.c $(CXX_TREE_H) $(C_COMMON_H) \
$(TM_H) coretypes.h pointer-set.h tree-iterator.h
cp/cxx-pretty-print.o: cp/cxx-pretty-print.c $(CXX_PRETTY_PRINT_H) \
$(CONFIG_H) $(SYSTEM_H) $(TM_H) coretypes.h $(CXX_TREE_H) tree-pretty-print.h
-
-
-# Objective-C++ related rules:
-
-cp/parser.o: $(objdir)/objcp/plugin/parser.h $(srcdir)/objcp/plugin/parser.c \
- c-family/c-objc.h
-
-cp/lex.o: $(objdir)/objcp/plugin/lex.h c-family/c-objc.h
-
-# Would like to get rid of the #, but we always rebuild the checksum
-# if we do
-build/slashify: # $(srcdir)/config/slashify.c
- $(COMPILER_FOR_BUILD) $(BUILD_COMPILERFLAGS) $(BUILD_CPPFLAGS) $(srcdir)/config/slashify.c -o $@
-
-$(objdir)/objcp/plugin/parser.h: $(srcdir)/objcp/plugin/parser.h build/slashify
- $(mkinstalldirs) objcp/plugin
- build/slashify < $< > $@
-
-$(objdir)/objcp/plugin/lex.h: $(srcdir)/objcp/plugin/lex.h build/slashify
- $(mkinstalldirs) objcp/plugin
- build/slashify < $< > $@
#include "cpplib.h"
#include "flags.h"
#include "c-family/c-pragma.h"
-#include "objcp/plugin/lex.h"
+#include "c-family/c-objc.h"
#include "output.h"
#include "tm_p.h"
#include "timevar.h"
}
else
{
- if (!PLUGIN_UNQUALIFIED_NAME_LOOKUP_ERROR (name))
+ if (!objc_diagnose_private_ivar (name))
{
error ("%qD was not declared in this scope", name);
suggest_alternatives_for (location_of (name), name);
#include "target.h"
#include "cgraph.h"
#include "c-family/c-common.h"
+#include "c-family/c-objc.h"
#include "plugin.h"
\f
static bool cp_parser_pragma
(cp_parser *, enum pragma_context);
-#include "objcp/plugin/parser.h"
+/* 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 bool cp_parser_objc_selector_p
+ (enum cpp_ttype);
+static tree cp_parser_objc_selector
+ (cp_parser *);
+static tree cp_parser_objc_protocol_refs_opt
+ (cp_parser *);
+static void cp_parser_objc_declaration
+ (cp_parser *, tree);
+static tree cp_parser_objc_statement
+ (cp_parser *);
+static bool cp_parser_objc_valid_prefix_attributes
+ (cp_parser *, tree *);
+static void cp_parser_objc_at_property_declaration
+ (cp_parser *) ;
+static void cp_parser_objc_at_synthesize_declaration
+ (cp_parser *) ;
+static void cp_parser_objc_at_dynamic_declaration
+ (cp_parser *) ;
+static tree cp_parser_objc_struct_declaration
+ (cp_parser *) ;
/* Utility Routines */
}
case CPP_OPEN_SQUARE:
- PLUGIN_PRIMARY_EXPRESSION_3 (parser);
+ if (c_dialect_objc ())
+ /* We have an Objective-C++ message. */
+ return cp_parser_objc_expression (parser);
maybe_warn_cpp0x (CPP0X_LAMBDA_EXPR);
return cp_parser_lambda_expression (parser);
- PLUGIN_PRIMARY_EXPRESSION_2 (parser, cp_parser_error)
+ case CPP_OBJC_STRING:
+ if (c_dialect_objc ())
+ /* We have an Objective-C++ string literal. */
+ return cp_parser_objc_expression (parser);
+ cp_parser_error (parser, "expected primary-expression");
+ return error_mark_node;
case CPP_KEYWORD:
switch (token->keyword)
case RID_IS_LITERAL_TYPE:
return cp_parser_trait_expr (parser, token->keyword);
- PLUGIN_PRIMARY_EXPRESSION_1 (parser)
+ /* Objective-C++ expressions. */
+ case RID_AT_ENCODE:
+ case RID_AT_PROTOCOL:
+ case RID_AT_SELECTOR:
+ return cp_parser_objc_expression (parser);
case RID_TEMPLATE:
if (parser->in_function_body
if (ambiguous_decls)
return error_mark_node;
- PLUGIN_PRIMARY_EXPRESSION (parser, decl, cp_lexer_consume_token,
- cp_lexer_peek_token);
+ /* In Objective-C++, we may have an Objective-C 2.0
+ dot-syntax for classes here. */
+ if (c_dialect_objc ()
+ && cp_lexer_peek_token (parser->lexer)->type == CPP_DOT
+ && TREE_CODE (decl) == TYPE_DECL
+ && objc_is_class_name (decl))
+ {
+ tree component;
+ cp_lexer_consume_token (parser->lexer);
+ component = cp_parser_identifier (parser);
+ if (component == error_mark_node)
+ return error_mark_node;
+
+ return objc_build_class_component_ref (id_expression, component);
+ }
+
+ /* In Objective-C++, an instance variable (ivar) may be preferred
+ to whatever cp_parser_lookup_name() found. */
+ decl = objc_lookup_ivar (decl, id_expression);
/* If name lookup gives us a SCOPE_REF, then the
qualifying scope was dependent. */
case CPP_EOF:
return false;
+ /* '[' may start a primary-expression in obj-c++. */
case CPP_OPEN_SQUARE:
- PLUGIN_TOKEN_STARTS_CAST_EXPR;
- return false;
+ return c_dialect_objc ();
default:
return true;
statement = cp_parser_jump_statement (parser);
break;
- PLUGIN_STATEMENT
+ /* 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;
case RID_TRY:
statement = cp_parser_try_block (parser);
else if (token1.keyword == RID_INLINE
&& token2.keyword == RID_NAMESPACE)
cp_parser_namespace_definition (parser);
- PLUGIN_DECLARATION (token1, attributes)
+ /* Objective-C++ declaration/definition. */
+ else if (c_dialect_objc () && OBJC_IS_AT_KEYWORD (token1.keyword))
+ cp_parser_objc_declaration (parser, NULL_TREE);
+ else if (c_dialect_objc ()
+ && token1.keyword == RID_ATTRIBUTE
+ && cp_parser_objc_valid_prefix_attributes (parser, &attributes))
+ cp_parser_objc_declaration (parser, attributes);
/* We must have either a block declaration or a function
definition. */
else
if (type && type != error_mark_node)
{
- PLUGIN_SIMPLE_TYPE_SPECIFIER (parser, type, decl_specs);
+ /* See if TYPE is an Objective-C type, and if so, parse and
+ accept any protocol references following it. Do this before
+ the cp_parser_check_for_invalid_template_id() call, because
+ Objective-C types can be followed by '<...>' which would
+ enclose protocol names rather than template arguments, and so
+ everything is fine. */
+ if (c_dialect_objc () && !parser->scope
+ && (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-qualified version. */
+ if (decl_specs)
+ decl_specs->type = qual_type;
+
+ return qual_type;
+ }
/* There is no valid C++ program where a non-template type is
followed by a "<". That usually indicates that the user
/* Look up the type-name. */
type_decl = cp_parser_lookup_name_simple (parser, identifier, token->location);
- PLUGIN_NONCLASS_NAME1 (parser, type_decl, identifier);
+ 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);
+ }
/* Issue an error if we did not find a type-name. */
if (TREE_CODE (type_decl) != TYPE_DECL
- PLUGIN_NONCLASS_NAME (parser, type_decl, cp_lexer_peek_token))
+ /* In Objective-C, we have the complication that class names are
+ normally type names and start declarations (eg, the
+ "NSObject" in "NSObject *object;"), but can be used in an
+ Objective-C 2.0 dot-syntax (as in "NSObject.version") which
+ is an expression. So, a classname followed by a dot is not a
+ valid type-name. */
+ || (objc_is_class_name (TREE_TYPE (type_decl))
+ && cp_lexer_peek_token (parser->lexer)->type == CPP_DOT))
{
if (!cp_parser_simulate_error (parser))
cp_parser_name_lookup_error (parser, identifier, type_decl,
else if (TREE_CODE (decl) != TYPE_DECL
|| TREE_TYPE (decl) == error_mark_node
|| !MAYBE_CLASS_TYPE_P (TREE_TYPE (decl))
- PLUGIN_CLASS_NAME (parser, cp_lexer_peek_token, CPP_DOT))
+ /* In Objective-C 2.0, a classname followed by '.' starts a
+ dot-syntax expression, and it's not a type-name. */
+ || (c_dialect_objc ()
+ && cp_lexer_peek_token (parser->lexer)->type == CPP_DOT
+ && objc_is_class_name (decl)))
decl = error_mark_node;
if (decl == error_mark_node)
return;
}
- PLUGIN_MEMBER_DECLARATION (parser, cp_lexer_next_token_is_keyword,
- finish_member_declaration);
+ /* 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;
+ }
/* If the next token is `static_assert' we have a static assertion. */
if (cp_lexer_next_token_is_keyword (parser->lexer, RID_STATIC_ASSERT))
{
return parser->allow_gnu_extensions_p;
}
-
\f
/* Objective-C++ Productions */
-#include "../objcp/plugin/parser.c"
+
+/* 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->u.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_at (kwd->location,
+ "misplaced %<@%D%> Objective-C++ construct",
+ kwd->u.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, RT_CLOSE_SQUARE);
+
+ return objc_build_message_expr (build_tree_list (receiver, messageargs));
+}
+
+/* Parse an objc-message-receiver.
+
+ objc-message-receiver:
+ expression
+ simple-type-specifier
+
+ Returns a representation of the type or expression. */
+
+static tree
+cp_parser_objc_message_receiver (cp_parser* parser)
+{
+ tree rcv;
+
+ /* 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, NULL);
+
+ if (cp_parser_parse_definitely (parser))
+ return rcv;
+
+ rcv = cp_parser_simple_type_specifier (parser,
+ /*decl_specs=*/NULL,
+ CP_PARSER_FLAGS_NONE);
+
+ 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, RT_COLON);
+ arg = cp_parser_assignment_expression (parser, false, NULL);
+
+ 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, NULL);
+
+ addl_args
+ = chainon (addl_args,
+ build_tree_list (NULL_TREE, arg));
+
+ token = cp_lexer_peek_token (parser->lexer);
+ }
+
+ if (sel_args == NULL_TREE && addl_args == NULL_TREE)
+ {
+ cp_parser_error (parser, "objective-c++ message argument(s) are expected");
+ return build_tree_list (error_mark_node, error_mark_node);
+ }
+
+ 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_token *token;
+
+ cp_lexer_consume_token (parser->lexer); /* Eat '@encode'. */
+ cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
+ token = cp_lexer_peek_token (parser->lexer);
+ type = complete_type (cp_parser_type_id (parser));
+ cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+
+ if (!type)
+ {
+ error_at (token->location,
+ "%<@encode%> must specify a type as an argument");
+ return error_mark_node;
+ }
+
+ /* This happens if we find @encode(T) (where T is a template
+ typename or something dependent on a template typename) when
+ parsing a template. In that case, we can't compile it
+ immediately, but we rather create an AT_ENCODE_EXPR which will
+ need to be instantiated when the template is used.
+ */
+ if (dependent_type_p (type))
+ {
+ tree value = build_min (AT_ENCODE_EXPR, size_type_node, type);
+ TREE_READONLY (value) = 1;
+ return value;
+ }
+
+ 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, RT_OPEN_PAREN);
+ name = cp_parser_identifier (parser);
+ cp_parser_require (parser, CPP_CLOSE_PAREN, RT_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, RT_OPEN_PAREN);
+ proto = cp_parser_identifier (parser);
+ cp_parser_require (parser, CPP_CLOSE_PAREN, RT_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;
+ location_t loc = cp_lexer_peek_token (parser->lexer)->location;
+
+ cp_lexer_consume_token (parser->lexer); /* Eat '@selector'. */
+ cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
+ token = cp_lexer_peek_token (parser->lexer);
+
+ while (cp_parser_objc_selector_p (token->type) || token->type == CPP_COLON
+ || token->type == CPP_SCOPE)
+ {
+ tree selector = NULL_TREE;
+
+ if (token->type != CPP_COLON
+ || token->type == CPP_SCOPE)
+ selector = cp_parser_objc_selector (parser);
+
+ if (cp_lexer_next_token_is_not (parser->lexer, CPP_COLON)
+ && cp_lexer_next_token_is_not (parser->lexer, CPP_SCOPE))
+ {
+ /* Detect if we have a unary selector. */
+ if (maybe_unary_selector_p)
+ {
+ sel_seq = selector;
+ goto finish_selector;
+ }
+ else
+ {
+ cp_parser_error (parser, "expected %<:%>");
+ }
+ }
+ maybe_unary_selector_p = false;
+ token = cp_lexer_consume_token (parser->lexer);
+
+ if (token->type == CPP_SCOPE)
+ {
+ sel_seq
+ = chainon (sel_seq,
+ build_tree_list (selector, NULL_TREE));
+ sel_seq
+ = chainon (sel_seq,
+ build_tree_list (NULL_TREE, NULL_TREE));
+ }
+ else
+ 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, RT_CLOSE_PAREN);
+
+ return objc_build_selector_expr (loc, 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 identifier;
+ tree list;
+ cp_token *sep;
+
+ identifier = cp_parser_identifier (parser);
+ if (identifier == error_mark_node)
+ return error_mark_node;
+
+ list = build_tree_list (NULL_TREE, identifier);
+ sep = cp_lexer_peek_token (parser->lexer);
+
+ while (sep->type == CPP_COMMA)
+ {
+ cp_lexer_consume_token (parser->lexer); /* Eat ','. */
+ identifier = cp_parser_identifier (parser);
+ if (identifier == error_mark_node)
+ return list;
+
+ list = chainon (list, build_tree_list (NULL_TREE,
+ identifier));
+ 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, RT_GREATER);
+ }
+
+ return protorefs;
+}
+
+/* Parse a Objective-C visibility specification. */
+
+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 (OBJC_IVAR_VIS_PRIVATE);
+ break;
+ case RID_AT_PROTECTED:
+ objc_set_visibility (OBJC_IVAR_VIS_PROTECTED);
+ break;
+ case RID_AT_PUBLIC:
+ objc_set_visibility (OBJC_IVAR_VIS_PUBLIC);
+ break;
+ case RID_AT_PACKAGE:
+ objc_set_visibility (OBJC_IVAR_VIS_PACKAGE);
+ break;
+ default:
+ return;
+ }
+
+ /* Eat '@private'/'@protected'/'@public'. */
+ cp_lexer_consume_token (parser->lexer);
+}
+
+/* Parse an Objective-C method type. Return 'true' if it is a class
+ (+) method, and 'false' if it is an instance (-) method. */
+
+static inline bool
+cp_parser_objc_method_type (cp_parser* parser)
+{
+ if (cp_lexer_consume_token (parser->lexer)->type == CPP_PLUS)
+ return true;
+ else
+ return false;
+}
+
+/* Parse an Objective-C protocol qualifier. */
+
+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->u.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->u.value;
+ }
+
+ return quals;
+}
+
+/* Parse an Objective-C typename. */
+
+static tree
+cp_parser_objc_typename (cp_parser* parser)
+{
+ tree type_name = 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);
+
+ /* If the type could not be parsed, an error has already
+ been produced. For error recovery, behave as if it had
+ not been specified, which will use the default type
+ 'id'. */
+ if (cp_type == error_mark_node)
+ {
+ cp_type = NULL_TREE;
+ /* We need to skip to the closing parenthesis as
+ cp_parser_type_id() does not seem to do it for
+ us. */
+ cp_parser_skip_to_closing_parenthesis (parser,
+ /*recovering=*/true,
+ /*or_comma=*/false,
+ /*consume_paren=*/false);
+ }
+ }
+
+ cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+ type_name = build_tree_list (proto_quals, cp_type);
+ }
+
+ return type_name;
+}
+
+/* Check to see if TYPE refers to an Objective-C selector name. */
+
+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);
+}
+
+/* Parse an Objective-C selector. */
+
+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_at (token->location, "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->u.value;
+ }
+}
+
+/* Parse an Objective-C params list. */
+
+static tree
+cp_parser_objc_method_keyword_params (cp_parser* parser, tree* attributes)
+{
+ 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, type_name, identifier;
+ tree parm_attr = NULL_TREE;
+
+ if (token->keyword == RID_ATTRIBUTE)
+ break;
+
+ 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))
+ {
+ params = selector; /* Might be followed by attributes. */
+ break;
+ }
+
+ maybe_unary_selector_p = false;
+ if (!cp_parser_require (parser, CPP_COLON, RT_COLON))
+ {
+ /* Something went quite wrong. There should be a colon
+ here, but there is not. Stop parsing parameters. */
+ break;
+ }
+ type_name = cp_parser_objc_typename (parser);
+ /* New ObjC allows attributes on parameters too. */
+ if (cp_lexer_next_token_is_keyword (parser->lexer, RID_ATTRIBUTE))
+ parm_attr = cp_parser_attributes_opt (parser);
+ identifier = cp_parser_identifier (parser);
+
+ params
+ = chainon (params,
+ objc_build_keyword_decl (selector,
+ type_name,
+ identifier,
+ parm_attr));
+
+ token = cp_lexer_peek_token (parser->lexer);
+ }
+
+ if (params == NULL_TREE)
+ {
+ cp_parser_error (parser, "objective-c++ method declaration is expected");
+ return error_mark_node;
+ }
+
+ /* We allow tail attributes for the method. */
+ if (token->keyword == RID_ATTRIBUTE)
+ {
+ *attributes = cp_parser_attributes_opt (parser);
+ if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)
+ || cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
+ return params;
+ cp_parser_error (parser,
+ "method attributes must be specified at the end");
+ return error_mark_node;
+ }
+
+ if (params == NULL_TREE)
+ {
+ cp_parser_error (parser, "objective-c++ method declaration is expected");
+ return error_mark_node;
+ }
+ return params;
+}
+
+/* Parse the non-keyword Objective-C params. */
+
+static tree
+cp_parser_objc_method_tail_params_opt (cp_parser* parser, bool *ellipsisp,
+ tree* attributes)
+{
+ tree params = make_node (TREE_LIST);
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
+ *ellipsisp = false; /* 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 '...'. */
+ *ellipsisp = true;
+ token = cp_lexer_peek_token (parser->lexer);
+ break;
+ }
+
+ /* TODO: parse attributes for tail parameters. */
+ 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);
+ }
+
+ /* We allow tail attributes for the method. */
+ if (token->keyword == RID_ATTRIBUTE)
+ {
+ if (*attributes == NULL_TREE)
+ {
+ *attributes = cp_parser_attributes_opt (parser);
+ if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)
+ || cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
+ return params;
+ }
+ else
+ /* We have an error, but parse the attributes, so that we can
+ carry on. */
+ *attributes = cp_parser_attributes_opt (parser);
+
+ cp_parser_error (parser,
+ "method attributes must be specified at the end");
+ return error_mark_node;
+ }
+
+ return params;
+}
+
+/* Parse a linkage specification, a pragma, an extra semicolon or a block. */
+
+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_parser_pragma (parser, pragma_external);
+ /* Allow stray semicolons. */
+ else if (token->type == CPP_SEMICOLON)
+ cp_lexer_consume_token (parser->lexer);
+ /* Mark methods as optional or required, when building protocols. */
+ else if (token->keyword == RID_AT_OPTIONAL)
+ {
+ cp_lexer_consume_token (parser->lexer);
+ objc_set_method_opt (true);
+ }
+ else if (token->keyword == RID_AT_REQUIRED)
+ {
+ cp_lexer_consume_token (parser->lexer);
+ objc_set_method_opt (false);
+ }
+ else if (token->keyword == RID_NAMESPACE)
+ cp_parser_namespace_definition (parser);
+ /* Other stray characters must generate errors. */
+ else if (token->type == CPP_OPEN_BRACE || token->type == CPP_CLOSE_BRACE)
+ {
+ cp_lexer_consume_token (parser->lexer);
+ error ("stray %qs between Objective-C++ methods",
+ token->type == CPP_OPEN_BRACE ? "{" : "}");
+ }
+ /* Finally, try to parse a block-declaration, or a function-definition. */
+ else
+ cp_parser_block_declaration (parser, /*statement_p=*/false);
+}
+
+/* Parse a method signature. */
+
+static tree
+cp_parser_objc_method_signature (cp_parser* parser, tree* attributes)
+{
+ tree rettype, kwdparms, optparms;
+ bool ellipsis = false;
+ bool is_class_method;
+
+ is_class_method = cp_parser_objc_method_type (parser);
+ rettype = cp_parser_objc_typename (parser);
+ *attributes = NULL_TREE;
+ kwdparms = cp_parser_objc_method_keyword_params (parser, attributes);
+ if (kwdparms == error_mark_node)
+ return error_mark_node;
+ optparms = cp_parser_objc_method_tail_params_opt (parser, &ellipsis, attributes);
+ if (optparms == error_mark_node)
+ return error_mark_node;
+
+ return objc_build_method_signature (is_class_method, rettype, kwdparms, optparms, ellipsis);
+}
+
+static bool
+cp_parser_objc_method_maybe_bad_prefix_attributes (cp_parser* parser)
+{
+ tree tattr;
+ cp_lexer_save_tokens (parser->lexer);
+ tattr = cp_parser_attributes_opt (parser);
+ gcc_assert (tattr) ;
+
+ /* If the attributes are followed by a method introducer, this is not allowed.
+ Dump the attributes and flag the situation. */
+ if (cp_lexer_next_token_is (parser->lexer, CPP_PLUS)
+ || cp_lexer_next_token_is (parser->lexer, CPP_MINUS))
+ return true;
+
+ /* Otherwise, the attributes introduce some interstitial code, possibly so
+ rewind to allow that check. */
+ cp_lexer_rollback_tokens (parser->lexer);
+ return false;
+}
+
+/* Parse an Objective-C method prototype list. */
+
+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 && token->type != CPP_EOF)
+ {
+ if (token->type == CPP_PLUS || token->type == CPP_MINUS)
+ {
+ tree attributes, sig;
+ bool is_class_method;
+ if (token->type == CPP_PLUS)
+ is_class_method = true;
+ else
+ is_class_method = false;
+ sig = cp_parser_objc_method_signature (parser, &attributes);
+ if (sig == error_mark_node)
+ {
+ cp_parser_skip_to_end_of_block_or_statement (parser);
+ token = cp_lexer_peek_token (parser->lexer);
+ continue;
+ }
+ objc_add_method_declaration (is_class_method, sig, attributes);
+ cp_parser_consume_semicolon_at_end_of_statement (parser);
+ }
+ else if (token->keyword == RID_AT_PROPERTY)
+ cp_parser_objc_at_property_declaration (parser);
+ else if (token->keyword == RID_ATTRIBUTE
+ && cp_parser_objc_method_maybe_bad_prefix_attributes(parser))
+ warning_at (cp_lexer_peek_token (parser->lexer)->location,
+ OPT_Wattributes,
+ "prefix attributes are ignored for methods");
+ else
+ /* Allow for interspersed non-ObjC++ code. */
+ cp_parser_objc_interstitial_code (parser);
+
+ token = cp_lexer_peek_token (parser->lexer);
+ }
+
+ if (token->type != CPP_EOF)
+ cp_lexer_consume_token (parser->lexer); /* Eat '@end'. */
+ else
+ cp_parser_error (parser, "expected %<@end%>");
+
+ objc_finish_interface ();
+}
+
+/* Parse an Objective-C method definition list. */
+
+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 && token->type != CPP_EOF)
+ {
+ tree meth;
+
+ if (token->type == CPP_PLUS || token->type == CPP_MINUS)
+ {
+ cp_token *ptk;
+ tree sig, attribute;
+ bool is_class_method;
+ if (token->type == CPP_PLUS)
+ is_class_method = true;
+ else
+ is_class_method = false;
+ push_deferring_access_checks (dk_deferred);
+ sig = cp_parser_objc_method_signature (parser, &attribute);
+ if (sig == error_mark_node)
+ {
+ cp_parser_skip_to_end_of_block_or_statement (parser);
+ token = cp_lexer_peek_token (parser->lexer);
+ continue;
+ }
+ objc_start_method_definition (is_class_method, sig, attribute);
+
+ /* For historical reasons, we accept an optional semicolon. */
+ if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
+ cp_lexer_consume_token (parser->lexer);
+
+ ptk = cp_lexer_peek_token (parser->lexer);
+ if (!(ptk->type == CPP_PLUS || ptk->type == CPP_MINUS
+ || ptk->type == CPP_EOF || ptk->keyword == RID_AT_END))
+ {
+ 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);
+ }
+ }
+ /* The following case will be removed once @synthesize is
+ completely implemented. */
+ else if (token->keyword == RID_AT_PROPERTY)
+ cp_parser_objc_at_property_declaration (parser);
+ else if (token->keyword == RID_AT_SYNTHESIZE)
+ cp_parser_objc_at_synthesize_declaration (parser);
+ else if (token->keyword == RID_AT_DYNAMIC)
+ cp_parser_objc_at_dynamic_declaration (parser);
+ else if (token->keyword == RID_ATTRIBUTE
+ && cp_parser_objc_method_maybe_bad_prefix_attributes(parser))
+ warning_at (token->location, OPT_Wattributes,
+ "prefix attributes are ignored for methods");
+ else
+ /* Allow for interspersed non-ObjC++ code. */
+ cp_parser_objc_interstitial_code (parser);
+
+ token = cp_lexer_peek_token (parser->lexer);
+ }
+
+ if (token->type != CPP_EOF)
+ cp_lexer_consume_token (parser->lexer); /* Eat '@end'. */
+ else
+ cp_parser_error (parser, "expected %<@end%>");
+
+ objc_finish_implementation ();
+}
+
+/* Parse Objective-C ivars. */
+
+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
+ && token->keyword != RID_AT_END && token->type != CPP_EOF)
+ {
+ 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);
+
+ /* auto, register, static, extern, mutable. */
+ if (declspecs.storage_class != sc_none)
+ {
+ cp_parser_error (parser, "invalid type for instance variable");
+ declspecs.storage_class = sc_none;
+ }
+
+ /* __thread. */
+ if (declspecs.specs[(int) ds_thread])
+ {
+ cp_parser_error (parser, "invalid type for instance variable");
+ declspecs.specs[(int) ds_thread] = 0;
+ }
+
+ /* typedef. */
+ if (declspecs.specs[(int) ds_typedef])
+ {
+ cp_parser_error (parser, "invalid type for instance variable");
+ declspecs.specs[(int) ds_typedef] = 0;
+ }
+
+ 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),
+ sfk_none);
+
+ 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,
+ attributes);
+ else
+ decl = grokfield (declarator, &declspecs,
+ NULL_TREE, /*init_const_expr_p=*/false,
+ 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);
+ }
+
+ if (token->keyword == RID_AT_END)
+ cp_parser_error (parser, "expected %<}%>");
+
+ /* Do not consume the RID_AT_END, so it will be read again as terminating
+ the @interface of @implementation. */
+ if (token->keyword != RID_AT_END && token->type != CPP_EOF)
+ 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);
+}
+
+/* Parse an Objective-C protocol declaration. */
+
+static void
+cp_parser_objc_protocol_declaration (cp_parser* parser, tree attributes)
+{
+ 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))
+ {
+ tok = cp_lexer_peek_token (parser->lexer);
+ error_at (tok->location, "identifier expected after %<@protocol%>");
+ goto finish;
+ }
+
+ /* See if we have a forward 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),
+ attributes);
+ 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, attributes);
+ cp_parser_objc_method_prototype_list (parser);
+ }
+}
+
+/* Parse an Objective-C superclass or category. */
+
+static void
+cp_parser_objc_superclass_or_category (cp_parser *parser,
+ bool iface_p,
+ tree *super,
+ tree *categ, bool *is_class_extension)
+{
+ cp_token *next = cp_lexer_peek_token (parser->lexer);
+
+ *super = *categ = NULL_TREE;
+ *is_class_extension = false;
+ 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 '('. */
+
+ /* If there is no category name, and this is an @interface, we
+ have a class extension. */
+ if (iface_p && cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN))
+ {
+ *categ = NULL_TREE;
+ *is_class_extension = true;
+ }
+ else
+ *categ = cp_parser_identifier (parser);
+
+ cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+ }
+}
+
+/* Parse an Objective-C class interface. */
+
+static void
+cp_parser_objc_class_interface (cp_parser* parser, tree attributes)
+{
+ tree name, super, categ, protos;
+ bool is_class_extension;
+
+ cp_lexer_consume_token (parser->lexer); /* Eat '@interface'. */
+ name = cp_parser_identifier (parser);
+ if (name == error_mark_node)
+ {
+ /* It's hard to recover because even if valid @interface stuff
+ is to follow, we can't compile it (or validate it) if we
+ don't even know which class it refers to. Let's assume this
+ was a stray '@interface' token in the stream and skip it.
+ */
+ return;
+ }
+ cp_parser_objc_superclass_or_category (parser, true, &super, &categ,
+ &is_class_extension);
+ protos = cp_parser_objc_protocol_refs_opt (parser);
+
+ /* We have either a class or a category on our hands. */
+ if (categ || is_class_extension)
+ objc_start_category_interface (name, categ, protos, attributes);
+ else
+ {
+ objc_start_class_interface (name, super, protos, attributes);
+ /* Handle instance variable declarations, if any. */
+ cp_parser_objc_class_ivars (parser);
+ objc_continue_interface ();
+ }
+
+ cp_parser_objc_method_prototype_list (parser);
+}
+
+/* Parse an Objective-C class implementation. */
+
+static void
+cp_parser_objc_class_implementation (cp_parser* parser)
+{
+ tree name, super, categ;
+ bool is_class_extension;
+
+ cp_lexer_consume_token (parser->lexer); /* Eat '@implementation'. */
+ name = cp_parser_identifier (parser);
+ if (name == error_mark_node)
+ {
+ /* It's hard to recover because even if valid @implementation
+ stuff is to follow, we can't compile it (or validate it) if
+ we don't even know which class it refers to. Let's assume
+ this was a stray '@implementation' token in the stream and
+ skip it.
+ */
+ return;
+ }
+ cp_parser_objc_superclass_or_category (parser, false, &super, &categ,
+ &is_class_extension);
+
+ /* 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);
+}
+
+/* Consume the @end token and finish off the implementation. */
+
+static void
+cp_parser_objc_end_implementation (cp_parser* parser)
+{
+ cp_lexer_consume_token (parser->lexer); /* Eat '@end'. */
+ objc_finish_implementation ();
+}
+
+/* Parse an Objective-C declaration. */
+
+static void
+cp_parser_objc_declaration (cp_parser* parser, tree attributes)
+{
+ /* Try to figure out what kind of declaration is present. */
+ cp_token *kwd = cp_lexer_peek_token (parser->lexer);
+
+ if (attributes)
+ switch (kwd->keyword)
+ {
+ case RID_AT_ALIAS:
+ case RID_AT_CLASS:
+ case RID_AT_END:
+ error_at (kwd->location, "attributes may not be specified before"
+ " the %<@%D%> Objective-C++ keyword",
+ kwd->u.value);
+ attributes = NULL;
+ break;
+ case RID_AT_IMPLEMENTATION:
+ warning_at (kwd->location, OPT_Wattributes,
+ "prefix attributes are ignored before %<@%D%>",
+ kwd->u.value);
+ attributes = NULL;
+ default:
+ break;
+ }
+
+ 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, attributes);
+ break;
+ case RID_AT_INTERFACE:
+ cp_parser_objc_class_interface (parser, attributes);
+ 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_at (kwd->location, "misplaced %<@%D%> Objective-C++ construct",
+ kwd->u.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 ( objc-exception-declaration ) compound-statement
+
+ objc-finally-clause:
+ @finally compound-statement
+
+ objc-exception-declaration:
+ parameter-declaration
+ '...'
+
+ where '...' is to be interpreted literally, that is, it means CPP_ELLIPSIS.
+
+ Returns NULL_TREE.
+
+ PS: This function is identical to c_parser_objc_try_catch_finally_statement
+ for C. Keep them in sync. */
+
+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, RT_AT_TRY);
+ location = cp_lexer_peek_token (parser->lexer)->location;
+ objc_maybe_warn_exceptions (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 *parm;
+ tree parameter_declaration = error_mark_node;
+ bool seen_open_paren = false;
+
+ cp_lexer_consume_token (parser->lexer);
+ if (cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+ seen_open_paren = true;
+ if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
+ {
+ /* We have "@catch (...)" (where the '...' are literally
+ what is in the code). Skip the '...'.
+ parameter_declaration is set to NULL_TREE, and
+ objc_being_catch_clauses() knows that that means
+ '...'. */
+ cp_lexer_consume_token (parser->lexer);
+ parameter_declaration = NULL_TREE;
+ }
+ else
+ {
+ /* We have "@catch (NSException *exception)" or something
+ like that. Parse the parameter declaration. */
+ parm = cp_parser_parameter_declaration (parser, false, NULL);
+ if (parm == NULL)
+ parameter_declaration = error_mark_node;
+ else
+ parameter_declaration = grokdeclarator (parm->declarator,
+ &parm->decl_specifiers,
+ PARM, /*initialized=*/0,
+ /*attrlist=*/NULL);
+ }
+ if (seen_open_paren)
+ cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+ else
+ {
+ /* If there was no open parenthesis, we are recovering from
+ an error, and we are trying to figure out what mistake
+ the user has made. */
+
+ /* If there is an immediate closing parenthesis, the user
+ probably forgot the opening one (ie, they typed "@catch
+ NSException *e)". Parse the closing parenthesis and keep
+ going. */
+ if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN))
+ cp_lexer_consume_token (parser->lexer);
+
+ /* If these is no immediate closing parenthesis, the user
+ probably doesn't know that parenthesis are required at
+ all (ie, they typed "@catch NSException *e"). So, just
+ forget about the closing parenthesis and keep going. */
+ }
+ objc_begin_catch_clause (parameter_declaration);
+ 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, RT_AT_SYNCHRONIZED);
+
+ location = cp_lexer_peek_token (parser->lexer)->location;
+ objc_maybe_warn_exceptions (location);
+ cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
+ lock = cp_parser_expression (parser, false, NULL);
+ cp_parser_require (parser, CPP_CLOSE_PAREN, RT_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;
+ location_t loc = cp_lexer_peek_token (parser->lexer)->location;
+
+ cp_parser_require_keyword (parser, RID_AT_THROW, RT_AT_THROW);
+
+ if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
+ expr = cp_parser_expression (parser, /*cast_p=*/false, NULL);
+
+ cp_parser_consume_semicolon_at_end_of_statement (parser);
+
+ return objc_build_throw_stmt (loc, expr);
+}
+
+/* Parse an Objective-C statement. */
+
+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_at (kwd->location, "misplaced %<@%D%> Objective-C++ construct",
+ kwd->u.value);
+ cp_parser_skip_to_end_of_block_or_statement (parser);
+ }
+
+ return error_mark_node;
+}
+
+/* If we are compiling ObjC++ and we see an __attribute__ we neeed to
+ look ahead to see if an objc keyword follows the attributes. This
+ is to detect the use of prefix attributes on ObjC @interface and
+ @protocol. */
+
+static bool
+cp_parser_objc_valid_prefix_attributes (cp_parser* parser, tree *attrib)
+{
+ cp_lexer_save_tokens (parser->lexer);
+ *attrib = cp_parser_attributes_opt (parser);
+ gcc_assert (*attrib);
+ if (OBJC_IS_AT_KEYWORD (cp_lexer_peek_token (parser->lexer)->keyword))
+ {
+ cp_lexer_commit_tokens (parser->lexer);
+ return true;
+ }
+ cp_lexer_rollback_tokens (parser->lexer);
+ return false;
+}
+
+/* This routine is a minimal replacement for
+ c_parser_struct_declaration () used when parsing the list of
+ types/names or ObjC++ properties. For example, when parsing the
+ code
+
+ @property (readonly) int a, b, c;
+
+ this function is responsible for parsing "int a, int b, int c" and
+ returning the declarations as CHAIN of DECLs.
+
+ TODO: Share this code with cp_parser_objc_class_ivars. It's very
+ similar parsing. */
+static tree
+cp_parser_objc_struct_declaration (cp_parser *parser)
+{
+ tree decls = NULL_TREE;
+ cp_decl_specifier_seq declspecs;
+ int decl_class_or_enum_p;
+ tree prefix_attributes;
+
+ cp_parser_decl_specifier_seq (parser,
+ CP_PARSER_FLAGS_NONE,
+ &declspecs,
+ &decl_class_or_enum_p);
+
+ if (declspecs.type == error_mark_node)
+ return error_mark_node;
+
+ /* auto, register, static, extern, mutable. */
+ if (declspecs.storage_class != sc_none)
+ {
+ cp_parser_error (parser, "invalid type for property");
+ declspecs.storage_class = sc_none;
+ }
+
+ /* __thread. */
+ if (declspecs.specs[(int) ds_thread])
+ {
+ cp_parser_error (parser, "invalid type for property");
+ declspecs.specs[(int) ds_thread] = 0;
+ }
+
+ /* typedef. */
+ if (declspecs.specs[(int) ds_typedef])
+ {
+ cp_parser_error (parser, "invalid type for property");
+ declspecs.specs[(int) ds_typedef] = 0;
+ }
+
+ 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 attributes, first_attribute, decl;
+ cp_declarator *declarator;
+ cp_token *token;
+
+ /* Parse the declarator. */
+ declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
+ NULL, NULL, 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);
+
+ decl = grokfield (declarator, &declspecs,
+ NULL_TREE, /*init_const_expr_p=*/false,
+ NULL_TREE, attributes);
+
+ if (decl == error_mark_node || decl == NULL_TREE)
+ return error_mark_node;
+
+ /* Reset PREFIX_ATTRIBUTES. */
+ while (attributes && TREE_CHAIN (attributes) != first_attribute)
+ attributes = TREE_CHAIN (attributes);
+ if (attributes)
+ TREE_CHAIN (attributes) = NULL_TREE;
+
+ DECL_CHAIN (decl) = decls;
+ decls = decl;
+
+ token = cp_lexer_peek_token (parser->lexer);
+ if (token->type == CPP_COMMA)
+ {
+ cp_lexer_consume_token (parser->lexer); /* Eat ','. */
+ continue;
+ }
+ else
+ break;
+ }
+ return decls;
+}
+
+/* Parse an Objective-C @property declaration. The syntax is:
+
+ objc-property-declaration:
+ '@property' objc-property-attributes[opt] struct-declaration ;
+
+ objc-property-attributes:
+ '(' objc-property-attribute-list ')'
+
+ objc-property-attribute-list:
+ objc-property-attribute
+ objc-property-attribute-list, objc-property-attribute
+
+ objc-property-attribute
+ 'getter' = identifier
+ 'setter' = identifier
+ 'readonly'
+ 'readwrite'
+ 'assign'
+ 'retain'
+ 'copy'
+ 'nonatomic'
+
+ For example:
+ @property NSString *name;
+ @property (readonly) id object;
+ @property (retain, nonatomic, getter=getTheName) id name;
+ @property int a, b, c;
+
+ PS: This function is identical to
+ c_parser_objc_at_property_declaration for C. Keep them in sync. */
+static void
+cp_parser_objc_at_property_declaration (cp_parser *parser)
+{
+ /* The following variables hold the attributes of the properties as
+ parsed. They are 'false' or 'NULL_TREE' if the attribute was not
+ seen. When we see an attribute, we set them to 'true' (if they
+ are boolean properties) or to the identifier (if they have an
+ argument, ie, for getter and setter). Note that here we only
+ parse the list of attributes, check the syntax and accumulate the
+ attributes that we find. objc_add_property_declaration() will
+ then process the information. */
+ bool property_assign = false;
+ bool property_copy = false;
+ tree property_getter_ident = NULL_TREE;
+ bool property_nonatomic = false;
+ bool property_readonly = false;
+ bool property_readwrite = false;
+ bool property_retain = false;
+ tree property_setter_ident = NULL_TREE;
+
+ /* 'properties' is the list of properties that we read. Usually a
+ single one, but maybe more (eg, in "@property int a, b, c;" there
+ are three). */
+ tree properties;
+ location_t loc;
+
+ loc = cp_lexer_peek_token (parser->lexer)->location;
+
+ cp_lexer_consume_token (parser->lexer); /* Eat '@property'. */
+
+ /* Parse the optional attribute list... */
+ if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
+ {
+ /* Eat the '('. */
+ cp_lexer_consume_token (parser->lexer);
+
+ while (true)
+ {
+ bool syntax_error = false;
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
+ enum rid keyword;
+
+ if (token->type != CPP_NAME)
+ {
+ cp_parser_error (parser, "expected identifier");
+ break;
+ }
+ keyword = C_RID_CODE (token->u.value);
+ cp_lexer_consume_token (parser->lexer);
+ switch (keyword)
+ {
+ case RID_ASSIGN: property_assign = true; break;
+ case RID_COPY: property_copy = true; break;
+ case RID_NONATOMIC: property_nonatomic = true; break;
+ case RID_READONLY: property_readonly = true; break;
+ case RID_READWRITE: property_readwrite = true; break;
+ case RID_RETAIN: property_retain = true; break;
+
+ case RID_GETTER:
+ case RID_SETTER:
+ if (cp_lexer_next_token_is_not (parser->lexer, CPP_EQ))
+ {
+ if (keyword == RID_GETTER)
+ cp_parser_error (parser,
+ "missing %<=%> (after %<getter%> attribute)");
+ else
+ cp_parser_error (parser,
+ "missing %<=%> (after %<setter%> attribute)");
+ syntax_error = true;
+ break;
+ }
+ cp_lexer_consume_token (parser->lexer); /* eat the = */
+ if (cp_lexer_next_token_is_not (parser->lexer, CPP_NAME))
+ {
+ cp_parser_error (parser, "expected identifier");
+ syntax_error = true;
+ break;
+ }
+ if (keyword == RID_SETTER)
+ {
+ if (property_setter_ident != NULL_TREE)
+ cp_parser_error (parser, "the %<setter%> attribute may only be specified once");
+ else
+ property_setter_ident = cp_lexer_peek_token (parser->lexer)->u.value;
+ cp_lexer_consume_token (parser->lexer);
+ if (cp_lexer_next_token_is_not (parser->lexer, CPP_COLON))
+ cp_parser_error (parser, "setter name must terminate with %<:%>");
+ else
+ cp_lexer_consume_token (parser->lexer);
+ }
+ else
+ {
+ if (property_getter_ident != NULL_TREE)
+ cp_parser_error (parser, "the %<getter%> attribute may only be specified once");
+ else
+ property_getter_ident = cp_lexer_peek_token (parser->lexer)->u.value;
+ cp_lexer_consume_token (parser->lexer);
+ }
+ break;
+ default:
+ cp_parser_error (parser, "unknown property attribute");
+ syntax_error = true;
+ break;
+ }
+
+ if (syntax_error)
+ break;
+
+ if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+ cp_lexer_consume_token (parser->lexer);
+ else
+ break;
+ }
+
+ /* FIXME: "@property (setter, assign);" will generate a spurious
+ "error: expected ‘)’ before ‘,’ token". This is because
+ cp_parser_require, unlike the C counterpart, will produce an
+ error even if we are in error recovery. */
+ if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ {
+ cp_parser_skip_to_closing_parenthesis (parser,
+ /*recovering=*/true,
+ /*or_comma=*/false,
+ /*consume_paren=*/true);
+ }
+ }
+
+ /* ... and the property declaration(s). */
+ properties = cp_parser_objc_struct_declaration (parser);
+
+ if (properties == error_mark_node)
+ {
+ cp_parser_skip_to_end_of_statement (parser);
+ /* If the next token is now a `;', consume it. */
+ if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
+ cp_lexer_consume_token (parser->lexer);
+ return;
+ }
+
+ if (properties == NULL_TREE)
+ cp_parser_error (parser, "expected identifier");
+ else
+ {
+ /* Comma-separated properties are chained together in
+ reverse order; add them one by one. */
+ properties = nreverse (properties);
+
+ for (; properties; properties = TREE_CHAIN (properties))
+ objc_add_property_declaration (loc, copy_node (properties),
+ property_readonly, property_readwrite,
+ property_assign, property_retain,
+ property_copy, property_nonatomic,
+ property_getter_ident, property_setter_ident);
+ }
+
+ cp_parser_consume_semicolon_at_end_of_statement (parser);
+}
+
+/* Parse an Objective-C++ @synthesize declaration. The syntax is:
+
+ objc-synthesize-declaration:
+ @synthesize objc-synthesize-identifier-list ;
+
+ objc-synthesize-identifier-list:
+ objc-synthesize-identifier
+ objc-synthesize-identifier-list, objc-synthesize-identifier
+
+ objc-synthesize-identifier
+ identifier
+ identifier = identifier
+
+ For example:
+ @synthesize MyProperty;
+ @synthesize OneProperty, AnotherProperty=MyIvar, YetAnotherProperty;
+
+ PS: This function is identical to c_parser_objc_at_synthesize_declaration
+ for C. Keep them in sync.
+*/
+static void
+cp_parser_objc_at_synthesize_declaration (cp_parser *parser)
+{
+ tree list = NULL_TREE;
+ location_t loc;
+ loc = cp_lexer_peek_token (parser->lexer)->location;
+
+ cp_lexer_consume_token (parser->lexer); /* Eat '@synthesize'. */
+ while (true)
+ {
+ tree property, ivar;
+ property = cp_parser_identifier (parser);
+ if (property == error_mark_node)
+ {
+ cp_parser_consume_semicolon_at_end_of_statement (parser);
+ return;
+ }
+ if (cp_lexer_next_token_is (parser->lexer, CPP_EQ))
+ {
+ cp_lexer_consume_token (parser->lexer);
+ ivar = cp_parser_identifier (parser);
+ if (ivar == error_mark_node)
+ {
+ cp_parser_consume_semicolon_at_end_of_statement (parser);
+ return;
+ }
+ }
+ else
+ ivar = NULL_TREE;
+ list = chainon (list, build_tree_list (ivar, property));
+ if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+ cp_lexer_consume_token (parser->lexer);
+ else
+ break;
+ }
+ cp_parser_consume_semicolon_at_end_of_statement (parser);
+ objc_add_synthesize_declaration (loc, list);
+}
+
+/* Parse an Objective-C++ @dynamic declaration. The syntax is:
+
+ objc-dynamic-declaration:
+ @dynamic identifier-list ;
+
+ For example:
+ @dynamic MyProperty;
+ @dynamic MyProperty, AnotherProperty;
+
+ PS: This function is identical to c_parser_objc_at_dynamic_declaration
+ for C. Keep them in sync.
+*/
+static void
+cp_parser_objc_at_dynamic_declaration (cp_parser *parser)
+{
+ tree list = NULL_TREE;
+ location_t loc;
+ loc = cp_lexer_peek_token (parser->lexer)->location;
+
+ cp_lexer_consume_token (parser->lexer); /* Eat '@dynamic'. */
+ while (true)
+ {
+ tree property;
+ property = cp_parser_identifier (parser);
+ if (property == error_mark_node)
+ {
+ cp_parser_consume_semicolon_at_end_of_statement (parser);
+ return;
+ }
+ list = chainon (list, build_tree_list (NULL, property));
+ if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+ cp_lexer_consume_token (parser->lexer);
+ else
+ break;
+ }
+ cp_parser_consume_semicolon_at_end_of_statement (parser);
+ objc_add_dynamic_declaration (loc, list);
+}
\f
/* OpenMP 2.5 parsing routines. */
-2011-02-13 Mike Stump <mikestump@comcast.net>
-
- * plugin/parser.h: Add arguments to all plugins.
- * plugin/lex.h: Plugify.
-
-2011-02-12 Mike Stump <mikestump@comcast.net>
-
- * Make-lang.in (obj-c++.tags): Plugify Objective-C++.
- * plugin/parser.h: Likewise.
- * plugin/parser.c: Likewise.
-
2011-02-07 Mike Stump <mikestump@comcast.net>
* Make-lang.in (obj-c++.tags): Don't include *.y.
obj-c++.install-plugin:
obj-c++.tags: force
- cd $(srcdir)/objcp; etags -o TAGS.sub *.c *.h plugin/*.h plugin/*.c; \
+ cd $(srcdir)/objcp; etags -o TAGS.sub *.c *.h; \
etags --include TAGS.sub --include ../TAGS.sub
lang_checks += check-obj-c++
+++ /dev/null
-/* Objective-C++ Parser plugin
- Copyright (C) 2011 Free Software Foundation, Inc.
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3, or (at your option)
- any later version.
-
- GCC is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
-
-
-#ifndef HIDE_OBJC
-
-#include "c-family/c-objc.h"
-
-#define PLUGIN_UNQUALIFIED_NAME_LOOKUP_ERROR(name) @(
- objc_diagnose_private_ivar (name)@)
-
-#else
-
-#define PLUGIN_UNQUALIFIED_NAME_LOOKUP_ERROR(name) 0
-
-#endif
+++ /dev/null
-/* Objective-C++ Parser plugin
- Copyright (C) 2000, 2001, 2002, 2003, 2004,
- 2005, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3, or (at your option)
- any later version.
-
- GCC is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
-
-
-#ifndef HIDE_OBJC
-
-/* 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->u.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_at (kwd->location,
- "misplaced %<@%D%> Objective-C++ construct",
- kwd->u.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, RT_CLOSE_SQUARE);
-
- return objc_build_message_expr (build_tree_list (receiver, messageargs));
-}
-
-/* Parse an objc-message-receiver.
-
- objc-message-receiver:
- expression
- simple-type-specifier
-
- Returns a representation of the type or expression. */
-
-static tree
-cp_parser_objc_message_receiver (cp_parser* parser)
-{
- tree rcv;
-
- /* 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, NULL);
-
- if (cp_parser_parse_definitely (parser))
- return rcv;
-
- rcv = cp_parser_simple_type_specifier (parser,
- /*decl_specs=*/NULL,
- CP_PARSER_FLAGS_NONE);
-
- 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, RT_COLON);
- arg = cp_parser_assignment_expression (parser, false, NULL);
-
- 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, NULL);
-
- addl_args
- = chainon (addl_args,
- build_tree_list (NULL_TREE, arg));
-
- token = cp_lexer_peek_token (parser->lexer);
- }
-
- if (sel_args == NULL_TREE && addl_args == NULL_TREE)
- {
- cp_parser_error (parser, "objective-c++ message argument(s) are expected");
- return build_tree_list (error_mark_node, error_mark_node);
- }
-
- 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_token *token;
-
- cp_lexer_consume_token (parser->lexer); /* Eat '@encode'. */
- cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
- token = cp_lexer_peek_token (parser->lexer);
- type = complete_type (cp_parser_type_id (parser));
- cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
-
- if (!type)
- {
- error_at (token->location,
- "%<@encode%> must specify a type as an argument");
- return error_mark_node;
- }
-
- /* This happens if we find @encode(T) (where T is a template
- typename or something dependent on a template typename) when
- parsing a template. In that case, we can't compile it
- immediately, but we rather create an AT_ENCODE_EXPR which will
- need to be instantiated when the template is used.
- */
- if (dependent_type_p (type))
- {
- tree value = build_min (AT_ENCODE_EXPR, size_type_node, type);
- TREE_READONLY (value) = 1;
- return value;
- }
-
- 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, RT_OPEN_PAREN);
- name = cp_parser_identifier (parser);
- cp_parser_require (parser, CPP_CLOSE_PAREN, RT_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, RT_OPEN_PAREN);
- proto = cp_parser_identifier (parser);
- cp_parser_require (parser, CPP_CLOSE_PAREN, RT_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;
- location_t loc = cp_lexer_peek_token (parser->lexer)->location;
-
- cp_lexer_consume_token (parser->lexer); /* Eat '@selector'. */
- cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
- token = cp_lexer_peek_token (parser->lexer);
-
- while (cp_parser_objc_selector_p (token->type) || token->type == CPP_COLON
- || token->type == CPP_SCOPE)
- {
- tree selector = NULL_TREE;
-
- if (token->type != CPP_COLON
- || token->type == CPP_SCOPE)
- selector = cp_parser_objc_selector (parser);
-
- if (cp_lexer_next_token_is_not (parser->lexer, CPP_COLON)
- && cp_lexer_next_token_is_not (parser->lexer, CPP_SCOPE))
- {
- /* Detect if we have a unary selector. */
- if (maybe_unary_selector_p)
- {
- sel_seq = selector;
- goto finish_selector;
- }
- else
- {
- cp_parser_error (parser, "expected %<:%>");
- }
- }
- maybe_unary_selector_p = false;
- token = cp_lexer_consume_token (parser->lexer);
-
- if (token->type == CPP_SCOPE)
- {
- sel_seq
- = chainon (sel_seq,
- build_tree_list (selector, NULL_TREE));
- sel_seq
- = chainon (sel_seq,
- build_tree_list (NULL_TREE, NULL_TREE));
- }
- else
- 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, RT_CLOSE_PAREN);
-
- return objc_build_selector_expr (loc, 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 identifier;
- tree list;
- cp_token *sep;
-
- identifier = cp_parser_identifier (parser);
- if (identifier == error_mark_node)
- return error_mark_node;
-
- list = build_tree_list (NULL_TREE, identifier);
- sep = cp_lexer_peek_token (parser->lexer);
-
- while (sep->type == CPP_COMMA)
- {
- cp_lexer_consume_token (parser->lexer); /* Eat ','. */
- identifier = cp_parser_identifier (parser);
- if (identifier == error_mark_node)
- return list;
-
- list = chainon (list, build_tree_list (NULL_TREE,
- identifier));
- 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, RT_GREATER);
- }
-
- return protorefs;
-}
-
-/* Parse a Objective-C visibility specification. */
-
-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 (OBJC_IVAR_VIS_PRIVATE);
- break;
- case RID_AT_PROTECTED:
- objc_set_visibility (OBJC_IVAR_VIS_PROTECTED);
- break;
- case RID_AT_PUBLIC:
- objc_set_visibility (OBJC_IVAR_VIS_PUBLIC);
- break;
- case RID_AT_PACKAGE:
- objc_set_visibility (OBJC_IVAR_VIS_PACKAGE);
- break;
- default:
- return;
- }
-
- /* Eat '@private'/'@protected'/'@public'. */
- cp_lexer_consume_token (parser->lexer);
-}
-
-/* Parse an Objective-C method type. Return 'true' if it is a class
- (+) method, and 'false' if it is an instance (-) method. */
-
-static inline bool
-cp_parser_objc_method_type (cp_parser* parser)
-{
- if (cp_lexer_consume_token (parser->lexer)->type == CPP_PLUS)
- return true;
- else
- return false;
-}
-
-/* Parse an Objective-C protocol qualifier. */
-
-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->u.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->u.value;
- }
-
- return quals;
-}
-
-/* Parse an Objective-C typename. */
-
-static tree
-cp_parser_objc_typename (cp_parser* parser)
-{
- tree type_name = 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);
-
- /* If the type could not be parsed, an error has already
- been produced. For error recovery, behave as if it had
- not been specified, which will use the default type
- 'id'. */
- if (cp_type == error_mark_node)
- {
- cp_type = NULL_TREE;
- /* We need to skip to the closing parenthesis as
- cp_parser_type_id() does not seem to do it for
- us. */
- cp_parser_skip_to_closing_parenthesis (parser,
- /*recovering=*/true,
- /*or_comma=*/false,
- /*consume_paren=*/false);
- }
- }
-
- cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
- type_name = build_tree_list (proto_quals, cp_type);
- }
-
- return type_name;
-}
-
-/* Check to see if TYPE refers to an Objective-C selector name. */
-
-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);
-}
-
-/* Parse an Objective-C selector. */
-
-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_at (token->location, "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->u.value;
- }
-}
-
-/* Parse an Objective-C params list. */
-
-static tree
-cp_parser_objc_method_keyword_params (cp_parser* parser, tree* attributes)
-{
- 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, type_name, identifier;
- tree parm_attr = NULL_TREE;
-
- if (token->keyword == RID_ATTRIBUTE)
- break;
-
- 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))
- {
- params = selector; /* Might be followed by attributes. */
- break;
- }
-
- maybe_unary_selector_p = false;
- if (!cp_parser_require (parser, CPP_COLON, RT_COLON))
- {
- /* Something went quite wrong. There should be a colon
- here, but there is not. Stop parsing parameters. */
- break;
- }
- type_name = cp_parser_objc_typename (parser);
- /* New ObjC allows attributes on parameters too. */
- if (cp_lexer_next_token_is_keyword (parser->lexer, RID_ATTRIBUTE))
- parm_attr = cp_parser_attributes_opt (parser);
- identifier = cp_parser_identifier (parser);
-
- params
- = chainon (params,
- objc_build_keyword_decl (selector,
- type_name,
- identifier,
- parm_attr));
-
- token = cp_lexer_peek_token (parser->lexer);
- }
-
- if (params == NULL_TREE)
- {
- cp_parser_error (parser, "objective-c++ method declaration is expected");
- return error_mark_node;
- }
-
- /* We allow tail attributes for the method. */
- if (token->keyword == RID_ATTRIBUTE)
- {
- *attributes = cp_parser_attributes_opt (parser);
- if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)
- || cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
- return params;
- cp_parser_error (parser,
- "method attributes must be specified at the end");
- return error_mark_node;
- }
-
- if (params == NULL_TREE)
- {
- cp_parser_error (parser, "objective-c++ method declaration is expected");
- return error_mark_node;
- }
- return params;
-}
-
-/* Parse the non-keyword Objective-C params. */
-
-static tree
-cp_parser_objc_method_tail_params_opt (cp_parser* parser, bool *ellipsisp,
- tree* attributes)
-{
- tree params = make_node (TREE_LIST);
- cp_token *token = cp_lexer_peek_token (parser->lexer);
- *ellipsisp = false; /* 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 '...'. */
- *ellipsisp = true;
- token = cp_lexer_peek_token (parser->lexer);
- break;
- }
-
- /* TODO: parse attributes for tail parameters. */
- 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);
- }
-
- /* We allow tail attributes for the method. */
- if (token->keyword == RID_ATTRIBUTE)
- {
- if (*attributes == NULL_TREE)
- {
- *attributes = cp_parser_attributes_opt (parser);
- if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)
- || cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
- return params;
- }
- else
- /* We have an error, but parse the attributes, so that we can
- carry on. */
- *attributes = cp_parser_attributes_opt (parser);
-
- cp_parser_error (parser,
- "method attributes must be specified at the end");
- return error_mark_node;
- }
-
- return params;
-}
-
-/* Parse a linkage specification, a pragma, an extra semicolon or a block. */
-
-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_parser_pragma (parser, pragma_external);
- /* Allow stray semicolons. */
- else if (token->type == CPP_SEMICOLON)
- cp_lexer_consume_token (parser->lexer);
- /* Mark methods as optional or required, when building protocols. */
- else if (token->keyword == RID_AT_OPTIONAL)
- {
- cp_lexer_consume_token (parser->lexer);
- objc_set_method_opt (true);
- }
- else if (token->keyword == RID_AT_REQUIRED)
- {
- cp_lexer_consume_token (parser->lexer);
- objc_set_method_opt (false);
- }
- else if (token->keyword == RID_NAMESPACE)
- cp_parser_namespace_definition (parser);
- /* Other stray characters must generate errors. */
- else if (token->type == CPP_OPEN_BRACE || token->type == CPP_CLOSE_BRACE)
- {
- cp_lexer_consume_token (parser->lexer);
- error ("stray %qs between Objective-C++ methods",
- token->type == CPP_OPEN_BRACE ? "{" : "}");
- }
- /* Finally, try to parse a block-declaration, or a function-definition. */
- else
- cp_parser_block_declaration (parser, /*statement_p=*/false);
-}
-
-/* Parse a method signature. */
-
-static tree
-cp_parser_objc_method_signature (cp_parser* parser, tree* attributes)
-{
- tree rettype, kwdparms, optparms;
- bool ellipsis = false;
- bool is_class_method;
-
- is_class_method = cp_parser_objc_method_type (parser);
- rettype = cp_parser_objc_typename (parser);
- *attributes = NULL_TREE;
- kwdparms = cp_parser_objc_method_keyword_params (parser, attributes);
- if (kwdparms == error_mark_node)
- return error_mark_node;
- optparms = cp_parser_objc_method_tail_params_opt (parser, &ellipsis, attributes);
- if (optparms == error_mark_node)
- return error_mark_node;
-
- return objc_build_method_signature (is_class_method, rettype, kwdparms, optparms, ellipsis);
-}
-
-static bool
-cp_parser_objc_method_maybe_bad_prefix_attributes (cp_parser* parser)
-{
- tree tattr;
- cp_lexer_save_tokens (parser->lexer);
- tattr = cp_parser_attributes_opt (parser);
- gcc_assert (tattr) ;
-
- /* If the attributes are followed by a method introducer, this is not allowed.
- Dump the attributes and flag the situation. */
- if (cp_lexer_next_token_is (parser->lexer, CPP_PLUS)
- || cp_lexer_next_token_is (parser->lexer, CPP_MINUS))
- return true;
-
- /* Otherwise, the attributes introduce some interstitial code, possibly so
- rewind to allow that check. */
- cp_lexer_rollback_tokens (parser->lexer);
- return false;
-}
-
-/* Parse an Objective-C method prototype list. */
-
-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 && token->type != CPP_EOF)
- {
- if (token->type == CPP_PLUS || token->type == CPP_MINUS)
- {
- tree attributes, sig;
- bool is_class_method;
- if (token->type == CPP_PLUS)
- is_class_method = true;
- else
- is_class_method = false;
- sig = cp_parser_objc_method_signature (parser, &attributes);
- if (sig == error_mark_node)
- {
- cp_parser_skip_to_end_of_block_or_statement (parser);
- token = cp_lexer_peek_token (parser->lexer);
- continue;
- }
- objc_add_method_declaration (is_class_method, sig, attributes);
- cp_parser_consume_semicolon_at_end_of_statement (parser);
- }
- else if (token->keyword == RID_AT_PROPERTY)
- cp_parser_objc_at_property_declaration (parser);
- else if (token->keyword == RID_ATTRIBUTE
- && cp_parser_objc_method_maybe_bad_prefix_attributes(parser))
- warning_at (cp_lexer_peek_token (parser->lexer)->location,
- OPT_Wattributes,
- "prefix attributes are ignored for methods");
- else
- /* Allow for interspersed non-ObjC++ code. */
- cp_parser_objc_interstitial_code (parser);
-
- token = cp_lexer_peek_token (parser->lexer);
- }
-
- if (token->type != CPP_EOF)
- cp_lexer_consume_token (parser->lexer); /* Eat '@end'. */
- else
- cp_parser_error (parser, "expected %<@end%>");
-
- objc_finish_interface ();
-}
-
-/* Parse an Objective-C method definition list. */
-
-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 && token->type != CPP_EOF)
- {
- tree meth;
-
- if (token->type == CPP_PLUS || token->type == CPP_MINUS)
- {
- cp_token *ptk;
- tree sig, attribute;
- bool is_class_method;
- if (token->type == CPP_PLUS)
- is_class_method = true;
- else
- is_class_method = false;
- push_deferring_access_checks (dk_deferred);
- sig = cp_parser_objc_method_signature (parser, &attribute);
- if (sig == error_mark_node)
- {
- cp_parser_skip_to_end_of_block_or_statement (parser);
- token = cp_lexer_peek_token (parser->lexer);
- continue;
- }
- objc_start_method_definition (is_class_method, sig, attribute);
-
- /* For historical reasons, we accept an optional semicolon. */
- if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
- cp_lexer_consume_token (parser->lexer);
-
- ptk = cp_lexer_peek_token (parser->lexer);
- if (!(ptk->type == CPP_PLUS || ptk->type == CPP_MINUS
- || ptk->type == CPP_EOF || ptk->keyword == RID_AT_END))
- {
- 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);
- }
- }
- /* The following case will be removed once @synthesize is
- completely implemented. */
- else if (token->keyword == RID_AT_PROPERTY)
- cp_parser_objc_at_property_declaration (parser);
- else if (token->keyword == RID_AT_SYNTHESIZE)
- cp_parser_objc_at_synthesize_declaration (parser);
- else if (token->keyword == RID_AT_DYNAMIC)
- cp_parser_objc_at_dynamic_declaration (parser);
- else if (token->keyword == RID_ATTRIBUTE
- && cp_parser_objc_method_maybe_bad_prefix_attributes(parser))
- warning_at (token->location, OPT_Wattributes,
- "prefix attributes are ignored for methods");
- else
- /* Allow for interspersed non-ObjC++ code. */
- cp_parser_objc_interstitial_code (parser);
-
- token = cp_lexer_peek_token (parser->lexer);
- }
-
- if (token->type != CPP_EOF)
- cp_lexer_consume_token (parser->lexer); /* Eat '@end'. */
- else
- cp_parser_error (parser, "expected %<@end%>");
-
- objc_finish_implementation ();
-}
-
-/* Parse Objective-C ivars. */
-
-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
- && token->keyword != RID_AT_END && token->type != CPP_EOF)
- {
- 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);
-
- /* auto, register, static, extern, mutable. */
- if (declspecs.storage_class != sc_none)
- {
- cp_parser_error (parser, "invalid type for instance variable");
- declspecs.storage_class = sc_none;
- }
-
- /* __thread. */
- if (declspecs.specs[(int) ds_thread])
- {
- cp_parser_error (parser, "invalid type for instance variable");
- declspecs.specs[(int) ds_thread] = 0;
- }
-
- /* typedef. */
- if (declspecs.specs[(int) ds_typedef])
- {
- cp_parser_error (parser, "invalid type for instance variable");
- declspecs.specs[(int) ds_typedef] = 0;
- }
-
- 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),
- sfk_none);
-
- 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,
- attributes);
- else
- decl = grokfield (declarator, &declspecs,
- NULL_TREE, /*init_const_expr_p=*/false,
- 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);
- }
-
- if (token->keyword == RID_AT_END)
- cp_parser_error (parser, "expected %<}%>");
-
- /* Do not consume the RID_AT_END, so it will be read again as terminating
- the @interface of @implementation. */
- if (token->keyword != RID_AT_END && token->type != CPP_EOF)
- 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);
-}
-
-/* Parse an Objective-C protocol declaration. */
-
-static void
-cp_parser_objc_protocol_declaration (cp_parser* parser, tree attributes)
-{
- 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))
- {
- tok = cp_lexer_peek_token (parser->lexer);
- error_at (tok->location, "identifier expected after %<@protocol%>");
- goto finish;
- }
-
- /* See if we have a forward 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),
- attributes);
- 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, attributes);
- cp_parser_objc_method_prototype_list (parser);
- }
-}
-
-/* Parse an Objective-C superclass or category. */
-
-static void
-cp_parser_objc_superclass_or_category (cp_parser *parser,
- bool iface_p,
- tree *super,
- tree *categ, bool *is_class_extension)
-{
- cp_token *next = cp_lexer_peek_token (parser->lexer);
-
- *super = *categ = NULL_TREE;
- *is_class_extension = false;
- 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 '('. */
-
- /* If there is no category name, and this is an @interface, we
- have a class extension. */
- if (iface_p && cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN))
- {
- *categ = NULL_TREE;
- *is_class_extension = true;
- }
- else
- *categ = cp_parser_identifier (parser);
-
- cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
- }
-}
-
-/* Parse an Objective-C class interface. */
-
-static void
-cp_parser_objc_class_interface (cp_parser* parser, tree attributes)
-{
- tree name, super, categ, protos;
- bool is_class_extension;
-
- cp_lexer_consume_token (parser->lexer); /* Eat '@interface'. */
- name = cp_parser_identifier (parser);
- if (name == error_mark_node)
- {
- /* It's hard to recover because even if valid @interface stuff
- is to follow, we can't compile it (or validate it) if we
- don't even know which class it refers to. Let's assume this
- was a stray '@interface' token in the stream and skip it.
- */
- return;
- }
- cp_parser_objc_superclass_or_category (parser, true, &super, &categ,
- &is_class_extension);
- protos = cp_parser_objc_protocol_refs_opt (parser);
-
- /* We have either a class or a category on our hands. */
- if (categ || is_class_extension)
- objc_start_category_interface (name, categ, protos, attributes);
- else
- {
- objc_start_class_interface (name, super, protos, attributes);
- /* Handle instance variable declarations, if any. */
- cp_parser_objc_class_ivars (parser);
- objc_continue_interface ();
- }
-
- cp_parser_objc_method_prototype_list (parser);
-}
-
-/* Parse an Objective-C class implementation. */
-
-static void
-cp_parser_objc_class_implementation (cp_parser* parser)
-{
- tree name, super, categ;
- bool is_class_extension;
-
- cp_lexer_consume_token (parser->lexer); /* Eat '@implementation'. */
- name = cp_parser_identifier (parser);
- if (name == error_mark_node)
- {
- /* It's hard to recover because even if valid @implementation
- stuff is to follow, we can't compile it (or validate it) if
- we don't even know which class it refers to. Let's assume
- this was a stray '@implementation' token in the stream and
- skip it.
- */
- return;
- }
- cp_parser_objc_superclass_or_category (parser, false, &super, &categ,
- &is_class_extension);
-
- /* 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);
-}
-
-/* Consume the @end token and finish off the implementation. */
-
-static void
-cp_parser_objc_end_implementation (cp_parser* parser)
-{
- cp_lexer_consume_token (parser->lexer); /* Eat '@end'. */
- objc_finish_implementation ();
-}
-
-/* Parse an Objective-C declaration. */
-
-static void
-cp_parser_objc_declaration (cp_parser* parser, tree attributes)
-{
- /* Try to figure out what kind of declaration is present. */
- cp_token *kwd = cp_lexer_peek_token (parser->lexer);
-
- if (attributes)
- switch (kwd->keyword)
- {
- case RID_AT_ALIAS:
- case RID_AT_CLASS:
- case RID_AT_END:
- error_at (kwd->location, "attributes may not be specified before"
- " the %<@%D%> Objective-C++ keyword",
- kwd->u.value);
- attributes = NULL;
- break;
- case RID_AT_IMPLEMENTATION:
- warning_at (kwd->location, OPT_Wattributes,
- "prefix attributes are ignored before %<@%D%>",
- kwd->u.value);
- attributes = NULL;
- default:
- break;
- }
-
- 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, attributes);
- break;
- case RID_AT_INTERFACE:
- cp_parser_objc_class_interface (parser, attributes);
- 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_at (kwd->location, "misplaced %<@%D%> Objective-C++ construct",
- kwd->u.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 ( objc-exception-declaration ) compound-statement
-
- objc-finally-clause:
- @finally compound-statement
-
- objc-exception-declaration:
- parameter-declaration
- '...'
-
- where '...' is to be interpreted literally, that is, it means CPP_ELLIPSIS.
-
- Returns NULL_TREE.
-
- PS: This function is identical to c_parser_objc_try_catch_finally_statement
- for C. Keep them in sync. */
-
-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, RT_AT_TRY);
- location = cp_lexer_peek_token (parser->lexer)->location;
- objc_maybe_warn_exceptions (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 *parm;
- tree parameter_declaration = error_mark_node;
- bool seen_open_paren = false;
-
- cp_lexer_consume_token (parser->lexer);
- if (cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
- seen_open_paren = true;
- if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
- {
- /* We have "@catch (...)" (where the '...' are literally
- what is in the code). Skip the '...'.
- parameter_declaration is set to NULL_TREE, and
- objc_being_catch_clauses() knows that that means
- '...'. */
- cp_lexer_consume_token (parser->lexer);
- parameter_declaration = NULL_TREE;
- }
- else
- {
- /* We have "@catch (NSException *exception)" or something
- like that. Parse the parameter declaration. */
- parm = cp_parser_parameter_declaration (parser, false, NULL);
- if (parm == NULL)
- parameter_declaration = error_mark_node;
- else
- parameter_declaration = grokdeclarator (parm->declarator,
- &parm->decl_specifiers,
- PARM, /*initialized=*/0,
- /*attrlist=*/NULL);
- }
- if (seen_open_paren)
- cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
- else
- {
- /* If there was no open parenthesis, we are recovering from
- an error, and we are trying to figure out what mistake
- the user has made. */
-
- /* If there is an immediate closing parenthesis, the user
- probably forgot the opening one (ie, they typed "@catch
- NSException *e)". Parse the closing parenthesis and keep
- going. */
- if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN))
- cp_lexer_consume_token (parser->lexer);
-
- /* If these is no immediate closing parenthesis, the user
- probably doesn't know that parenthesis are required at
- all (ie, they typed "@catch NSException *e"). So, just
- forget about the closing parenthesis and keep going. */
- }
- objc_begin_catch_clause (parameter_declaration);
- 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, RT_AT_SYNCHRONIZED);
-
- location = cp_lexer_peek_token (parser->lexer)->location;
- objc_maybe_warn_exceptions (location);
- cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
- lock = cp_parser_expression (parser, false, NULL);
- cp_parser_require (parser, CPP_CLOSE_PAREN, RT_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;
- location_t loc = cp_lexer_peek_token (parser->lexer)->location;
-
- cp_parser_require_keyword (parser, RID_AT_THROW, RT_AT_THROW);
-
- if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
- expr = cp_parser_expression (parser, /*cast_p=*/false, NULL);
-
- cp_parser_consume_semicolon_at_end_of_statement (parser);
-
- return objc_build_throw_stmt (loc, expr);
-}
-
-/* Parse an Objective-C statement. */
-
-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_at (kwd->location, "misplaced %<@%D%> Objective-C++ construct",
- kwd->u.value);
- cp_parser_skip_to_end_of_block_or_statement (parser);
- }
-
- return error_mark_node;
-}
-
-/* If we are compiling ObjC++ and we see an __attribute__ we neeed to
- look ahead to see if an objc keyword follows the attributes. This
- is to detect the use of prefix attributes on ObjC @interface and
- @protocol. */
-
-static bool
-cp_parser_objc_valid_prefix_attributes (cp_parser* parser, tree *attrib)
-{
- cp_lexer_save_tokens (parser->lexer);
- *attrib = cp_parser_attributes_opt (parser);
- gcc_assert (*attrib);
- if (OBJC_IS_AT_KEYWORD (cp_lexer_peek_token (parser->lexer)->keyword))
- {
- cp_lexer_commit_tokens (parser->lexer);
- return true;
- }
- cp_lexer_rollback_tokens (parser->lexer);
- return false;
-}
-
-/* This routine is a minimal replacement for
- c_parser_struct_declaration () used when parsing the list of
- types/names or ObjC++ properties. For example, when parsing the
- code
-
- @property (readonly) int a, b, c;
-
- this function is responsible for parsing "int a, int b, int c" and
- returning the declarations as CHAIN of DECLs.
-
- TODO: Share this code with cp_parser_objc_class_ivars. It's very
- similar parsing. */
-static tree
-cp_parser_objc_struct_declaration (cp_parser *parser)
-{
- tree decls = NULL_TREE;
- cp_decl_specifier_seq declspecs;
- int decl_class_or_enum_p;
- tree prefix_attributes;
-
- cp_parser_decl_specifier_seq (parser,
- CP_PARSER_FLAGS_NONE,
- &declspecs,
- &decl_class_or_enum_p);
-
- if (declspecs.type == error_mark_node)
- return error_mark_node;
-
- /* auto, register, static, extern, mutable. */
- if (declspecs.storage_class != sc_none)
- {
- cp_parser_error (parser, "invalid type for property");
- declspecs.storage_class = sc_none;
- }
-
- /* __thread. */
- if (declspecs.specs[(int) ds_thread])
- {
- cp_parser_error (parser, "invalid type for property");
- declspecs.specs[(int) ds_thread] = 0;
- }
-
- /* typedef. */
- if (declspecs.specs[(int) ds_typedef])
- {
- cp_parser_error (parser, "invalid type for property");
- declspecs.specs[(int) ds_typedef] = 0;
- }
-
- 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 attributes, first_attribute, decl;
- cp_declarator *declarator;
- cp_token *token;
-
- /* Parse the declarator. */
- declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
- NULL, NULL, 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);
-
- decl = grokfield (declarator, &declspecs,
- NULL_TREE, /*init_const_expr_p=*/false,
- NULL_TREE, attributes);
-
- if (decl == error_mark_node || decl == NULL_TREE)
- return error_mark_node;
-
- /* Reset PREFIX_ATTRIBUTES. */
- while (attributes && TREE_CHAIN (attributes) != first_attribute)
- attributes = TREE_CHAIN (attributes);
- if (attributes)
- TREE_CHAIN (attributes) = NULL_TREE;
-
- DECL_CHAIN (decl) = decls;
- decls = decl;
-
- token = cp_lexer_peek_token (parser->lexer);
- if (token->type == CPP_COMMA)
- {
- cp_lexer_consume_token (parser->lexer); /* Eat ','. */
- continue;
- }
- else
- break;
- }
- return decls;
-}
-
-/* Parse an Objective-C @property declaration. The syntax is:
-
- objc-property-declaration:
- '@property' objc-property-attributes[opt] struct-declaration ;
-
- objc-property-attributes:
- '(' objc-property-attribute-list ')'
-
- objc-property-attribute-list:
- objc-property-attribute
- objc-property-attribute-list, objc-property-attribute
-
- objc-property-attribute
- 'getter' = identifier
- 'setter' = identifier
- 'readonly'
- 'readwrite'
- 'assign'
- 'retain'
- 'copy'
- 'nonatomic'
-
- For example:
- @property NSString *name;
- @property (readonly) id object;
- @property (retain, nonatomic, getter=getTheName) id name;
- @property int a, b, c;
-
- PS: This function is identical to
- c_parser_objc_at_property_declaration for C. Keep them in sync. */
-static void
-cp_parser_objc_at_property_declaration (cp_parser *parser)
-{
- /* The following variables hold the attributes of the properties as
- parsed. They are 'false' or 'NULL_TREE' if the attribute was not
- seen. When we see an attribute, we set them to 'true' (if they
- are boolean properties) or to the identifier (if they have an
- argument, ie, for getter and setter). Note that here we only
- parse the list of attributes, check the syntax and accumulate the
- attributes that we find. objc_add_property_declaration() will
- then process the information. */
- bool property_assign = false;
- bool property_copy = false;
- tree property_getter_ident = NULL_TREE;
- bool property_nonatomic = false;
- bool property_readonly = false;
- bool property_readwrite = false;
- bool property_retain = false;
- tree property_setter_ident = NULL_TREE;
-
- /* 'properties' is the list of properties that we read. Usually a
- single one, but maybe more (eg, in "@property int a, b, c;" there
- are three). */
- tree properties;
- location_t loc;
-
- loc = cp_lexer_peek_token (parser->lexer)->location;
-
- cp_lexer_consume_token (parser->lexer); /* Eat '@property'. */
-
- /* Parse the optional attribute list... */
- if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
- {
- /* Eat the '('. */
- cp_lexer_consume_token (parser->lexer);
-
- while (true)
- {
- bool syntax_error = false;
- cp_token *token = cp_lexer_peek_token (parser->lexer);
- enum rid keyword;
-
- if (token->type != CPP_NAME)
- {
- cp_parser_error (parser, "expected identifier");
- break;
- }
- keyword = C_RID_CODE (token->u.value);
- cp_lexer_consume_token (parser->lexer);
- switch (keyword)
- {
- case RID_ASSIGN: property_assign = true; break;
- case RID_COPY: property_copy = true; break;
- case RID_NONATOMIC: property_nonatomic = true; break;
- case RID_READONLY: property_readonly = true; break;
- case RID_READWRITE: property_readwrite = true; break;
- case RID_RETAIN: property_retain = true; break;
-
- case RID_GETTER:
- case RID_SETTER:
- if (cp_lexer_next_token_is_not (parser->lexer, CPP_EQ))
- {
- if (keyword == RID_GETTER)
- cp_parser_error (parser,
- "missing %<=%> (after %<getter%> attribute)");
- else
- cp_parser_error (parser,
- "missing %<=%> (after %<setter%> attribute)");
- syntax_error = true;
- break;
- }
- cp_lexer_consume_token (parser->lexer); /* eat the = */
- if (cp_lexer_next_token_is_not (parser->lexer, CPP_NAME))
- {
- cp_parser_error (parser, "expected identifier");
- syntax_error = true;
- break;
- }
- if (keyword == RID_SETTER)
- {
- if (property_setter_ident != NULL_TREE)
- cp_parser_error (parser, "the %<setter%> attribute may only be specified once");
- else
- property_setter_ident = cp_lexer_peek_token (parser->lexer)->u.value;
- cp_lexer_consume_token (parser->lexer);
- if (cp_lexer_next_token_is_not (parser->lexer, CPP_COLON))
- cp_parser_error (parser, "setter name must terminate with %<:%>");
- else
- cp_lexer_consume_token (parser->lexer);
- }
- else
- {
- if (property_getter_ident != NULL_TREE)
- cp_parser_error (parser, "the %<getter%> attribute may only be specified once");
- else
- property_getter_ident = cp_lexer_peek_token (parser->lexer)->u.value;
- cp_lexer_consume_token (parser->lexer);
- }
- break;
- default:
- cp_parser_error (parser, "unknown property attribute");
- syntax_error = true;
- break;
- }
-
- if (syntax_error)
- break;
-
- if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
- cp_lexer_consume_token (parser->lexer);
- else
- break;
- }
-
- /* FIXME: "@property (setter, assign);" will generate a spurious
- "error: expected ‘)’ before ‘,’ token". This is because
- cp_parser_require, unlike the C counterpart, will produce an
- error even if we are in error recovery. */
- if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
- {
- cp_parser_skip_to_closing_parenthesis (parser,
- /*recovering=*/true,
- /*or_comma=*/false,
- /*consume_paren=*/true);
- }
- }
-
- /* ... and the property declaration(s). */
- properties = cp_parser_objc_struct_declaration (parser);
-
- if (properties == error_mark_node)
- {
- cp_parser_skip_to_end_of_statement (parser);
- /* If the next token is now a `;', consume it. */
- if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
- cp_lexer_consume_token (parser->lexer);
- return;
- }
-
- if (properties == NULL_TREE)
- cp_parser_error (parser, "expected identifier");
- else
- {
- /* Comma-separated properties are chained together in
- reverse order; add them one by one. */
- properties = nreverse (properties);
-
- for (; properties; properties = TREE_CHAIN (properties))
- objc_add_property_declaration (loc, copy_node (properties),
- property_readonly, property_readwrite,
- property_assign, property_retain,
- property_copy, property_nonatomic,
- property_getter_ident, property_setter_ident);
- }
-
- cp_parser_consume_semicolon_at_end_of_statement (parser);
-}
-
-/* Parse an Objective-C++ @synthesize declaration. The syntax is:
-
- objc-synthesize-declaration:
- @synthesize objc-synthesize-identifier-list ;
-
- objc-synthesize-identifier-list:
- objc-synthesize-identifier
- objc-synthesize-identifier-list, objc-synthesize-identifier
-
- objc-synthesize-identifier
- identifier
- identifier = identifier
-
- For example:
- @synthesize MyProperty;
- @synthesize OneProperty, AnotherProperty=MyIvar, YetAnotherProperty;
-
- PS: This function is identical to c_parser_objc_at_synthesize_declaration
- for C. Keep them in sync.
-*/
-static void
-cp_parser_objc_at_synthesize_declaration (cp_parser *parser)
-{
- tree list = NULL_TREE;
- location_t loc;
- loc = cp_lexer_peek_token (parser->lexer)->location;
-
- cp_lexer_consume_token (parser->lexer); /* Eat '@synthesize'. */
- while (true)
- {
- tree property, ivar;
- property = cp_parser_identifier (parser);
- if (property == error_mark_node)
- {
- cp_parser_consume_semicolon_at_end_of_statement (parser);
- return;
- }
- if (cp_lexer_next_token_is (parser->lexer, CPP_EQ))
- {
- cp_lexer_consume_token (parser->lexer);
- ivar = cp_parser_identifier (parser);
- if (ivar == error_mark_node)
- {
- cp_parser_consume_semicolon_at_end_of_statement (parser);
- return;
- }
- }
- else
- ivar = NULL_TREE;
- list = chainon (list, build_tree_list (ivar, property));
- if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
- cp_lexer_consume_token (parser->lexer);
- else
- break;
- }
- cp_parser_consume_semicolon_at_end_of_statement (parser);
- objc_add_synthesize_declaration (loc, list);
-}
-
-/* Parse an Objective-C++ @dynamic declaration. The syntax is:
-
- objc-dynamic-declaration:
- @dynamic identifier-list ;
-
- For example:
- @dynamic MyProperty;
- @dynamic MyProperty, AnotherProperty;
-
- PS: This function is identical to c_parser_objc_at_dynamic_declaration
- for C. Keep them in sync.
-*/
-static void
-cp_parser_objc_at_dynamic_declaration (cp_parser *parser)
-{
- tree list = NULL_TREE;
- location_t loc;
- loc = cp_lexer_peek_token (parser->lexer)->location;
-
- cp_lexer_consume_token (parser->lexer); /* Eat '@dynamic'. */
- while (true)
- {
- tree property;
- property = cp_parser_identifier (parser);
- if (property == error_mark_node)
- {
- cp_parser_consume_semicolon_at_end_of_statement (parser);
- return;
- }
- list = chainon (list, build_tree_list (NULL, property));
- if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
- cp_lexer_consume_token (parser->lexer);
- else
- break;
- }
- cp_parser_consume_semicolon_at_end_of_statement (parser);
- objc_add_dynamic_declaration (loc, list);
-}
-
-#endif
+++ /dev/null
-/* Objective-C++ Parser plugin
- Copyright (C) 2000, 2001, 2002, 2003, 2004,
- 2005, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3, or (at your option)
- any later version.
-
- GCC is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
-
-
-/* This isn't defined anywhere, yet, but it could be. This will turn off
- the entire C++ Objective-C++ plugin. */
-#ifndef HIDE_OBJC
-
-#include "c-family/c-objc.h"
-
-
-/* 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 bool cp_parser_objc_selector_p
- (enum cpp_ttype);
-static tree cp_parser_objc_selector
- (cp_parser *);
-static tree cp_parser_objc_protocol_refs_opt
- (cp_parser *);
-static void cp_parser_objc_declaration
- (cp_parser *, tree);
-static tree cp_parser_objc_statement
- (cp_parser *);
-static bool cp_parser_objc_valid_prefix_attributes
- (cp_parser *, tree *);
-static void cp_parser_objc_at_property_declaration
- (cp_parser *) ;
-static void cp_parser_objc_at_synthesize_declaration
- (cp_parser *) ;
-static void cp_parser_objc_at_dynamic_declaration
- (cp_parser *) ;
-static tree cp_parser_objc_struct_declaration
- (cp_parser *) ;
-
-#define PLUGIN_PRIMARY_EXPRESSION_3(parser) @(
- do {
- if (c_dialect_objc ())
- /* We have an Objective-C++ message. */
- return cp_parser_objc_expression (parser);
- } while (0)@)
-
-#define PLUGIN_PRIMARY_EXPRESSION_2(parser, cp_parser_error) @(
- case CPP_OBJC_STRING:
- if (c_dialect_objc ())
- /* We have an Objective-C++ string literal. */
- return cp_parser_objc_expression (parser);
- cp_parser_error (parser, "expected primary-expression");
- return error_mark_node;@)
-
-#define PLUGIN_PRIMARY_EXPRESSION_1(parser) @(
- /* Objective-C++ expressions. */
- case RID_AT_ENCODE:
- case RID_AT_PROTOCOL:
- case RID_AT_SELECTOR:
- return cp_parser_objc_expression (parser);@)
-
-#define PLUGIN_PRIMARY_EXPRESSION(parser, decl, cp_lexer_consume_token, cp_lexer_peek_token) @(
- do {
- /* In Objective-C++, we may have an Objective-C 2.0
- dot-syntax for classes here. */
- if (c_dialect_objc ()
- && cp_lexer_peek_token (parser->lexer)->type == CPP_DOT
- && TREE_CODE (decl) == TYPE_DECL
- && objc_is_class_name (decl))
- {
- tree component;
- cp_lexer_consume_token (parser->lexer);
- component = cp_parser_identifier (parser);
- if (component == error_mark_node)
- return error_mark_node;
-
- return objc_build_class_component_ref (id_expression, component);
- }
-
- /* In Objective-C++, an instance variable (ivar) may be preferred
- to whatever cp_parser_lookup_name() found. */
- decl = objc_lookup_ivar (decl, id_expression);
- } while (0)@)
-
-#define PLUGIN_TOKEN_STARTS_CAST_EXPR @(
- do {
- /* '[' may start a primary-expression in obj-c++. */
- return c_dialect_objc ();
- } while (0)@)
-
-#define PLUGIN_STATEMENT @(
- /* 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;@)
-
-
-#define PLUGIN_DECLARATION(token1, attributes) @(
- /* Objective-C++ declaration/definition. */
- else if (c_dialect_objc () && OBJC_IS_AT_KEYWORD (token1.keyword))
- cp_parser_objc_declaration (parser, NULL_TREE);
- else if (c_dialect_objc ()
- && token1.keyword == RID_ATTRIBUTE
- && cp_parser_objc_valid_prefix_attributes (parser, &attributes))
- cp_parser_objc_declaration (parser, attributes);@)
-
-#define PLUGIN_SIMPLE_TYPE_SPECIFIER(parser, type, decl_specs) @(
- do {
- /* See if TYPE is an Objective-C type, and if so, parse and
- accept any protocol references following it. Do this before
- the cp_parser_check_for_invalid_template_id() call, because
- Objective-C types can be followed by '<...>' which would
- enclose protocol names rather than template arguments, and so
- everything is fine. */
- if (c_dialect_objc () && !parser->scope
- && (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-qualified version. */
- if (decl_specs)
- decl_specs->type = qual_type;
-
- return qual_type;
- }
- } while (0)@)
-
-
-#define PLUGIN_NONCLASS_NAME1(parser, type_decl, identifier) @(
- do {
- 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);
- }
- } while (0)@)
-
-#define PLUGIN_NONCLASS_NAME(parser, type_decl, cp_lexer_peek_token) @(
- /* In Objective-C, we have the complication that class names are
- normally type names and start declarations (eg, the
- "NSObject" in "NSObject *object;"), but can be used in an
- Objective-C 2.0 dot-syntax (as in "NSObject.version") which
- is an expression. So, a classname followed by a dot is not a
- valid type-name. */
- || (objc_is_class_name (TREE_TYPE (type_decl))
- && cp_lexer_peek_token (parser->lexer)->type == CPP_DOT)@)
-
-#define PLUGIN_CLASS_NAME(parser, cp_lexer_peek_token, CPP_DOT) @(
- /* In Objective-C 2.0, a classname followed by '.' starts a
- dot-syntax expression, and it's not a type-name. */
- || (c_dialect_objc ()
- && cp_lexer_peek_token (parser->lexer)->type == CPP_DOT
- && objc_is_class_name (decl))@)
-
-#define PLUGIN_MEMBER_DECLARATION(parser, cp_lexer_next_token_is_keyword, finish_member_declaration) @(
- do {
- /* 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;
- }
- } while (0)@)
-
-#else
-
-#define PLUGIN_PRIMARY_EXPRESSION_3(parser)
-#define PLUGIN_PRIMARY_EXPRESSION_2(parser, cp_parser_error)
-#define PLUGIN_PRIMARY_EXPRESSION_1(parser)
-#define PLUGIN_PRIMARY_EXPRESSION(parser, decl, cp_lexer_consume_token, cp_lexer_peek_token)
-#define PLUGIN_TOKEN_STARTS_CAST_EXPR
-#define PLUGIN_STATEMENT
-#define PLUGIN_DECLARATION(token1, attributes)
-#define PLUGIN_SIMPLE_TYPE_SPECIFIER(parser, type, decl_specs)
-#define PLUGIN_NONCLASS_NAME1(parser, type_decl, identifier)
-#define PLUGIN_NONCLASS_NAME(parser, type_decl, cp_lexer_peek_token)
-#define PLUGIN_CLASS_NAME(parser, cp_lexer_peek_token, CPP_DOT)
-#define PLUGIN_MEMBER_DECLARATION(parser, cp_lexer_next_token_is_keyword, finish_member_declaration)
-
-#endif