configure.ac: Skip C if explicitly selected.
authorSteven Bosscher <steven@gcc.gnu.org>
Fri, 29 Jun 2012 16:12:35 +0000 (16:12 +0000)
committerSteven Bosscher <steven@gcc.gnu.org>
Fri, 29 Jun 2012 16:12:35 +0000 (16:12 +0000)
toplevel/
* configure.ac: Skip C if explicitly selected.
* configure: Regenerate.

gcc/
* configure.ac: Remove special gtfiles case for C.
* configure: Regenerate.
* Makefile.in: Remove C front-end hooks and build hooks that
will be picked up from c/Make-lang.in now.
Add tree-mudflap to C_COMMON_OBJS.
* gengtype.c (files_rules): Adjust gt-files for c/c-decl.c.
* config/vms/vms.c: Look for c-tree.h in c/.
* doc/gty.texi: Remove reference to c-config-lang.in.
* doc/sourcebuild.texi: Document the c/ subdirectory.

c/
* Make-lang.in: New file, rules migrated from gcc/Makefile.in
and add language Makefile hooks.
* config-lang.in: New file.
* c-config-lang.in: Moved from gcc/config-lang.in to here, and
add the required "normal" config-lang.in rules.
* c-lang.h: Moved from gcc/ to here.
* c-tree.h: Likewise.
* c-objc-common.c: Likewise.
* c-objc-common.h: Likewise.
* c-typeck.c: Likewise.
* c-convert.c: Likewise.
* c-lang.c: Likewise.
* c-aux-info.c: Likewise.
* c-errors.c: Likewise.
* gccspec.c: Likewise.
* c-decl.c: Likewise.  Include gt-c-c-decl.h, not gt-c-decl.h.
* c-parser.c: Likewise.  Include gt-c-c-parser.h, not gt-c-parser.h.

c-family/
* cppspec.c: Moved from gcc/ to here.

objc/
* Make-ang.in: Adjust for move of C front-end files.
* config-lang.in: Likewise.
* objc-encoding.c: Look for cp-tree.h in cp/, and for c-tree.h
and c-lang.h in c/.
* objc-runtime-shared-support.c: Likewise.
* objc-next-runtime-abi-01.c: Likewise.
* objc-next-runtime-abi-02.c: Likewise.
* objc-gnu-runtime-abi-01.c: Likewise.
* objc-act.c: Likewise.
* objc-lang.c: Likewise.

cp/
* Make-lang.in: Remove tree-mudflap.o from CXX_AND_OBJCXX_OBJS.

From-SVN: r189080

54 files changed:
ChangeLog
configure
configure.ac
gcc/ChangeLog
gcc/Makefile.in
gcc/c-aux-info.c [deleted file]
gcc/c-config-lang.in [deleted file]
gcc/c-convert.c [deleted file]
gcc/c-decl.c [deleted file]
gcc/c-errors.c [deleted file]
gcc/c-family/ChangeLog
gcc/c-family/cppspec.c [new file with mode: 0644]
gcc/c-lang.c [deleted file]
gcc/c-lang.h [deleted file]
gcc/c-objc-common.c [deleted file]
gcc/c-objc-common.h [deleted file]
gcc/c-parser.c [deleted file]
gcc/c-tree.h [deleted file]
gcc/c-typeck.c [deleted file]
gcc/c/ChangeLog [new file with mode: 0644]
gcc/c/Make-lang.in [new file with mode: 0644]
gcc/c/c-aux-info.c [new file with mode: 0644]
gcc/c/c-convert.c [new file with mode: 0644]
gcc/c/c-decl.c [new file with mode: 0644]
gcc/c/c-errors.c [new file with mode: 0644]
gcc/c/c-lang.c [new file with mode: 0644]
gcc/c/c-lang.h [new file with mode: 0644]
gcc/c/c-objc-common.c [new file with mode: 0644]
gcc/c/c-objc-common.h [new file with mode: 0644]
gcc/c/c-parser.c [new file with mode: 0644]
gcc/c/c-tree.h [new file with mode: 0644]
gcc/c/c-typeck.c [new file with mode: 0644]
gcc/c/config-lang.in [new file with mode: 0644]
gcc/c/gccspec.c [new file with mode: 0644]
gcc/config/vms/vms-c.c
gcc/configure
gcc/configure.ac
gcc/cp/ChangeLog
gcc/cp/Make-lang.in
gcc/cppspec.c [deleted file]
gcc/doc/gty.texi
gcc/doc/sourcebuild.texi
gcc/gccspec.c [deleted file]
gcc/gengtype.c
gcc/objc/ChangeLog
gcc/objc/Make-lang.in
gcc/objc/config-lang.in
gcc/objc/objc-act.c
gcc/objc/objc-encoding.c
gcc/objc/objc-gnu-runtime-abi-01.c
gcc/objc/objc-lang.c
gcc/objc/objc-next-runtime-abi-01.c
gcc/objc/objc-next-runtime-abi-02.c
gcc/objc/objc-runtime-shared-support.c

index ecdf0f7aefc9f60bd9dbd6206e4ec0d422a53aec..493ef682577ef17b6d10470ed28418f6c932f773 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2012-06-29  Steven Bosscher  <steven@gcc.gnu.org>
+
+       * configure.ac: Skip C if explicitly selected.
+       * configure: Regenerate.
+
 2012-06-28  Christophe Lyon <christophe.lyon@st.com>
 
        * configure.ac (CFLAGS_FOR_TARGET, CXXFLAGS_FOR_TARGET): Make sure
index 1ab12dba8a4c3421b35f45b5f89fc8ee23fca73b..5eba95c0739397b781d6d458f44dc73b7c68bbad 100755 (executable)
--- a/configure
+++ b/configure
@@ -6310,8 +6310,11 @@ if test -d ${srcdir}/gcc; then
 
         case ,${enable_languages}, in
           *,${language},*)
-            # Language was explicitly selected; include it.
-            add_this_lang=yes
+            # Language was explicitly selected; include it
+           # unless it is C, which is enabled by default.
+           if test "$language" != "c"; then
+             add_this_lang=yes
+           fi
             ;;
           *,all,*)
             # 'all' was selected, select it if it is a default language
index 82dbe4ce50c7ab971e244863544c1234560aee99..2ddd040d0e9c3c0ffc7eca773cea817b86092b38 100644 (file)
@@ -1816,8 +1816,11 @@ if test -d ${srcdir}/gcc; then
 
         case ,${enable_languages}, in
           *,${language},*)
-            # Language was explicitly selected; include it.
-            add_this_lang=yes
+            # Language was explicitly selected; include it
+           # unless it is C, which is enabled by default.
+           if test "$language" != "c"; then
+             add_this_lang=yes
+           fi
             ;;
           *,all,*)
             # 'all' was selected, select it if it is a default language
index b45840fda7ed2aa5b729dd985c059b791f9ff1b1..7a1c4cc9b84835681d0e84b322965003d954ea75 100644 (file)
@@ -1,3 +1,15 @@
+2012-06-29  Steven Bosscher  <steven@gcc.gnu.org>
+
+       * configure.ac: Remove special gtfiles case for C.
+       * configure: Regenerate.
+       * Makefile.in: Remove C front-end hooks and build hooks that
+       will be picked up from c/Make-lang.in now.
+       Add tree-mudflap to C_COMMON_OBJS.
+       * gengtype.c (files_rules): Adjust gt-files for c/c-decl.c.
+       * config/vms/vms.c: Look for c-tree.h in c/.
+       * doc/gty.texi: Remove reference to c-config-lang.in.
+       * doc/sourcebuild.texi: Document the c/ subdirectory.
+
 2012-06-29  Steven Bosscher  <steven@gcc.gnu.org>
 
        * system.h (CASE_USE_BIT_TESTS): Poison.
index c400e02b1c92ee77d39c97481d01afa7d43b8805..afea4f386221175777ec2bfad331e9568f7f91de 100644 (file)
@@ -502,8 +502,8 @@ host_xm_defines=@host_xm_defines@
 xm_file_list=@xm_file_list@
 xm_include_list=@xm_include_list@
 xm_defines=@xm_defines@
-lang_checks=check-gcc
-lang_checks_parallelized=check-gcc
+lang_checks=
+lang_checks_parallelized=
 dg_target_exps:=alpha.exp,arm.exp,avr.exp,bfin.exp,cris.exp,frv.exp
 dg_target_exps:=$(dg_target_exps),i386.exp,ia64.exp,m68k.exp,microblaze.exp
 dg_target_exps:=$(dg_target_exps),mips.exp,powerpc.exp,rx.exp,s390.exp,sh.exp
@@ -717,11 +717,11 @@ GENERATED_MANPAGES = @GENERATED_MANPAGES@
 OTHER_FIXINCLUDES_DIRS=
 
 # A list of all the language-specific executables.
-COMPILERS = cc1$(exeext) @all_compilers@
+COMPILERS = @all_compilers@
 
 # List of things which should already be built whenever we try to use xgcc
 # to compile anything (without linking).
-GCC_PASSES=xgcc$(exeext) cc1$(exeext) specs
+GCC_PASSES=xgcc$(exeext) specs
 
 # Directory to link to, when using the target `maketest'.
 DIR = ../gcc
@@ -1133,23 +1133,18 @@ CXX_TARGET_OBJS=@cxx_target_objs@
 # Target specific, Fortran specific object file
 FORTRAN_TARGET_OBJS=@fortran_target_objs@
 
-# Object files for gcc driver.
+# Object files for gcc many-languages driver.
 GCC_OBJS = gcc.o ggc-none.o
 
 # Language-specific object files shared by all C-family front ends.
+# FIXME: tree-mudflap is C-family only, but it is also part of the middle-end.
+# The mudflap machinery should be properly separated from the front ends, and
+# perhaps turned into a plugin.
 C_COMMON_OBJS = c-family/c-common.o c-family/c-cppbuiltin.o c-family/c-dump.o \
   c-family/c-format.o c-family/c-gimplify.o c-family/c-lex.o \
   c-family/c-omp.o c-family/c-opts.o c-family/c-pch.o \
   c-family/c-ppoutput.o c-family/c-pragma.o c-family/c-pretty-print.o \
-  c-family/c-semantics.o c-family/c-ada-spec.o
-
-# Language-specific object files for C and Objective C.
-C_AND_OBJC_OBJS = attribs.o c-errors.o c-decl.o c-typeck.o \
-  c-convert.o c-aux-info.o c-objc-common.o c-parser.o tree-mudflap.o \
-  $(C_COMMON_OBJS) $(C_TARGET_OBJS)
-
-# Language-specific object files for C.
-C_OBJS = c-lang.o c-family/stub-objc.o $(C_AND_OBJC_OBJS)
+  c-family/c-semantics.o c-family/c-ada-spec.o tree-mudflap.o
 
 # Language-independent object files.
 # We put the insn-*.o files first so that a parallel make will build
@@ -1475,11 +1470,10 @@ OBJS-libcommon-target = $(common_out_object_file) prefix.o params.o \
        opts.o opts-common.o options.o vec.o hooks.o common/common-targhooks.o
 
 # This lists all host objects for the front ends.
-ALL_HOST_FRONTEND_OBJS = $(C_OBJS) \
-  $(foreach v,$(CONFIG_LANGUAGES),$($(v)_OBJS))
+ALL_HOST_FRONTEND_OBJS = $(foreach v,$(CONFIG_LANGUAGES),$($(v)_OBJS))
 
 ALL_HOST_BACKEND_OBJS = $(GCC_OBJS) $(OBJS) $(OBJS-libcommon) \
-  $(OBJS-libcommon-target) @TREEBROWSER@ main.o gccspec.o cppspec.o \
+  $(OBJS-libcommon-target) @TREEBROWSER@ main.o c-family/cppspec.o \
   $(COLLECT2_OBJS) $(EXTRA_GCC_OBJS) $(GCOV_OBJS) $(GCOV_DUMP_OBJS)
 
 # This lists all host object files, whether they are included in this
@@ -1496,7 +1490,7 @@ MOSTLYCLEANFILES = insn-flags.h insn-config.h insn-codes.h \
  tm-preds.h tm-constrs.h checksum-options \
  tree-check.h min-insn-modes.c insn-modes.c insn-modes.h \
  genrtl.h gt-*.h gtype-*.h gtype-desc.c gtyp-input.list \
- xgcc$(exeext) cpp$(exeext) cc1$(exeext) \
+ xgcc$(exeext) cpp$(exeext) \
  $(EXTRA_PROGRAMS) gcc-cross$(exeext) \
  $(SPECS) collect2$(exeext) gcc-ar$(exeext) gcc-nm$(exeext) \
  gcc-ranlib$(exeext) \
@@ -1740,12 +1734,6 @@ ifeq ($(enable_plugin),yes)
 native: gengtype$(exeext)
 endif
 
-# Define the names for selecting languages in LANGUAGES.
-c: cc1$(exeext)
-
-# Tell GNU make these are phony targets.
-.PHONY: c
-
 # On the target machine, finish building a cross compiler.
 # This does the things that can't be done on the host machine.
 rest.cross: specs
@@ -1773,19 +1761,19 @@ libcommon.a: $(OBJS-libcommon)
 # We call this executable `xgcc' rather than `gcc'
 # to avoid confusion if the current directory is in the path
 # and CC is `gcc'.  It is renamed to `gcc' when it is installed.
-xgcc$(exeext): $(GCC_OBJS) gccspec.o libcommon-target.a $(LIBDEPS) \
+xgcc$(exeext): $(GCC_OBJS) c/gccspec.o libcommon-target.a $(LIBDEPS) \
        $(EXTRA_GCC_OBJS)
        +$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ $(GCC_OBJS) \
-         gccspec.o $(EXTRA_GCC_OBJS) libcommon-target.a \
+         c/gccspec.o $(EXTRA_GCC_OBJS) libcommon-target.a \
          $(EXTRA_GCC_LIBS) $(LIBS)
 
-# cpp is to cpp0 as gcc is to cc1.
-# The only difference from xgcc is that it's linked with cppspec.o
-# instead of gccspec.o.
-cpp$(exeext): $(GCC_OBJS) cppspec.o libcommon-target.a $(LIBDEPS) \
+# cpp is to cpp0 as e.g. g++ is to cc1plus: Just another driver.
+# It is part of c-family because the handled extensions are hard-coded
+# and only contain c-family extensions (see known_suffixes).
+cpp$(exeext): $(GCC_OBJS) c-family/cppspec.o libcommon-target.a $(LIBDEPS) \
        $(EXTRA_GCC_OBJS)
        +$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ $(GCC_OBJS) \
-         cppspec.o $(EXTRA_GCC_OBJS) libcommon-target.a \
+         c-family/cppspec.o $(EXTRA_GCC_OBJS) libcommon-target.a \
          $(EXTRA_GCC_LIBS) $(LIBS)
 
 # Dump a specs file to make -B./ read these specs over installed ones.
@@ -1803,19 +1791,6 @@ checksum-options:
        echo "$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS)" > checksum-options.tmp \
        && $(srcdir)/../move-if-change checksum-options.tmp checksum-options
 
-# compute checksum over all object files and the options
-cc1-checksum.c : build/genchecksum$(build_exeext) checksum-options \
-       $(C_OBJS) $(BACKEND) $(LIBDEPS) 
-       build/genchecksum$(build_exeext) $(C_OBJS) $(BACKEND) $(LIBDEPS) \
-                     checksum-options > cc1-checksum.c.tmp &&           \
-       $(srcdir)/../move-if-change cc1-checksum.c.tmp cc1-checksum.c
-
-cc1-checksum.o : cc1-checksum.c $(CONFIG_H) $(SYSTEM_H)
-
-cc1$(exeext): $(C_OBJS) cc1-checksum.o $(BACKEND) $(LIBDEPS)
-       +$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ $(C_OBJS) \
-         cc1-checksum.o $(BACKEND) $(LIBS) $(BACKENDLIBS)
-
 #\f
 # Build libgcc.a.
 
@@ -1865,52 +1840,6 @@ srcextra: gcc.srcextra lang.srcextra
 gcc.srcextra: gengtype-lex.c
        -cp -p $^ $(srcdir)
 
-# C language specific files.
-c-aux-info.o : c-aux-info.c  $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
-       $(C_TREE_H) $(TREE_H) $(FLAGS_H)
-
-c-convert.o : c-convert.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
-       $(TREE_H) $(C_TREE_H) $(FLAGS_H) $(C_COMMON_H) convert.h \
-       langhooks.h $(TARGET_H)
-
-c-decl.o : c-decl.c c-lang.h $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
-       $(TREE_H) $(C_TREE_H) $(GGC_H) $(TARGET_H) $(FLAGS_H) $(FUNCTION_H) \
-       output.h debug.h toplev.h intl.h $(TM_P_H) $(TREE_INLINE_H) \
-       $(TIMEVAR_H) $(OPTS_H) $(C_PRAGMA_H) gt-c-decl.h $(CGRAPH_H) \
-       $(HASHTAB_H) $(LANGHOOKS_DEF_H) \
-       $(TREE_DUMP_H) $(C_COMMON_H) $(CPPLIB_H) $(DIAGNOSTIC_CORE_H) \
-       $(INPUT_H) langhooks.h pointer-set.h tree-iterator.h \
-       $(PLUGIN_H) c-family/c-ada-spec.h c-family/c-objc.h
-
-c-errors.o: c-errors.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
-       $(C_TREE_H) $(FLAGS_H) $(DIAGNOSTIC_H) $(TM_P_H)
-
-c-lang.o : c-lang.c c-objc-common.h \
-       $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
-       $(C_TREE_H) $(DIAGNOSTIC_CORE_H) \
-       langhooks.h $(LANGHOOKS_DEF_H) $(C_COMMON_H) gtype-c.h \
-       $(C_PRAGMA_H) $(TREE_INLINE_H)
-
-c-objc-common.o : c-objc-common.c c-objc-common.h \
-       $(CONFIG_H) $(SYSTEM_H) coretypes.h \
-       $(TREE_H) $(C_TREE_H) $(FLAGS_H) $(DIAGNOSTIC_H) \
-       langhooks.h $(GGC_H) $(C_PRETTY_PRINT_H) intl.h \
-       $(TREE_PRETTY_PRINT_H)
-
-c-parser.o : c-parser.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
-       $(TM_H) $(TREE_H) $(C_TREE_H) $(C_COMMON_H) $(C_PRAGMA_H) $(CPPLIB_H) \
-       $(GGC_H) $(TIMEVAR_H) $(INPUT_H) $(FLAGS_H) \
-       gt-c-parser.h langhooks.h \
-       $(VEC_H) $(TARGET_H) $(CGRAPH_H) $(PLUGIN_H) \
-        c-family/c-objc.h
-
-c-typeck.o : c-typeck.c c-lang.h $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
-       $(TREE_H) $(C_TREE_H) $(TARGET_H) $(FLAGS_H) intl.h \
-       langhooks.h tree-iterator.h $(BITMAP_H) $(GIMPLE_H) \
-       c-family/c-objc.h
-
-
-
 graph.o: graph.c $(SYSTEM_H) coretypes.h $(TM_H) toplev.h $(DIAGNOSTIC_CORE_H) $(FLAGS_H) \
     $(RTL_H) $(FUNCTION_H) hard-reg-set.h $(BASIC_BLOCK_H) graph.h $(OBSTACK_H) \
     $(CONFIG_H) $(EMIT_RTL_H)
@@ -1987,7 +1916,10 @@ lto-wrapper$(exeext): lto-wrapper.o ggc-none.o libcommon-target.a $(LIBDEPS)
 lto-wrapper.o: lto-wrapper.c $(CONFIG_H) $(SYSTEM_H) coretypes.h intl.h \
        $(OBSTACK_H) $(DIAGNOSTIC_H) $(OPTS_H) $(OPTIONS_H)
 
-# Files used by all variants of C.
+# Files used by all variants of C or by the stand-alone pre-processor.
+c-family/cppspec.o: c-family/cppspec.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
+    $(TM_H) $(GCC_H) $(OPTS_H)
+
 c-family/c-common.o : c-family/c-common.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
        $(TM_H) $(TREE_H) \
        $(OBSTACK_H) $(C_COMMON_H) $(FLAGS_H) toplev.h output.h $(C_PRAGMA_H) \
@@ -2107,16 +2039,6 @@ gcc.o: gcc.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) intl.h multilib.h \
   $(DRIVER_DEFINES) \
   -c $(srcdir)/gcc.c $(OUTPUT_OPTION))
 
-gccspec.o: gccspec.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(GCC_H) \
-    $(OPTS_H)
-       (SHLIB='$(SHLIB)'; \
-       $(COMPILER) $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) \
-  $(DRIVER_DEFINES) \
-  -c $(srcdir)/gccspec.c $(OUTPUT_OPTION))
-
-cppspec.o: cppspec.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(GCC_H) \
-    $(OPTS_H)
-
 specs.h : s-specs ; @true
 s-specs : Makefile
        lsf="$(lang_specs_files)"; for f in $$lsf; do \
@@ -4999,7 +4921,7 @@ site.exp: ./config.status Makefile
                -e '1,/^## All variables above are.*##/ d' >> site.exp
        -@rm -f ./site.tmp
 
-CHECK_TARGETS = check-gcc @check_languages@
+CHECK_TARGETS = @check_languages@
 
 check: $(CHECK_TARGETS)
 
diff --git a/gcc/c-aux-info.c b/gcc/c-aux-info.c
deleted file mode 100644 (file)
index 694f9c1..0000000
+++ /dev/null
@@ -1,567 +0,0 @@
-/* Generate information regarding function declarations and definitions based
-   on information stored in GCC's tree structure.  This code implements the
-   -aux-info option.
-   Copyright (C) 1989, 1991, 1994, 1995, 1997, 1998,
-   1999, 2000, 2003, 2004, 2007, 2010 Free Software Foundation, Inc.
-   Contributed by Ron Guilmette (rfg@segfault.us.com).
-
-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/>.  */
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "tm.h"
-#include "flags.h"
-#include "tree.h"
-#include "c-tree.h"
-
-enum formals_style_enum {
-  ansi,
-  k_and_r_names,
-  k_and_r_decls
-};
-typedef enum formals_style_enum formals_style;
-
-
-static const char *data_type;
-
-static char *affix_data_type (const char *) ATTRIBUTE_MALLOC;
-static const char *gen_formal_list_for_type (tree, formals_style);
-static const char *gen_formal_list_for_func_def (tree, formals_style);
-static const char *gen_type (const char *, tree, formals_style);
-static const char *gen_decl (tree, int, formals_style);
-\f
-/* Given a string representing an entire type or an entire declaration
-   which only lacks the actual "data-type" specifier (at its left end),
-   affix the data-type specifier to the left end of the given type
-   specification or object declaration.
-
-   Because of C language weirdness, the data-type specifier (which normally
-   goes in at the very left end) may have to be slipped in just to the
-   right of any leading "const" or "volatile" qualifiers (there may be more
-   than one).  Actually this may not be strictly necessary because it seems
-   that GCC (at least) accepts `<data-type> const foo;' and treats it the
-   same as `const <data-type> foo;' but people are accustomed to seeing
-   `const char *foo;' and *not* `char const *foo;' so we try to create types
-   that look as expected.  */
-
-static char *
-affix_data_type (const char *param)
-{
-  char *const type_or_decl = ASTRDUP (param);
-  char *p = type_or_decl;
-  char *qualifiers_then_data_type;
-  char saved;
-
-  /* Skip as many leading const's or volatile's as there are.  */
-
-  for (;;)
-    {
-      if (!strncmp (p, "volatile ", 9))
-       {
-         p += 9;
-         continue;
-       }
-      if (!strncmp (p, "const ", 6))
-       {
-         p += 6;
-         continue;
-       }
-      break;
-    }
-
-  /* p now points to the place where we can insert the data type.  We have to
-     add a blank after the data-type of course.  */
-
-  if (p == type_or_decl)
-    return concat (data_type, " ", type_or_decl, NULL);
-
-  saved = *p;
-  *p = '\0';
-  qualifiers_then_data_type = concat (type_or_decl, data_type, NULL);
-  *p = saved;
-  return reconcat (qualifiers_then_data_type,
-                  qualifiers_then_data_type, " ", p, NULL);
-}
-
-/* Given a tree node which represents some "function type", generate the
-   source code version of a formal parameter list (of some given style) for
-   this function type.  Return the whole formal parameter list (including
-   a pair of surrounding parens) as a string.   Note that if the style
-   we are currently aiming for is non-ansi, then we just return a pair
-   of empty parens here.  */
-
-static const char *
-gen_formal_list_for_type (tree fntype, formals_style style)
-{
-  const char *formal_list = "";
-  tree formal_type;
-
-  if (style != ansi)
-    return "()";
-
-  formal_type = TYPE_ARG_TYPES (fntype);
-  while (formal_type && TREE_VALUE (formal_type) != void_type_node)
-    {
-      const char *this_type;
-
-      if (*formal_list)
-       formal_list = concat (formal_list, ", ", NULL);
-
-      this_type = gen_type ("", TREE_VALUE (formal_type), ansi);
-      formal_list
-       = ((strlen (this_type))
-          ? concat (formal_list, affix_data_type (this_type), NULL)
-          : concat (formal_list, data_type, NULL));
-
-      formal_type = TREE_CHAIN (formal_type);
-    }
-
-  /* If we got to here, then we are trying to generate an ANSI style formal
-     parameters list.
-
-     New style prototyped ANSI formal parameter lists should in theory always
-     contain some stuff between the opening and closing parens, even if it is
-     only "void".
-
-     The brutal truth though is that there is lots of old K&R code out there
-     which contains declarations of "pointer-to-function" parameters and
-     these almost never have fully specified formal parameter lists associated
-     with them.  That is, the pointer-to-function parameters are declared
-     with just empty parameter lists.
-
-     In cases such as these, protoize should really insert *something* into
-     the vacant parameter lists, but what?  It has no basis on which to insert
-     anything in particular.
-
-     Here, we make life easy for protoize by trying to distinguish between
-     K&R empty parameter lists and new-style prototyped parameter lists
-     that actually contain "void".  In the latter case we (obviously) want
-     to output the "void" verbatim, and that what we do.  In the former case,
-     we do our best to give protoize something nice to insert.
-
-     This "something nice" should be something that is still valid (when
-     re-compiled) but something that can clearly indicate to the user that
-     more typing information (for the parameter list) should be added (by
-     hand) at some convenient moment.
-
-     The string chosen here is a comment with question marks in it.  */
-
-  if (!*formal_list)
-    {
-      if (prototype_p (fntype))
-       /* assert (TREE_VALUE (TYPE_ARG_TYPES (fntype)) == void_type_node);  */
-       formal_list = "void";
-      else
-       formal_list = "/* ??? */";
-    }
-  else
-    {
-      /* If there were at least some parameters, and if the formals-types-list
-        petered out to a NULL (i.e. without being terminated by a
-        void_type_node) then we need to tack on an ellipsis.  */
-      if (!formal_type)
-       formal_list = concat (formal_list, ", ...", NULL);
-    }
-
-  return concat (" (", formal_list, ")", NULL);
-}
-
-/* Generate a parameter list for a function definition (in some given style).
-
-   Note that this routine has to be separate (and different) from the code that
-   generates the prototype parameter lists for function declarations, because
-   in the case of a function declaration, all we have to go on is a tree node
-   representing the function's own "function type".  This can tell us the types
-   of all of the formal parameters for the function, but it cannot tell us the
-   actual *names* of each of the formal parameters.  We need to output those
-   parameter names for each function definition.
-
-   This routine gets a pointer to a tree node which represents the actual
-   declaration of the given function, and this DECL node has a list of formal
-   parameter (variable) declarations attached to it.  These formal parameter
-   (variable) declaration nodes give us the actual names of the formal
-   parameters for the given function definition.
-
-   This routine returns a string which is the source form for the entire
-   function formal parameter list.  */
-
-static const char *
-gen_formal_list_for_func_def (tree fndecl, formals_style style)
-{
-  const char *formal_list = "";
-  tree formal_decl;
-
-  formal_decl = DECL_ARGUMENTS (fndecl);
-  while (formal_decl)
-    {
-      const char *this_formal;
-
-      if (*formal_list && ((style == ansi) || (style == k_and_r_names)))
-       formal_list = concat (formal_list, ", ", NULL);
-      this_formal = gen_decl (formal_decl, 0, style);
-      if (style == k_and_r_decls)
-       formal_list = concat (formal_list, this_formal, "; ", NULL);
-      else
-       formal_list = concat (formal_list, this_formal, NULL);
-      formal_decl = TREE_CHAIN (formal_decl);
-    }
-  if (style == ansi)
-    {
-      if (!DECL_ARGUMENTS (fndecl))
-       formal_list = concat (formal_list, "void", NULL);
-      if (stdarg_p (TREE_TYPE (fndecl)))
-       formal_list = concat (formal_list, ", ...", NULL);
-    }
-  if ((style == ansi) || (style == k_and_r_names))
-    formal_list = concat (" (", formal_list, ")", NULL);
-  return formal_list;
-}
-
-/* Generate a string which is the source code form for a given type (t).  This
-   routine is ugly and complex because the C syntax for declarations is ugly
-   and complex.  This routine is straightforward so long as *no* pointer types,
-   array types, or function types are involved.
-
-   In the simple cases, this routine will return the (string) value which was
-   passed in as the "ret_val" argument.  Usually, this starts out either as an
-   empty string, or as the name of the declared item (i.e. the formal function
-   parameter variable).
-
-   This routine will also return with the global variable "data_type" set to
-   some string value which is the "basic" data-type of the given complete type.
-   This "data_type" string can be concatenated onto the front of the returned
-   string after this routine returns to its caller.
-
-   In complicated cases involving pointer types, array types, or function
-   types, the C declaration syntax requires an "inside out" approach, i.e. if
-   you have a type which is a "pointer-to-function" type, you need to handle
-   the "pointer" part first, but it also has to be "innermost" (relative to
-   the declaration stuff for the "function" type).  Thus, is this case, you
-   must prepend a "(*" and append a ")" to the name of the item (i.e. formal
-   variable).  Then you must append and prepend the other info for the
-   "function type" part of the overall type.
-
-   To handle the "innermost precedence" rules of complicated C declarators, we
-   do the following (in this routine).  The input parameter called "ret_val"
-   is treated as a "seed".  Each time gen_type is called (perhaps recursively)
-   some additional strings may be appended or prepended (or both) to the "seed"
-   string.  If yet another (lower) level of the GCC tree exists for the given
-   type (as in the case of a pointer type, an array type, or a function type)
-   then the (wrapped) seed is passed to a (recursive) invocation of gen_type()
-   this recursive invocation may again "wrap" the (new) seed with yet more
-   declarator stuff, by appending, prepending (or both).  By the time the
-   recursion bottoms out, the "seed value" at that point will have a value
-   which is (almost) the complete source version of the declarator (except
-   for the data_type info).  Thus, this deepest "seed" value is simply passed
-   back up through all of the recursive calls until it is given (as the return
-   value) to the initial caller of the gen_type() routine.  All that remains
-   to do at this point is for the initial caller to prepend the "data_type"
-   string onto the returned "seed".  */
-
-static const char *
-gen_type (const char *ret_val, tree t, formals_style style)
-{
-  tree chain_p;
-
-  /* If there is a typedef name for this type, use it.  */
-  if (TYPE_NAME (t) && TREE_CODE (TYPE_NAME (t)) == TYPE_DECL)
-    data_type = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (t)));
-  else
-    {
-      switch (TREE_CODE (t))
-       {
-       case POINTER_TYPE:
-         if (TYPE_READONLY (t))
-           ret_val = concat ("const ", ret_val, NULL);
-         if (TYPE_VOLATILE (t))
-           ret_val = concat ("volatile ", ret_val, NULL);
-
-         ret_val = concat ("*", ret_val, NULL);
-
-         if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE || TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE)
-           ret_val = concat ("(", ret_val, ")", NULL);
-
-         ret_val = gen_type (ret_val, TREE_TYPE (t), style);
-
-         return ret_val;
-
-       case ARRAY_TYPE:
-         if (!COMPLETE_TYPE_P (t) || TREE_CODE (TYPE_SIZE (t)) != INTEGER_CST)
-           ret_val = gen_type (concat (ret_val, "[]", NULL),
-                               TREE_TYPE (t), style);
-         else if (int_size_in_bytes (t) == 0)
-           ret_val = gen_type (concat (ret_val, "[0]", NULL),
-                               TREE_TYPE (t), style);
-         else
-           {
-             int size = (int_size_in_bytes (t) / int_size_in_bytes (TREE_TYPE (t)));
-             char buff[10];
-             sprintf (buff, "[%d]", size);
-             ret_val = gen_type (concat (ret_val, buff, NULL),
-                                 TREE_TYPE (t), style);
-           }
-         break;
-
-       case FUNCTION_TYPE:
-         ret_val = gen_type (concat (ret_val,
-                                     gen_formal_list_for_type (t, style),
-                                     NULL),
-                             TREE_TYPE (t), style);
-         break;
-
-       case IDENTIFIER_NODE:
-         data_type = IDENTIFIER_POINTER (t);
-         break;
-
-       /* The following three cases are complicated by the fact that a
-          user may do something really stupid, like creating a brand new
-          "anonymous" type specification in a formal argument list (or as
-          part of a function return type specification).  For example:
-
-               int f (enum { red, green, blue } color);
-
-          In such cases, we have no name that we can put into the prototype
-          to represent the (anonymous) type.  Thus, we have to generate the
-          whole darn type specification.  Yuck!  */
-
-       case RECORD_TYPE:
-         if (TYPE_NAME (t))
-           data_type = IDENTIFIER_POINTER (TYPE_NAME (t));
-         else
-           {
-             data_type = "";
-             chain_p = TYPE_FIELDS (t);
-             while (chain_p)
-               {
-                 data_type = concat (data_type, gen_decl (chain_p, 0, ansi),
-                                     NULL);
-                 chain_p = TREE_CHAIN (chain_p);
-                 data_type = concat (data_type, "; ", NULL);
-               }
-             data_type = concat ("{ ", data_type, "}", NULL);
-           }
-         data_type = concat ("struct ", data_type, NULL);
-         break;
-
-       case UNION_TYPE:
-         if (TYPE_NAME (t))
-           data_type = IDENTIFIER_POINTER (TYPE_NAME (t));
-         else
-           {
-             data_type = "";
-             chain_p = TYPE_FIELDS (t);
-             while (chain_p)
-               {
-                 data_type = concat (data_type, gen_decl (chain_p, 0, ansi),
-                                     NULL);
-                 chain_p = TREE_CHAIN (chain_p);
-                 data_type = concat (data_type, "; ", NULL);
-               }
-             data_type = concat ("{ ", data_type, "}", NULL);
-           }
-         data_type = concat ("union ", data_type, NULL);
-         break;
-
-       case ENUMERAL_TYPE:
-         if (TYPE_NAME (t))
-           data_type = IDENTIFIER_POINTER (TYPE_NAME (t));
-         else
-           {
-             data_type = "";
-             chain_p = TYPE_VALUES (t);
-             while (chain_p)
-               {
-                 data_type = concat (data_type,
-                       IDENTIFIER_POINTER (TREE_PURPOSE (chain_p)), NULL);
-                 chain_p = TREE_CHAIN (chain_p);
-                 if (chain_p)
-                   data_type = concat (data_type, ", ", NULL);
-               }
-             data_type = concat ("{ ", data_type, " }", NULL);
-           }
-         data_type = concat ("enum ", data_type, NULL);
-         break;
-
-       case TYPE_DECL:
-         data_type = IDENTIFIER_POINTER (DECL_NAME (t));
-         break;
-
-       case INTEGER_TYPE:
-       case FIXED_POINT_TYPE:
-         data_type = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (t)));
-         /* Normally, `unsigned' is part of the deal.  Not so if it comes
-            with a type qualifier.  */
-         if (TYPE_UNSIGNED (t) && TYPE_QUALS (t))
-           data_type = concat ("unsigned ", data_type, NULL);
-         break;
-
-       case REAL_TYPE:
-         data_type = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (t)));
-         break;
-
-       case VOID_TYPE:
-         data_type = "void";
-         break;
-
-       case ERROR_MARK:
-         data_type = "[ERROR]";
-         break;
-
-       default:
-         gcc_unreachable ();
-       }
-    }
-  if (TYPE_READONLY (t))
-    ret_val = concat ("const ", ret_val, NULL);
-  if (TYPE_VOLATILE (t))
-    ret_val = concat ("volatile ", ret_val, NULL);
-  if (TYPE_RESTRICT (t))
-    ret_val = concat ("restrict ", ret_val, NULL);
-  return ret_val;
-}
-
-/* Generate a string (source) representation of an entire entity declaration
-   (using some particular style for function types).
-
-   The given entity may be either a variable or a function.
-
-   If the "is_func_definition" parameter is nonzero, assume that the thing
-   we are generating a declaration for is a FUNCTION_DECL node which is
-   associated with a function definition.  In this case, we can assume that
-   an attached list of DECL nodes for function formal arguments is present.  */
-
-static const char *
-gen_decl (tree decl, int is_func_definition, formals_style style)
-{
-  const char *ret_val;
-
-  if (DECL_NAME (decl))
-    ret_val = IDENTIFIER_POINTER (DECL_NAME (decl));
-  else
-    ret_val = "";
-
-  /* If we are just generating a list of names of formal parameters, we can
-     simply return the formal parameter name (with no typing information
-     attached to it) now.  */
-
-  if (style == k_and_r_names)
-    return ret_val;
-
-  /* Note that for the declaration of some entity (either a function or a
-     data object, like for instance a parameter) if the entity itself was
-     declared as either const or volatile, then const and volatile properties
-     are associated with just the declaration of the entity, and *not* with
-     the `type' of the entity.  Thus, for such declared entities, we have to
-     generate the qualifiers here.  */
-
-  if (TREE_THIS_VOLATILE (decl))
-    ret_val = concat ("volatile ", ret_val, NULL);
-  if (TREE_READONLY (decl))
-    ret_val = concat ("const ", ret_val, NULL);
-
-  data_type = "";
-
-  /* For FUNCTION_DECL nodes, there are two possible cases here.  First, if
-     this FUNCTION_DECL node was generated from a function "definition", then
-     we will have a list of DECL_NODE's, one for each of the function's formal
-     parameters.  In this case, we can print out not only the types of each
-     formal, but also each formal's name.  In the second case, this
-     FUNCTION_DECL node came from an actual function declaration (and *not*
-     a definition).  In this case, we do nothing here because the formal
-     argument type-list will be output later, when the "type" of the function
-     is added to the string we are building.  Note that the ANSI-style formal
-     parameter list is considered to be a (suffix) part of the "type" of the
-     function.  */
-
-  if (TREE_CODE (decl) == FUNCTION_DECL && is_func_definition)
-    {
-      ret_val = concat (ret_val, gen_formal_list_for_func_def (decl, ansi),
-                       NULL);
-
-      /* Since we have already added in the formals list stuff, here we don't
-        add the whole "type" of the function we are considering (which
-        would include its parameter-list info), rather, we only add in
-        the "type" of the "type" of the function, which is really just
-        the return-type of the function (and does not include the parameter
-        list info).  */
-
-      ret_val = gen_type (ret_val, TREE_TYPE (TREE_TYPE (decl)), style);
-    }
-  else
-    ret_val = gen_type (ret_val, TREE_TYPE (decl), style);
-
-  ret_val = affix_data_type (ret_val);
-
-  if (TREE_CODE (decl) != FUNCTION_DECL && C_DECL_REGISTER (decl))
-    ret_val = concat ("register ", ret_val, NULL);
-  if (TREE_PUBLIC (decl))
-    ret_val = concat ("extern ", ret_val, NULL);
-  if (TREE_CODE (decl) == FUNCTION_DECL && !TREE_PUBLIC (decl))
-    ret_val = concat ("static ", ret_val, NULL);
-
-  return ret_val;
-}
-
-extern FILE *aux_info_file;
-
-/* Generate and write a new line of info to the aux-info (.X) file.  This
-   routine is called once for each function declaration, and once for each
-   function definition (even the implicit ones).  */
-
-void
-gen_aux_info_record (tree fndecl, int is_definition, int is_implicit,
-                    int is_prototyped)
-{
-  if (flag_gen_aux_info)
-    {
-      static int compiled_from_record = 0;
-      expanded_location xloc = expand_location (DECL_SOURCE_LOCATION (fndecl));
-
-      /* Each output .X file must have a header line.  Write one now if we
-        have not yet done so.  */
-
-      if (!compiled_from_record++)
-       {
-         /* The first line tells which directory file names are relative to.
-            Currently, -aux-info works only for files in the working
-            directory, so just use a `.' as a placeholder for now.  */
-         fprintf (aux_info_file, "/* compiled from: . */\n");
-       }
-
-      /* Write the actual line of auxiliary info.  */
-
-      fprintf (aux_info_file, "/* %s:%d:%c%c */ %s;",
-              xloc.file, xloc.line,
-              (is_implicit) ? 'I' : (is_prototyped) ? 'N' : 'O',
-              (is_definition) ? 'F' : 'C',
-              gen_decl (fndecl, is_definition, ansi));
-
-      /* If this is an explicit function declaration, we need to also write
-        out an old-style (i.e. K&R) function header, just in case the user
-        wants to run unprotoize.  */
-
-      if (is_definition)
-       {
-         fprintf (aux_info_file, " /*%s %s*/",
-                  gen_formal_list_for_func_def (fndecl, k_and_r_names),
-                  gen_formal_list_for_func_def (fndecl, k_and_r_decls));
-       }
-
-      fprintf (aux_info_file, "\n");
-    }
-}
diff --git a/gcc/c-config-lang.in b/gcc/c-config-lang.in
deleted file mode 100644 (file)
index 5e14002..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-# Top level configure fragment for GNU C - C language.
-# Copyright (C) 1994, 1995, 1997, 1998, 2000, 2001, 2002, 2005, 2007, 2010
-# 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 file c-config-lang.c is a special pseudo config-lang.in file
-# for the language C. It has limited use, specifically to record the
-# files used by C that have garbage collection GTY macros in them
-# which therefore need to be scanned by gengtype.c.
-
-gtfiles="\$(srcdir)/c-lang.c \$(srcdir)/c-tree.h \$(srcdir)/c-decl.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-objc.h \$(srcdir)/c-family/c-cppbuiltin.c \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c \$(srcdir)/c-objc-common.c \$(srcdir)/c-parser.c \$(srcdir)/c-lang.h"
diff --git a/gcc/c-convert.c b/gcc/c-convert.c
deleted file mode 100644 (file)
index f4583c5..0000000
+++ /dev/null
@@ -1,183 +0,0 @@
-/* Language-level data type conversion for GNU C.
-   Copyright (C) 1987, 1988, 1991, 1998, 2002, 2003, 2004, 2005, 2007, 2008,
-   2009, 2010 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 file contains the functions for converting C expressions
-   to different data types.  The only entry point is `convert'.
-   Every language front end must have a `convert' function
-   but what kind of conversions it does will depend on the language.  */
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "tm.h"
-#include "tree.h"
-#include "flags.h"
-#include "convert.h"
-#include "c-family/c-common.h"
-#include "c-tree.h"
-#include "langhooks.h"
-#include "target.h"
-
-/* Change of width--truncation and extension of integers or reals--
-   is represented with NOP_EXPR.  Proper functioning of many things
-   assumes that no other conversions can be NOP_EXPRs.
-
-   Conversion between integer and pointer is represented with CONVERT_EXPR.
-   Converting integer to real uses FLOAT_EXPR
-   and real to integer uses FIX_TRUNC_EXPR.
-
-   Here is a list of all the functions that assume that widening and
-   narrowing is always done with a NOP_EXPR:
-     In convert.c, convert_to_integer.
-     In c-typeck.c, build_binary_op (boolean ops), and
-       c_common_truthvalue_conversion.
-     In expr.c: expand_expr, for operands of a MULT_EXPR.
-     In fold-const.c: fold.
-     In tree.c: get_narrower and get_unwidened.  */
-\f
-/* Subroutines of `convert'.  */
-
-
-\f
-/* Create an expression whose value is that of EXPR,
-   converted to type TYPE.  The TREE_TYPE of the value
-   is always TYPE.  This function implements all reasonable
-   conversions; callers should filter out those that are
-   not permitted by the language being compiled.  */
-
-tree
-convert (tree type, tree expr)
-{
-  tree e = expr;
-  enum tree_code code = TREE_CODE (type);
-  const char *invalid_conv_diag;
-  tree ret;
-  location_t loc = EXPR_LOCATION (expr);
-
-  if (type == error_mark_node
-      || expr == error_mark_node
-      || TREE_TYPE (expr) == error_mark_node)
-    return error_mark_node;
-
-  if ((invalid_conv_diag
-       = targetm.invalid_conversion (TREE_TYPE (expr), type)))
-    {
-      error (invalid_conv_diag);
-      return error_mark_node;
-    }
-
-  if (type == TREE_TYPE (expr))
-    return expr;
-  ret = targetm.convert_to_type (type, expr);
-  if (ret)
-      return ret;
-
-  STRIP_TYPE_NOPS (e);
-
-  if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (expr)))
-    return fold_convert_loc (loc, type, expr);
-  if (TREE_CODE (TREE_TYPE (expr)) == ERROR_MARK)
-    return error_mark_node;
-  if (TREE_CODE (TREE_TYPE (expr)) == VOID_TYPE)
-    {
-      error ("void value not ignored as it ought to be");
-      return error_mark_node;
-    }
-
-  switch (code)
-    {
-    case VOID_TYPE:
-      return fold_convert_loc (loc, type, e);
-
-    case INTEGER_TYPE:
-    case ENUMERAL_TYPE:
-      ret = convert_to_integer (type, e);
-      goto maybe_fold;
-
-    case BOOLEAN_TYPE:
-      return fold_convert_loc
-       (loc, type, c_objc_common_truthvalue_conversion (input_location, expr));
-
-    case POINTER_TYPE:
-    case REFERENCE_TYPE:
-      ret = convert_to_pointer (type, e);
-      goto maybe_fold;
-
-    case REAL_TYPE:
-      ret = convert_to_real (type, e);
-      goto maybe_fold;
-
-    case FIXED_POINT_TYPE:
-      ret = convert_to_fixed (type, e);
-      goto maybe_fold;
-
-    case COMPLEX_TYPE:
-      /* If converting from COMPLEX_TYPE to a different COMPLEX_TYPE
-        and e is not COMPLEX_EXPR, convert_to_complex uses save_expr,
-        but for the C FE c_save_expr needs to be called instead.  */
-      if (TREE_CODE (TREE_TYPE (e)) == COMPLEX_TYPE)
-       {
-         tree subtype = TREE_TYPE (type);
-         tree elt_type = TREE_TYPE (TREE_TYPE (e));
-
-         if (TYPE_MAIN_VARIANT (elt_type) != TYPE_MAIN_VARIANT (subtype)
-             && TREE_CODE (e) != COMPLEX_EXPR)
-           {
-             if (in_late_binary_op)
-               e = save_expr (e);
-             else
-               e = c_save_expr (e);
-             ret
-               = fold_build2 (COMPLEX_EXPR, type,
-                              convert (subtype,
-                                       fold_build1 (REALPART_EXPR,
-                                                    elt_type, e)),
-                              convert (subtype,
-                                       fold_build1 (IMAGPART_EXPR,
-                                                    elt_type, e)));
-             goto maybe_fold;
-           }
-       }
-      ret = convert_to_complex (type, e);
-      goto maybe_fold;
-
-    case VECTOR_TYPE:
-      ret = convert_to_vector (type, e);
-      goto maybe_fold;
-
-    case RECORD_TYPE:
-    case UNION_TYPE:
-      if (lang_hooks.types_compatible_p (type, TREE_TYPE (expr)))
-       return e;
-      break;
-
-    default:
-      break;
-
-    maybe_fold:
-      if (TREE_CODE (ret) != C_MAYBE_CONST_EXPR)
-       ret = fold (ret);
-      return ret;
-    }
-
-  error ("conversion to non-scalar type requested");
-  return error_mark_node;
-}
diff --git a/gcc/c-decl.c b/gcc/c-decl.c
deleted file mode 100644 (file)
index bbb437d..0000000
+++ /dev/null
@@ -1,10155 +0,0 @@
-/* Process declarations and variables for C compiler.
-   Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-   2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
-   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/>.  */
-
-/* Process declarations and symbol lookup for C front end.
-   Also constructs types; the standard scalar types at initialization,
-   and structure, union, array and enum types when they are declared.  */
-
-/* ??? not all decl nodes are given the most useful possible
-   line numbers.  For example, the CONST_DECLs for enum values.  */
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "input.h"
-#include "tm.h"
-#include "intl.h"
-#include "tree.h"
-#include "tree-inline.h"
-#include "flags.h"
-#include "function.h"
-#include "c-tree.h"
-#include "toplev.h"
-#include "tm_p.h"
-#include "cpplib.h"
-#include "target.h"
-#include "debug.h"
-#include "opts.h"
-#include "timevar.h"
-#include "c-family/c-common.h"
-#include "c-family/c-objc.h"
-#include "c-family/c-pragma.h"
-#include "c-lang.h"
-#include "langhooks.h"
-#include "tree-iterator.h"
-#include "diagnostic-core.h"
-#include "tree-dump.h"
-#include "cgraph.h"
-#include "hashtab.h"
-#include "langhooks-def.h"
-#include "pointer-set.h"
-#include "plugin.h"
-#include "c-family/c-ada-spec.h"
-
-/* In grokdeclarator, distinguish syntactic contexts of declarators.  */
-enum decl_context
-{ NORMAL,                      /* Ordinary declaration */
-  FUNCDEF,                     /* Function definition */
-  PARM,                                /* Declaration of parm before function body */
-  FIELD,                       /* Declaration inside struct or union */
-  TYPENAME};                   /* Typename (inside cast or sizeof)  */
-
-/* States indicating how grokdeclarator() should handle declspecs marked
-   with __attribute__((deprecated)).  An object declared as
-   __attribute__((deprecated)) suppresses warnings of uses of other
-   deprecated items.  */
-
-enum deprecated_states {
-  DEPRECATED_NORMAL,
-  DEPRECATED_SUPPRESS
-};
-
-\f
-/* Nonzero if we have seen an invalid cross reference
-   to a struct, union, or enum, but not yet printed the message.  */
-tree pending_invalid_xref;
-
-/* File and line to appear in the eventual error message.  */
-location_t pending_invalid_xref_location;
-
-/* The file and line that the prototype came from if this is an
-   old-style definition; used for diagnostics in
-   store_parm_decls_oldstyle.  */
-
-static location_t current_function_prototype_locus;
-
-/* Whether this prototype was built-in.  */
-
-static bool current_function_prototype_built_in;
-
-/* The argument type information of this prototype.  */
-
-static tree current_function_prototype_arg_types;
-
-/* The argument information structure for the function currently being
-   defined.  */
-
-static struct c_arg_info *current_function_arg_info;
-
-/* The obstack on which parser and related data structures, which are
-   not live beyond their top-level declaration or definition, are
-   allocated.  */
-struct obstack parser_obstack;
-
-/* The current statement tree.  */
-
-static GTY(()) struct stmt_tree_s c_stmt_tree;
-
-/* State saving variables.  */
-tree c_break_label;
-tree c_cont_label;
-
-/* A list of decls to be made automatically visible in each file scope.  */
-static GTY(()) tree visible_builtins;
-
-/* Set to 0 at beginning of a function definition, set to 1 if
-   a return statement that specifies a return value is seen.  */
-
-int current_function_returns_value;
-
-/* Set to 0 at beginning of a function definition, set to 1 if
-   a return statement with no argument is seen.  */
-
-int current_function_returns_null;
-
-/* Set to 0 at beginning of a function definition, set to 1 if
-   a call to a noreturn function is seen.  */
-
-int current_function_returns_abnormally;
-
-/* Set to nonzero by `grokdeclarator' for a function
-   whose return type is defaulted, if warnings for this are desired.  */
-
-static int warn_about_return_type;
-
-/* Nonzero when the current toplevel function contains a declaration
-   of a nested function which is never defined.  */
-
-static bool undef_nested_function;
-
-/* Mode used to build pointers (VOIDmode means ptr_mode).  */
-
-enum machine_mode c_default_pointer_mode = VOIDmode;
-
-\f
-/* Each c_binding structure describes one binding of an identifier to
-   a decl.  All the decls in a scope - irrespective of namespace - are
-   chained together by the ->prev field, which (as the name implies)
-   runs in reverse order.  All the decls in a given namespace bound to
-   a given identifier are chained by the ->shadowed field, which runs
-   from inner to outer scopes.
-
-   The ->decl field usually points to a DECL node, but there are two
-   exceptions.  In the namespace of type tags, the bound entity is a
-   RECORD_TYPE, UNION_TYPE, or ENUMERAL_TYPE node.  If an undeclared
-   identifier is encountered, it is bound to error_mark_node to
-   suppress further errors about that identifier in the current
-   function.
-
-   The ->u.type field stores the type of the declaration in this scope;
-   if NULL, the type is the type of the ->decl field.  This is only of
-   relevance for objects with external or internal linkage which may
-   be redeclared in inner scopes, forming composite types that only
-   persist for the duration of those scopes.  In the external scope,
-   this stores the composite of all the types declared for this
-   object, visible or not.  The ->inner_comp field (used only at file
-   scope) stores whether an incomplete array type at file scope was
-   completed at an inner scope to an array size other than 1.
-
-   The ->u.label field is used for labels.  It points to a structure
-   which stores additional information used for warnings.
-
-   The depth field is copied from the scope structure that holds this
-   decl.  It is used to preserve the proper ordering of the ->shadowed
-   field (see bind()) and also for a handful of special-case checks.
-   Finally, the invisible bit is true for a decl which should be
-   ignored for purposes of normal name lookup, and the nested bit is
-   true for a decl that's been bound a second time in an inner scope;
-   in all such cases, the binding in the outer scope will have its
-   invisible bit true.  */
-
-struct GTY((chain_next ("%h.prev"))) c_binding {
-  union GTY(()) {              /* first so GTY desc can use decl */
-    tree GTY((tag ("0"))) type; /* the type in this scope */
-    struct c_label_vars * GTY((tag ("1"))) label; /* for warnings */
-  } GTY((desc ("TREE_CODE (%0.decl) == LABEL_DECL"))) u;
-  tree decl;                   /* the decl bound */
-  tree id;                     /* the identifier it's bound to */
-  struct c_binding *prev;      /* the previous decl in this scope */
-  struct c_binding *shadowed;  /* the innermost decl shadowed by this one */
-  unsigned int depth : 28;      /* depth of this scope */
-  BOOL_BITFIELD invisible : 1;  /* normal lookup should ignore this binding */
-  BOOL_BITFIELD nested : 1;     /* do not set DECL_CONTEXT when popping */
-  BOOL_BITFIELD inner_comp : 1; /* incomplete array completed in inner scope */
-  BOOL_BITFIELD in_struct : 1; /* currently defined as struct field */
-  location_t locus;            /* location for nested bindings */
-};
-#define B_IN_SCOPE(b1, b2) ((b1)->depth == (b2)->depth)
-#define B_IN_CURRENT_SCOPE(b) ((b)->depth == current_scope->depth)
-#define B_IN_FILE_SCOPE(b) ((b)->depth == 1 /*file_scope->depth*/)
-#define B_IN_EXTERNAL_SCOPE(b) ((b)->depth == 0 /*external_scope->depth*/)
-
-#define I_SYMBOL_BINDING(node) \
-  (((struct lang_identifier *) IDENTIFIER_NODE_CHECK(node))->symbol_binding)
-#define I_SYMBOL_DECL(node) \
- (I_SYMBOL_BINDING(node) ? I_SYMBOL_BINDING(node)->decl : 0)
-
-#define I_TAG_BINDING(node) \
-  (((struct lang_identifier *) IDENTIFIER_NODE_CHECK(node))->tag_binding)
-#define I_TAG_DECL(node) \
- (I_TAG_BINDING(node) ? I_TAG_BINDING(node)->decl : 0)
-
-#define I_LABEL_BINDING(node) \
-  (((struct lang_identifier *) IDENTIFIER_NODE_CHECK(node))->label_binding)
-#define I_LABEL_DECL(node) \
- (I_LABEL_BINDING(node) ? I_LABEL_BINDING(node)->decl : 0)
-
-/* Each C symbol points to three linked lists of c_binding structures.
-   These describe the values of the identifier in the three different
-   namespaces defined by the language.  */
-
-struct GTY(()) lang_identifier {
-  struct c_common_identifier common_id;
-  struct c_binding *symbol_binding; /* vars, funcs, constants, typedefs */
-  struct c_binding *tag_binding;    /* struct/union/enum tags */
-  struct c_binding *label_binding;  /* labels */
-};
-
-/* Validate c-lang.c's assumptions.  */
-extern char C_SIZEOF_STRUCT_LANG_IDENTIFIER_isnt_accurate
-[(sizeof(struct lang_identifier) == C_SIZEOF_STRUCT_LANG_IDENTIFIER) ? 1 : -1];
-
-/* The resulting tree type.  */
-
-union GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"),
-       chain_next ("(union lang_tree_node *) c_tree_chain_next (&%h.generic)"))) lang_tree_node
- {
-  union tree_node GTY ((tag ("0"),
-                       desc ("tree_node_structure (&%h)")))
-    generic;
-  struct lang_identifier GTY ((tag ("1"))) identifier;
-};
-
-/* Track bindings and other things that matter for goto warnings.  For
-   efficiency, we do not gather all the decls at the point of
-   definition.  Instead, we point into the bindings structure.  As
-   scopes are popped, we update these structures and gather the decls
-   that matter at that time.  */
-
-struct GTY(()) c_spot_bindings {
-  /* The currently open scope which holds bindings defined when the
-     label was defined or the goto statement was found.  */
-  struct c_scope *scope;
-  /* The bindings in the scope field which were defined at the point
-     of the label or goto.  This lets us look at older or newer
-     bindings in the scope, as appropriate.  */
-  struct c_binding *bindings_in_scope;
-  /* The number of statement expressions that have started since this
-     label or goto statement was defined.  This is zero if we are at
-     the same statement expression level.  It is positive if we are in
-     a statement expression started since this spot.  It is negative
-     if this spot was in a statement expression and we have left
-     it.  */
-  int stmt_exprs;
-  /* Whether we started in a statement expression but are no longer in
-     it.  This is set to true if stmt_exprs ever goes negative.  */
-  bool left_stmt_expr;
-};
-
-/* This structure is used to keep track of bindings seen when a goto
-   statement is defined.  This is only used if we see the goto
-   statement before we see the label.  */
-
-struct GTY(()) c_goto_bindings {
-  /* The location of the goto statement.  */
-  location_t loc;
-  /* The bindings of the goto statement.  */
-  struct c_spot_bindings goto_bindings;
-};
-
-typedef struct c_goto_bindings *c_goto_bindings_p;
-DEF_VEC_P(c_goto_bindings_p);
-DEF_VEC_ALLOC_P(c_goto_bindings_p,gc);
-
-/* The additional information we keep track of for a label binding.
-   These fields are updated as scopes are popped.  */
-
-struct GTY(()) c_label_vars {
-  /* The shadowed c_label_vars, when one label shadows another (which
-     can only happen using a __label__ declaration).  */
-  struct c_label_vars *shadowed;
-  /* The bindings when the label was defined.  */
-  struct c_spot_bindings label_bindings;
-  /* A list of decls that we care about: decls about which we should
-     warn if a goto branches to this label from later in the function.
-     Decls are added to this list as scopes are popped.  We only add
-     the decls that matter.  */
-  VEC(tree,gc) *decls_in_scope;
-  /* A list of goto statements to this label.  This is only used for
-     goto statements seen before the label was defined, so that we can
-     issue appropriate warnings for them.  */
-  VEC(c_goto_bindings_p,gc) *gotos;
-};
-
-/* Each c_scope structure describes the complete contents of one
-   scope.  Four scopes are distinguished specially: the innermost or
-   current scope, the innermost function scope, the file scope (always
-   the second to outermost) and the outermost or external scope.
-
-   Most declarations are recorded in the current scope.
-
-   All normal label declarations are recorded in the innermost
-   function scope, as are bindings of undeclared identifiers to
-   error_mark_node.  (GCC permits nested functions as an extension,
-   hence the 'innermost' qualifier.)  Explicitly declared labels
-   (using the __label__ extension) appear in the current scope.
-
-   Being in the file scope (current_scope == file_scope) causes
-   special behavior in several places below.  Also, under some
-   conditions the Objective-C front end records declarations in the
-   file scope even though that isn't the current scope.
-
-   All declarations with external linkage are recorded in the external
-   scope, even if they aren't visible there; this models the fact that
-   such declarations are visible to the entire program, and (with a
-   bit of cleverness, see pushdecl) allows diagnosis of some violations
-   of C99 6.2.2p7 and 6.2.7p2:
-
-     If, within the same translation unit, the same identifier appears
-     with both internal and external linkage, the behavior is
-     undefined.
-
-     All declarations that refer to the same object or function shall
-     have compatible type; otherwise, the behavior is undefined.
-
-   Initially only the built-in declarations, which describe compiler
-   intrinsic functions plus a subset of the standard library, are in
-   this scope.
-
-   The order of the blocks list matters, and it is frequently appended
-   to.  To avoid having to walk all the way to the end of the list on
-   each insertion, or reverse the list later, we maintain a pointer to
-   the last list entry.  (FIXME: It should be feasible to use a reversed
-   list here.)
-
-   The bindings list is strictly in reverse order of declarations;
-   pop_scope relies on this.  */
-
-
-struct GTY((chain_next ("%h.outer"))) c_scope {
-  /* The scope containing this one.  */
-  struct c_scope *outer;
-
-  /* The next outermost function scope.  */
-  struct c_scope *outer_function;
-
-  /* All bindings in this scope.  */
-  struct c_binding *bindings;
-
-  /* For each scope (except the global one), a chain of BLOCK nodes
-     for all the scopes that were entered and exited one level down.  */
-  tree blocks;
-  tree blocks_last;
-
-  /* The depth of this scope.  Used to keep the ->shadowed chain of
-     bindings sorted innermost to outermost.  */
-  unsigned int depth : 28;
-
-  /* True if we are currently filling this scope with parameter
-     declarations.  */
-  BOOL_BITFIELD parm_flag : 1;
-
-  /* True if we saw [*] in this scope.  Used to give an error messages
-     if these appears in a function definition.  */
-  BOOL_BITFIELD had_vla_unspec : 1;
-
-  /* True if we already complained about forward parameter decls
-     in this scope.  This prevents double warnings on
-     foo (int a; int b; ...)  */
-  BOOL_BITFIELD warned_forward_parm_decls : 1;
-
-  /* True if this is the outermost block scope of a function body.
-     This scope contains the parameters, the local variables declared
-     in the outermost block, and all the labels (except those in
-     nested functions, or declared at block scope with __label__).  */
-  BOOL_BITFIELD function_body : 1;
-
-  /* True means make a BLOCK for this scope no matter what.  */
-  BOOL_BITFIELD keep : 1;
-
-  /* True means that an unsuffixed float constant is _Decimal64.  */
-  BOOL_BITFIELD float_const_decimal64 : 1;
-
-  /* True if this scope has any label bindings.  This is used to speed
-     up searching for labels when popping scopes, particularly since
-     labels are normally only found at function scope.  */
-  BOOL_BITFIELD has_label_bindings : 1;
-
-  /* True if we should issue a warning if a goto statement crosses any
-     of the bindings.  We still need to check the list of bindings to
-     find the specific ones we need to warn about.  This is true if
-     decl_jump_unsafe would return true for any of the bindings.  This
-     is used to avoid looping over all the bindings unnecessarily.  */
-  BOOL_BITFIELD has_jump_unsafe_decl : 1;
-};
-
-/* The scope currently in effect.  */
-
-static GTY(()) struct c_scope *current_scope;
-
-/* The innermost function scope.  Ordinary (not explicitly declared)
-   labels, bindings to error_mark_node, and the lazily-created
-   bindings of __func__ and its friends get this scope.  */
-
-static GTY(()) struct c_scope *current_function_scope;
-
-/* The C file scope.  This is reset for each input translation unit.  */
-
-static GTY(()) struct c_scope *file_scope;
-
-/* The outermost scope.  This is used for all declarations with
-   external linkage, and only these, hence the name.  */
-
-static GTY(()) struct c_scope *external_scope;
-
-/* A chain of c_scope structures awaiting reuse.  */
-
-static GTY((deletable)) struct c_scope *scope_freelist;
-
-/* A chain of c_binding structures awaiting reuse.  */
-
-static GTY((deletable)) struct c_binding *binding_freelist;
-
-/* Append VAR to LIST in scope SCOPE.  */
-#define SCOPE_LIST_APPEND(scope, list, decl) do {      \
-  struct c_scope *s_ = (scope);                                \
-  tree d_ = (decl);                                    \
-  if (s_->list##_last)                                 \
-    BLOCK_CHAIN (s_->list##_last) = d_;                        \
-  else                                                 \
-    s_->list = d_;                                     \
-  s_->list##_last = d_;                                        \
-} while (0)
-
-/* Concatenate FROM in scope FSCOPE onto TO in scope TSCOPE.  */
-#define SCOPE_LIST_CONCAT(tscope, to, fscope, from) do {       \
-  struct c_scope *t_ = (tscope);                               \
-  struct c_scope *f_ = (fscope);                               \
-  if (t_->to##_last)                                           \
-    BLOCK_CHAIN (t_->to##_last) = f_->from;                    \
-  else                                                         \
-    t_->to = f_->from;                                         \
-  t_->to##_last = f_->from##_last;                             \
-} while (0)
-
-/* A c_inline_static structure stores details of a static identifier
-   referenced in a definition of a function that may be an inline
-   definition if no subsequent declaration of that function uses
-   "extern" or does not use "inline".  */
-
-struct GTY((chain_next ("%h.next"))) c_inline_static {
-  /* The location for a diagnostic.  */
-  location_t location;
-
-  /* The function that may be an inline definition.  */
-  tree function;
-
-  /* The object or function referenced.  */
-  tree static_decl;
-
-  /* What sort of reference this is.  */
-  enum c_inline_static_type type;
-
-  /* The next such structure or NULL.  */
-  struct c_inline_static *next;
-};
-
-/* List of static identifiers used or referenced in functions that may
-   be inline definitions.  */
-static GTY(()) struct c_inline_static *c_inline_statics;
-
-/* True means unconditionally make a BLOCK for the next scope pushed.  */
-
-static bool keep_next_level_flag;
-
-/* True means the next call to push_scope will be the outermost scope
-   of a function body, so do not push a new scope, merely cease
-   expecting parameter decls.  */
-
-static bool next_is_function_body;
-
-/* A VEC of pointers to c_binding structures.  */
-
-typedef struct c_binding *c_binding_ptr;
-DEF_VEC_P(c_binding_ptr);
-DEF_VEC_ALLOC_P(c_binding_ptr,heap);
-
-/* Information that we keep for a struct or union while it is being
-   parsed.  */
-
-struct c_struct_parse_info
-{
-  /* If warn_cxx_compat, a list of types defined within this
-     struct.  */
-  VEC(tree,heap) *struct_types;
-  /* If warn_cxx_compat, a list of field names which have bindings,
-     and which are defined in this struct, but which are not defined
-     in any enclosing struct.  This is used to clear the in_struct
-     field of the c_bindings structure.  */
-  VEC(c_binding_ptr,heap) *fields;
-  /* If warn_cxx_compat, a list of typedef names used when defining
-     fields in this struct.  */
-  VEC(tree,heap) *typedefs_seen;
-};
-
-/* Information for the struct or union currently being parsed, or
-   NULL if not parsing a struct or union.  */
-static struct c_struct_parse_info *struct_parse_info;
-
-/* Forward declarations.  */
-static tree lookup_name_in_scope (tree, struct c_scope *);
-static tree c_make_fname_decl (location_t, tree, int);
-static tree grokdeclarator (const struct c_declarator *,
-                           struct c_declspecs *,
-                           enum decl_context, bool, tree *, tree *, tree *,
-                           bool *, enum deprecated_states);
-static tree grokparms (struct c_arg_info *, bool);
-static void layout_array_type (tree);
-\f
-/* T is a statement.  Add it to the statement-tree.  This is the
-   C/ObjC version--C++ has a slightly different version of this
-   function.  */
-
-tree
-add_stmt (tree t)
-{
-  enum tree_code code = TREE_CODE (t);
-
-  if (CAN_HAVE_LOCATION_P (t) && code != LABEL_EXPR)
-    {
-      if (!EXPR_HAS_LOCATION (t))
-       SET_EXPR_LOCATION (t, input_location);
-    }
-
-  if (code == LABEL_EXPR || code == CASE_LABEL_EXPR)
-    STATEMENT_LIST_HAS_LABEL (cur_stmt_list) = 1;
-
-  /* Add T to the statement-tree.  Non-side-effect statements need to be
-     recorded during statement expressions.  */
-  if (!building_stmt_list_p ())
-    push_stmt_list ();
-  append_to_statement_list_force (t, &cur_stmt_list);
-
-  return t;
-}
-\f
-/* Build a pointer type using the default pointer mode.  */
-
-static tree
-c_build_pointer_type (tree to_type)
-{
-  addr_space_t as = to_type == error_mark_node? ADDR_SPACE_GENERIC
-                                             : TYPE_ADDR_SPACE (to_type);
-  enum machine_mode pointer_mode;
-
-  if (as != ADDR_SPACE_GENERIC || c_default_pointer_mode == VOIDmode)
-    pointer_mode = targetm.addr_space.pointer_mode (as);
-  else
-    pointer_mode = c_default_pointer_mode;
-  return build_pointer_type_for_mode (to_type, pointer_mode, false);
-}
-
-\f
-/* Return true if we will want to say something if a goto statement
-   crosses DECL.  */
-
-static bool
-decl_jump_unsafe (tree decl)
-{
-  if (error_operand_p (decl))
-    return false;
-
-  /* Always warn about crossing variably modified types.  */
-  if ((TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == TYPE_DECL)
-      && variably_modified_type_p (TREE_TYPE (decl), NULL_TREE))
-    return true;
-
-  /* Otherwise, only warn if -Wgoto-misses-init and this is an
-     initialized automatic decl.  */
-  if (warn_jump_misses_init
-      && TREE_CODE (decl) == VAR_DECL
-      && !TREE_STATIC (decl)
-      && DECL_INITIAL (decl) != NULL_TREE)
-    return true;
-
-  return false;
-}
-\f
-
-void
-c_print_identifier (FILE *file, tree node, int indent)
-{
-  print_node (file, "symbol", I_SYMBOL_DECL (node), indent + 4);
-  print_node (file, "tag", I_TAG_DECL (node), indent + 4);
-  print_node (file, "label", I_LABEL_DECL (node), indent + 4);
-  if (C_IS_RESERVED_WORD (node) && C_RID_CODE (node) != RID_CXX_COMPAT_WARN)
-    {
-      tree rid = ridpointers[C_RID_CODE (node)];
-      indent_to (file, indent + 4);
-      fprintf (file, "rid " HOST_PTR_PRINTF " \"%s\"",
-              (void *) rid, IDENTIFIER_POINTER (rid));
-    }
-}
-
-/* Establish a binding between NAME, an IDENTIFIER_NODE, and DECL,
-   which may be any of several kinds of DECL or TYPE or error_mark_node,
-   in the scope SCOPE.  */
-static void
-bind (tree name, tree decl, struct c_scope *scope, bool invisible,
-      bool nested, location_t locus)
-{
-  struct c_binding *b, **here;
-
-  if (binding_freelist)
-    {
-      b = binding_freelist;
-      binding_freelist = b->prev;
-    }
-  else
-    b = ggc_alloc_c_binding ();
-
-  b->shadowed = 0;
-  b->decl = decl;
-  b->id = name;
-  b->depth = scope->depth;
-  b->invisible = invisible;
-  b->nested = nested;
-  b->inner_comp = 0;
-  b->in_struct = 0;
-  b->locus = locus;
-
-  b->u.type = NULL;
-
-  b->prev = scope->bindings;
-  scope->bindings = b;
-
-  if (decl_jump_unsafe (decl))
-    scope->has_jump_unsafe_decl = 1;
-
-  if (!name)
-    return;
-
-  switch (TREE_CODE (decl))
-    {
-    case LABEL_DECL:     here = &I_LABEL_BINDING (name);   break;
-    case ENUMERAL_TYPE:
-    case UNION_TYPE:
-    case RECORD_TYPE:    here = &I_TAG_BINDING (name);     break;
-    case VAR_DECL:
-    case FUNCTION_DECL:
-    case TYPE_DECL:
-    case CONST_DECL:
-    case PARM_DECL:
-    case ERROR_MARK:     here = &I_SYMBOL_BINDING (name);  break;
-
-    default:
-      gcc_unreachable ();
-    }
-
-  /* Locate the appropriate place in the chain of shadowed decls
-     to insert this binding.  Normally, scope == current_scope and
-     this does nothing.  */
-  while (*here && (*here)->depth > scope->depth)
-    here = &(*here)->shadowed;
-
-  b->shadowed = *here;
-  *here = b;
-}
-
-/* Clear the binding structure B, stick it on the binding_freelist,
-   and return the former value of b->prev.  This is used by pop_scope
-   and get_parm_info to iterate destructively over all the bindings
-   from a given scope.  */
-static struct c_binding *
-free_binding_and_advance (struct c_binding *b)
-{
-  struct c_binding *prev = b->prev;
-
-  memset (b, 0, sizeof (struct c_binding));
-  b->prev = binding_freelist;
-  binding_freelist = b;
-
-  return prev;
-}
-
-/* Bind a label.  Like bind, but skip fields which aren't used for
-   labels, and add the LABEL_VARS value.  */
-static void
-bind_label (tree name, tree label, struct c_scope *scope,
-           struct c_label_vars *label_vars)
-{
-  struct c_binding *b;
-
-  bind (name, label, scope, /*invisible=*/false, /*nested=*/false,
-       UNKNOWN_LOCATION);
-
-  scope->has_label_bindings = true;
-
-  b = scope->bindings;
-  gcc_assert (b->decl == label);
-  label_vars->shadowed = b->u.label;
-  b->u.label = label_vars;
-}
-\f
-/* Hook called at end of compilation to assume 1 elt
-   for a file-scope tentative array defn that wasn't complete before.  */
-
-void
-c_finish_incomplete_decl (tree decl)
-{
-  if (TREE_CODE (decl) == VAR_DECL)
-    {
-      tree type = TREE_TYPE (decl);
-      if (type != error_mark_node
-         && TREE_CODE (type) == ARRAY_TYPE
-         && !DECL_EXTERNAL (decl)
-         && TYPE_DOMAIN (type) == 0)
-       {
-         warning_at (DECL_SOURCE_LOCATION (decl),
-                     0, "array %q+D assumed to have one element", decl);
-
-         complete_array_type (&TREE_TYPE (decl), NULL_TREE, true);
-
-         relayout_decl (decl);
-       }
-    }
-}
-\f
-/* Record that inline function FUNC contains a reference (location
-   LOC) to static DECL (file-scope or function-local according to
-   TYPE).  */
-
-void
-record_inline_static (location_t loc, tree func, tree decl,
-                     enum c_inline_static_type type)
-{
-  struct c_inline_static *csi = ggc_alloc_c_inline_static ();
-  csi->location = loc;
-  csi->function = func;
-  csi->static_decl = decl;
-  csi->type = type;
-  csi->next = c_inline_statics;
-  c_inline_statics = csi;
-}
-
-/* Check for references to static declarations in inline functions at
-   the end of the translation unit and diagnose them if the functions
-   are still inline definitions.  */
-
-static void
-check_inline_statics (void)
-{
-  struct c_inline_static *csi;
-  for (csi = c_inline_statics; csi; csi = csi->next)
-    {
-      if (DECL_EXTERNAL (csi->function))
-       switch (csi->type)
-         {
-         case csi_internal:
-           pedwarn (csi->location, 0,
-                    "%qD is static but used in inline function %qD "
-                    "which is not static", csi->static_decl, csi->function);
-           break;
-         case csi_modifiable:
-           pedwarn (csi->location, 0,
-                    "%q+D is static but declared in inline function %qD "
-                    "which is not static", csi->static_decl, csi->function);
-           break;
-         default:
-           gcc_unreachable ();
-         }
-    }
-  c_inline_statics = NULL;
-}
-\f
-/* Fill in a c_spot_bindings structure.  If DEFINING is true, set it
-   for the current state, otherwise set it to uninitialized.  */
-
-static void
-set_spot_bindings (struct c_spot_bindings *p, bool defining)
-{
-  if (defining)
-    {
-      p->scope = current_scope;
-      p->bindings_in_scope = current_scope->bindings;
-    }
-  else
-    {
-      p->scope = NULL;
-      p->bindings_in_scope = NULL;
-    }
-  p->stmt_exprs = 0;
-  p->left_stmt_expr = false;
-}
-
-/* Update spot bindings P as we pop out of SCOPE.  Return true if we
-   should push decls for a label.  */
-
-static bool
-update_spot_bindings (struct c_scope *scope, struct c_spot_bindings *p)
-{
-  if (p->scope != scope)
-    {
-      /* This label or goto is defined in some other scope, or it is a
-        label which is not yet defined.  There is nothing to
-        update.  */
-      return false;
-    }
-
-  /* Adjust the spot bindings to refer to the bindings already defined
-     in the enclosing scope.  */
-  p->scope = scope->outer;
-  p->bindings_in_scope = p->scope->bindings;
-
-  return true;
-}
-\f
-/* The Objective-C front-end often needs to determine the current scope.  */
-
-void *
-objc_get_current_scope (void)
-{
-  return current_scope;
-}
-
-/* The following function is used only by Objective-C.  It needs to live here
-   because it accesses the innards of c_scope.  */
-
-void
-objc_mark_locals_volatile (void *enclosing_blk)
-{
-  struct c_scope *scope;
-  struct c_binding *b;
-
-  for (scope = current_scope;
-       scope && scope != enclosing_blk;
-       scope = scope->outer)
-    {
-      for (b = scope->bindings; b; b = b->prev)
-       objc_volatilize_decl (b->decl);
-
-      /* Do not climb up past the current function.  */
-      if (scope->function_body)
-       break;
-    }
-}
-
-/* Return true if we are in the global binding level.  */
-
-bool
-global_bindings_p (void)
-{
-  return current_scope == file_scope;
-}
-
-void
-keep_next_level (void)
-{
-  keep_next_level_flag = true;
-}
-
-/* Set the flag for the FLOAT_CONST_DECIMAL64 pragma being ON.  */
-
-void
-set_float_const_decimal64 (void)
-{
-  current_scope->float_const_decimal64 = true;
-}
-
-/* Clear the flag for the FLOAT_CONST_DECIMAL64 pragma.  */
-
-void
-clear_float_const_decimal64 (void)
-{
-  current_scope->float_const_decimal64 = false;
-}
-
-/* Return nonzero if an unsuffixed float constant is _Decimal64.  */
-
-bool
-float_const_decimal64_p (void)
-{
-  return current_scope->float_const_decimal64;
-}
-
-/* Identify this scope as currently being filled with parameters.  */
-
-void
-declare_parm_level (void)
-{
-  current_scope->parm_flag = true;
-}
-
-void
-push_scope (void)
-{
-  if (next_is_function_body)
-    {
-      /* This is the transition from the parameters to the top level
-        of the function body.  These are the same scope
-        (C99 6.2.1p4,6) so we do not push another scope structure.
-        next_is_function_body is set only by store_parm_decls, which
-        in turn is called when and only when we are about to
-        encounter the opening curly brace for the function body.
-
-        The outermost block of a function always gets a BLOCK node,
-        because the debugging output routines expect that each
-        function has at least one BLOCK.  */
-      current_scope->parm_flag         = false;
-      current_scope->function_body     = true;
-      current_scope->keep              = true;
-      current_scope->outer_function    = current_function_scope;
-      current_function_scope           = current_scope;
-
-      keep_next_level_flag = false;
-      next_is_function_body = false;
-
-      /* The FLOAT_CONST_DECIMAL64 pragma applies to nested scopes.  */
-      if (current_scope->outer)
-       current_scope->float_const_decimal64
-         = current_scope->outer->float_const_decimal64;
-      else
-       current_scope->float_const_decimal64 = false;
-    }
-  else
-    {
-      struct c_scope *scope;
-      if (scope_freelist)
-       {
-         scope = scope_freelist;
-         scope_freelist = scope->outer;
-       }
-      else
-       scope = ggc_alloc_cleared_c_scope ();
-
-      /* The FLOAT_CONST_DECIMAL64 pragma applies to nested scopes.  */
-      if (current_scope)
-       scope->float_const_decimal64 = current_scope->float_const_decimal64;
-      else
-       scope->float_const_decimal64 = false;
-
-      scope->keep          = keep_next_level_flag;
-      scope->outer         = current_scope;
-      scope->depth        = current_scope ? (current_scope->depth + 1) : 0;
-
-      /* Check for scope depth overflow.  Unlikely (2^28 == 268,435,456) but
-        possible.  */
-      if (current_scope && scope->depth == 0)
-       {
-         scope->depth--;
-         sorry ("GCC supports only %u nested scopes", scope->depth);
-       }
-
-      current_scope        = scope;
-      keep_next_level_flag = false;
-    }
-}
-
-/* This is called when we are leaving SCOPE.  For each label defined
-   in SCOPE, add any appropriate decls to its decls_in_scope fields.
-   These are the decls whose initialization will be skipped by a goto
-   later in the function.  */
-
-static void
-update_label_decls (struct c_scope *scope)
-{
-  struct c_scope *s;
-
-  s = scope;
-  while (s != NULL)
-    {
-      if (s->has_label_bindings)
-       {
-         struct c_binding *b;
-
-         for (b = s->bindings; b != NULL; b = b->prev)
-           {
-             struct c_label_vars *label_vars;
-             struct c_binding *b1;
-             bool hjud;
-             unsigned int ix;
-             struct c_goto_bindings *g;
-
-             if (TREE_CODE (b->decl) != LABEL_DECL)
-               continue;
-             label_vars = b->u.label;
-
-             b1 = label_vars->label_bindings.bindings_in_scope;
-             if (label_vars->label_bindings.scope == NULL)
-               hjud = false;
-             else
-               hjud = label_vars->label_bindings.scope->has_jump_unsafe_decl;
-             if (update_spot_bindings (scope, &label_vars->label_bindings))
-               {
-                 /* This label is defined in this scope.  */
-                 if (hjud)
-                   {
-                     for (; b1 != NULL; b1 = b1->prev)
-                       {
-                         /* A goto from later in the function to this
-                            label will never see the initialization
-                            of B1, if any.  Save it to issue a
-                            warning if needed.  */
-                         if (decl_jump_unsafe (b1->decl))
-                           VEC_safe_push (tree, gc,
-                                          label_vars->decls_in_scope,
-                                          b1->decl);
-                       }
-                   }
-               }
-
-             /* Update the bindings of any goto statements associated
-                with this label.  */
-             FOR_EACH_VEC_ELT (c_goto_bindings_p, label_vars->gotos, ix, g)
-               update_spot_bindings (scope, &g->goto_bindings);
-           }
-       }
-
-      /* Don't search beyond the current function.  */
-      if (s == current_function_scope)
-       break;
-
-      s = s->outer;
-    }
-}
-
-/* Set the TYPE_CONTEXT of all of TYPE's variants to CONTEXT.  */
-
-static void
-set_type_context (tree type, tree context)
-{
-  for (type = TYPE_MAIN_VARIANT (type); type;
-       type = TYPE_NEXT_VARIANT (type))
-    TYPE_CONTEXT (type) = context;
-}
-
-/* Exit a scope.  Restore the state of the identifier-decl mappings
-   that were in effect when this scope was entered.  Return a BLOCK
-   node containing all the DECLs in this scope that are of interest
-   to debug info generation.  */
-
-tree
-pop_scope (void)
-{
-  struct c_scope *scope = current_scope;
-  tree block, context, p;
-  struct c_binding *b;
-
-  bool functionbody = scope->function_body;
-  bool keep = functionbody || scope->keep || scope->bindings;
-
-  update_label_decls (scope);
-
-  /* If appropriate, create a BLOCK to record the decls for the life
-     of this function.  */
-  block = 0;
-  if (keep)
-    {
-      block = make_node (BLOCK);
-      BLOCK_SUBBLOCKS (block) = scope->blocks;
-      TREE_USED (block) = 1;
-
-      /* In each subblock, record that this is its superior.  */
-      for (p = scope->blocks; p; p = BLOCK_CHAIN (p))
-       BLOCK_SUPERCONTEXT (p) = block;
-
-      BLOCK_VARS (block) = 0;
-    }
-
-  /* The TYPE_CONTEXTs for all of the tagged types belonging to this
-     scope must be set so that they point to the appropriate
-     construct, i.e.  either to the current FUNCTION_DECL node, or
-     else to the BLOCK node we just constructed.
-
-     Note that for tagged types whose scope is just the formal
-     parameter list for some function type specification, we can't
-     properly set their TYPE_CONTEXTs here, because we don't have a
-     pointer to the appropriate FUNCTION_TYPE node readily available
-     to us.  For those cases, the TYPE_CONTEXTs of the relevant tagged
-     type nodes get set in `grokdeclarator' as soon as we have created
-     the FUNCTION_TYPE node which will represent the "scope" for these
-     "parameter list local" tagged types.  */
-  if (scope->function_body)
-    context = current_function_decl;
-  else if (scope == file_scope)
-    {
-      tree file_decl = build_translation_unit_decl (NULL_TREE);
-      context = file_decl;
-    }
-  else
-    context = block;
-
-  /* Clear all bindings in this scope.  */
-  for (b = scope->bindings; b; b = free_binding_and_advance (b))
-    {
-      p = b->decl;
-      switch (TREE_CODE (p))
-       {
-       case LABEL_DECL:
-         /* Warnings for unused labels, errors for undefined labels.  */
-         if (TREE_USED (p) && !DECL_INITIAL (p))
-           {
-             error ("label %q+D used but not defined", p);
-             DECL_INITIAL (p) = error_mark_node;
-           }
-         else
-           warn_for_unused_label (p);
-
-         /* Labels go in BLOCK_VARS.  */
-         DECL_CHAIN (p) = BLOCK_VARS (block);
-         BLOCK_VARS (block) = p;
-         gcc_assert (I_LABEL_BINDING (b->id) == b);
-         I_LABEL_BINDING (b->id) = b->shadowed;
-
-         /* Also pop back to the shadowed label_vars.  */
-         release_tree_vector (b->u.label->decls_in_scope);
-         b->u.label = b->u.label->shadowed;
-         break;
-
-       case ENUMERAL_TYPE:
-       case UNION_TYPE:
-       case RECORD_TYPE:
-         set_type_context (p, context);
-
-         /* Types may not have tag-names, in which case the type
-            appears in the bindings list with b->id NULL.  */
-         if (b->id)
-           {
-             gcc_assert (I_TAG_BINDING (b->id) == b);
-             I_TAG_BINDING (b->id) = b->shadowed;
-           }
-         break;
-
-       case FUNCTION_DECL:
-         /* Propagate TREE_ADDRESSABLE from nested functions to their
-            containing functions.  */
-         if (!TREE_ASM_WRITTEN (p)
-             && DECL_INITIAL (p) != 0
-             && TREE_ADDRESSABLE (p)
-             && DECL_ABSTRACT_ORIGIN (p) != 0
-             && DECL_ABSTRACT_ORIGIN (p) != p)
-           TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (p)) = 1;
-         if (!DECL_EXTERNAL (p)
-             && !DECL_INITIAL (p)
-             && scope != file_scope
-             && scope != external_scope)
-           {
-             error ("nested function %q+D declared but never defined", p);
-             undef_nested_function = true;
-           }
-         else if (DECL_DECLARED_INLINE_P (p)
-                  && TREE_PUBLIC (p)
-                  && !DECL_INITIAL (p))
-           {
-             /* C99 6.7.4p6: "a function with external linkage... declared
-                with an inline function specifier ... shall also be defined
-                in the same translation unit."  */
-             if (!flag_gnu89_inline)
-               pedwarn (input_location, 0,
-                        "inline function %q+D declared but never defined", p);
-             DECL_EXTERNAL (p) = 1;
-           }
-
-         goto common_symbol;
-
-       case VAR_DECL:
-         /* Warnings for unused variables.  */
-         if ((!TREE_USED (p) || !DECL_READ_P (p))
-             && !TREE_NO_WARNING (p)
-             && !DECL_IN_SYSTEM_HEADER (p)
-             && DECL_NAME (p)
-             && !DECL_ARTIFICIAL (p)
-             && scope != file_scope
-             && scope != external_scope)
-           {
-             if (!TREE_USED (p))
-               warning (OPT_Wunused_variable, "unused variable %q+D", p);
-             else if (DECL_CONTEXT (p) == current_function_decl)
-               warning_at (DECL_SOURCE_LOCATION (p),
-                           OPT_Wunused_but_set_variable,
-                           "variable %qD set but not used", p);
-           }
-
-         if (b->inner_comp)
-           {
-             error ("type of array %q+D completed incompatibly with"
-                    " implicit initialization", p);
-           }
-
-         /* Fall through.  */
-       case TYPE_DECL:
-       case CONST_DECL:
-       common_symbol:
-         /* All of these go in BLOCK_VARS, but only if this is the
-            binding in the home scope.  */
-         if (!b->nested)
-           {
-             DECL_CHAIN (p) = BLOCK_VARS (block);
-             BLOCK_VARS (block) = p;
-           }
-         else if (VAR_OR_FUNCTION_DECL_P (p) && scope != file_scope)
-           {
-             /* For block local externs add a special
-                DECL_EXTERNAL decl for debug info generation.  */
-             tree extp = copy_node (p);
-
-             DECL_EXTERNAL (extp) = 1;
-             TREE_STATIC (extp) = 0;
-             TREE_PUBLIC (extp) = 1;
-             DECL_INITIAL (extp) = NULL_TREE;
-             DECL_LANG_SPECIFIC (extp) = NULL;
-             DECL_CONTEXT (extp) = current_function_decl;
-             if (TREE_CODE (p) == FUNCTION_DECL)
-               {
-                 DECL_RESULT (extp) = NULL_TREE;
-                 DECL_SAVED_TREE (extp) = NULL_TREE;
-                 DECL_STRUCT_FUNCTION (extp) = NULL;
-               }
-             if (b->locus != UNKNOWN_LOCATION)
-               DECL_SOURCE_LOCATION (extp) = b->locus;
-             DECL_CHAIN (extp) = BLOCK_VARS (block);
-             BLOCK_VARS (block) = extp;
-           }
-         /* If this is the file scope set DECL_CONTEXT of each decl to
-            the TRANSLATION_UNIT_DECL.  This makes same_translation_unit_p
-            work.  */
-         if (scope == file_scope)
-           {
-             DECL_CONTEXT (p) = context;
-             if (TREE_CODE (p) == TYPE_DECL
-                 && TREE_TYPE (p) != error_mark_node)
-               set_type_context (TREE_TYPE (p), context);
-           }
-
-         /* Fall through.  */
-         /* Parameters go in DECL_ARGUMENTS, not BLOCK_VARS, and have
-            already been put there by store_parm_decls.  Unused-
-            parameter warnings are handled by function.c.
-            error_mark_node obviously does not go in BLOCK_VARS and
-            does not get unused-variable warnings.  */
-       case PARM_DECL:
-       case ERROR_MARK:
-         /* It is possible for a decl not to have a name.  We get
-            here with b->id NULL in this case.  */
-         if (b->id)
-           {
-             gcc_assert (I_SYMBOL_BINDING (b->id) == b);
-             I_SYMBOL_BINDING (b->id) = b->shadowed;
-             if (b->shadowed && b->shadowed->u.type)
-               TREE_TYPE (b->shadowed->decl) = b->shadowed->u.type;
-           }
-         break;
-
-       default:
-         gcc_unreachable ();
-       }
-    }
-
-
-  /* Dispose of the block that we just made inside some higher level.  */
-  if ((scope->function_body || scope == file_scope) && context)
-    {
-      DECL_INITIAL (context) = block;
-      BLOCK_SUPERCONTEXT (block) = context;
-    }
-  else if (scope->outer)
-    {
-      if (block)
-       SCOPE_LIST_APPEND (scope->outer, blocks, block);
-      /* If we did not make a block for the scope just exited, any
-        blocks made for inner scopes must be carried forward so they
-        will later become subblocks of something else.  */
-      else if (scope->blocks)
-       SCOPE_LIST_CONCAT (scope->outer, blocks, scope, blocks);
-    }
-
-  /* Pop the current scope, and free the structure for reuse.  */
-  current_scope = scope->outer;
-  if (scope->function_body)
-    current_function_scope = scope->outer_function;
-
-  memset (scope, 0, sizeof (struct c_scope));
-  scope->outer = scope_freelist;
-  scope_freelist = scope;
-
-  return block;
-}
-
-void
-push_file_scope (void)
-{
-  tree decl;
-
-  if (file_scope)
-    return;
-
-  push_scope ();
-  file_scope = current_scope;
-
-  start_fname_decls ();
-
-  for (decl = visible_builtins; decl; decl = DECL_CHAIN (decl))
-    bind (DECL_NAME (decl), decl, file_scope,
-         /*invisible=*/false, /*nested=*/true, DECL_SOURCE_LOCATION (decl));
-}
-
-void
-pop_file_scope (void)
-{
-  /* In case there were missing closebraces, get us back to the global
-     binding level.  */
-  while (current_scope != file_scope)
-    pop_scope ();
-
-  /* __FUNCTION__ is defined at file scope ("").  This
-     call may not be necessary as my tests indicate it
-     still works without it.  */
-  finish_fname_decls ();
-
-  check_inline_statics ();
-
-  /* This is the point to write out a PCH if we're doing that.
-     In that case we do not want to do anything else.  */
-  if (pch_file)
-    {
-      c_common_write_pch ();
-      return;
-    }
-
-  /* Pop off the file scope and close this translation unit.  */
-  pop_scope ();
-  file_scope = 0;
-
-  maybe_apply_pending_pragma_weaks ();
-}
-\f
-/* Adjust the bindings for the start of a statement expression.  */
-
-void
-c_bindings_start_stmt_expr (struct c_spot_bindings* switch_bindings)
-{
-  struct c_scope *scope;
-
-  for (scope = current_scope; scope != NULL; scope = scope->outer)
-    {
-      struct c_binding *b;
-
-      if (!scope->has_label_bindings)
-       continue;
-
-      for (b = scope->bindings; b != NULL; b = b->prev)
-       {
-         struct c_label_vars *label_vars;
-         unsigned int ix;
-         struct c_goto_bindings *g;
-
-         if (TREE_CODE (b->decl) != LABEL_DECL)
-           continue;
-         label_vars = b->u.label;
-         ++label_vars->label_bindings.stmt_exprs;
-         FOR_EACH_VEC_ELT (c_goto_bindings_p, label_vars->gotos, ix, g)
-           ++g->goto_bindings.stmt_exprs;
-       }
-    }
-
-  if (switch_bindings != NULL)
-    ++switch_bindings->stmt_exprs;
-}
-
-/* Adjust the bindings for the end of a statement expression.  */
-
-void
-c_bindings_end_stmt_expr (struct c_spot_bindings *switch_bindings)
-{
-  struct c_scope *scope;
-
-  for (scope = current_scope; scope != NULL; scope = scope->outer)
-    {
-      struct c_binding *b;
-
-      if (!scope->has_label_bindings)
-       continue;
-
-      for (b = scope->bindings; b != NULL; b = b->prev)
-       {
-         struct c_label_vars *label_vars;
-         unsigned int ix;
-         struct c_goto_bindings *g;
-
-         if (TREE_CODE (b->decl) != LABEL_DECL)
-           continue;
-         label_vars = b->u.label;
-         --label_vars->label_bindings.stmt_exprs;
-         if (label_vars->label_bindings.stmt_exprs < 0)
-           {
-             label_vars->label_bindings.left_stmt_expr = true;
-             label_vars->label_bindings.stmt_exprs = 0;
-           }
-         FOR_EACH_VEC_ELT (c_goto_bindings_p, label_vars->gotos, ix, g)
-           {
-             --g->goto_bindings.stmt_exprs;
-             if (g->goto_bindings.stmt_exprs < 0)
-               {
-                 g->goto_bindings.left_stmt_expr = true;
-                 g->goto_bindings.stmt_exprs = 0;
-               }
-           }
-       }
-    }
-
-  if (switch_bindings != NULL)
-    {
-      --switch_bindings->stmt_exprs;
-      gcc_assert (switch_bindings->stmt_exprs >= 0);
-    }
-}
-\f
-/* Push a definition or a declaration of struct, union or enum tag "name".
-   "type" should be the type node.
-   We assume that the tag "name" is not already defined, and has a location
-   of LOC.
-
-   Note that the definition may really be just a forward reference.
-   In that case, the TYPE_SIZE will be zero.  */
-
-static void
-pushtag (location_t loc, tree name, tree type)
-{
-  /* Record the identifier as the type's name if it has none.  */
-  if (name && !TYPE_NAME (type))
-    TYPE_NAME (type) = name;
-  bind (name, type, current_scope, /*invisible=*/false, /*nested=*/false, loc);
-
-  /* Create a fake NULL-named TYPE_DECL node whose TREE_TYPE will be the
-     tagged type we just added to the current scope.  This fake
-     NULL-named TYPE_DECL node helps dwarfout.c to know when it needs
-     to output a representation of a tagged type, and it also gives
-     us a convenient place to record the "scope start" address for the
-     tagged type.  */
-
-  TYPE_STUB_DECL (type) = pushdecl (build_decl (loc,
-                                               TYPE_DECL, NULL_TREE, type));
-
-  /* An approximation for now, so we can tell this is a function-scope tag.
-     This will be updated in pop_scope.  */
-  TYPE_CONTEXT (type) = DECL_CONTEXT (TYPE_STUB_DECL (type));
-
-  if (warn_cxx_compat && name != NULL_TREE)
-    {
-      struct c_binding *b = I_SYMBOL_BINDING (name);
-
-      if (b != NULL
-         && b->decl != NULL_TREE
-         && TREE_CODE (b->decl) == TYPE_DECL
-         && (B_IN_CURRENT_SCOPE (b)
-             || (current_scope == file_scope && B_IN_EXTERNAL_SCOPE (b)))
-         && (TYPE_MAIN_VARIANT (TREE_TYPE (b->decl))
-             != TYPE_MAIN_VARIANT (type)))
-       {
-         warning_at (loc, OPT_Wc___compat,
-                     ("using %qD as both a typedef and a tag is "
-                      "invalid in C++"),
-                     b->decl);
-         if (b->locus != UNKNOWN_LOCATION)
-           inform (b->locus, "originally defined here");
-       }
-    }
-}
-\f
-/* Subroutine of compare_decls.  Allow harmless mismatches in return
-   and argument types provided that the type modes match.  This function
-   return a unified type given a suitable match, and 0 otherwise.  */
-
-static tree
-match_builtin_function_types (tree newtype, tree oldtype)
-{
-  tree newrettype, oldrettype;
-  tree newargs, oldargs;
-  tree trytype, tryargs;
-
-  /* Accept the return type of the new declaration if same modes.  */
-  oldrettype = TREE_TYPE (oldtype);
-  newrettype = TREE_TYPE (newtype);
-
-  if (TYPE_MODE (oldrettype) != TYPE_MODE (newrettype))
-    return 0;
-
-  oldargs = TYPE_ARG_TYPES (oldtype);
-  newargs = TYPE_ARG_TYPES (newtype);
-  tryargs = newargs;
-
-  while (oldargs || newargs)
-    {
-      if (!oldargs
-         || !newargs
-         || !TREE_VALUE (oldargs)
-         || !TREE_VALUE (newargs)
-         || TYPE_MODE (TREE_VALUE (oldargs))
-            != TYPE_MODE (TREE_VALUE (newargs)))
-       return 0;
-
-      oldargs = TREE_CHAIN (oldargs);
-      newargs = TREE_CHAIN (newargs);
-    }
-
-  trytype = build_function_type (newrettype, tryargs);
-  return build_type_attribute_variant (trytype, TYPE_ATTRIBUTES (oldtype));
-}
-
-/* Subroutine of diagnose_mismatched_decls.  Check for function type
-   mismatch involving an empty arglist vs a nonempty one and give clearer
-   diagnostics.  */
-static void
-diagnose_arglist_conflict (tree newdecl, tree olddecl,
-                          tree newtype, tree oldtype)
-{
-  tree t;
-
-  if (TREE_CODE (olddecl) != FUNCTION_DECL
-      || !comptypes (TREE_TYPE (oldtype), TREE_TYPE (newtype))
-      || !((!prototype_p (oldtype) && DECL_INITIAL (olddecl) == 0)
-          || (!prototype_p (newtype) && DECL_INITIAL (newdecl) == 0)))
-    return;
-
-  t = TYPE_ARG_TYPES (oldtype);
-  if (t == 0)
-    t = TYPE_ARG_TYPES (newtype);
-  for (; t; t = TREE_CHAIN (t))
-    {
-      tree type = TREE_VALUE (t);
-
-      if (TREE_CHAIN (t) == 0
-         && TYPE_MAIN_VARIANT (type) != void_type_node)
-       {
-         inform (input_location, "a parameter list with an ellipsis can%'t match "
-                 "an empty parameter name list declaration");
-         break;
-       }
-
-      if (c_type_promotes_to (type) != type)
-       {
-         inform (input_location, "an argument type that has a default promotion can%'t match "
-                 "an empty parameter name list declaration");
-         break;
-       }
-    }
-}
-
-/* Another subroutine of diagnose_mismatched_decls.  OLDDECL is an
-   old-style function definition, NEWDECL is a prototype declaration.
-   Diagnose inconsistencies in the argument list.  Returns TRUE if
-   the prototype is compatible, FALSE if not.  */
-static bool
-validate_proto_after_old_defn (tree newdecl, tree newtype, tree oldtype)
-{
-  tree newargs, oldargs;
-  int i;
-
-#define END_OF_ARGLIST(t) ((t) == void_type_node)
-
-  oldargs = TYPE_ACTUAL_ARG_TYPES (oldtype);
-  newargs = TYPE_ARG_TYPES (newtype);
-  i = 1;
-
-  for (;;)
-    {
-      tree oldargtype = TREE_VALUE (oldargs);
-      tree newargtype = TREE_VALUE (newargs);
-
-      if (oldargtype == error_mark_node || newargtype == error_mark_node)
-       return false;
-
-      oldargtype = TYPE_MAIN_VARIANT (oldargtype);
-      newargtype = TYPE_MAIN_VARIANT (newargtype);
-
-      if (END_OF_ARGLIST (oldargtype) && END_OF_ARGLIST (newargtype))
-       break;
-
-      /* Reaching the end of just one list means the two decls don't
-        agree on the number of arguments.  */
-      if (END_OF_ARGLIST (oldargtype))
-       {
-         error ("prototype for %q+D declares more arguments "
-                "than previous old-style definition", newdecl);
-         return false;
-       }
-      else if (END_OF_ARGLIST (newargtype))
-       {
-         error ("prototype for %q+D declares fewer arguments "
-                "than previous old-style definition", newdecl);
-         return false;
-       }
-
-      /* Type for passing arg must be consistent with that declared
-        for the arg.  */
-      else if (!comptypes (oldargtype, newargtype))
-       {
-         error ("prototype for %q+D declares argument %d"
-                " with incompatible type",
-                newdecl, i);
-         return false;
-       }
-
-      oldargs = TREE_CHAIN (oldargs);
-      newargs = TREE_CHAIN (newargs);
-      i++;
-    }
-
-  /* If we get here, no errors were found, but do issue a warning
-     for this poor-style construct.  */
-  warning (0, "prototype for %q+D follows non-prototype definition",
-          newdecl);
-  return true;
-#undef END_OF_ARGLIST
-}
-
-/* Subroutine of diagnose_mismatched_decls.  Report the location of DECL,
-   first in a pair of mismatched declarations, using the diagnostic
-   function DIAG.  */
-static void
-locate_old_decl (tree decl)
-{
-  if (TREE_CODE (decl) == FUNCTION_DECL && DECL_BUILT_IN (decl))
-    ;
-  else if (DECL_INITIAL (decl))
-    inform (input_location, "previous definition of %q+D was here", decl);
-  else if (C_DECL_IMPLICIT (decl))
-    inform (input_location, "previous implicit declaration of %q+D was here", decl);
-  else
-    inform (input_location, "previous declaration of %q+D was here", decl);
-}
-
-/* Subroutine of duplicate_decls.  Compare NEWDECL to OLDDECL.
-   Returns true if the caller should proceed to merge the two, false
-   if OLDDECL should simply be discarded.  As a side effect, issues
-   all necessary diagnostics for invalid or poor-style combinations.
-   If it returns true, writes the types of NEWDECL and OLDDECL to
-   *NEWTYPEP and *OLDTYPEP - these may have been adjusted from
-   TREE_TYPE (NEWDECL, OLDDECL) respectively.  */
-
-static bool
-diagnose_mismatched_decls (tree newdecl, tree olddecl,
-                          tree *newtypep, tree *oldtypep)
-{
-  tree newtype, oldtype;
-  bool pedwarned = false;
-  bool warned = false;
-  bool retval = true;
-
-#define DECL_EXTERN_INLINE(DECL) (DECL_DECLARED_INLINE_P (DECL)  \
-                                 && DECL_EXTERNAL (DECL))
-
-  /* If we have error_mark_node for either decl or type, just discard
-     the previous decl - we're in an error cascade already.  */
-  if (olddecl == error_mark_node || newdecl == error_mark_node)
-    return false;
-  *oldtypep = oldtype = TREE_TYPE (olddecl);
-  *newtypep = newtype = TREE_TYPE (newdecl);
-  if (oldtype == error_mark_node || newtype == error_mark_node)
-    return false;
-
-  /* Two different categories of symbol altogether.  This is an error
-     unless OLDDECL is a builtin.  OLDDECL will be discarded in any case.  */
-  if (TREE_CODE (olddecl) != TREE_CODE (newdecl))
-    {
-      if (!(TREE_CODE (olddecl) == FUNCTION_DECL
-           && DECL_BUILT_IN (olddecl)
-           && !C_DECL_DECLARED_BUILTIN (olddecl)))
-       {
-         error ("%q+D redeclared as different kind of symbol", newdecl);
-         locate_old_decl (olddecl);
-       }
-      else if (TREE_PUBLIC (newdecl))
-       warning (0, "built-in function %q+D declared as non-function",
-                newdecl);
-      else
-       warning (OPT_Wshadow, "declaration of %q+D shadows "
-                "a built-in function", newdecl);
-      return false;
-    }
-
-  /* Enumerators have no linkage, so may only be declared once in a
-     given scope.  */
-  if (TREE_CODE (olddecl) == CONST_DECL)
-    {
-      error ("redeclaration of enumerator %q+D", newdecl);
-      locate_old_decl (olddecl);
-      return false;
-    }
-
-  if (!comptypes (oldtype, newtype))
-    {
-      if (TREE_CODE (olddecl) == FUNCTION_DECL
-         && DECL_BUILT_IN (olddecl) && !C_DECL_DECLARED_BUILTIN (olddecl))
-       {
-         /* Accept harmless mismatch in function types.
-            This is for the ffs and fprintf builtins.  */
-         tree trytype = match_builtin_function_types (newtype, oldtype);
-
-         if (trytype && comptypes (newtype, trytype))
-           *oldtypep = oldtype = trytype;
-         else
-           {
-             /* If types don't match for a built-in, throw away the
-                built-in.  No point in calling locate_old_decl here, it
-                won't print anything.  */
-             warning (0, "conflicting types for built-in function %q+D",
-                      newdecl);
-             return false;
-           }
-       }
-      else if (TREE_CODE (olddecl) == FUNCTION_DECL
-              && DECL_IS_BUILTIN (olddecl))
-       {
-         /* A conflicting function declaration for a predeclared
-            function that isn't actually built in.  Objective C uses
-            these.  The new declaration silently overrides everything
-            but the volatility (i.e. noreturn) indication.  See also
-            below.  FIXME: Make Objective C use normal builtins.  */
-         TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl);
-         return false;
-       }
-      /* Permit void foo (...) to match int foo (...) if the latter is
-        the definition and implicit int was used.  See
-        c-torture/compile/920625-2.c.  */
-      else if (TREE_CODE (newdecl) == FUNCTION_DECL && DECL_INITIAL (newdecl)
-              && TYPE_MAIN_VARIANT (TREE_TYPE (oldtype)) == void_type_node
-              && TYPE_MAIN_VARIANT (TREE_TYPE (newtype)) == integer_type_node
-              && C_FUNCTION_IMPLICIT_INT (newdecl) && !DECL_INITIAL (olddecl))
-       {
-         pedwarned = pedwarn (input_location, 0,
-                              "conflicting types for %q+D", newdecl);
-         /* Make sure we keep void as the return type.  */
-         TREE_TYPE (newdecl) = *newtypep = newtype = oldtype;
-         C_FUNCTION_IMPLICIT_INT (newdecl) = 0;
-       }
-      /* Permit void foo (...) to match an earlier call to foo (...) with
-        no declared type (thus, implicitly int).  */
-      else if (TREE_CODE (newdecl) == FUNCTION_DECL
-              && TYPE_MAIN_VARIANT (TREE_TYPE (newtype)) == void_type_node
-              && TYPE_MAIN_VARIANT (TREE_TYPE (oldtype)) == integer_type_node
-              && C_DECL_IMPLICIT (olddecl) && !DECL_INITIAL (olddecl))
-       {
-         pedwarned = pedwarn (input_location, 0,
-                              "conflicting types for %q+D", newdecl);
-         /* Make sure we keep void as the return type.  */
-         TREE_TYPE (olddecl) = *oldtypep = oldtype = newtype;
-       }
-      else
-       {
-         int new_quals = TYPE_QUALS (newtype);
-         int old_quals = TYPE_QUALS (oldtype);
-
-         if (new_quals != old_quals)
-           {
-             addr_space_t new_addr = DECODE_QUAL_ADDR_SPACE (new_quals);
-             addr_space_t old_addr = DECODE_QUAL_ADDR_SPACE (old_quals);
-             if (new_addr != old_addr)
-               {
-                 if (ADDR_SPACE_GENERIC_P (new_addr))
-                   error ("conflicting named address spaces (generic vs %s) "
-                          "for %q+D",
-                          c_addr_space_name (old_addr), newdecl);
-                 else if (ADDR_SPACE_GENERIC_P (old_addr))
-                   error ("conflicting named address spaces (%s vs generic) "
-                          "for %q+D",
-                          c_addr_space_name (new_addr), newdecl);
-                 else
-                   error ("conflicting named address spaces (%s vs %s) "
-                          "for %q+D",
-                          c_addr_space_name (new_addr),
-                          c_addr_space_name (old_addr),
-                          newdecl);
-               }
-
-             if (CLEAR_QUAL_ADDR_SPACE (new_quals)
-                 != CLEAR_QUAL_ADDR_SPACE (old_quals))
-               error ("conflicting type qualifiers for %q+D", newdecl);
-           }
-         else
-           error ("conflicting types for %q+D", newdecl);
-         diagnose_arglist_conflict (newdecl, olddecl, newtype, oldtype);
-         locate_old_decl (olddecl);
-         return false;
-       }
-    }
-
-  /* Redeclaration of a type is a constraint violation (6.7.2.3p1),
-     but silently ignore the redeclaration if either is in a system
-     header.  (Conflicting redeclarations were handled above.)  This
-     is allowed for C11 if the types are the same, not just
-     compatible.  */
-  if (TREE_CODE (newdecl) == TYPE_DECL)
-    {
-      bool types_different = false;
-      int comptypes_result;
-
-      comptypes_result
-       = comptypes_check_different_types (oldtype, newtype, &types_different);
-
-      if (comptypes_result != 1 || types_different)
-       {
-         error ("redefinition of typedef %q+D with different type", newdecl);
-         locate_old_decl (olddecl);
-         return false;
-       }
-
-      if (DECL_IN_SYSTEM_HEADER (newdecl)
-         || DECL_IN_SYSTEM_HEADER (olddecl)
-         || TREE_NO_WARNING (newdecl)
-         || TREE_NO_WARNING (olddecl))
-       return true;  /* Allow OLDDECL to continue in use.  */
-
-      if (variably_modified_type_p (newtype, NULL))
-       {
-         error ("redefinition of typedef %q+D with variably modified type",
-                newdecl);
-         locate_old_decl (olddecl);
-       }
-      else if (pedantic && !flag_isoc11)
-       {
-         pedwarn (input_location, OPT_Wpedantic,
-                  "redefinition of typedef %q+D", newdecl);
-         locate_old_decl (olddecl);
-       }
-
-      return true;
-    }
-
-  /* Function declarations can either be 'static' or 'extern' (no
-     qualifier is equivalent to 'extern' - C99 6.2.2p5) and therefore
-     can never conflict with each other on account of linkage
-     (6.2.2p4).  Multiple definitions are not allowed (6.9p3,5) but
-     gnu89 mode permits two definitions if one is 'extern inline' and
-     one is not.  The non- extern-inline definition supersedes the
-     extern-inline definition.  */
-
-  else if (TREE_CODE (newdecl) == FUNCTION_DECL)
-    {
-      /* If you declare a built-in function name as static, or
-        define the built-in with an old-style definition (so we
-        can't validate the argument list) the built-in definition is
-        overridden, but optionally warn this was a bad choice of name.  */
-      if (DECL_BUILT_IN (olddecl)
-         && !C_DECL_DECLARED_BUILTIN (olddecl)
-         && (!TREE_PUBLIC (newdecl)
-             || (DECL_INITIAL (newdecl)
-                 && !prototype_p (TREE_TYPE (newdecl)))))
-       {
-         warning (OPT_Wshadow, "declaration of %q+D shadows "
-                  "a built-in function", newdecl);
-         /* Discard the old built-in function.  */
-         return false;
-       }
-
-      if (DECL_INITIAL (newdecl))
-       {
-         if (DECL_INITIAL (olddecl))
-           {
-             /* If both decls are in the same TU and the new declaration
-                isn't overriding an extern inline reject the new decl.
-                In c99, no overriding is allowed in the same translation
-                unit.  */
-             if ((!DECL_EXTERN_INLINE (olddecl)
-                  || DECL_EXTERN_INLINE (newdecl)
-                  || (!flag_gnu89_inline
-                      && (!DECL_DECLARED_INLINE_P (olddecl)
-                          || !lookup_attribute ("gnu_inline",
-                                                DECL_ATTRIBUTES (olddecl)))
-                      && (!DECL_DECLARED_INLINE_P (newdecl)
-                          || !lookup_attribute ("gnu_inline",
-                                                DECL_ATTRIBUTES (newdecl))))
-                 )
-                 && same_translation_unit_p (newdecl, olddecl))
-               {
-                 error ("redefinition of %q+D", newdecl);
-                 locate_old_decl (olddecl);
-                 return false;
-               }
-           }
-       }
-      /* If we have a prototype after an old-style function definition,
-        the argument types must be checked specially.  */
-      else if (DECL_INITIAL (olddecl)
-              && !prototype_p (oldtype) && prototype_p (newtype)
-              && TYPE_ACTUAL_ARG_TYPES (oldtype)
-              && !validate_proto_after_old_defn (newdecl, newtype, oldtype))
-       {
-         locate_old_decl (olddecl);
-         return false;
-       }
-      /* A non-static declaration (even an "extern") followed by a
-        static declaration is undefined behavior per C99 6.2.2p3-5,7.
-        The same is true for a static forward declaration at block
-        scope followed by a non-static declaration/definition at file
-        scope.  Static followed by non-static at the same scope is
-        not undefined behavior, and is the most convenient way to get
-        some effects (see e.g.  what unwind-dw2-fde-glibc.c does to
-        the definition of _Unwind_Find_FDE in unwind-dw2-fde.c), but
-        we do diagnose it if -Wtraditional.  */
-      if (TREE_PUBLIC (olddecl) && !TREE_PUBLIC (newdecl))
-       {
-         /* Two exceptions to the rule.  If olddecl is an extern
-            inline, or a predeclared function that isn't actually
-            built in, newdecl silently overrides olddecl.  The latter
-            occur only in Objective C; see also above.  (FIXME: Make
-            Objective C use normal builtins.)  */
-         if (!DECL_IS_BUILTIN (olddecl)
-             && !DECL_EXTERN_INLINE (olddecl))
-           {
-             error ("static declaration of %q+D follows "
-                    "non-static declaration", newdecl);
-             locate_old_decl (olddecl);
-           }
-         return false;
-       }
-      else if (TREE_PUBLIC (newdecl) && !TREE_PUBLIC (olddecl))
-       {
-         if (DECL_CONTEXT (olddecl))
-           {
-             error ("non-static declaration of %q+D follows "
-                    "static declaration", newdecl);
-             locate_old_decl (olddecl);
-             return false;
-           }
-         else if (warn_traditional)
-           {
-             warned |= warning (OPT_Wtraditional,
-                                "non-static declaration of %q+D "
-                                "follows static declaration", newdecl);
-           }
-       }
-
-      /* Make sure gnu_inline attribute is either not present, or
-        present on all inline decls.  */
-      if (DECL_DECLARED_INLINE_P (olddecl)
-         && DECL_DECLARED_INLINE_P (newdecl))
-       {
-         bool newa = lookup_attribute ("gnu_inline",
-                                       DECL_ATTRIBUTES (newdecl)) != NULL;
-         bool olda = lookup_attribute ("gnu_inline",
-                                       DECL_ATTRIBUTES (olddecl)) != NULL;
-         if (newa != olda)
-           {
-             error_at (input_location, "%<gnu_inline%> attribute present on %q+D",
-                       newa ? newdecl : olddecl);
-             error_at (DECL_SOURCE_LOCATION (newa ? olddecl : newdecl),
-                       "but not here");
-           }
-       }
-    }
-  else if (TREE_CODE (newdecl) == VAR_DECL)
-    {
-      /* Only variables can be thread-local, and all declarations must
-        agree on this property.  */
-      if (C_DECL_THREADPRIVATE_P (olddecl) && !DECL_THREAD_LOCAL_P (newdecl))
-       {
-         /* Nothing to check.  Since OLDDECL is marked threadprivate
-            and NEWDECL does not have a thread-local attribute, we
-            will merge the threadprivate attribute into NEWDECL.  */
-         ;
-       }
-      else if (DECL_THREAD_LOCAL_P (newdecl) != DECL_THREAD_LOCAL_P (olddecl))
-       {
-         if (DECL_THREAD_LOCAL_P (newdecl))
-           error ("thread-local declaration of %q+D follows "
-                  "non-thread-local declaration", newdecl);
-         else
-           error ("non-thread-local declaration of %q+D follows "
-                  "thread-local declaration", newdecl);
-
-         locate_old_decl (olddecl);
-         return false;
-       }
-
-      /* Multiple initialized definitions are not allowed (6.9p3,5).  */
-      if (DECL_INITIAL (newdecl) && DECL_INITIAL (olddecl))
-       {
-         error ("redefinition of %q+D", newdecl);
-         locate_old_decl (olddecl);
-         return false;
-       }
-
-      /* Objects declared at file scope: if the first declaration had
-        external linkage (even if it was an external reference) the
-        second must have external linkage as well, or the behavior is
-        undefined.  If the first declaration had internal linkage, then
-        the second must too, or else be an external reference (in which
-        case the composite declaration still has internal linkage).
-        As for function declarations, we warn about the static-then-
-        extern case only for -Wtraditional.  See generally 6.2.2p3-5,7.  */
-      if (DECL_FILE_SCOPE_P (newdecl)
-         && TREE_PUBLIC (newdecl) != TREE_PUBLIC (olddecl))
-       {
-         if (DECL_EXTERNAL (newdecl))
-           {
-             if (!DECL_FILE_SCOPE_P (olddecl))
-               {
-                 error ("extern declaration of %q+D follows "
-                        "declaration with no linkage", newdecl);
-                 locate_old_decl (olddecl);
-                 return false;
-               }
-             else if (warn_traditional)
-               {
-                 warned |= warning (OPT_Wtraditional,
-                                    "non-static declaration of %q+D "
-                                    "follows static declaration", newdecl);
-               }
-           }
-         else
-           {
-             if (TREE_PUBLIC (newdecl))
-               error ("non-static declaration of %q+D follows "
-                      "static declaration", newdecl);
-             else
-               error ("static declaration of %q+D follows "
-                      "non-static declaration", newdecl);
-
-             locate_old_decl (olddecl);
-             return false;
-           }
-       }
-      /* Two objects with the same name declared at the same block
-        scope must both be external references (6.7p3).  */
-      else if (!DECL_FILE_SCOPE_P (newdecl))
-       {
-         if (DECL_EXTERNAL (newdecl))
-           {
-             /* Extern with initializer at block scope, which will
-                already have received an error.  */
-           }
-         else if (DECL_EXTERNAL (olddecl))
-           {
-             error ("declaration of %q+D with no linkage follows "
-                    "extern declaration", newdecl);
-             locate_old_decl (olddecl);
-           }
-         else
-           {
-             error ("redeclaration of %q+D with no linkage", newdecl);
-             locate_old_decl (olddecl);
-           }
-
-         return false;
-       }
-
-      /* C++ does not permit a decl to appear multiple times at file
-        scope.  */
-      if (warn_cxx_compat
-         && DECL_FILE_SCOPE_P (newdecl)
-         && !DECL_EXTERNAL (newdecl)
-         && !DECL_EXTERNAL (olddecl))
-       warned |= warning_at (DECL_SOURCE_LOCATION (newdecl),
-                             OPT_Wc___compat,
-                             ("duplicate declaration of %qD is "
-                              "invalid in C++"),
-                             newdecl);
-    }
-
-  /* warnings */
-  /* All decls must agree on a visibility.  */
-  if (CODE_CONTAINS_STRUCT (TREE_CODE (newdecl), TS_DECL_WITH_VIS)
-      && DECL_VISIBILITY_SPECIFIED (newdecl) && DECL_VISIBILITY_SPECIFIED (olddecl)
-      && DECL_VISIBILITY (newdecl) != DECL_VISIBILITY (olddecl))
-    {
-      warned |= warning (0, "redeclaration of %q+D with different visibility "
-                        "(old visibility preserved)", newdecl);
-    }
-
-  if (TREE_CODE (newdecl) == FUNCTION_DECL)
-    {
-      /* Diagnose inline __attribute__ ((noinline)) which is silly.  */
-      if (DECL_DECLARED_INLINE_P (newdecl)
-         && lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
-       {
-         warned |= warning (OPT_Wattributes,
-                            "inline declaration of %qD follows "
-                            "declaration with attribute noinline", newdecl);
-       }
-      else if (DECL_DECLARED_INLINE_P (olddecl)
-              && lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl)))
-       {
-         warned |= warning (OPT_Wattributes,
-                            "declaration of %q+D with attribute "
-                            "noinline follows inline declaration ", newdecl);
-       }
-    }
-  else /* PARM_DECL, VAR_DECL */
-    {
-      /* Redeclaration of a parameter is a constraint violation (this is
-        not explicitly stated, but follows from C99 6.7p3 [no more than
-        one declaration of the same identifier with no linkage in the
-        same scope, except type tags] and 6.2.2p6 [parameters have no
-        linkage]).  We must check for a forward parameter declaration,
-        indicated by TREE_ASM_WRITTEN on the old declaration - this is
-        an extension, the mandatory diagnostic for which is handled by
-        mark_forward_parm_decls.  */
-
-      if (TREE_CODE (newdecl) == PARM_DECL
-         && (!TREE_ASM_WRITTEN (olddecl) || TREE_ASM_WRITTEN (newdecl)))
-       {
-         error ("redefinition of parameter %q+D", newdecl);
-         locate_old_decl (olddecl);
-         return false;
-       }
-    }
-
-  /* Optional warning for completely redundant decls.  */
-  if (!warned && !pedwarned
-      && warn_redundant_decls
-      /* Don't warn about a function declaration followed by a
-        definition.  */
-      && !(TREE_CODE (newdecl) == FUNCTION_DECL
-          && DECL_INITIAL (newdecl) && !DECL_INITIAL (olddecl))
-      /* Don't warn about redundant redeclarations of builtins.  */
-      && !(TREE_CODE (newdecl) == FUNCTION_DECL
-          && !DECL_BUILT_IN (newdecl)
-          && DECL_BUILT_IN (olddecl)
-          && !C_DECL_DECLARED_BUILTIN (olddecl))
-      /* Don't warn about an extern followed by a definition.  */
-      && !(DECL_EXTERNAL (olddecl) && !DECL_EXTERNAL (newdecl))
-      /* Don't warn about forward parameter decls.  */
-      && !(TREE_CODE (newdecl) == PARM_DECL
-          && TREE_ASM_WRITTEN (olddecl) && !TREE_ASM_WRITTEN (newdecl))
-      /* Don't warn about a variable definition following a declaration.  */
-      && !(TREE_CODE (newdecl) == VAR_DECL
-          && DECL_INITIAL (newdecl) && !DECL_INITIAL (olddecl)))
-    {
-      warned = warning (OPT_Wredundant_decls, "redundant redeclaration of %q+D",
-                       newdecl);
-    }
-
-  /* Report location of previous decl/defn.  */
-  if (warned || pedwarned)
-    locate_old_decl (olddecl);
-
-#undef DECL_EXTERN_INLINE
-
-  return retval;
-}
-
-/* Subroutine of duplicate_decls.  NEWDECL has been found to be
-   consistent with OLDDECL, but carries new information.  Merge the
-   new information into OLDDECL.  This function issues no
-   diagnostics.  */
-
-static void
-merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
-{
-  bool new_is_definition = (TREE_CODE (newdecl) == FUNCTION_DECL
-                           && DECL_INITIAL (newdecl) != 0);
-  bool new_is_prototype = (TREE_CODE (newdecl) == FUNCTION_DECL
-                          && prototype_p (TREE_TYPE (newdecl)));
-  bool old_is_prototype = (TREE_CODE (olddecl) == FUNCTION_DECL
-                          && prototype_p (TREE_TYPE (olddecl)));
-
-  /* For real parm decl following a forward decl, rechain the old decl
-     in its new location and clear TREE_ASM_WRITTEN (it's not a
-     forward decl anymore).  */
-  if (TREE_CODE (newdecl) == PARM_DECL
-      && TREE_ASM_WRITTEN (olddecl) && !TREE_ASM_WRITTEN (newdecl))
-    {
-      struct c_binding *b, **here;
-
-      for (here = &current_scope->bindings; *here; here = &(*here)->prev)
-       if ((*here)->decl == olddecl)
-         goto found;
-      gcc_unreachable ();
-
-    found:
-      b = *here;
-      *here = b->prev;
-      b->prev = current_scope->bindings;
-      current_scope->bindings = b;
-
-      TREE_ASM_WRITTEN (olddecl) = 0;
-    }
-
-  DECL_ATTRIBUTES (newdecl)
-    = targetm.merge_decl_attributes (olddecl, newdecl);
-
-  /* Merge the data types specified in the two decls.  */
-  TREE_TYPE (newdecl)
-    = TREE_TYPE (olddecl)
-    = composite_type (newtype, oldtype);
-
-  /* Lay the type out, unless already done.  */
-  if (!comptypes (oldtype, TREE_TYPE (newdecl)))
-    {
-      if (TREE_TYPE (newdecl) != error_mark_node)
-       layout_type (TREE_TYPE (newdecl));
-      if (TREE_CODE (newdecl) != FUNCTION_DECL
-         && TREE_CODE (newdecl) != TYPE_DECL
-         && TREE_CODE (newdecl) != CONST_DECL)
-       layout_decl (newdecl, 0);
-    }
-  else
-    {
-      /* Since the type is OLDDECL's, make OLDDECL's size go with.  */
-      DECL_SIZE (newdecl) = DECL_SIZE (olddecl);
-      DECL_SIZE_UNIT (newdecl) = DECL_SIZE_UNIT (olddecl);
-      DECL_MODE (newdecl) = DECL_MODE (olddecl);
-      if (DECL_ALIGN (olddecl) > DECL_ALIGN (newdecl))
-       {
-         DECL_ALIGN (newdecl) = DECL_ALIGN (olddecl);
-         DECL_USER_ALIGN (newdecl) |= DECL_USER_ALIGN (olddecl);
-       }
-    }
-
-  /* Keep the old rtl since we can safely use it.  */
-  if (HAS_RTL_P (olddecl))
-    COPY_DECL_RTL (olddecl, newdecl);
-
-  /* Merge the type qualifiers.  */
-  if (TREE_READONLY (newdecl))
-    TREE_READONLY (olddecl) = 1;
-
-  if (TREE_THIS_VOLATILE (newdecl))
-    TREE_THIS_VOLATILE (olddecl) = 1;
-
-  /* Merge deprecatedness.  */
-  if (TREE_DEPRECATED (newdecl))
-    TREE_DEPRECATED (olddecl) = 1;
-
-  /* If a decl is in a system header and the other isn't, keep the one on the
-     system header. Otherwise, keep source location of definition rather than
-     declaration and of prototype rather than non-prototype unless that
-     prototype is built-in.  */
-  if (CODE_CONTAINS_STRUCT (TREE_CODE (olddecl), TS_DECL_WITH_VIS)
-      && DECL_IN_SYSTEM_HEADER (olddecl)
-      && !DECL_IN_SYSTEM_HEADER (newdecl) )
-    DECL_SOURCE_LOCATION (newdecl) = DECL_SOURCE_LOCATION (olddecl);
-  else if (CODE_CONTAINS_STRUCT (TREE_CODE (olddecl), TS_DECL_WITH_VIS)
-          && DECL_IN_SYSTEM_HEADER (newdecl)
-          && !DECL_IN_SYSTEM_HEADER (olddecl))
-    DECL_SOURCE_LOCATION (olddecl) = DECL_SOURCE_LOCATION (newdecl);
-  else if ((DECL_INITIAL (newdecl) == 0 && DECL_INITIAL (olddecl) != 0)
-          || (old_is_prototype && !new_is_prototype
-              && !C_DECL_BUILTIN_PROTOTYPE (olddecl)))
-    DECL_SOURCE_LOCATION (newdecl) = DECL_SOURCE_LOCATION (olddecl);
-
-  /* Merge the initialization information.  */
-   if (DECL_INITIAL (newdecl) == 0)
-    DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
-
-  /* Merge the threadprivate attribute.  */
-  if (TREE_CODE (olddecl) == VAR_DECL && C_DECL_THREADPRIVATE_P (olddecl))
-    {
-      DECL_TLS_MODEL (newdecl) = DECL_TLS_MODEL (olddecl);
-      C_DECL_THREADPRIVATE_P (newdecl) = 1;
-    }
-
-  if (CODE_CONTAINS_STRUCT (TREE_CODE (olddecl), TS_DECL_WITH_VIS))
-    {
-      /* Merge the section attribute.
-        We want to issue an error if the sections conflict but that
-        must be done later in decl_attributes since we are called
-        before attributes are assigned.  */
-      if (DECL_SECTION_NAME (newdecl) == NULL_TREE)
-       DECL_SECTION_NAME (newdecl) = DECL_SECTION_NAME (olddecl);
-
-      /* Copy the assembler name.
-        Currently, it can only be defined in the prototype.  */
-      COPY_DECL_ASSEMBLER_NAME (olddecl, newdecl);
-
-      /* Use visibility of whichever declaration had it specified */
-      if (DECL_VISIBILITY_SPECIFIED (olddecl))
-       {
-         DECL_VISIBILITY (newdecl) = DECL_VISIBILITY (olddecl);
-         DECL_VISIBILITY_SPECIFIED (newdecl) = 1;
-       }
-
-      if (TREE_CODE (newdecl) == FUNCTION_DECL)
-       {
-         DECL_STATIC_CONSTRUCTOR(newdecl) |= DECL_STATIC_CONSTRUCTOR(olddecl);
-         DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl);
-         DECL_NO_LIMIT_STACK (newdecl) |= DECL_NO_LIMIT_STACK (olddecl);
-         DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (newdecl)
-           |= DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (olddecl);
-         TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl);
-         DECL_IS_MALLOC (newdecl) |= DECL_IS_MALLOC (olddecl);
-         DECL_IS_OPERATOR_NEW (newdecl) |= DECL_IS_OPERATOR_NEW (olddecl);
-         TREE_READONLY (newdecl) |= TREE_READONLY (olddecl);
-         DECL_PURE_P (newdecl) |= DECL_PURE_P (olddecl);
-         DECL_IS_NOVOPS (newdecl) |= DECL_IS_NOVOPS (olddecl);
-       }
-
-      /* Merge the storage class information.  */
-      merge_weak (newdecl, olddecl);
-
-      /* For functions, static overrides non-static.  */
-      if (TREE_CODE (newdecl) == FUNCTION_DECL)
-       {
-         TREE_PUBLIC (newdecl) &= TREE_PUBLIC (olddecl);
-         /* This is since we don't automatically
-            copy the attributes of NEWDECL into OLDDECL.  */
-         TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
-         /* If this clears `static', clear it in the identifier too.  */
-         if (!TREE_PUBLIC (olddecl))
-           TREE_PUBLIC (DECL_NAME (olddecl)) = 0;
-       }
-    }
-
-  /* In c99, 'extern' declaration before (or after) 'inline' means this
-     function is not DECL_EXTERNAL, unless 'gnu_inline' attribute
-     is present.  */
-  if (TREE_CODE (newdecl) == FUNCTION_DECL
-      && !flag_gnu89_inline
-      && (DECL_DECLARED_INLINE_P (newdecl)
-         || DECL_DECLARED_INLINE_P (olddecl))
-      && (!DECL_DECLARED_INLINE_P (newdecl)
-         || !DECL_DECLARED_INLINE_P (olddecl)
-         || !DECL_EXTERNAL (olddecl))
-      && DECL_EXTERNAL (newdecl)
-      && !lookup_attribute ("gnu_inline", DECL_ATTRIBUTES (newdecl))
-      && !current_function_decl)
-    DECL_EXTERNAL (newdecl) = 0;
-
-  if (DECL_EXTERNAL (newdecl))
-    {
-      TREE_STATIC (newdecl) = TREE_STATIC (olddecl);
-      DECL_EXTERNAL (newdecl) = DECL_EXTERNAL (olddecl);
-
-      /* An extern decl does not override previous storage class.  */
-      TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl);
-      if (!DECL_EXTERNAL (newdecl))
-       {
-         DECL_CONTEXT (newdecl) = DECL_CONTEXT (olddecl);
-         DECL_COMMON (newdecl) = DECL_COMMON (olddecl);
-       }
-    }
-  else
-    {
-      TREE_STATIC (olddecl) = TREE_STATIC (newdecl);
-      TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
-    }
-
-  if (TREE_CODE (newdecl) == FUNCTION_DECL)
-    {
-      /* If we're redefining a function previously defined as extern
-        inline, make sure we emit debug info for the inline before we
-        throw it away, in case it was inlined into a function that
-        hasn't been written out yet.  */
-      if (new_is_definition && DECL_INITIAL (olddecl))
-       /* The new defn must not be inline.  */
-       DECL_UNINLINABLE (newdecl) = 1;
-      else
-       {
-         /* If either decl says `inline', this fn is inline, unless
-            its definition was passed already.  */
-         if (DECL_DECLARED_INLINE_P (newdecl)
-             || DECL_DECLARED_INLINE_P (olddecl))
-           DECL_DECLARED_INLINE_P (newdecl) = 1;
-
-         DECL_UNINLINABLE (newdecl) = DECL_UNINLINABLE (olddecl)
-           = (DECL_UNINLINABLE (newdecl) || DECL_UNINLINABLE (olddecl));
-
-         DECL_DISREGARD_INLINE_LIMITS (newdecl)
-           = DECL_DISREGARD_INLINE_LIMITS (olddecl)
-           = (DECL_DISREGARD_INLINE_LIMITS (newdecl)
-              || DECL_DISREGARD_INLINE_LIMITS (olddecl));
-       }
-
-      if (DECL_BUILT_IN (olddecl))
-       {
-         /* If redeclaring a builtin function, it stays built in.
-            But it gets tagged as having been declared.  */
-         DECL_BUILT_IN_CLASS (newdecl) = DECL_BUILT_IN_CLASS (olddecl);
-         DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
-         C_DECL_DECLARED_BUILTIN (newdecl) = 1;
-         if (new_is_prototype)
-           {
-             C_DECL_BUILTIN_PROTOTYPE (newdecl) = 0;
-             if (DECL_BUILT_IN_CLASS (newdecl) == BUILT_IN_NORMAL)
-               {
-                 enum built_in_function fncode = DECL_FUNCTION_CODE (newdecl);
-                 switch (fncode)
-                   {
-                     /* If a compatible prototype of these builtin functions
-                        is seen, assume the runtime implements it with the
-                        expected semantics.  */
-                   case BUILT_IN_STPCPY:
-                     if (builtin_decl_explicit_p (fncode))
-                       set_builtin_decl_implicit_p (fncode, true);
-                     break;
-                   default:
-                     break;
-                   }
-               }
-           }
-         else
-           C_DECL_BUILTIN_PROTOTYPE (newdecl)
-             = C_DECL_BUILTIN_PROTOTYPE (olddecl);
-       }
-
-      /* Preserve function specific target and optimization options */
-      if (DECL_FUNCTION_SPECIFIC_TARGET (olddecl)
-         && !DECL_FUNCTION_SPECIFIC_TARGET (newdecl))
-       DECL_FUNCTION_SPECIFIC_TARGET (newdecl)
-         = DECL_FUNCTION_SPECIFIC_TARGET (olddecl);
-
-      if (DECL_FUNCTION_SPECIFIC_OPTIMIZATION (olddecl)
-         && !DECL_FUNCTION_SPECIFIC_OPTIMIZATION (newdecl))
-       DECL_FUNCTION_SPECIFIC_OPTIMIZATION (newdecl)
-         = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (olddecl);
-
-      /* Also preserve various other info from the definition.  */
-      if (!new_is_definition)
-       {
-         tree t;
-         DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
-         DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
-         DECL_STRUCT_FUNCTION (newdecl) = DECL_STRUCT_FUNCTION (olddecl);
-         DECL_SAVED_TREE (newdecl) = DECL_SAVED_TREE (olddecl);
-         DECL_ARGUMENTS (newdecl) = copy_list (DECL_ARGUMENTS (olddecl));
-         for (t = DECL_ARGUMENTS (newdecl); t ; t = DECL_CHAIN (t))
-           DECL_CONTEXT (t) = newdecl;
-
-         /* See if we've got a function to instantiate from.  */
-         if (DECL_SAVED_TREE (olddecl))
-           DECL_ABSTRACT_ORIGIN (newdecl)
-             = DECL_ABSTRACT_ORIGIN (olddecl);
-       }
-    }
-
-  /* Merge the USED information.  */
-  if (TREE_USED (olddecl))
-    TREE_USED (newdecl) = 1;
-  else if (TREE_USED (newdecl))
-    TREE_USED (olddecl) = 1;
-  if (TREE_CODE (olddecl) == VAR_DECL || TREE_CODE (olddecl) == PARM_DECL)
-    DECL_READ_P (newdecl) |= DECL_READ_P (olddecl);
-  if (DECL_PRESERVE_P (olddecl))
-    DECL_PRESERVE_P (newdecl) = 1;
-  else if (DECL_PRESERVE_P (newdecl))
-    DECL_PRESERVE_P (olddecl) = 1;
-
-  /* Copy most of the decl-specific fields of NEWDECL into OLDDECL.
-     But preserve OLDDECL's DECL_UID, DECL_CONTEXT and
-     DECL_ARGUMENTS (if appropriate).  */
-  {
-    unsigned olddecl_uid = DECL_UID (olddecl);
-    tree olddecl_context = DECL_CONTEXT (olddecl);
-    tree olddecl_arguments = NULL;
-    if (TREE_CODE (olddecl) == FUNCTION_DECL)
-      olddecl_arguments = DECL_ARGUMENTS (olddecl);
-
-    memcpy ((char *) olddecl + sizeof (struct tree_common),
-           (char *) newdecl + sizeof (struct tree_common),
-           sizeof (struct tree_decl_common) - sizeof (struct tree_common));
-    DECL_USER_ALIGN (olddecl) = DECL_USER_ALIGN (newdecl);
-    switch (TREE_CODE (olddecl))
-      {
-      case FUNCTION_DECL:
-      case FIELD_DECL:
-      case VAR_DECL:
-      case PARM_DECL:
-      case LABEL_DECL:
-      case RESULT_DECL:
-      case CONST_DECL:
-      case TYPE_DECL:
-       memcpy ((char *) olddecl + sizeof (struct tree_decl_common),
-               (char *) newdecl + sizeof (struct tree_decl_common),
-               tree_code_size (TREE_CODE (olddecl)) - sizeof (struct tree_decl_common));
-       break;
-
-      default:
-
-       memcpy ((char *) olddecl + sizeof (struct tree_decl_common),
-               (char *) newdecl + sizeof (struct tree_decl_common),
-               sizeof (struct tree_decl_non_common) - sizeof (struct tree_decl_common));
-      }
-    DECL_UID (olddecl) = olddecl_uid;
-    DECL_CONTEXT (olddecl) = olddecl_context;
-    if (TREE_CODE (olddecl) == FUNCTION_DECL)
-      DECL_ARGUMENTS (olddecl) = olddecl_arguments;
-  }
-
-  /* If OLDDECL had its DECL_RTL instantiated, re-invoke make_decl_rtl
-     so that encode_section_info has a chance to look at the new decl
-     flags and attributes.  */
-  if (DECL_RTL_SET_P (olddecl)
-      && (TREE_CODE (olddecl) == FUNCTION_DECL
-         || (TREE_CODE (olddecl) == VAR_DECL
-             && TREE_STATIC (olddecl))))
-    make_decl_rtl (olddecl);
-}
-
-/* Handle when a new declaration NEWDECL has the same name as an old
-   one OLDDECL in the same binding contour.  Prints an error message
-   if appropriate.
-
-   If safely possible, alter OLDDECL to look like NEWDECL, and return
-   true.  Otherwise, return false.  */
-
-static bool
-duplicate_decls (tree newdecl, tree olddecl)
-{
-  tree newtype = NULL, oldtype = NULL;
-
-  if (!diagnose_mismatched_decls (newdecl, olddecl, &newtype, &oldtype))
-    {
-      /* Avoid `unused variable' and other warnings for OLDDECL.  */
-      TREE_NO_WARNING (olddecl) = 1;
-      return false;
-    }
-
-  merge_decls (newdecl, olddecl, newtype, oldtype);
-  return true;
-}
-
-\f
-/* Check whether decl-node NEW_DECL shadows an existing declaration.  */
-static void
-warn_if_shadowing (tree new_decl)
-{
-  struct c_binding *b;
-
-  /* Shadow warnings wanted?  */
-  if (!warn_shadow
-      /* No shadow warnings for internally generated vars.  */
-      || DECL_IS_BUILTIN (new_decl)
-      /* No shadow warnings for vars made for inlining.  */
-      || DECL_FROM_INLINE (new_decl))
-    return;
-
-  /* Is anything being shadowed?  Invisible decls do not count.  */
-  for (b = I_SYMBOL_BINDING (DECL_NAME (new_decl)); b; b = b->shadowed)
-    if (b->decl && b->decl != new_decl && !b->invisible
-       && (b->decl == error_mark_node
-           || diagnostic_report_warnings_p (global_dc,
-                                            DECL_SOURCE_LOCATION (b->decl))))
-      {
-       tree old_decl = b->decl;
-
-       if (old_decl == error_mark_node)
-         {
-           warning (OPT_Wshadow, "declaration of %q+D shadows previous "
-                    "non-variable", new_decl);
-           break;
-         }
-       else if (TREE_CODE (old_decl) == PARM_DECL)
-         warning (OPT_Wshadow, "declaration of %q+D shadows a parameter",
-                  new_decl);
-       else if (DECL_FILE_SCOPE_P (old_decl))
-         warning (OPT_Wshadow, "declaration of %q+D shadows a global "
-                  "declaration", new_decl);
-       else if (TREE_CODE (old_decl) == FUNCTION_DECL
-                && DECL_BUILT_IN (old_decl))
-         {
-           warning (OPT_Wshadow, "declaration of %q+D shadows "
-                    "a built-in function", new_decl);
-           break;
-         }
-       else
-         warning (OPT_Wshadow, "declaration of %q+D shadows a previous local",
-                  new_decl);
-
-       warning_at (DECL_SOURCE_LOCATION (old_decl), OPT_Wshadow,
-                   "shadowed declaration is here");
-
-       break;
-      }
-}
-
-/* Record a decl-node X as belonging to the current lexical scope.
-   Check for errors (such as an incompatible declaration for the same
-   name already seen in the same scope).
-
-   Returns either X or an old decl for the same name.
-   If an old decl is returned, it may have been smashed
-   to agree with what X says.  */
-
-tree
-pushdecl (tree x)
-{
-  tree name = DECL_NAME (x);
-  struct c_scope *scope = current_scope;
-  struct c_binding *b;
-  bool nested = false;
-  location_t locus = DECL_SOURCE_LOCATION (x);
-
-  /* Must set DECL_CONTEXT for everything not at file scope or
-     DECL_FILE_SCOPE_P won't work.  Local externs don't count
-     unless they have initializers (which generate code).  */
-  if (current_function_decl
-      && ((TREE_CODE (x) != FUNCTION_DECL && TREE_CODE (x) != VAR_DECL)
-         || DECL_INITIAL (x) || !DECL_EXTERNAL (x)))
-    DECL_CONTEXT (x) = current_function_decl;
-
-  /* Anonymous decls are just inserted in the scope.  */
-  if (!name)
-    {
-      bind (name, x, scope, /*invisible=*/false, /*nested=*/false,
-           locus);
-      return x;
-    }
-
-  /* First, see if there is another declaration with the same name in
-     the current scope.  If there is, duplicate_decls may do all the
-     work for us.  If duplicate_decls returns false, that indicates
-     two incompatible decls in the same scope; we are to silently
-     replace the old one (duplicate_decls has issued all appropriate
-     diagnostics).  In particular, we should not consider possible
-     duplicates in the external scope, or shadowing.  */
-  b = I_SYMBOL_BINDING (name);
-  if (b && B_IN_SCOPE (b, scope))
-    {
-      struct c_binding *b_ext, *b_use;
-      tree type = TREE_TYPE (x);
-      tree visdecl = b->decl;
-      tree vistype = TREE_TYPE (visdecl);
-      if (TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE
-         && COMPLETE_TYPE_P (TREE_TYPE (x)))
-       b->inner_comp = false;
-      b_use = b;
-      b_ext = b;
-      /* If this is an external linkage declaration, we should check
-        for compatibility with the type in the external scope before
-        setting the type at this scope based on the visible
-        information only.  */
-      if (TREE_PUBLIC (x) && TREE_PUBLIC (visdecl))
-       {
-         while (b_ext && !B_IN_EXTERNAL_SCOPE (b_ext))
-           b_ext = b_ext->shadowed;
-         if (b_ext)
-           {
-             b_use = b_ext;
-             if (b_use->u.type)
-               TREE_TYPE (b_use->decl) = b_use->u.type;
-           }
-       }
-      if (duplicate_decls (x, b_use->decl))
-       {
-         if (b_use != b)
-           {
-             /* Save the updated type in the external scope and
-                restore the proper type for this scope.  */
-             tree thistype;
-             if (comptypes (vistype, type))
-               thistype = composite_type (vistype, type);
-             else
-               thistype = TREE_TYPE (b_use->decl);
-             b_use->u.type = TREE_TYPE (b_use->decl);
-             if (TREE_CODE (b_use->decl) == FUNCTION_DECL
-                 && DECL_BUILT_IN (b_use->decl))
-               thistype
-                 = build_type_attribute_variant (thistype,
-                                                 TYPE_ATTRIBUTES
-                                                 (b_use->u.type));
-             TREE_TYPE (b_use->decl) = thistype;
-           }
-         return b_use->decl;
-       }
-      else
-       goto skip_external_and_shadow_checks;
-    }
-
-  /* All declarations with external linkage, and all external
-     references, go in the external scope, no matter what scope is
-     current.  However, the binding in that scope is ignored for
-     purposes of normal name lookup.  A separate binding structure is
-     created in the requested scope; this governs the normal
-     visibility of the symbol.
-
-     The binding in the externals scope is used exclusively for
-     detecting duplicate declarations of the same object, no matter
-     what scope they are in; this is what we do here.  (C99 6.2.7p2:
-     All declarations that refer to the same object or function shall
-     have compatible type; otherwise, the behavior is undefined.)  */
-  if (DECL_EXTERNAL (x) || scope == file_scope)
-    {
-      tree type = TREE_TYPE (x);
-      tree vistype = 0;
-      tree visdecl = 0;
-      bool type_saved = false;
-      if (b && !B_IN_EXTERNAL_SCOPE (b)
-         && (TREE_CODE (b->decl) == FUNCTION_DECL
-             || TREE_CODE (b->decl) == VAR_DECL)
-         && DECL_FILE_SCOPE_P (b->decl))
-       {
-         visdecl = b->decl;
-         vistype = TREE_TYPE (visdecl);
-       }
-      if (scope != file_scope
-         && !DECL_IN_SYSTEM_HEADER (x))
-       warning (OPT_Wnested_externs, "nested extern declaration of %qD", x);
-
-      while (b && !B_IN_EXTERNAL_SCOPE (b))
-       {
-         /* If this decl might be modified, save its type.  This is
-            done here rather than when the decl is first bound
-            because the type may change after first binding, through
-            being completed or through attributes being added.  If we
-            encounter multiple such decls, only the first should have
-            its type saved; the others will already have had their
-            proper types saved and the types will not have changed as
-            their scopes will not have been re-entered.  */
-         if (DECL_P (b->decl) && DECL_FILE_SCOPE_P (b->decl) && !type_saved)
-           {
-             b->u.type = TREE_TYPE (b->decl);
-             type_saved = true;
-           }
-         if (B_IN_FILE_SCOPE (b)
-             && TREE_CODE (b->decl) == VAR_DECL
-             && TREE_STATIC (b->decl)
-             && TREE_CODE (TREE_TYPE (b->decl)) == ARRAY_TYPE
-             && !TYPE_DOMAIN (TREE_TYPE (b->decl))
-             && TREE_CODE (type) == ARRAY_TYPE
-             && TYPE_DOMAIN (type)
-             && TYPE_MAX_VALUE (TYPE_DOMAIN (type))
-             && !integer_zerop (TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
-           {
-             /* Array type completed in inner scope, which should be
-                diagnosed if the completion does not have size 1 and
-                it does not get completed in the file scope.  */
-             b->inner_comp = true;
-           }
-         b = b->shadowed;
-       }
-
-      /* If a matching external declaration has been found, set its
-        type to the composite of all the types of that declaration.
-        After the consistency checks, it will be reset to the
-        composite of the visible types only.  */
-      if (b && (TREE_PUBLIC (x) || same_translation_unit_p (x, b->decl))
-         && b->u.type)
-       TREE_TYPE (b->decl) = b->u.type;
-
-      /* The point of the same_translation_unit_p check here is,
-        we want to detect a duplicate decl for a construct like
-        foo() { extern bar(); } ... static bar();  but not if
-        they are in different translation units.  In any case,
-        the static does not go in the externals scope.  */
-      if (b
-         && (TREE_PUBLIC (x) || same_translation_unit_p (x, b->decl))
-         && duplicate_decls (x, b->decl))
-       {
-         tree thistype;
-         if (vistype)
-           {
-             if (comptypes (vistype, type))
-               thistype = composite_type (vistype, type);
-             else
-               thistype = TREE_TYPE (b->decl);
-           }
-         else
-           thistype = type;
-         b->u.type = TREE_TYPE (b->decl);
-         if (TREE_CODE (b->decl) == FUNCTION_DECL && DECL_BUILT_IN (b->decl))
-           thistype
-             = build_type_attribute_variant (thistype,
-                                             TYPE_ATTRIBUTES (b->u.type));
-         TREE_TYPE (b->decl) = thistype;
-         bind (name, b->decl, scope, /*invisible=*/false, /*nested=*/true,
-               locus);
-         return b->decl;
-       }
-      else if (TREE_PUBLIC (x))
-       {
-         if (visdecl && !b && duplicate_decls (x, visdecl))
-           {
-             /* An external declaration at block scope referring to a
-                visible entity with internal linkage.  The composite
-                type will already be correct for this scope, so we
-                just need to fall through to make the declaration in
-                this scope.  */
-             nested = true;
-             x = visdecl;
-           }
-         else
-           {
-             bind (name, x, external_scope, /*invisible=*/true,
-                   /*nested=*/false, locus);
-             nested = true;
-           }
-       }
-    }
-
-  if (TREE_CODE (x) != PARM_DECL)
-    warn_if_shadowing (x);
-
- skip_external_and_shadow_checks:
-  if (TREE_CODE (x) == TYPE_DECL)
-    {
-      /* So this is a typedef, set its underlying type.  */
-      set_underlying_type (x);
-
-      /* If X is a typedef defined in the current function, record it
-        for the purpose of implementing the -Wunused-local-typedefs
-        warning.  */
-      record_locally_defined_typedef (x);
-    }
-
-  bind (name, x, scope, /*invisible=*/false, nested, locus);
-
-  /* If x's type is incomplete because it's based on a
-     structure or union which has not yet been fully declared,
-     attach it to that structure or union type, so we can go
-     back and complete the variable declaration later, if the
-     structure or union gets fully declared.
-
-     If the input is erroneous, we can have error_mark in the type
-     slot (e.g. "f(void a, ...)") - that doesn't count as an
-     incomplete type.  */
-  if (TREE_TYPE (x) != error_mark_node
-      && !COMPLETE_TYPE_P (TREE_TYPE (x)))
-    {
-      tree element = TREE_TYPE (x);
-
-      while (TREE_CODE (element) == ARRAY_TYPE)
-       element = TREE_TYPE (element);
-      element = TYPE_MAIN_VARIANT (element);
-
-      if ((TREE_CODE (element) == RECORD_TYPE
-          || TREE_CODE (element) == UNION_TYPE)
-         && (TREE_CODE (x) != TYPE_DECL
-             || TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE)
-         && !COMPLETE_TYPE_P (element))
-       C_TYPE_INCOMPLETE_VARS (element)
-         = tree_cons (NULL_TREE, x, C_TYPE_INCOMPLETE_VARS (element));
-    }
-  return x;
-}
-
-/* Record X as belonging to file scope.
-   This is used only internally by the Objective-C front end,
-   and is limited to its needs.  duplicate_decls is not called;
-   if there is any preexisting decl for this identifier, it is an ICE.  */
-
-tree
-pushdecl_top_level (tree x)
-{
-  tree name;
-  bool nested = false;
-  gcc_assert (TREE_CODE (x) == VAR_DECL || TREE_CODE (x) == CONST_DECL);
-
-  name = DECL_NAME (x);
-
- gcc_assert (TREE_CODE (x) == CONST_DECL || !I_SYMBOL_BINDING (name));
-
-  if (TREE_PUBLIC (x))
-    {
-      bind (name, x, external_scope, /*invisible=*/true, /*nested=*/false,
-           UNKNOWN_LOCATION);
-      nested = true;
-    }
-  if (file_scope)
-    bind (name, x, file_scope, /*invisible=*/false, nested, UNKNOWN_LOCATION);
-
-  return x;
-}
-\f
-static void
-implicit_decl_warning (tree id, tree olddecl)
-{
-  if (warn_implicit_function_declaration)
-    {
-      bool warned;
-
-      if (flag_isoc99)
-       warned = pedwarn (input_location, OPT_Wimplicit_function_declaration,
-                         "implicit declaration of function %qE", id);
-      else
-       warned = warning (OPT_Wimplicit_function_declaration,
-                         G_("implicit declaration of function %qE"), id);
-      if (olddecl && warned)
-       locate_old_decl (olddecl);
-    }
-}
-
-/* Generate an implicit declaration for identifier FUNCTIONID at LOC as a
-   function of type int ().  */
-
-tree
-implicitly_declare (location_t loc, tree functionid)
-{
-  struct c_binding *b;
-  tree decl = 0;
-  tree asmspec_tree;
-
-  for (b = I_SYMBOL_BINDING (functionid); b; b = b->shadowed)
-    {
-      if (B_IN_SCOPE (b, external_scope))
-       {
-         decl = b->decl;
-         break;
-       }
-    }
-
-  if (decl)
-    {
-      if (decl == error_mark_node)
-       return decl;
-
-      /* FIXME: Objective-C has weird not-really-builtin functions
-        which are supposed to be visible automatically.  They wind up
-        in the external scope because they're pushed before the file
-        scope gets created.  Catch this here and rebind them into the
-        file scope.  */
-      if (!DECL_BUILT_IN (decl) && DECL_IS_BUILTIN (decl))
-       {
-         bind (functionid, decl, file_scope,
-               /*invisible=*/false, /*nested=*/true,
-               DECL_SOURCE_LOCATION (decl));
-         return decl;
-       }
-      else
-       {
-         tree newtype = default_function_type;
-         if (b->u.type)
-           TREE_TYPE (decl) = b->u.type;
-         /* Implicit declaration of a function already declared
-            (somehow) in a different scope, or as a built-in.
-            If this is the first time this has happened, warn;
-            then recycle the old declaration but with the new type.  */
-         if (!C_DECL_IMPLICIT (decl))
-           {
-             implicit_decl_warning (functionid, decl);
-             C_DECL_IMPLICIT (decl) = 1;
-           }
-         if (DECL_BUILT_IN (decl))
-           {
-             newtype = build_type_attribute_variant (newtype,
-                                                     TYPE_ATTRIBUTES
-                                                     (TREE_TYPE (decl)));
-             if (!comptypes (newtype, TREE_TYPE (decl)))
-               {
-                 warning_at (loc, 0, "incompatible implicit declaration of "
-                             "built-in function %qD", decl);
-                 newtype = TREE_TYPE (decl);
-               }
-           }
-         else
-           {
-             if (!comptypes (newtype, TREE_TYPE (decl)))
-               {
-                 error_at (loc, "incompatible implicit declaration of function %qD", decl);
-                 locate_old_decl (decl);
-               }
-           }
-         b->u.type = TREE_TYPE (decl);
-         TREE_TYPE (decl) = newtype;
-         bind (functionid, decl, current_scope,
-               /*invisible=*/false, /*nested=*/true,
-               DECL_SOURCE_LOCATION (decl));
-         return decl;
-       }
-    }
-
-  /* Not seen before.  */
-  decl = build_decl (loc, FUNCTION_DECL, functionid, default_function_type);
-  DECL_EXTERNAL (decl) = 1;
-  TREE_PUBLIC (decl) = 1;
-  C_DECL_IMPLICIT (decl) = 1;
-  implicit_decl_warning (functionid, 0);
-  asmspec_tree = maybe_apply_renaming_pragma (decl, /*asmname=*/NULL);
-  if (asmspec_tree)
-    set_user_assembler_name (decl, TREE_STRING_POINTER (asmspec_tree));
-
-  /* C89 says implicit declarations are in the innermost block.
-     So we record the decl in the standard fashion.  */
-  decl = pushdecl (decl);
-
-  /* No need to call objc_check_decl here - it's a function type.  */
-  rest_of_decl_compilation (decl, 0, 0);
-
-  /* Write a record describing this implicit function declaration
-     to the prototypes file (if requested).  */
-  gen_aux_info_record (decl, 0, 1, 0);
-
-  /* Possibly apply some default attributes to this implicit declaration.  */
-  decl_attributes (&decl, NULL_TREE, 0);
-
-  return decl;
-}
-
-/* Issue an error message for a reference to an undeclared variable
-   ID, including a reference to a builtin outside of function-call
-   context.  Establish a binding of the identifier to error_mark_node
-   in an appropriate scope, which will suppress further errors for the
-   same identifier.  The error message should be given location LOC.  */
-void
-undeclared_variable (location_t loc, tree id)
-{
-  static bool already = false;
-  struct c_scope *scope;
-
-  if (current_function_decl == 0)
-    {
-      error_at (loc, "%qE undeclared here (not in a function)", id);
-      scope = current_scope;
-    }
-  else
-    {
-      if (!objc_diagnose_private_ivar (id))
-        error_at (loc, "%qE undeclared (first use in this function)", id);
-      if (!already)
-       {
-          inform (loc, "each undeclared identifier is reported only"
-                  " once for each function it appears in");
-         already = true;
-       }
-
-      /* If we are parsing old-style parameter decls, current_function_decl
-        will be nonnull but current_function_scope will be null.  */
-      scope = current_function_scope ? current_function_scope : current_scope;
-    }
-  bind (id, error_mark_node, scope, /*invisible=*/false, /*nested=*/false,
-       UNKNOWN_LOCATION);
-}
-\f
-/* Subroutine of lookup_label, declare_label, define_label: construct a
-   LABEL_DECL with all the proper frills.  Also create a struct
-   c_label_vars initialized for the current scope.  */
-
-static tree
-make_label (location_t location, tree name, bool defining,
-           struct c_label_vars **p_label_vars)
-{
-  tree label = build_decl (location, LABEL_DECL, name, void_type_node);
-  struct c_label_vars *label_vars;
-
-  DECL_CONTEXT (label) = current_function_decl;
-  DECL_MODE (label) = VOIDmode;
-
-  label_vars = ggc_alloc_c_label_vars ();
-  label_vars->shadowed = NULL;
-  set_spot_bindings (&label_vars->label_bindings, defining);
-  label_vars->decls_in_scope = make_tree_vector ();
-  label_vars->gotos = VEC_alloc (c_goto_bindings_p, gc, 0);
-  *p_label_vars = label_vars;
-
-  return label;
-}
-
-/* Get the LABEL_DECL corresponding to identifier NAME as a label.
-   Create one if none exists so far for the current function.
-   This is called when a label is used in a goto expression or
-   has its address taken.  */
-
-tree
-lookup_label (tree name)
-{
-  tree label;
-  struct c_label_vars *label_vars;
-
-  if (current_function_scope == 0)
-    {
-      error ("label %qE referenced outside of any function", name);
-      return 0;
-    }
-
-  /* Use a label already defined or ref'd with this name, but not if
-     it is inherited from a containing function and wasn't declared
-     using __label__.  */
-  label = I_LABEL_DECL (name);
-  if (label && (DECL_CONTEXT (label) == current_function_decl
-               || C_DECLARED_LABEL_FLAG (label)))
-    {
-      /* If the label has only been declared, update its apparent
-        location to point here, for better diagnostics if it
-        turns out not to have been defined.  */
-      if (DECL_INITIAL (label) == NULL_TREE)
-       DECL_SOURCE_LOCATION (label) = input_location;
-      return label;
-    }
-
-  /* No label binding for that identifier; make one.  */
-  label = make_label (input_location, name, false, &label_vars);
-
-  /* Ordinary labels go in the current function scope.  */
-  bind_label (name, label, current_function_scope, label_vars);
-
-  return label;
-}
-
-/* Issue a warning about DECL for a goto statement at GOTO_LOC going
-   to LABEL.  */
-
-static void
-warn_about_goto (location_t goto_loc, tree label, tree decl)
-{
-  if (variably_modified_type_p (TREE_TYPE (decl), NULL_TREE))
-    error_at (goto_loc,
-             "jump into scope of identifier with variably modified type");
-  else
-    warning_at (goto_loc, OPT_Wjump_misses_init,
-               "jump skips variable initialization");
-  inform (DECL_SOURCE_LOCATION (label), "label %qD defined here", label);
-  inform (DECL_SOURCE_LOCATION (decl), "%qD declared here", decl);
-}
-
-/* Look up a label because of a goto statement.  This is like
-   lookup_label, but also issues any appropriate warnings.  */
-
-tree
-lookup_label_for_goto (location_t loc, tree name)
-{
-  tree label;
-  struct c_label_vars *label_vars;
-  unsigned int ix;
-  tree decl;
-
-  label = lookup_label (name);
-  if (label == NULL_TREE)
-    return NULL_TREE;
-
-  /* If we are jumping to a different function, we can't issue any
-     useful warnings.  */
-  if (DECL_CONTEXT (label) != current_function_decl)
-    {
-      gcc_assert (C_DECLARED_LABEL_FLAG (label));
-      return label;
-    }
-
-  label_vars = I_LABEL_BINDING (name)->u.label;
-
-  /* If the label has not yet been defined, then push this goto on a
-     list for possible later warnings.  */
-  if (label_vars->label_bindings.scope == NULL)
-    {
-      struct c_goto_bindings *g;
-
-      g = ggc_alloc_c_goto_bindings ();
-      g->loc = loc;
-      set_spot_bindings (&g->goto_bindings, true);
-      VEC_safe_push (c_goto_bindings_p, gc, label_vars->gotos, g);
-      return label;
-    }
-
-  /* If there are any decls in label_vars->decls_in_scope, then this
-     goto has missed the declaration of the decl.  This happens for a
-     case like
-       int i = 1;
-      lab:
-       ...
-       goto lab;
-     Issue a warning or error.  */
-  FOR_EACH_VEC_ELT (tree, label_vars->decls_in_scope, ix, decl)
-    warn_about_goto (loc, label, decl);
-
-  if (label_vars->label_bindings.left_stmt_expr)
-    {
-      error_at (loc, "jump into statement expression");
-      inform (DECL_SOURCE_LOCATION (label), "label %qD defined here", label);
-    }
-
-  return label;
-}
-
-/* Make a label named NAME in the current function, shadowing silently
-   any that may be inherited from containing functions or containing
-   scopes.  This is called for __label__ declarations.  */
-
-tree
-declare_label (tree name)
-{
-  struct c_binding *b = I_LABEL_BINDING (name);
-  tree label;
-  struct c_label_vars *label_vars;
-
-  /* Check to make sure that the label hasn't already been declared
-     at this scope */
-  if (b && B_IN_CURRENT_SCOPE (b))
-    {
-      error ("duplicate label declaration %qE", name);
-      locate_old_decl (b->decl);
-
-      /* Just use the previous declaration.  */
-      return b->decl;
-    }
-
-  label = make_label (input_location, name, false, &label_vars);
-  C_DECLARED_LABEL_FLAG (label) = 1;
-
-  /* Declared labels go in the current scope.  */
-  bind_label (name, label, current_scope, label_vars);
-
-  return label;
-}
-
-/* When we define a label, issue any appropriate warnings if there are
-   any gotos earlier in the function which jump to this label.  */
-
-static void
-check_earlier_gotos (tree label, struct c_label_vars* label_vars)
-{
-  unsigned int ix;
-  struct c_goto_bindings *g;
-
-  FOR_EACH_VEC_ELT (c_goto_bindings_p, label_vars->gotos, ix, g)
-    {
-      struct c_binding *b;
-      struct c_scope *scope;
-
-      /* We have a goto to this label.  The goto is going forward.  In
-        g->scope, the goto is going to skip any binding which was
-        defined after g->bindings_in_scope.  */
-      if (g->goto_bindings.scope->has_jump_unsafe_decl)
-       {
-         for (b = g->goto_bindings.scope->bindings;
-              b != g->goto_bindings.bindings_in_scope;
-              b = b->prev)
-           {
-             if (decl_jump_unsafe (b->decl))
-               warn_about_goto (g->loc, label, b->decl);
-           }
-       }
-
-      /* We also need to warn about decls defined in any scopes
-        between the scope of the label and the scope of the goto.  */
-      for (scope = label_vars->label_bindings.scope;
-          scope != g->goto_bindings.scope;
-          scope = scope->outer)
-       {
-         gcc_assert (scope != NULL);
-         if (scope->has_jump_unsafe_decl)
-           {
-             if (scope == label_vars->label_bindings.scope)
-               b = label_vars->label_bindings.bindings_in_scope;
-             else
-               b = scope->bindings;
-             for (; b != NULL; b = b->prev)
-               {
-                 if (decl_jump_unsafe (b->decl))
-                   warn_about_goto (g->loc, label, b->decl);
-               }
-           }
-       }
-
-      if (g->goto_bindings.stmt_exprs > 0)
-       {
-         error_at (g->loc, "jump into statement expression");
-         inform (DECL_SOURCE_LOCATION (label), "label %qD defined here",
-                 label);
-       }
-    }
-
-  /* Now that the label is defined, we will issue warnings about
-     subsequent gotos to this label when we see them.  */
-  VEC_truncate (c_goto_bindings_p, label_vars->gotos, 0);
-  label_vars->gotos = NULL;
-}
-
-/* Define a label, specifying the location in the source file.
-   Return the LABEL_DECL node for the label, if the definition is valid.
-   Otherwise return 0.  */
-
-tree
-define_label (location_t location, tree name)
-{
-  /* Find any preexisting label with this name.  It is an error
-     if that label has already been defined in this function, or
-     if there is a containing function with a declared label with
-     the same name.  */
-  tree label = I_LABEL_DECL (name);
-
-  if (label
-      && ((DECL_CONTEXT (label) == current_function_decl
-          && DECL_INITIAL (label) != 0)
-         || (DECL_CONTEXT (label) != current_function_decl
-             && C_DECLARED_LABEL_FLAG (label))))
-    {
-      error_at (location, "duplicate label %qD", label);
-      locate_old_decl (label);
-      return 0;
-    }
-  else if (label && DECL_CONTEXT (label) == current_function_decl)
-    {
-      struct c_label_vars *label_vars = I_LABEL_BINDING (name)->u.label;
-
-      /* The label has been used or declared already in this function,
-        but not defined.  Update its location to point to this
-        definition.  */
-      DECL_SOURCE_LOCATION (label) = location;
-      set_spot_bindings (&label_vars->label_bindings, true);
-
-      /* Issue warnings as required about any goto statements from
-        earlier in the function.  */
-      check_earlier_gotos (label, label_vars);
-    }
-  else
-    {
-      struct c_label_vars *label_vars;
-
-      /* No label binding for that identifier; make one.  */
-      label = make_label (location, name, true, &label_vars);
-
-      /* Ordinary labels go in the current function scope.  */
-      bind_label (name, label, current_function_scope, label_vars);
-    }
-
-  if (!in_system_header && lookup_name (name))
-    warning_at (location, OPT_Wtraditional,
-               "traditional C lacks a separate namespace "
-               "for labels, identifier %qE conflicts", name);
-
-  /* Mark label as having been defined.  */
-  DECL_INITIAL (label) = error_mark_node;
-  return label;
-}
-\f
-/* Get the bindings for a new switch statement.  This is used to issue
-   warnings as appropriate for jumps from the switch to case or
-   default labels.  */
-
-struct c_spot_bindings *
-c_get_switch_bindings (void)
-{
-  struct c_spot_bindings *switch_bindings;
-
-  switch_bindings = XNEW (struct c_spot_bindings);
-  set_spot_bindings (switch_bindings, true);
-  return switch_bindings;
-}
-
-void
-c_release_switch_bindings (struct c_spot_bindings *bindings)
-{
-  gcc_assert (bindings->stmt_exprs == 0 && !bindings->left_stmt_expr);
-  XDELETE (bindings);
-}
-
-/* This is called at the point of a case or default label to issue
-   warnings about decls as needed.  It returns true if it found an
-   error, not just a warning.  */
-
-bool
-c_check_switch_jump_warnings (struct c_spot_bindings *switch_bindings,
-                             location_t switch_loc, location_t case_loc)
-{
-  bool saw_error;
-  struct c_scope *scope;
-
-  saw_error = false;
-  for (scope = current_scope;
-       scope != switch_bindings->scope;
-       scope = scope->outer)
-    {
-      struct c_binding *b;
-
-      gcc_assert (scope != NULL);
-
-      if (!scope->has_jump_unsafe_decl)
-       continue;
-
-      for (b = scope->bindings; b != NULL; b = b->prev)
-       {
-         if (decl_jump_unsafe (b->decl))
-           {
-             if (variably_modified_type_p (TREE_TYPE (b->decl), NULL_TREE))
-               {
-                 saw_error = true;
-                 error_at (case_loc,
-                           ("switch jumps into scope of identifier with "
-                            "variably modified type"));
-               }
-             else
-               warning_at (case_loc, OPT_Wjump_misses_init,
-                           "switch jumps over variable initialization");
-             inform (switch_loc, "switch starts here");
-             inform (DECL_SOURCE_LOCATION (b->decl), "%qD declared here",
-                     b->decl);
-           }
-       }
-    }
-
-  if (switch_bindings->stmt_exprs > 0)
-    {
-      saw_error = true;
-      error_at (case_loc, "switch jumps into statement expression");
-      inform (switch_loc, "switch starts here");
-    }
-
-  return saw_error;
-}
-\f
-/* Given NAME, an IDENTIFIER_NODE,
-   return the structure (or union or enum) definition for that name.
-   If THISLEVEL_ONLY is nonzero, searches only the current_scope.
-   CODE says which kind of type the caller wants;
-   it is RECORD_TYPE or UNION_TYPE or ENUMERAL_TYPE.
-   If PLOC is not NULL and this returns non-null, it sets *PLOC to the
-   location where the tag was defined.
-   If the wrong kind of type is found, an error is reported.  */
-
-static tree
-lookup_tag (enum tree_code code, tree name, int thislevel_only,
-           location_t *ploc)
-{
-  struct c_binding *b = I_TAG_BINDING (name);
-  int thislevel = 0;
-
-  if (!b || !b->decl)
-    return 0;
-
-  /* We only care about whether it's in this level if
-     thislevel_only was set or it might be a type clash.  */
-  if (thislevel_only || TREE_CODE (b->decl) != code)
-    {
-      /* For our purposes, a tag in the external scope is the same as
-        a tag in the file scope.  (Primarily relevant to Objective-C
-        and its builtin structure tags, which get pushed before the
-        file scope is created.)  */
-      if (B_IN_CURRENT_SCOPE (b)
-         || (current_scope == file_scope && B_IN_EXTERNAL_SCOPE (b)))
-       thislevel = 1;
-    }
-
-  if (thislevel_only && !thislevel)
-    return 0;
-
-  if (TREE_CODE (b->decl) != code)
-    {
-      /* Definition isn't the kind we were looking for.  */
-      pending_invalid_xref = name;
-      pending_invalid_xref_location = input_location;
-
-      /* If in the same binding level as a declaration as a tag
-        of a different type, this must not be allowed to
-        shadow that tag, so give the error immediately.
-        (For example, "struct foo; union foo;" is invalid.)  */
-      if (thislevel)
-       pending_xref_error ();
-    }
-
-  if (ploc != NULL)
-    *ploc = b->locus;
-
-  return b->decl;
-}
-
-/* Print an error message now
-   for a recent invalid struct, union or enum cross reference.
-   We don't print them immediately because they are not invalid
-   when used in the `struct foo;' construct for shadowing.  */
-
-void
-pending_xref_error (void)
-{
-  if (pending_invalid_xref != 0)
-    error_at (pending_invalid_xref_location, "%qE defined as wrong kind of tag",
-             pending_invalid_xref);
-  pending_invalid_xref = 0;
-}
-
-\f
-/* Look up NAME in the current scope and its superiors
-   in the namespace of variables, functions and typedefs.
-   Return a ..._DECL node of some kind representing its definition,
-   or return 0 if it is undefined.  */
-
-tree
-lookup_name (tree name)
-{
-  struct c_binding *b = I_SYMBOL_BINDING (name);
-  if (b && !b->invisible)
-    {
-      maybe_record_typedef_use (b->decl);
-      return b->decl;
-    }
-  return 0;
-}
-
-/* Similar to `lookup_name' but look only at the indicated scope.  */
-
-static tree
-lookup_name_in_scope (tree name, struct c_scope *scope)
-{
-  struct c_binding *b;
-
-  for (b = I_SYMBOL_BINDING (name); b; b = b->shadowed)
-    if (B_IN_SCOPE (b, scope))
-      return b->decl;
-  return 0;
-}
-\f
-/* Create the predefined scalar types of C,
-   and some nodes representing standard constants (0, 1, (void *) 0).
-   Initialize the global scope.
-   Make definitions for built-in primitive functions.  */
-
-void
-c_init_decl_processing (void)
-{
-  location_t save_loc = input_location;
-
-  /* Initialize reserved words for parser.  */
-  c_parse_init ();
-
-  current_function_decl = 0;
-
-  gcc_obstack_init (&parser_obstack);
-
-  /* Make the externals scope.  */
-  push_scope ();
-  external_scope = current_scope;
-
-  /* Declarations from c_common_nodes_and_builtins must not be associated
-     with this input file, lest we get differences between using and not
-     using preprocessed headers.  */
-  input_location = BUILTINS_LOCATION;
-
-  c_common_nodes_and_builtins ();
-
-  /* In C, comparisons and TRUTH_* expressions have type int.  */
-  truthvalue_type_node = integer_type_node;
-  truthvalue_true_node = integer_one_node;
-  truthvalue_false_node = integer_zero_node;
-
-  /* Even in C99, which has a real boolean type.  */
-  pushdecl (build_decl (UNKNOWN_LOCATION, TYPE_DECL, get_identifier ("_Bool"),
-                       boolean_type_node));
-
-  input_location = save_loc;
-
-  pedantic_lvalues = true;
-
-  make_fname_decl = c_make_fname_decl;
-  start_fname_decls ();
-}
-
-/* Create the VAR_DECL at LOC for __FUNCTION__ etc. ID is the name to
-   give the decl, NAME is the initialization string and TYPE_DEP
-   indicates whether NAME depended on the type of the function.  As we
-   don't yet implement delayed emission of static data, we mark the
-   decl as emitted so it is not placed in the output.  Anything using
-   it must therefore pull out the STRING_CST initializer directly.
-   FIXME.  */
-
-static tree
-c_make_fname_decl (location_t loc, tree id, int type_dep)
-{
-  const char *name = fname_as_string (type_dep);
-  tree decl, type, init;
-  size_t length = strlen (name);
-
-  type = build_array_type (char_type_node,
-                          build_index_type (size_int (length)));
-  type = c_build_qualified_type (type, TYPE_QUAL_CONST);
-
-  decl = build_decl (loc, VAR_DECL, id, type);
-
-  TREE_STATIC (decl) = 1;
-  TREE_READONLY (decl) = 1;
-  DECL_ARTIFICIAL (decl) = 1;
-
-  init = build_string (length + 1, name);
-  free (CONST_CAST (char *, name));
-  TREE_TYPE (init) = type;
-  DECL_INITIAL (decl) = init;
-
-  TREE_USED (decl) = 1;
-
-  if (current_function_decl
-      /* For invalid programs like this:
-
-         void foo()
-         const char* p = __FUNCTION__;
-
-        the __FUNCTION__ is believed to appear in K&R style function
-        parameter declarator.  In that case we still don't have
-        function_scope.  */
-      && (!seen_error () || current_function_scope))
-    {
-      DECL_CONTEXT (decl) = current_function_decl;
-      bind (id, decl, current_function_scope,
-           /*invisible=*/false, /*nested=*/false, UNKNOWN_LOCATION);
-    }
-
-  finish_decl (decl, loc, init, NULL_TREE, NULL_TREE);
-
-  return decl;
-}
-
-tree
-c_builtin_function (tree decl)
-{
-  tree type = TREE_TYPE (decl);
-  tree   id = DECL_NAME (decl);
-
-  const char *name = IDENTIFIER_POINTER (id);
-  C_DECL_BUILTIN_PROTOTYPE (decl) = prototype_p (type);
-
-  /* Should never be called on a symbol with a preexisting meaning.  */
-  gcc_assert (!I_SYMBOL_BINDING (id));
-
-  bind (id, decl, external_scope, /*invisible=*/true, /*nested=*/false,
-       UNKNOWN_LOCATION);
-
-  /* Builtins in the implementation namespace are made visible without
-     needing to be explicitly declared.  See push_file_scope.  */
-  if (name[0] == '_' && (name[1] == '_' || ISUPPER (name[1])))
-    {
-      DECL_CHAIN (decl) = visible_builtins;
-      visible_builtins = decl;
-    }
-
-  return decl;
-}
-
-tree
-c_builtin_function_ext_scope (tree decl)
-{
-  tree type = TREE_TYPE (decl);
-  tree   id = DECL_NAME (decl);
-
-  const char *name = IDENTIFIER_POINTER (id);
-  C_DECL_BUILTIN_PROTOTYPE (decl) = prototype_p (type);
-
-  /* Should never be called on a symbol with a preexisting meaning.  */
-  gcc_assert (!I_SYMBOL_BINDING (id));
-
-  bind (id, decl, external_scope, /*invisible=*/false, /*nested=*/false,
-       UNKNOWN_LOCATION);
-
-  /* Builtins in the implementation namespace are made visible without
-     needing to be explicitly declared.  See push_file_scope.  */
-  if (name[0] == '_' && (name[1] == '_' || ISUPPER (name[1])))
-    {
-      DECL_CHAIN (decl) = visible_builtins;
-      visible_builtins = decl;
-    }
-
-  return decl;
-}
-\f
-/* Called when a declaration is seen that contains no names to declare.
-   If its type is a reference to a structure, union or enum inherited
-   from a containing scope, shadow that tag name for the current scope
-   with a forward reference.
-   If its type defines a new named structure or union
-   or defines an enum, it is valid but we need not do anything here.
-   Otherwise, it is an error.  */
-
-void
-shadow_tag (const struct c_declspecs *declspecs)
-{
-  shadow_tag_warned (declspecs, 0);
-}
-
-/* WARNED is 1 if we have done a pedwarn, 2 if we have done a warning,
-   but no pedwarn.  */
-void
-shadow_tag_warned (const struct c_declspecs *declspecs, int warned)
-{
-  bool found_tag = false;
-
-  if (declspecs->type && !declspecs->default_int_p && !declspecs->typedef_p)
-    {
-      tree value = declspecs->type;
-      enum tree_code code = TREE_CODE (value);
-
-      if (code == RECORD_TYPE || code == UNION_TYPE || code == ENUMERAL_TYPE)
-       /* Used to test also that TYPE_SIZE (value) != 0.
-          That caused warning for `struct foo;' at top level in the file.  */
-       {
-         tree name = TYPE_NAME (value);
-         tree t;
-
-         found_tag = true;
-
-         if (declspecs->restrict_p)
-           {
-             error ("invalid use of %<restrict%>");
-             warned = 1;
-           }
-
-         if (name == 0)
-           {
-             if (warned != 1 && code != ENUMERAL_TYPE)
-               /* Empty unnamed enum OK */
-               {
-                 pedwarn (input_location, 0,
-                          "unnamed struct/union that defines no instances");
-                 warned = 1;
-               }
-           }
-         else if (declspecs->typespec_kind != ctsk_tagdef
-                   && declspecs->typespec_kind != ctsk_tagfirstref
-                  && declspecs->storage_class != csc_none)
-           {
-             if (warned != 1)
-               pedwarn (input_location, 0,
-                        "empty declaration with storage class specifier "
-                        "does not redeclare tag");
-             warned = 1;
-             pending_xref_error ();
-           }
-         else if (declspecs->typespec_kind != ctsk_tagdef
-                   && declspecs->typespec_kind != ctsk_tagfirstref
-                  && (declspecs->const_p
-                      || declspecs->volatile_p
-                      || declspecs->restrict_p
-                      || declspecs->address_space))
-           {
-             if (warned != 1)
-               pedwarn (input_location, 0,
-                        "empty declaration with type qualifier "
-                         "does not redeclare tag");
-             warned = 1;
-             pending_xref_error ();
-           }
-         else if (declspecs->typespec_kind != ctsk_tagdef
-                   && declspecs->typespec_kind != ctsk_tagfirstref
-                  && declspecs->alignas_p)
-           {
-             if (warned != 1)
-               pedwarn (input_location, 0,
-                        "empty declaration with %<_Alignas%> "
-                         "does not redeclare tag");
-             warned = 1;
-             pending_xref_error ();
-           }
-         else
-           {
-             pending_invalid_xref = 0;
-             t = lookup_tag (code, name, 1, NULL);
-
-             if (t == 0)
-               {
-                 t = make_node (code);
-                 pushtag (input_location, name, t);
-               }
-           }
-       }
-      else
-       {
-         if (warned != 1 && !in_system_header)
-           {
-             pedwarn (input_location, 0,
-                      "useless type name in empty declaration");
-             warned = 1;
-           }
-       }
-    }
-  else if (warned != 1 && !in_system_header && declspecs->typedef_p)
-    {
-      pedwarn (input_location, 0, "useless type name in empty declaration");
-      warned = 1;
-    }
-
-  pending_invalid_xref = 0;
-
-  if (declspecs->inline_p)
-    {
-      error ("%<inline%> in empty declaration");
-      warned = 1;
-    }
-
-  if (declspecs->noreturn_p)
-    {
-      error ("%<_Noreturn%> in empty declaration");
-      warned = 1;
-    }
-
-  if (current_scope == file_scope && declspecs->storage_class == csc_auto)
-    {
-      error ("%<auto%> in file-scope empty declaration");
-      warned = 1;
-    }
-
-  if (current_scope == file_scope && declspecs->storage_class == csc_register)
-    {
-      error ("%<register%> in file-scope empty declaration");
-      warned = 1;
-    }
-
-  if (!warned && !in_system_header && declspecs->storage_class != csc_none)
-    {
-      warning (0, "useless storage class specifier in empty declaration");
-      warned = 2;
-    }
-
-  if (!warned && !in_system_header && declspecs->thread_p)
-    {
-      warning (0, "useless %<__thread%> in empty declaration");
-      warned = 2;
-    }
-
-  if (!warned && !in_system_header && (declspecs->const_p
-                                      || declspecs->volatile_p
-                                      || declspecs->restrict_p
-                                      || declspecs->address_space))
-    {
-      warning (0, "useless type qualifier in empty declaration");
-      warned = 2;
-    }
-
-  if (!warned && !in_system_header && declspecs->alignas_p)
-    {
-      warning (0, "useless %<_Alignas%> in empty declaration");
-      warned = 2;
-    }
-
-  if (warned != 1)
-    {
-      if (!found_tag)
-       pedwarn (input_location, 0, "empty declaration");
-    }
-}
-\f
-
-/* Return the qualifiers from SPECS as a bitwise OR of TYPE_QUAL_*
-   bits.  SPECS represents declaration specifiers that the grammar
-   only permits to contain type qualifiers and attributes.  */
-
-int
-quals_from_declspecs (const struct c_declspecs *specs)
-{
-  int quals = ((specs->const_p ? TYPE_QUAL_CONST : 0)
-              | (specs->volatile_p ? TYPE_QUAL_VOLATILE : 0)
-              | (specs->restrict_p ? TYPE_QUAL_RESTRICT : 0)
-              | (ENCODE_QUAL_ADDR_SPACE (specs->address_space)));
-  gcc_assert (!specs->type
-             && !specs->decl_attr
-             && specs->typespec_word == cts_none
-             && specs->storage_class == csc_none
-             && !specs->typedef_p
-             && !specs->explicit_signed_p
-             && !specs->deprecated_p
-             && !specs->long_p
-             && !specs->long_long_p
-             && !specs->short_p
-             && !specs->signed_p
-             && !specs->unsigned_p
-             && !specs->complex_p
-             && !specs->inline_p
-             && !specs->noreturn_p
-             && !specs->thread_p);
-  return quals;
-}
-
-/* Construct an array declarator.  LOC is the location of the
-   beginning of the array (usually the opening brace).  EXPR is the
-   expression inside [], or NULL_TREE.  QUALS are the type qualifiers
-   inside the [] (to be applied to the pointer to which a parameter
-   array is converted).  STATIC_P is true if "static" is inside the
-   [], false otherwise.  VLA_UNSPEC_P is true if the array is [*], a
-   VLA of unspecified length which is nevertheless a complete type,
-   false otherwise.  The field for the contained declarator is left to
-   be filled in by set_array_declarator_inner.  */
-
-struct c_declarator *
-build_array_declarator (location_t loc,
-                       tree expr, struct c_declspecs *quals, bool static_p,
-                       bool vla_unspec_p)
-{
-  struct c_declarator *declarator = XOBNEW (&parser_obstack,
-                                           struct c_declarator);
-  declarator->id_loc = loc;
-  declarator->kind = cdk_array;
-  declarator->declarator = 0;
-  declarator->u.array.dimen = expr;
-  if (quals)
-    {
-      declarator->u.array.attrs = quals->attrs;
-      declarator->u.array.quals = quals_from_declspecs (quals);
-    }
-  else
-    {
-      declarator->u.array.attrs = NULL_TREE;
-      declarator->u.array.quals = 0;
-    }
-  declarator->u.array.static_p = static_p;
-  declarator->u.array.vla_unspec_p = vla_unspec_p;
-  if (!flag_isoc99)
-    {
-      if (static_p || quals != NULL)
-       pedwarn (loc, OPT_Wpedantic,
-                "ISO C90 does not support %<static%> or type "
-                "qualifiers in parameter array declarators");
-      if (vla_unspec_p)
-       pedwarn (loc, OPT_Wpedantic,
-                "ISO C90 does not support %<[*]%> array declarators");
-    }
-  if (vla_unspec_p)
-    {
-      if (!current_scope->parm_flag)
-       {
-         /* C99 6.7.5.2p4 */
-         error_at (loc, "%<[*]%> not allowed in other than "
-                   "function prototype scope");
-         declarator->u.array.vla_unspec_p = false;
-         return NULL;
-       }
-      current_scope->had_vla_unspec = true;
-    }
-  return declarator;
-}
-
-/* Set the contained declarator of an array declarator.  DECL is the
-   declarator, as constructed by build_array_declarator; INNER is what
-   appears on the left of the [].  */
-
-struct c_declarator *
-set_array_declarator_inner (struct c_declarator *decl,
-                           struct c_declarator *inner)
-{
-  decl->declarator = inner;
-  return decl;
-}
-
-/* INIT is a constructor that forms DECL's initializer.  If the final
-   element initializes a flexible array field, add the size of that
-   initializer to DECL's size.  */
-
-static void
-add_flexible_array_elts_to_size (tree decl, tree init)
-{
-  tree elt, type;
-
-  if (VEC_empty (constructor_elt, CONSTRUCTOR_ELTS (init)))
-    return;
-
-  elt = VEC_last (constructor_elt, CONSTRUCTOR_ELTS (init))->value;
-  type = TREE_TYPE (elt);
-  if (TREE_CODE (type) == ARRAY_TYPE
-      && TYPE_SIZE (type) == NULL_TREE
-      && TYPE_DOMAIN (type) != NULL_TREE
-      && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL_TREE)
-    {
-      complete_array_type (&type, elt, false);
-      DECL_SIZE (decl)
-       = size_binop (PLUS_EXPR, DECL_SIZE (decl), TYPE_SIZE (type));
-      DECL_SIZE_UNIT (decl)
-       = size_binop (PLUS_EXPR, DECL_SIZE_UNIT (decl), TYPE_SIZE_UNIT (type));
-    }
-}
-\f
-/* Decode a "typename", such as "int **", returning a ..._TYPE node.
-   Set *EXPR, if EXPR not NULL, to any expression to be evaluated
-   before the type name, and set *EXPR_CONST_OPERANDS, if
-   EXPR_CONST_OPERANDS not NULL, to indicate whether the type name may
-   appear in a constant expression.  */
-
-tree
-groktypename (struct c_type_name *type_name, tree *expr,
-             bool *expr_const_operands)
-{
-  tree type;
-  tree attrs = type_name->specs->attrs;
-
-  type_name->specs->attrs = NULL_TREE;
-
-  type = grokdeclarator (type_name->declarator, type_name->specs, TYPENAME,
-                        false, NULL, &attrs, expr, expr_const_operands,
-                        DEPRECATED_NORMAL);
-
-  /* Apply attributes.  */
-  decl_attributes (&type, attrs, 0);
-
-  return type;
-}
-
-/* Decode a declarator in an ordinary declaration or data definition.
-   This is called as soon as the type information and variable name
-   have been parsed, before parsing the initializer if any.
-   Here we create the ..._DECL node, fill in its type,
-   and put it on the list of decls for the current context.
-   The ..._DECL node is returned as the value.
-
-   Exception: for arrays where the length is not specified,
-   the type is left null, to be filled in by `finish_decl'.
-
-   Function definitions do not come here; they go to start_function
-   instead.  However, external and forward declarations of functions
-   do go through here.  Structure field declarations are done by
-   grokfield and not through here.  */
-
-tree
-start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs,
-           bool initialized, tree attributes)
-{
-  tree decl;
-  tree tem;
-  tree expr = NULL_TREE;
-  enum deprecated_states deprecated_state = DEPRECATED_NORMAL;
-
-  /* An object declared as __attribute__((deprecated)) suppresses
-     warnings of uses of other deprecated items.  */
-  if (lookup_attribute ("deprecated", attributes))
-    deprecated_state = DEPRECATED_SUPPRESS;
-
-  decl = grokdeclarator (declarator, declspecs,
-                        NORMAL, initialized, NULL, &attributes, &expr, NULL,
-                        deprecated_state);
-  if (!decl)
-    return 0;
-
-  if (expr)
-    add_stmt (fold_convert (void_type_node, expr));
-
-  if (TREE_CODE (decl) != FUNCTION_DECL && MAIN_NAME_P (DECL_NAME (decl)))
-    warning (OPT_Wmain, "%q+D is usually a function", decl);
-
-  if (initialized)
-    /* Is it valid for this decl to have an initializer at all?
-       If not, set INITIALIZED to zero, which will indirectly
-       tell 'finish_decl' to ignore the initializer once it is parsed.  */
-    switch (TREE_CODE (decl))
-      {
-      case TYPE_DECL:
-       error ("typedef %qD is initialized (use __typeof__ instead)", decl);
-       initialized = 0;
-       break;
-
-      case FUNCTION_DECL:
-       error ("function %qD is initialized like a variable", decl);
-       initialized = 0;
-       break;
-
-      case PARM_DECL:
-       /* DECL_INITIAL in a PARM_DECL is really DECL_ARG_TYPE.  */
-       error ("parameter %qD is initialized", decl);
-       initialized = 0;
-       break;
-
-      default:
-       /* Don't allow initializations for incomplete types except for
-          arrays which might be completed by the initialization.  */
-
-       /* This can happen if the array size is an undefined macro.
-          We already gave a warning, so we don't need another one.  */
-       if (TREE_TYPE (decl) == error_mark_node)
-         initialized = 0;
-       else if (COMPLETE_TYPE_P (TREE_TYPE (decl)))
-         {
-           /* A complete type is ok if size is fixed.  */
-
-           if (TREE_CODE (TYPE_SIZE (TREE_TYPE (decl))) != INTEGER_CST
-               || C_DECL_VARIABLE_SIZE (decl))
-             {
-               error ("variable-sized object may not be initialized");
-               initialized = 0;
-             }
-         }
-       else if (TREE_CODE (TREE_TYPE (decl)) != ARRAY_TYPE)
-         {
-           error ("variable %qD has initializer but incomplete type", decl);
-           initialized = 0;
-         }
-       else if (C_DECL_VARIABLE_SIZE (decl))
-         {
-           /* Although C99 is unclear about whether incomplete arrays
-              of VLAs themselves count as VLAs, it does not make
-              sense to permit them to be initialized given that
-              ordinary VLAs may not be initialized.  */
-           error ("variable-sized object may not be initialized");
-           initialized = 0;
-         }
-      }
-
-  if (initialized)
-    {
-      if (current_scope == file_scope)
-       TREE_STATIC (decl) = 1;
-
-      /* Tell 'pushdecl' this is an initialized decl
-        even though we don't yet have the initializer expression.
-        Also tell 'finish_decl' it may store the real initializer.  */
-      DECL_INITIAL (decl) = error_mark_node;
-    }
-
-  /* If this is a function declaration, write a record describing it to the
-     prototypes file (if requested).  */
-
-  if (TREE_CODE (decl) == FUNCTION_DECL)
-    gen_aux_info_record (decl, 0, 0, prototype_p (TREE_TYPE (decl)));
-
-  /* ANSI specifies that a tentative definition which is not merged with
-     a non-tentative definition behaves exactly like a definition with an
-     initializer equal to zero.  (Section 3.7.2)
-
-     -fno-common gives strict ANSI behavior, though this tends to break
-     a large body of code that grew up without this rule.
-
-     Thread-local variables are never common, since there's no entrenched
-     body of code to break, and it allows more efficient variable references
-     in the presence of dynamic linking.  */
-
-  if (TREE_CODE (decl) == VAR_DECL
-      && !initialized
-      && TREE_PUBLIC (decl)
-      && !DECL_THREAD_LOCAL_P (decl)
-      && !flag_no_common)
-    DECL_COMMON (decl) = 1;
-
-  /* Set attributes here so if duplicate decl, will have proper attributes.  */
-  decl_attributes (&decl, attributes, 0);
-
-  /* Handle gnu_inline attribute.  */
-  if (declspecs->inline_p
-      && !flag_gnu89_inline
-      && TREE_CODE (decl) == FUNCTION_DECL
-      && (lookup_attribute ("gnu_inline", DECL_ATTRIBUTES (decl))
-         || current_function_decl))
-    {
-      if (declspecs->storage_class == csc_auto && current_scope != file_scope)
-       ;
-      else if (declspecs->storage_class != csc_static)
-       DECL_EXTERNAL (decl) = !DECL_EXTERNAL (decl);
-    }
-
-  if (TREE_CODE (decl) == FUNCTION_DECL
-      && targetm.calls.promote_prototypes (TREE_TYPE (decl)))
-    {
-      struct c_declarator *ce = declarator;
-
-      if (ce->kind == cdk_pointer)
-       ce = declarator->declarator;
-      if (ce->kind == cdk_function)
-       {
-         tree args = ce->u.arg_info->parms;
-         for (; args; args = DECL_CHAIN (args))
-           {
-             tree type = TREE_TYPE (args);
-             if (type && INTEGRAL_TYPE_P (type)
-                 && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
-               DECL_ARG_TYPE (args) = integer_type_node;
-           }
-       }
-    }
-
-  if (TREE_CODE (decl) == FUNCTION_DECL
-      && DECL_DECLARED_INLINE_P (decl)
-      && DECL_UNINLINABLE (decl)
-      && lookup_attribute ("noinline", DECL_ATTRIBUTES (decl)))
-    warning (OPT_Wattributes, "inline function %q+D given attribute noinline",
-            decl);
-
-  /* C99 6.7.4p3: An inline definition of a function with external
-     linkage shall not contain a definition of a modifiable object
-     with static storage duration...  */
-  if (TREE_CODE (decl) == VAR_DECL
-      && current_scope != file_scope
-      && TREE_STATIC (decl)
-      && !TREE_READONLY (decl)
-      && DECL_DECLARED_INLINE_P (current_function_decl)
-      && DECL_EXTERNAL (current_function_decl))
-    record_inline_static (input_location, current_function_decl,
-                         decl, csi_modifiable);
-
-  if (c_dialect_objc () 
-      && (TREE_CODE (decl) == VAR_DECL
-          || TREE_CODE (decl) == FUNCTION_DECL))
-      objc_check_global_decl (decl);
-
-  /* Add this decl to the current scope.
-     TEM may equal DECL or it may be a previous decl of the same name.  */
-  tem = pushdecl (decl);
-
-  if (initialized && DECL_EXTERNAL (tem))
-    {
-      DECL_EXTERNAL (tem) = 0;
-      TREE_STATIC (tem) = 1;
-    }
-
-  return tem;
-}
-
-/* Subroutine of finish_decl. TYPE is the type of an uninitialized object
-   DECL or the non-array element type if DECL is an uninitialized array.
-   If that type has a const member, diagnose this. */
-
-static void
-diagnose_uninitialized_cst_member (tree decl, tree type)
-{
-  tree field;
-  for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
-    {
-      tree field_type;
-      if (TREE_CODE (field) != FIELD_DECL)
-       continue;
-      field_type = strip_array_types (TREE_TYPE (field));
-
-      if (TYPE_QUALS (field_type) & TYPE_QUAL_CONST)
-       {
-         warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wc___compat,
-                     "uninitialized const member in %qT is invalid in C++",
-                     strip_array_types (TREE_TYPE (decl)));
-         inform (DECL_SOURCE_LOCATION (field), "%qD should be initialized", field);
-       }
-
-      if (TREE_CODE (field_type) == RECORD_TYPE
-         || TREE_CODE (field_type) == UNION_TYPE)
-       diagnose_uninitialized_cst_member (decl, field_type);
-    }
-}
-
-/* Finish processing of a declaration;
-   install its initial value.
-   If ORIGTYPE is not NULL_TREE, it is the original type of INIT.
-   If the length of an array type is not known before,
-   it must be determined now, from the initial value, or it is an error.
-
-   INIT_LOC is the location of the initial value.  */
-
-void
-finish_decl (tree decl, location_t init_loc, tree init,
-            tree origtype, tree asmspec_tree)
-{
-  tree type;
-  bool was_incomplete = (DECL_SIZE (decl) == 0);
-  const char *asmspec = 0;
-
-  /* If a name was specified, get the string.  */
-  if ((TREE_CODE (decl) == FUNCTION_DECL || TREE_CODE (decl) == VAR_DECL)
-      && DECL_FILE_SCOPE_P (decl))
-    asmspec_tree = maybe_apply_renaming_pragma (decl, asmspec_tree);
-  if (asmspec_tree)
-    asmspec = TREE_STRING_POINTER (asmspec_tree);
-
-  if (TREE_CODE (decl) == VAR_DECL
-      && TREE_STATIC (decl)
-      && global_bindings_p ())
-    /* So decl is a global variable. Record the types it uses
-       so that we can decide later to emit debug info for them.  */
-    record_types_used_by_current_var_decl (decl);
-
-  /* If `start_decl' didn't like having an initialization, ignore it now.  */
-  if (init != 0 && DECL_INITIAL (decl) == 0)
-    init = 0;
-
-  /* Don't crash if parm is initialized.  */
-  if (TREE_CODE (decl) == PARM_DECL)
-    init = 0;
-
-  if (init)
-    store_init_value (init_loc, decl, init, origtype);
-
-  if (c_dialect_objc () && (TREE_CODE (decl) == VAR_DECL
-                           || TREE_CODE (decl) == FUNCTION_DECL
-                           || TREE_CODE (decl) == FIELD_DECL))
-    objc_check_decl (decl);
-
-  type = TREE_TYPE (decl);
-
-  /* Deduce size of array from initialization, if not already known.  */
-  if (TREE_CODE (type) == ARRAY_TYPE
-      && TYPE_DOMAIN (type) == 0
-      && TREE_CODE (decl) != TYPE_DECL)
-    {
-      bool do_default
-       = (TREE_STATIC (decl)
-          /* Even if pedantic, an external linkage array
-             may have incomplete type at first.  */
-          ? pedantic && !TREE_PUBLIC (decl)
-          : !DECL_EXTERNAL (decl));
-      int failure
-       = complete_array_type (&TREE_TYPE (decl), DECL_INITIAL (decl),
-                              do_default);
-
-      /* Get the completed type made by complete_array_type.  */
-      type = TREE_TYPE (decl);
-
-      switch (failure)
-       {
-       case 1:
-         error ("initializer fails to determine size of %q+D", decl);
-         break;
-
-       case 2:
-         if (do_default)
-           error ("array size missing in %q+D", decl);
-         /* If a `static' var's size isn't known,
-            make it extern as well as static, so it does not get
-            allocated.
-            If it is not `static', then do not mark extern;
-            finish_incomplete_decl will give it a default size
-            and it will get allocated.  */
-         else if (!pedantic && TREE_STATIC (decl) && !TREE_PUBLIC (decl))
-           DECL_EXTERNAL (decl) = 1;
-         break;
-
-       case 3:
-         error ("zero or negative size array %q+D", decl);
-         break;
-
-       case 0:
-         /* For global variables, update the copy of the type that
-            exists in the binding.  */
-         if (TREE_PUBLIC (decl))
-           {
-             struct c_binding *b_ext = I_SYMBOL_BINDING (DECL_NAME (decl));
-             while (b_ext && !B_IN_EXTERNAL_SCOPE (b_ext))
-               b_ext = b_ext->shadowed;
-             if (b_ext)
-               {
-                 if (b_ext->u.type && comptypes (b_ext->u.type, type))
-                   b_ext->u.type = composite_type (b_ext->u.type, type);
-                 else
-                   b_ext->u.type = type;
-               }
-           }
-         break;
-
-       default:
-         gcc_unreachable ();
-       }
-
-      if (DECL_INITIAL (decl))
-       TREE_TYPE (DECL_INITIAL (decl)) = type;
-
-      relayout_decl (decl);
-    }
-
-  if (TREE_CODE (decl) == VAR_DECL)
-    {
-      if (init && TREE_CODE (init) == CONSTRUCTOR)
-       add_flexible_array_elts_to_size (decl, init);
-
-      if (DECL_SIZE (decl) == 0 && TREE_TYPE (decl) != error_mark_node
-         && COMPLETE_TYPE_P (TREE_TYPE (decl)))
-       layout_decl (decl, 0);
-
-      if (DECL_SIZE (decl) == 0
-         /* Don't give an error if we already gave one earlier.  */
-         && TREE_TYPE (decl) != error_mark_node
-         && (TREE_STATIC (decl)
-             /* A static variable with an incomplete type
-                is an error if it is initialized.
-                Also if it is not file scope.
-                Otherwise, let it through, but if it is not `extern'
-                then it may cause an error message later.  */
-             ? (DECL_INITIAL (decl) != 0
-                || !DECL_FILE_SCOPE_P (decl))
-             /* An automatic variable with an incomplete type
-                is an error.  */
-             : !DECL_EXTERNAL (decl)))
-        {
-          error ("storage size of %q+D isn%'t known", decl);
-          TREE_TYPE (decl) = error_mark_node;
-        }
-
-      if ((DECL_EXTERNAL (decl) || TREE_STATIC (decl))
-         && DECL_SIZE (decl) != 0)
-       {
-         if (TREE_CODE (DECL_SIZE (decl)) == INTEGER_CST)
-           constant_expression_warning (DECL_SIZE (decl));
-         else
-           {
-             error ("storage size of %q+D isn%'t constant", decl);
-             TREE_TYPE (decl) = error_mark_node;
-           }
-       }
-
-      if (TREE_USED (type))
-       {
-         TREE_USED (decl) = 1;
-         DECL_READ_P (decl) = 1;
-       }
-    }
-
-  /* If this is a function and an assembler name is specified, reset DECL_RTL
-     so we can give it its new name.  Also, update builtin_decl if it
-     was a normal built-in.  */
-  if (TREE_CODE (decl) == FUNCTION_DECL && asmspec)
-    {
-      if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL)
-       set_builtin_user_assembler_name (decl, asmspec);
-      set_user_assembler_name (decl, asmspec);
-    }
-
-  /* If #pragma weak was used, mark the decl weak now.  */
-  maybe_apply_pragma_weak (decl);
-
-  /* Output the assembler code and/or RTL code for variables and functions,
-     unless the type is an undefined structure or union.
-     If not, it will get done when the type is completed.  */
-
-  if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL)
-    {
-      /* Determine the ELF visibility.  */
-      if (TREE_PUBLIC (decl))
-       c_determine_visibility (decl);
-
-      /* This is a no-op in c-lang.c or something real in objc-act.c.  */
-      if (c_dialect_objc ())
-       objc_check_decl (decl);
-
-      if (asmspec)
-       {
-         /* If this is not a static variable, issue a warning.
-            It doesn't make any sense to give an ASMSPEC for an
-            ordinary, non-register local variable.  Historically,
-            GCC has accepted -- but ignored -- the ASMSPEC in
-            this case.  */
-         if (!DECL_FILE_SCOPE_P (decl)
-             && TREE_CODE (decl) == VAR_DECL
-             && !C_DECL_REGISTER (decl)
-             && !TREE_STATIC (decl))
-           warning (0, "ignoring asm-specifier for non-static local "
-                    "variable %q+D", decl);
-         else
-           set_user_assembler_name (decl, asmspec);
-       }
-
-      if (DECL_FILE_SCOPE_P (decl))
-       {
-         if (DECL_INITIAL (decl) == NULL_TREE
-             || DECL_INITIAL (decl) == error_mark_node)
-           /* Don't output anything
-              when a tentative file-scope definition is seen.
-              But at end of compilation, do output code for them.  */
-           DECL_DEFER_OUTPUT (decl) = 1;
-         if (asmspec && C_DECL_REGISTER (decl))
-           DECL_HARD_REGISTER (decl) = 1;
-         rest_of_decl_compilation (decl, true, 0);
-       }
-      else
-       {
-         /* In conjunction with an ASMSPEC, the `register'
-            keyword indicates that we should place the variable
-            in a particular register.  */
-         if (asmspec && C_DECL_REGISTER (decl))
-           {
-             DECL_HARD_REGISTER (decl) = 1;
-             /* This cannot be done for a structure with volatile
-                fields, on which DECL_REGISTER will have been
-                reset.  */
-             if (!DECL_REGISTER (decl))
-               error ("cannot put object with volatile field into register");
-           }
-
-         if (TREE_CODE (decl) != FUNCTION_DECL)
-           {
-             /* If we're building a variable sized type, and we might be
-                reachable other than via the top of the current binding
-                level, then create a new BIND_EXPR so that we deallocate
-                the object at the right time.  */
-             /* Note that DECL_SIZE can be null due to errors.  */
-             if (DECL_SIZE (decl)
-                 && !TREE_CONSTANT (DECL_SIZE (decl))
-                 && STATEMENT_LIST_HAS_LABEL (cur_stmt_list))
-               {
-                 tree bind;
-                 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
-                 TREE_SIDE_EFFECTS (bind) = 1;
-                 add_stmt (bind);
-                 BIND_EXPR_BODY (bind) = push_stmt_list ();
-               }
-             add_stmt (build_stmt (DECL_SOURCE_LOCATION (decl),
-                                   DECL_EXPR, decl));
-           }
-       }
-
-
-      if (!DECL_FILE_SCOPE_P (decl))
-       {
-         /* Recompute the RTL of a local array now
-            if it used to be an incomplete type.  */
-         if (was_incomplete
-             && !TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
-           {
-             /* If we used it already as memory, it must stay in memory.  */
-             TREE_ADDRESSABLE (decl) = TREE_USED (decl);
-             /* If it's still incomplete now, no init will save it.  */
-             if (DECL_SIZE (decl) == 0)
-               DECL_INITIAL (decl) = 0;
-           }
-       }
-    }
-
-  if (TREE_CODE (decl) == TYPE_DECL)
-    {
-      if (!DECL_FILE_SCOPE_P (decl)
-         && variably_modified_type_p (TREE_TYPE (decl), NULL_TREE))
-       add_stmt (build_stmt (DECL_SOURCE_LOCATION (decl), DECL_EXPR, decl));
-
-      rest_of_decl_compilation (decl, DECL_FILE_SCOPE_P (decl), 0);
-    }
-
-  /* Install a cleanup (aka destructor) if one was given.  */
-  if (TREE_CODE (decl) == VAR_DECL && !TREE_STATIC (decl))
-    {
-      tree attr = lookup_attribute ("cleanup", DECL_ATTRIBUTES (decl));
-      if (attr)
-       {
-         tree cleanup_id = TREE_VALUE (TREE_VALUE (attr));
-         tree cleanup_decl = lookup_name (cleanup_id);
-         tree cleanup;
-         VEC(tree,gc) *vec;
-
-         /* Build "cleanup(&decl)" for the destructor.  */
-         cleanup = build_unary_op (input_location, ADDR_EXPR, decl, 0);
-         vec = VEC_alloc (tree, gc, 1);
-         VEC_quick_push (tree, vec, cleanup);
-         cleanup = build_function_call_vec (DECL_SOURCE_LOCATION (decl),
-                                            cleanup_decl, vec, NULL);
-         VEC_free (tree, gc, vec);
-
-         /* Don't warn about decl unused; the cleanup uses it.  */
-         TREE_USED (decl) = 1;
-         TREE_USED (cleanup_decl) = 1;
-         DECL_READ_P (decl) = 1;
-
-         push_cleanup (decl, cleanup, false);
-       }
-    }
-
-  if (warn_cxx_compat
-      && TREE_CODE (decl) == VAR_DECL
-      && !DECL_EXTERNAL (decl)
-      && DECL_INITIAL (decl) == NULL_TREE)
-    {
-      type = strip_array_types (type);
-      if (TREE_READONLY (decl))
-       warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wc___compat,
-                   "uninitialized const %qD is invalid in C++", decl);
-      else if ((TREE_CODE (type) == RECORD_TYPE
-               || TREE_CODE (type) == UNION_TYPE)
-              && C_TYPE_FIELDS_READONLY (type))
-       diagnose_uninitialized_cst_member (decl, type);
-    }
-
-       invoke_plugin_callbacks (PLUGIN_FINISH_DECL, decl);
-}
-
-/* Given a parsed parameter declaration, decode it into a PARM_DECL.
-   EXPR is NULL or a pointer to an expression that needs to be
-   evaluated for the side effects of array size expressions in the
-   parameters.  */
-
-tree
-grokparm (const struct c_parm *parm, tree *expr)
-{
-  tree attrs = parm->attrs;
-  tree decl = grokdeclarator (parm->declarator, parm->specs, PARM, false,
-                             NULL, &attrs, expr, NULL, DEPRECATED_NORMAL);
-
-  decl_attributes (&decl, attrs, 0);
-
-  return decl;
-}
-
-/* Given a parsed parameter declaration, decode it into a PARM_DECL
-   and push that on the current scope.  EXPR is a pointer to an
-   expression that needs to be evaluated for the side effects of array
-   size expressions in the parameters.  */
-
-void
-push_parm_decl (const struct c_parm *parm, tree *expr)
-{
-  tree attrs = parm->attrs;
-  tree decl;
-
-  decl = grokdeclarator (parm->declarator, parm->specs, PARM, false, NULL,
-                        &attrs, expr, NULL, DEPRECATED_NORMAL);
-  decl_attributes (&decl, attrs, 0);
-
-  decl = pushdecl (decl);
-
-  finish_decl (decl, input_location, NULL_TREE, NULL_TREE, NULL_TREE);
-}
-
-/* Mark all the parameter declarations to date as forward decls.
-   Also diagnose use of this extension.  */
-
-void
-mark_forward_parm_decls (void)
-{
-  struct c_binding *b;
-
-  if (pedantic && !current_scope->warned_forward_parm_decls)
-    {
-      pedwarn (input_location, OPT_Wpedantic,
-              "ISO C forbids forward parameter declarations");
-      current_scope->warned_forward_parm_decls = true;
-    }
-
-  for (b = current_scope->bindings; b; b = b->prev)
-    if (TREE_CODE (b->decl) == PARM_DECL)
-      TREE_ASM_WRITTEN (b->decl) = 1;
-}
-\f
-/* Build a COMPOUND_LITERAL_EXPR.  TYPE is the type given in the compound
-   literal, which may be an incomplete array type completed by the
-   initializer; INIT is a CONSTRUCTOR at LOC that initializes the compound
-   literal.  NON_CONST is true if the initializers contain something
-   that cannot occur in a constant expression.  */
-
-tree
-build_compound_literal (location_t loc, tree type, tree init, bool non_const)
-{
-  /* We do not use start_decl here because we have a type, not a declarator;
-     and do not use finish_decl because the decl should be stored inside
-     the COMPOUND_LITERAL_EXPR rather than added elsewhere as a DECL_EXPR.  */
-  tree decl;
-  tree complit;
-  tree stmt;
-
-  if (type == error_mark_node
-      || init == error_mark_node)
-    return error_mark_node;
-
-  decl = build_decl (loc, VAR_DECL, NULL_TREE, type);
-  DECL_EXTERNAL (decl) = 0;
-  TREE_PUBLIC (decl) = 0;
-  TREE_STATIC (decl) = (current_scope == file_scope);
-  DECL_CONTEXT (decl) = current_function_decl;
-  TREE_USED (decl) = 1;
-  DECL_READ_P (decl) = 1;
-  TREE_TYPE (decl) = type;
-  TREE_READONLY (decl) = (TYPE_READONLY (type)
-                         || (TREE_CODE (type) == ARRAY_TYPE
-                             && TYPE_READONLY (TREE_TYPE (type))));
-  store_init_value (loc, decl, init, NULL_TREE);
-
-  if (TREE_CODE (type) == ARRAY_TYPE && !COMPLETE_TYPE_P (type))
-    {
-      int failure = complete_array_type (&TREE_TYPE (decl),
-                                        DECL_INITIAL (decl), true);
-      gcc_assert (!failure);
-
-      type = TREE_TYPE (decl);
-      TREE_TYPE (DECL_INITIAL (decl)) = type;
-    }
-
-  if (type == error_mark_node || !COMPLETE_TYPE_P (type))
-    {
-      c_incomplete_type_error (NULL_TREE, type);
-      return error_mark_node;
-    }
-
-  stmt = build_stmt (DECL_SOURCE_LOCATION (decl), DECL_EXPR, decl);
-  complit = build1 (COMPOUND_LITERAL_EXPR, type, stmt);
-  TREE_SIDE_EFFECTS (complit) = 1;
-
-  layout_decl (decl, 0);
-
-  if (TREE_STATIC (decl))
-    {
-      /* This decl needs a name for the assembler output.  */
-      set_compound_literal_name (decl);
-      DECL_DEFER_OUTPUT (decl) = 1;
-      DECL_COMDAT (decl) = 1;
-      DECL_ARTIFICIAL (decl) = 1;
-      DECL_IGNORED_P (decl) = 1;
-      pushdecl (decl);
-      rest_of_decl_compilation (decl, 1, 0);
-    }
-
-  if (non_const)
-    {
-      complit = build2 (C_MAYBE_CONST_EXPR, type, NULL, complit);
-      C_MAYBE_CONST_EXPR_NON_CONST (complit) = 1;
-    }
-
-  return complit;
-}
-
-/* Check the type of a compound literal.  Here we just check that it
-   is valid for C++.  */
-
-void
-check_compound_literal_type (location_t loc, struct c_type_name *type_name)
-{
-  if (warn_cxx_compat
-      && (type_name->specs->typespec_kind == ctsk_tagdef
-          || type_name->specs->typespec_kind == ctsk_tagfirstref))
-    warning_at (loc, OPT_Wc___compat,
-               "defining a type in a compound literal is invalid in C++");
-}
-\f
-/* Determine whether TYPE is a structure with a flexible array member,
-   or a union containing such a structure (possibly recursively).  */
-
-static bool
-flexible_array_type_p (tree type)
-{
-  tree x;
-  switch (TREE_CODE (type))
-    {
-    case RECORD_TYPE:
-      x = TYPE_FIELDS (type);
-      if (x == NULL_TREE)
-       return false;
-      while (DECL_CHAIN (x) != NULL_TREE)
-       x = DECL_CHAIN (x);
-      if (TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE
-         && TYPE_SIZE (TREE_TYPE (x)) == NULL_TREE
-         && TYPE_DOMAIN (TREE_TYPE (x)) != NULL_TREE
-         && TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (x))) == NULL_TREE)
-       return true;
-      return false;
-    case UNION_TYPE:
-      for (x = TYPE_FIELDS (type); x != NULL_TREE; x = DECL_CHAIN (x))
-       {
-         if (flexible_array_type_p (TREE_TYPE (x)))
-           return true;
-       }
-      return false;
-    default:
-    return false;
-  }
-}
-\f
-/* Performs sanity checks on the TYPE and WIDTH of the bit-field NAME,
-   replacing with appropriate values if they are invalid.  */
-static void
-check_bitfield_type_and_width (tree *type, tree *width, tree orig_name)
-{
-  tree type_mv;
-  unsigned int max_width;
-  unsigned HOST_WIDE_INT w;
-  const char *name = (orig_name
-                     ? identifier_to_locale (IDENTIFIER_POINTER (orig_name))
-                     : _("<anonymous>"));
-
-  /* Detect and ignore out of range field width and process valid
-     field widths.  */
-  if (!INTEGRAL_TYPE_P (TREE_TYPE (*width)))
-    {
-      error ("bit-field %qs width not an integer constant", name);
-      *width = integer_one_node;
-    }
-  else
-    {
-      if (TREE_CODE (*width) != INTEGER_CST)
-       {
-         *width = c_fully_fold (*width, false, NULL);
-         if (TREE_CODE (*width) == INTEGER_CST)
-           pedwarn (input_location, OPT_Wpedantic,
-                    "bit-field %qs width not an integer constant expression",
-                    name);
-       }
-      if (TREE_CODE (*width) != INTEGER_CST)
-       {
-         error ("bit-field %qs width not an integer constant", name);
-         *width = integer_one_node;
-       }
-      constant_expression_warning (*width);
-      if (tree_int_cst_sgn (*width) < 0)
-       {
-         error ("negative width in bit-field %qs", name);
-         *width = integer_one_node;
-       }
-      else if (integer_zerop (*width) && orig_name)
-       {
-         error ("zero width for bit-field %qs", name);
-         *width = integer_one_node;
-       }
-    }
-
-  /* Detect invalid bit-field type.  */
-  if (TREE_CODE (*type) != INTEGER_TYPE
-      && TREE_CODE (*type) != BOOLEAN_TYPE
-      && TREE_CODE (*type) != ENUMERAL_TYPE)
-    {
-      error ("bit-field %qs has invalid type", name);
-      *type = unsigned_type_node;
-    }
-
-  type_mv = TYPE_MAIN_VARIANT (*type);
-  if (!in_system_header
-      && type_mv != integer_type_node
-      && type_mv != unsigned_type_node
-      && type_mv != boolean_type_node)
-    pedwarn (input_location, OPT_Wpedantic,
-            "type of bit-field %qs is a GCC extension", name);
-
-  max_width = TYPE_PRECISION (*type);
-
-  if (0 < compare_tree_int (*width, max_width))
-    {
-      error ("width of %qs exceeds its type", name);
-      w = max_width;
-      *width = build_int_cst (integer_type_node, w);
-    }
-  else
-    w = tree_low_cst (*width, 1);
-
-  if (TREE_CODE (*type) == ENUMERAL_TYPE)
-    {
-      struct lang_type *lt = TYPE_LANG_SPECIFIC (*type);
-      if (!lt
-         || w < tree_int_cst_min_precision (lt->enum_min, TYPE_UNSIGNED (*type))
-         || w < tree_int_cst_min_precision (lt->enum_max, TYPE_UNSIGNED (*type)))
-       warning (0, "%qs is narrower than values of its type", name);
-    }
-}
-
-\f
-
-/* Print warning about variable length array if necessary.  */
-
-static void
-warn_variable_length_array (tree name, tree size)
-{
-  int const_size = TREE_CONSTANT (size);
-
-  if (!flag_isoc99 && pedantic && warn_vla != 0)
-    {
-      if (const_size)
-       {
-         if (name)
-           pedwarn (input_location, OPT_Wvla,
-                    "ISO C90 forbids array %qE whose size "
-                    "can%'t be evaluated",
-                    name);
-         else
-           pedwarn (input_location, OPT_Wvla, "ISO C90 forbids array whose size "
-                    "can%'t be evaluated");
-       }
-      else
-       {
-         if (name)
-           pedwarn (input_location, OPT_Wvla,
-                    "ISO C90 forbids variable length array %qE",
-                    name);
-         else
-           pedwarn (input_location, OPT_Wvla, "ISO C90 forbids variable length array");
-       }
-    }
-  else if (warn_vla > 0)
-    {
-      if (const_size)
-        {
-         if (name)
-           warning (OPT_Wvla,
-                    "the size of array %qE can"
-                    "%'t be evaluated", name);
-         else
-           warning (OPT_Wvla,
-                    "the size of array can %'t be evaluated");
-       }
-      else
-       {
-         if (name)
-           warning (OPT_Wvla,
-                    "variable length array %qE is used",
-                    name);
-         else
-           warning (OPT_Wvla,
-                    "variable length array is used");
-       }
-    }
-}
-
-/* Given declspecs and a declarator,
-   determine the name and type of the object declared
-   and construct a ..._DECL node for it.
-   (In one case we can return a ..._TYPE node instead.
-    For invalid input we sometimes return 0.)
-
-   DECLSPECS is a c_declspecs structure for the declaration specifiers.
-
-   DECL_CONTEXT says which syntactic context this declaration is in:
-     NORMAL for most contexts.  Make a VAR_DECL or FUNCTION_DECL or TYPE_DECL.
-     FUNCDEF for a function definition.  Like NORMAL but a few different
-      error messages in each case.  Return value may be zero meaning
-      this definition is too screwy to try to parse.
-     PARM for a parameter declaration (either within a function prototype
-      or before a function body).  Make a PARM_DECL, or return void_type_node.
-     TYPENAME if for a typename (in a cast or sizeof).
-      Don't make a DECL node; just return the ..._TYPE node.
-     FIELD for a struct or union field; make a FIELD_DECL.
-   INITIALIZED is true if the decl has an initializer.
-   WIDTH is non-NULL for bit-fields, and is a pointer to an INTEGER_CST node
-   representing the width of the bit-field.
-   DECL_ATTRS points to the list of attributes that should be added to this
-     decl.  Any nested attributes that belong on the decl itself will be
-     added to this list.
-   If EXPR is not NULL, any expressions that need to be evaluated as
-     part of evaluating variably modified types will be stored in *EXPR.
-   If EXPR_CONST_OPERANDS is not NULL, *EXPR_CONST_OPERANDS will be
-     set to indicate whether operands in *EXPR can be used in constant
-     expressions.
-   DEPRECATED_STATE is a deprecated_states value indicating whether
-   deprecation warnings should be suppressed.
-
-   In the TYPENAME case, DECLARATOR is really an absolute declarator.
-   It may also be so in the PARM case, for a prototype where the
-   argument type is specified but not the name.
-
-   This function is where the complicated C meanings of `static'
-   and `extern' are interpreted.  */
-
-static tree
-grokdeclarator (const struct c_declarator *declarator,
-               struct c_declspecs *declspecs,
-               enum decl_context decl_context, bool initialized, tree *width,
-               tree *decl_attrs, tree *expr, bool *expr_const_operands,
-               enum deprecated_states deprecated_state)
-{
-  tree type = declspecs->type;
-  bool threadp = declspecs->thread_p;
-  enum c_storage_class storage_class = declspecs->storage_class;
-  int constp;
-  int restrictp;
-  int volatilep;
-  int type_quals = TYPE_UNQUALIFIED;
-  tree name = NULL_TREE;
-  bool funcdef_flag = false;
-  bool funcdef_syntax = false;
-  bool size_varies = false;
-  tree decl_attr = declspecs->decl_attr;
-  int array_ptr_quals = TYPE_UNQUALIFIED;
-  tree array_ptr_attrs = NULL_TREE;
-  int array_parm_static = 0;
-  bool array_parm_vla_unspec_p = false;
-  tree returned_attrs = NULL_TREE;
-  bool bitfield = width != NULL;
-  tree element_type;
-  struct c_arg_info *arg_info = 0;
-  addr_space_t as1, as2, address_space;
-  location_t loc = UNKNOWN_LOCATION;
-  const char *errmsg;
-  tree expr_dummy;
-  bool expr_const_operands_dummy;
-  enum c_declarator_kind first_non_attr_kind;
-  unsigned int alignas_align = 0;
-
-  if (TREE_CODE (type) == ERROR_MARK)
-    return error_mark_node;
-  if (expr == NULL)
-    expr = &expr_dummy;
-  if (expr_const_operands == NULL)
-    expr_const_operands = &expr_const_operands_dummy;
-
-  *expr = declspecs->expr;
-  *expr_const_operands = declspecs->expr_const_operands;
-
-  if (decl_context == FUNCDEF)
-    funcdef_flag = true, decl_context = NORMAL;
-
-  /* Look inside a declarator for the name being declared
-     and get it as an IDENTIFIER_NODE, for an error message.  */
-  {
-    const struct c_declarator *decl = declarator;
-
-    first_non_attr_kind = cdk_attrs;
-    while (decl)
-      switch (decl->kind)
-       {
-       case cdk_array:
-         loc = decl->id_loc;
-         /* FALL THRU.  */
-
-       case cdk_function:
-       case cdk_pointer:
-         funcdef_syntax = (decl->kind == cdk_function);
-         decl = decl->declarator;
-         if (first_non_attr_kind == cdk_attrs)
-           first_non_attr_kind = decl->kind;
-         break;
-
-       case cdk_attrs:
-         decl = decl->declarator;
-         break;
-
-       case cdk_id:
-         loc = decl->id_loc;
-         if (decl->u.id)
-           name = decl->u.id;
-         if (first_non_attr_kind == cdk_attrs)
-           first_non_attr_kind = decl->kind;
-         decl = 0;
-         break;
-
-       default:
-         gcc_unreachable ();
-       }
-    if (name == 0)
-      {
-       gcc_assert (decl_context == PARM
-                   || decl_context == TYPENAME
-                   || (decl_context == FIELD
-                       && declarator->kind == cdk_id));
-       gcc_assert (!initialized);
-      }
-  }
-
-  /* A function definition's declarator must have the form of
-     a function declarator.  */
-
-  if (funcdef_flag && !funcdef_syntax)
-    return 0;
-
-  /* If this looks like a function definition, make it one,
-     even if it occurs where parms are expected.
-     Then store_parm_decls will reject it and not use it as a parm.  */
-  if (decl_context == NORMAL && !funcdef_flag && current_scope->parm_flag)
-    decl_context = PARM;
-
-  if (declspecs->deprecated_p && deprecated_state != DEPRECATED_SUPPRESS)
-    warn_deprecated_use (declspecs->type, declspecs->decl_attr);
-
-  if ((decl_context == NORMAL || decl_context == FIELD)
-      && current_scope == file_scope
-      && variably_modified_type_p (type, NULL_TREE))
-    {
-      if (name)
-       error_at (loc, "variably modified %qE at file scope", name);
-      else
-       error_at (loc, "variably modified field at file scope");
-      type = integer_type_node;
-    }
-
-  size_varies = C_TYPE_VARIABLE_SIZE (type) != 0;
-
-  /* Diagnose defaulting to "int".  */
-
-  if (declspecs->default_int_p && !in_system_header)
-    {
-      /* Issue a warning if this is an ISO C 99 program or if
-        -Wreturn-type and this is a function, or if -Wimplicit;
-        prefer the former warning since it is more explicit.  */
-      if ((warn_implicit_int || warn_return_type || flag_isoc99)
-         && funcdef_flag)
-       warn_about_return_type = 1;
-      else
-       {
-         if (name)
-           pedwarn_c99 (loc, flag_isoc99 ? 0 : OPT_Wimplicit_int,
-                        "type defaults to %<int%> in declaration of %qE",
-                        name);
-         else
-           pedwarn_c99 (input_location, flag_isoc99 ? 0 : OPT_Wimplicit_int,
-                        "type defaults to %<int%> in type name");
-       }
-    }
-
-  /* Adjust the type if a bit-field is being declared,
-     -funsigned-bitfields applied and the type is not explicitly
-     "signed".  */
-  if (bitfield && !flag_signed_bitfields && !declspecs->explicit_signed_p
-      && TREE_CODE (type) == INTEGER_TYPE)
-    type = unsigned_type_for (type);
-
-  /* Figure out the type qualifiers for the declaration.  There are
-     two ways a declaration can become qualified.  One is something
-     like `const int i' where the `const' is explicit.  Another is
-     something like `typedef const int CI; CI i' where the type of the
-     declaration contains the `const'.  A third possibility is that
-     there is a type qualifier on the element type of a typedefed
-     array type, in which case we should extract that qualifier so
-     that c_apply_type_quals_to_decl receives the full list of
-     qualifiers to work with (C90 is not entirely clear about whether
-     duplicate qualifiers should be diagnosed in this case, but it
-     seems most appropriate to do so).  */
-  element_type = strip_array_types (type);
-  constp = declspecs->const_p + TYPE_READONLY (element_type);
-  restrictp = declspecs->restrict_p + TYPE_RESTRICT (element_type);
-  volatilep = declspecs->volatile_p + TYPE_VOLATILE (element_type);
-  as1 = declspecs->address_space;
-  as2 = TYPE_ADDR_SPACE (element_type);
-  address_space = ADDR_SPACE_GENERIC_P (as1)? as2 : as1;
-
-  if (pedantic && !flag_isoc99)
-    {
-      if (constp > 1)
-       pedwarn (loc, OPT_Wpedantic, "duplicate %<const%>");
-      if (restrictp > 1)
-       pedwarn (loc, OPT_Wpedantic, "duplicate %<restrict%>");
-      if (volatilep > 1)
-       pedwarn (loc, OPT_Wpedantic, "duplicate %<volatile%>");
-    }
-
-  if (!ADDR_SPACE_GENERIC_P (as1) && !ADDR_SPACE_GENERIC_P (as2) && as1 != as2)
-    error_at (loc, "conflicting named address spaces (%s vs %s)",
-             c_addr_space_name (as1), c_addr_space_name (as2));
-
-  if ((TREE_CODE (type) == ARRAY_TYPE
-       || first_non_attr_kind == cdk_array)
-      && TYPE_QUALS (element_type))
-    type = TYPE_MAIN_VARIANT (type);
-  type_quals = ((constp ? TYPE_QUAL_CONST : 0)
-               | (restrictp ? TYPE_QUAL_RESTRICT : 0)
-               | (volatilep ? TYPE_QUAL_VOLATILE : 0)
-               | ENCODE_QUAL_ADDR_SPACE (address_space));
-
-  /* Warn about storage classes that are invalid for certain
-     kinds of declarations (parameters, typenames, etc.).  */
-
-  if (funcdef_flag
-      && (threadp
-         || storage_class == csc_auto
-         || storage_class == csc_register
-         || storage_class == csc_typedef))
-    {
-      if (storage_class == csc_auto)
-       pedwarn (loc,
-                (current_scope == file_scope) ? 0 : OPT_Wpedantic,
-                "function definition declared %<auto%>");
-      if (storage_class == csc_register)
-       error_at (loc, "function definition declared %<register%>");
-      if (storage_class == csc_typedef)
-       error_at (loc, "function definition declared %<typedef%>");
-      if (threadp)
-       error_at (loc, "function definition declared %<__thread%>");
-      threadp = false;
-      if (storage_class == csc_auto
-         || storage_class == csc_register
-         || storage_class == csc_typedef)
-       storage_class = csc_none;
-    }
-  else if (decl_context != NORMAL && (storage_class != csc_none || threadp))
-    {
-      if (decl_context == PARM && storage_class == csc_register)
-       ;
-      else
-       {
-         switch (decl_context)
-           {
-           case FIELD:
-             if (name)
-               error_at (loc, "storage class specified for structure "
-                         "field %qE", name);
-             else
-               error_at (loc, "storage class specified for structure field");
-             break;
-           case PARM:
-             if (name)
-               error_at (loc, "storage class specified for parameter %qE",
-                         name);
-             else
-               error_at (loc, "storage class specified for unnamed parameter");
-             break;
-           default:
-             error_at (loc, "storage class specified for typename");
-             break;
-           }
-         storage_class = csc_none;
-         threadp = false;
-       }
-    }
-  else if (storage_class == csc_extern
-          && initialized
-          && !funcdef_flag)
-    {
-      /* 'extern' with initialization is invalid if not at file scope.  */
-       if (current_scope == file_scope)
-         {
-           /* It is fine to have 'extern const' when compiling at C
-              and C++ intersection.  */
-           if (!(warn_cxx_compat && constp))
-             warning_at (loc, 0, "%qE initialized and declared %<extern%>",
-                        name);
-         }
-      else
-       error_at (loc, "%qE has both %<extern%> and initializer", name);
-    }
-  else if (current_scope == file_scope)
-    {
-      if (storage_class == csc_auto)
-       error_at (loc, "file-scope declaration of %qE specifies %<auto%>",
-                 name);
-      if (pedantic && storage_class == csc_register)
-       pedwarn (input_location, OPT_Wpedantic,
-                "file-scope declaration of %qE specifies %<register%>", name);
-    }
-  else
-    {
-      if (storage_class == csc_extern && funcdef_flag)
-       error_at (loc, "nested function %qE declared %<extern%>", name);
-      else if (threadp && storage_class == csc_none)
-       {
-         error_at (loc, "function-scope %qE implicitly auto and declared "
-                   "%<__thread%>",
-                   name);
-         threadp = false;
-       }
-    }
-
-  /* Now figure out the structure of the declarator proper.
-     Descend through it, creating more complex types, until we reach
-     the declared identifier (or NULL_TREE, in an absolute declarator).
-     At each stage we maintain an unqualified version of the type
-     together with any qualifiers that should be applied to it with
-     c_build_qualified_type; this way, array types including
-     multidimensional array types are first built up in unqualified
-     form and then the qualified form is created with
-     TYPE_MAIN_VARIANT pointing to the unqualified form.  */
-
-  while (declarator && declarator->kind != cdk_id)
-    {
-      if (type == error_mark_node)
-       {
-         declarator = declarator->declarator;
-         continue;
-       }
-
-      /* Each level of DECLARATOR is either a cdk_array (for ...[..]),
-        a cdk_pointer (for *...),
-        a cdk_function (for ...(...)),
-        a cdk_attrs (for nested attributes),
-        or a cdk_id (for the name being declared
-        or the place in an absolute declarator
-        where the name was omitted).
-        For the last case, we have just exited the loop.
-
-        At this point, TYPE is the type of elements of an array,
-        or for a function to return, or for a pointer to point to.
-        After this sequence of ifs, TYPE is the type of the
-        array or function or pointer, and DECLARATOR has had its
-        outermost layer removed.  */
-
-      if (array_ptr_quals != TYPE_UNQUALIFIED
-         || array_ptr_attrs != NULL_TREE
-         || array_parm_static)
-       {
-         /* Only the innermost declarator (making a parameter be of
-            array type which is converted to pointer type)
-            may have static or type qualifiers.  */
-         error_at (loc, "static or type qualifiers in non-parameter array declarator");
-         array_ptr_quals = TYPE_UNQUALIFIED;
-         array_ptr_attrs = NULL_TREE;
-         array_parm_static = 0;
-       }
-
-      switch (declarator->kind)
-       {
-       case cdk_attrs:
-         {
-           /* A declarator with embedded attributes.  */
-           tree attrs = declarator->u.attrs;
-           const struct c_declarator *inner_decl;
-           int attr_flags = 0;
-           declarator = declarator->declarator;
-           inner_decl = declarator;
-           while (inner_decl->kind == cdk_attrs)
-             inner_decl = inner_decl->declarator;
-           if (inner_decl->kind == cdk_id)
-             attr_flags |= (int) ATTR_FLAG_DECL_NEXT;
-           else if (inner_decl->kind == cdk_function)
-             attr_flags |= (int) ATTR_FLAG_FUNCTION_NEXT;
-           else if (inner_decl->kind == cdk_array)
-             attr_flags |= (int) ATTR_FLAG_ARRAY_NEXT;
-           returned_attrs = decl_attributes (&type,
-                                             chainon (returned_attrs, attrs),
-                                             attr_flags);
-           break;
-         }
-       case cdk_array:
-         {
-           tree itype = NULL_TREE;
-           tree size = declarator->u.array.dimen;
-           /* The index is a signed object `sizetype' bits wide.  */
-           tree index_type = c_common_signed_type (sizetype);
-
-           array_ptr_quals = declarator->u.array.quals;
-           array_ptr_attrs = declarator->u.array.attrs;
-           array_parm_static = declarator->u.array.static_p;
-           array_parm_vla_unspec_p = declarator->u.array.vla_unspec_p;
-
-           declarator = declarator->declarator;
-
-           /* Check for some types that there cannot be arrays of.  */
-
-           if (VOID_TYPE_P (type))
-             {
-               if (name)
-                 error_at (loc, "declaration of %qE as array of voids", name);
-               else
-                 error_at (loc, "declaration of type name as array of voids");
-               type = error_mark_node;
-             }
-
-           if (TREE_CODE (type) == FUNCTION_TYPE)
-             {
-               if (name)
-                 error_at (loc, "declaration of %qE as array of functions",
-                           name);
-               else
-                 error_at (loc, "declaration of type name as array of "
-                           "functions");
-               type = error_mark_node;
-             }
-
-           if (pedantic && !in_system_header && flexible_array_type_p (type))
-             pedwarn (loc, OPT_Wpedantic,
-                      "invalid use of structure with flexible array member");
-
-           if (size == error_mark_node)
-             type = error_mark_node;
-
-           if (type == error_mark_node)
-             continue;
-
-           /* If size was specified, set ITYPE to a range-type for
-              that size.  Otherwise, ITYPE remains null.  finish_decl
-              may figure it out from an initial value.  */
-
-           if (size)
-             {
-               bool size_maybe_const = true;
-               bool size_int_const = (TREE_CODE (size) == INTEGER_CST
-                                      && !TREE_OVERFLOW (size));
-               bool this_size_varies = false;
-
-               /* Strip NON_LVALUE_EXPRs since we aren't using as an
-                  lvalue.  */
-               STRIP_TYPE_NOPS (size);
-
-               if (!INTEGRAL_TYPE_P (TREE_TYPE (size)))
-                 {
-                   if (name)
-                     error_at (loc, "size of array %qE has non-integer type",
-                               name);
-                   else
-                     error_at (loc,
-                               "size of unnamed array has non-integer type");
-                   size = integer_one_node;
-                 }
-
-               size = c_fully_fold (size, false, &size_maybe_const);
-
-               if (pedantic && size_maybe_const && integer_zerop (size))
-                 {
-                   if (name)
-                     pedwarn (loc, OPT_Wpedantic,
-                              "ISO C forbids zero-size array %qE", name);
-                   else
-                     pedwarn (loc, OPT_Wpedantic,
-                              "ISO C forbids zero-size array");
-                 }
-
-               if (TREE_CODE (size) == INTEGER_CST && size_maybe_const)
-                 {
-                   constant_expression_warning (size);
-                   if (tree_int_cst_sgn (size) < 0)
-                     {
-                       if (name)
-                         error_at (loc, "size of array %qE is negative", name);
-                       else
-                         error_at (loc, "size of unnamed array is negative");
-                       size = integer_one_node;
-                     }
-                   /* Handle a size folded to an integer constant but
-                      not an integer constant expression.  */
-                   if (!size_int_const)
-                     {
-                       /* If this is a file scope declaration of an
-                          ordinary identifier, this is invalid code;
-                          diagnosing it here and not subsequently
-                          treating the type as variable-length avoids
-                          more confusing diagnostics later.  */
-                       if ((decl_context == NORMAL || decl_context == FIELD)
-                           && current_scope == file_scope)
-                         pedwarn (input_location, 0,
-                                  "variably modified %qE at file scope",
-                                  name);
-                       else
-                         this_size_varies = size_varies = true;
-                       warn_variable_length_array (name, size);
-                     }
-                 }
-               else if ((decl_context == NORMAL || decl_context == FIELD)
-                        && current_scope == file_scope)
-                 {
-                   error_at (loc, "variably modified %qE at file scope", name);
-                   size = integer_one_node;
-                 }
-               else
-                 {
-                   /* Make sure the array size remains visibly
-                      nonconstant even if it is (eg) a const variable
-                      with known value.  */
-                   this_size_varies = size_varies = true;
-                   warn_variable_length_array (name, size);
-                 }
-
-               if (integer_zerop (size) && !this_size_varies)
-                 {
-                   /* A zero-length array cannot be represented with
-                      an unsigned index type, which is what we'll
-                      get with build_index_type.  Create an
-                      open-ended range instead.  */
-                   itype = build_range_type (sizetype, size, NULL_TREE);
-                 }
-               else
-                 {
-                   /* Arrange for the SAVE_EXPR on the inside of the
-                      MINUS_EXPR, which allows the -1 to get folded
-                      with the +1 that happens when building TYPE_SIZE.  */
-                   if (size_varies)
-                     size = save_expr (size);
-                   if (this_size_varies && TREE_CODE (size) == INTEGER_CST)
-                     size = build2 (COMPOUND_EXPR, TREE_TYPE (size),
-                                    integer_zero_node, size);
-
-                   /* Compute the maximum valid index, that is, size
-                      - 1.  Do the calculation in index_type, so that
-                      if it is a variable the computations will be
-                      done in the proper mode.  */
-                   itype = fold_build2_loc (loc, MINUS_EXPR, index_type,
-                                            convert (index_type, size),
-                                            convert (index_type,
-                                                     size_one_node));
-
-                   /* The above overflows when size does not fit
-                      in index_type.
-                      ???  While a size of INT_MAX+1 technically shouldn't
-                      cause an overflow (because we subtract 1), handling
-                      this case seems like an unnecessary complication.  */
-                   if (TREE_CODE (size) == INTEGER_CST
-                       && !int_fits_type_p (size, index_type))
-                     {
-                       if (name)
-                         error_at (loc, "size of array %qE is too large",
-                                   name);
-                       else
-                         error_at (loc, "size of unnamed array is too large");
-                       type = error_mark_node;
-                       continue;
-                     }
-
-                   itype = build_index_type (itype);
-                 }
-               if (this_size_varies)
-                 {
-                   if (*expr)
-                     *expr = build2 (COMPOUND_EXPR, TREE_TYPE (size),
-                                     *expr, size);
-                   else
-                     *expr = size;
-                   *expr_const_operands &= size_maybe_const;
-                 }
-             }
-           else if (decl_context == FIELD)
-             {
-               bool flexible_array_member = false;
-               if (array_parm_vla_unspec_p)
-                 /* Field names can in fact have function prototype
-                    scope so [*] is disallowed here through making
-                    the field variably modified, not through being
-                    something other than a declaration with function
-                    prototype scope.  */
-                 size_varies = true;
-               else
-                 {
-                   const struct c_declarator *t = declarator;
-                   while (t->kind == cdk_attrs)
-                     t = t->declarator;
-                   flexible_array_member = (t->kind == cdk_id);
-                 }
-               if (flexible_array_member
-                   && pedantic && !flag_isoc99 && !in_system_header)
-                 pedwarn (loc, OPT_Wpedantic,
-                          "ISO C90 does not support flexible array members");
-
-               /* ISO C99 Flexible array members are effectively
-                  identical to GCC's zero-length array extension.  */
-               if (flexible_array_member || array_parm_vla_unspec_p)
-                 itype = build_range_type (sizetype, size_zero_node,
-                                           NULL_TREE);
-             }
-           else if (decl_context == PARM)
-             {
-               if (array_parm_vla_unspec_p)
-                 {
-                   itype = build_range_type (sizetype, size_zero_node, NULL_TREE);
-                   size_varies = true;
-                 }
-             }
-           else if (decl_context == TYPENAME)
-             {
-               if (array_parm_vla_unspec_p)
-                 {
-                   /* C99 6.7.5.2p4 */
-                   warning (0, "%<[*]%> not in a declaration");
-                   /* We use this to avoid messing up with incomplete
-                      array types of the same type, that would
-                      otherwise be modified below.  */
-                   itype = build_range_type (sizetype, size_zero_node,
-                                             NULL_TREE);
-                   size_varies = true;
-                 }
-             }
-
-           /* Complain about arrays of incomplete types.  */
-           if (!COMPLETE_TYPE_P (type))
-             {
-               error_at (loc, "array type has incomplete element type");
-               type = error_mark_node;
-             }
-           else
-           /* When itype is NULL, a shared incomplete array type is
-              returned for all array of a given type.  Elsewhere we
-              make sure we don't complete that type before copying
-              it, but here we want to make sure we don't ever
-              modify the shared type, so we gcc_assert (itype)
-              below.  */
-             {
-               addr_space_t as = DECODE_QUAL_ADDR_SPACE (type_quals);
-               if (!ADDR_SPACE_GENERIC_P (as) && as != TYPE_ADDR_SPACE (type))
-                 type = build_qualified_type (type,
-                                              ENCODE_QUAL_ADDR_SPACE (as));
-
-               type = build_array_type (type, itype);
-             }
-
-           if (type != error_mark_node)
-             {
-               if (size_varies)
-                 {
-                   /* It is ok to modify type here even if itype is
-                      NULL: if size_varies, we're in a
-                      multi-dimensional array and the inner type has
-                      variable size, so the enclosing shared array type
-                      must too.  */
-                   if (size && TREE_CODE (size) == INTEGER_CST)
-                     type
-                       = build_distinct_type_copy (TYPE_MAIN_VARIANT (type));
-                   C_TYPE_VARIABLE_SIZE (type) = 1;
-                 }
-
-               /* The GCC extension for zero-length arrays differs from
-                  ISO flexible array members in that sizeof yields
-                  zero.  */
-               if (size && integer_zerop (size))
-                 {
-                   gcc_assert (itype);
-                   type = build_distinct_type_copy (TYPE_MAIN_VARIANT (type));
-                   TYPE_SIZE (type) = bitsize_zero_node;
-                   TYPE_SIZE_UNIT (type) = size_zero_node;
-                   SET_TYPE_STRUCTURAL_EQUALITY (type);
-                 }
-               if (array_parm_vla_unspec_p)
-                 {
-                   gcc_assert (itype);
-                   /* The type is complete.  C99 6.7.5.2p4  */
-                   type = build_distinct_type_copy (TYPE_MAIN_VARIANT (type));
-                   TYPE_SIZE (type) = bitsize_zero_node;
-                   TYPE_SIZE_UNIT (type) = size_zero_node;
-                   SET_TYPE_STRUCTURAL_EQUALITY (type);
-                 }
-             }
-
-           if (decl_context != PARM
-               && (array_ptr_quals != TYPE_UNQUALIFIED
-                   || array_ptr_attrs != NULL_TREE
-                   || array_parm_static))
-             {
-               error_at (loc, "static or type qualifiers in non-parameter array declarator");
-               array_ptr_quals = TYPE_UNQUALIFIED;
-               array_ptr_attrs = NULL_TREE;
-               array_parm_static = 0;
-             }
-           break;
-         }
-       case cdk_function:
-         {
-           /* Say it's a definition only for the declarator closest
-              to the identifier, apart possibly from some
-              attributes.  */
-           bool really_funcdef = false;
-           tree arg_types;
-           if (funcdef_flag)
-             {
-               const struct c_declarator *t = declarator->declarator;
-               while (t->kind == cdk_attrs)
-                 t = t->declarator;
-               really_funcdef = (t->kind == cdk_id);
-             }
-
-           /* Declaring a function type.  Make sure we have a valid
-              type for the function to return.  */
-           if (type == error_mark_node)
-             continue;
-
-           size_varies = false;
-
-           /* Warn about some types functions can't return.  */
-           if (TREE_CODE (type) == FUNCTION_TYPE)
-             {
-               if (name)
-                 error_at (loc, "%qE declared as function returning a "
-                                "function", name);
-               else
-                 error_at (loc, "type name declared as function "
-                           "returning a function");
-               type = integer_type_node;
-             }
-           if (TREE_CODE (type) == ARRAY_TYPE)
-             {
-               if (name)
-                 error_at (loc, "%qE declared as function returning an array",
-                           name);
-               else
-                 error_at (loc, "type name declared as function returning "
-                           "an array");
-               type = integer_type_node;
-             }
-           errmsg = targetm.invalid_return_type (type);
-           if (errmsg)
-             {
-               error (errmsg);
-               type = integer_type_node;
-             }
-
-           /* Construct the function type and go to the next
-              inner layer of declarator.  */
-           arg_info = declarator->u.arg_info;
-           arg_types = grokparms (arg_info, really_funcdef);
-
-           /* Type qualifiers before the return type of the function
-              qualify the return type, not the function type.  */
-           if (type_quals)
-             {
-               /* Type qualifiers on a function return type are
-                  normally permitted by the standard but have no
-                  effect, so give a warning at -Wreturn-type.
-                  Qualifiers on a void return type are banned on
-                  function definitions in ISO C; GCC used to used
-                  them for noreturn functions.  */
-               if (VOID_TYPE_P (type) && really_funcdef)
-                 pedwarn (loc, 0,
-                          "function definition has qualified void return type");
-               else
-                 warning_at (loc, OPT_Wignored_qualifiers,
-                          "type qualifiers ignored on function return type");
-
-               type = c_build_qualified_type (type, type_quals);
-             }
-           type_quals = TYPE_UNQUALIFIED;
-
-           type = build_function_type (type, arg_types);
-           declarator = declarator->declarator;
-
-           /* Set the TYPE_CONTEXTs for each tagged type which is local to
-              the formal parameter list of this FUNCTION_TYPE to point to
-              the FUNCTION_TYPE node itself.  */
-           {
-             c_arg_tag *tag;
-             unsigned ix;
-
-             FOR_EACH_VEC_ELT_REVERSE (c_arg_tag, arg_info->tags, ix, tag)
-               TYPE_CONTEXT (tag->type) = type;
-           }
-           break;
-         }
-       case cdk_pointer:
-         {
-           /* Merge any constancy or volatility into the target type
-              for the pointer.  */
-
-           if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
-               && type_quals)
-             pedwarn (loc, OPT_Wpedantic,
-                      "ISO C forbids qualified function types");
-           if (type_quals)
-             type = c_build_qualified_type (type, type_quals);
-           size_varies = false;
-
-           /* When the pointed-to type involves components of variable size,
-              care must be taken to ensure that the size evaluation code is
-              emitted early enough to dominate all the possible later uses
-              and late enough for the variables on which it depends to have
-              been assigned.
-
-              This is expected to happen automatically when the pointed-to
-              type has a name/declaration of it's own, but special attention
-              is required if the type is anonymous.
-
-              We handle the NORMAL and FIELD contexts here by attaching an
-              artificial TYPE_DECL to such pointed-to type.  This forces the
-              sizes evaluation at a safe point and ensures it is not deferred
-              until e.g. within a deeper conditional context.
-
-              We expect nothing to be needed here for PARM or TYPENAME.
-              Pushing a TYPE_DECL at this point for TYPENAME would actually
-              be incorrect, as we might be in the middle of an expression
-              with side effects on the pointed-to type size "arguments" prior
-              to the pointer declaration point and the fake TYPE_DECL in the
-              enclosing context would force the size evaluation prior to the
-              side effects.  */
-
-           if (!TYPE_NAME (type)
-               && (decl_context == NORMAL || decl_context == FIELD)
-               && variably_modified_type_p (type, NULL_TREE))
-             {
-               tree decl = build_decl (loc, TYPE_DECL, NULL_TREE, type);
-               DECL_ARTIFICIAL (decl) = 1;
-               pushdecl (decl);
-               finish_decl (decl, loc, NULL_TREE, NULL_TREE, NULL_TREE);
-               TYPE_NAME (type) = decl;
-             }
-
-           type = c_build_pointer_type (type);
-
-           /* Process type qualifiers (such as const or volatile)
-              that were given inside the `*'.  */
-           type_quals = declarator->u.pointer_quals;
-
-           declarator = declarator->declarator;
-           break;
-         }
-       default:
-         gcc_unreachable ();
-       }
-    }
-  *decl_attrs = chainon (returned_attrs, *decl_attrs);
-
-  /* Now TYPE has the actual type, apart from any qualifiers in
-     TYPE_QUALS.  */
-
-  /* Warn about address space used for things other than static memory or
-     pointers.  */
-  address_space = DECODE_QUAL_ADDR_SPACE (type_quals);
-  if (!ADDR_SPACE_GENERIC_P (address_space))
-    {
-      if (decl_context == NORMAL)
-       {
-         switch (storage_class)
-           {
-           case csc_auto:
-             error ("%qs combined with %<auto%> qualifier for %qE",
-                    c_addr_space_name (address_space), name);
-             break;
-           case csc_register:
-             error ("%qs combined with %<register%> qualifier for %qE",
-                    c_addr_space_name (address_space), name);
-             break;
-           case csc_none:
-             if (current_function_scope)
-               {
-                 error ("%qs specified for auto variable %qE",
-                        c_addr_space_name (address_space), name);
-                 break;
-               }
-             break;
-           case csc_static:
-           case csc_extern:
-           case csc_typedef:
-             break;
-           default:
-             gcc_unreachable ();
-           }
-       }
-      else if (decl_context == PARM && TREE_CODE (type) != ARRAY_TYPE)
-       {
-         if (name)
-           error ("%qs specified for parameter %qE",
-                  c_addr_space_name (address_space), name);
-         else
-           error ("%qs specified for unnamed parameter",
-                  c_addr_space_name (address_space));
-       }
-      else if (decl_context == FIELD)
-       {
-         if (name)
-           error ("%qs specified for structure field %qE",
-                  c_addr_space_name (address_space), name);
-         else
-           error ("%qs specified for structure field",
-                  c_addr_space_name (address_space));
-       }
-    }
-
-  /* Check the type and width of a bit-field.  */
-  if (bitfield)
-    check_bitfield_type_and_width (&type, width, name);
-
-  /* Reject invalid uses of _Alignas.  */
-  if (declspecs->alignas_p)
-    {
-      if (storage_class == csc_typedef)
-       error_at (loc, "alignment specified for typedef %qE", name);
-      else if (storage_class == csc_register)
-       error_at (loc, "alignment specified for %<register%> object %qE",
-                 name);
-      else if (decl_context == PARM)
-       {
-         if (name)
-           error_at (loc, "alignment specified for parameter %qE", name);
-         else
-           error_at (loc, "alignment specified for unnamed parameter");
-       }
-      else if (bitfield)
-       {
-         if (name)
-           error_at (loc, "alignment specified for bit-field %qE", name);
-         else
-           error_at (loc, "alignment specified for unnamed bit-field");
-       }
-      else if (TREE_CODE (type) == FUNCTION_TYPE)
-       error_at (loc, "alignment specified for function %qE", name);
-      else if (declspecs->align_log != -1)
-       {
-         alignas_align = 1U << declspecs->align_log;
-         if (alignas_align < TYPE_ALIGN_UNIT (type))
-           {
-             if (name)
-               error_at (loc, "%<_Alignas%> specifiers cannot reduce "
-                         "alignment of %qE", name);
-             else
-               error_at (loc, "%<_Alignas%> specifiers cannot reduce "
-                         "alignment of unnamed field");
-             alignas_align = 0;
-           }
-       }
-    }
-
-  /* Did array size calculations overflow or does the array cover more
-     than half of the address-space?  */
-  if (TREE_CODE (type) == ARRAY_TYPE
-      && COMPLETE_TYPE_P (type)
-      && TREE_CODE (TYPE_SIZE_UNIT (type)) == INTEGER_CST
-      && ! valid_constant_size_p (TYPE_SIZE_UNIT (type)))
-    {
-      if (name)
-       error_at (loc, "size of array %qE is too large", name);
-      else
-       error_at (loc, "size of unnamed array is too large");
-      /* If we proceed with the array type as it is, we'll eventually
-        crash in tree_low_cst().  */
-      type = error_mark_node;
-    }
-
-  /* If this is declaring a typedef name, return a TYPE_DECL.  */
-
-  if (storage_class == csc_typedef)
-    {
-      tree decl;
-      if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
-         && type_quals)
-       pedwarn (loc, OPT_Wpedantic,
-                "ISO C forbids qualified function types");
-      if (type_quals)
-       type = c_build_qualified_type (type, type_quals);
-      decl = build_decl (declarator->id_loc,
-                        TYPE_DECL, declarator->u.id, type);
-      if (declspecs->explicit_signed_p)
-       C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1;
-      if (declspecs->inline_p)
-       pedwarn (loc, 0,"typedef %q+D declared %<inline%>", decl);
-      if (declspecs->noreturn_p)
-       pedwarn (loc, 0,"typedef %q+D declared %<_Noreturn%>", decl);
-
-      if (warn_cxx_compat && declarator->u.id != NULL_TREE)
-       {
-         struct c_binding *b = I_TAG_BINDING (declarator->u.id);
-
-         if (b != NULL
-             && b->decl != NULL_TREE
-             && (B_IN_CURRENT_SCOPE (b)
-                 || (current_scope == file_scope && B_IN_EXTERNAL_SCOPE (b)))
-             && TYPE_MAIN_VARIANT (b->decl) != TYPE_MAIN_VARIANT (type))
-           {
-             warning_at (declarator->id_loc, OPT_Wc___compat,
-                         ("using %qD as both a typedef and a tag is "
-                          "invalid in C++"),
-                         decl);
-             if (b->locus != UNKNOWN_LOCATION)
-               inform (b->locus, "originally defined here");
-           }
-       }
-
-      return decl;
-    }
-
-  /* If this is a type name (such as, in a cast or sizeof),
-     compute the type and return it now.  */
-
-  if (decl_context == TYPENAME)
-    {
-      /* Note that the grammar rejects storage classes in typenames
-        and fields.  */
-      gcc_assert (storage_class == csc_none && !threadp
-                 && !declspecs->inline_p && !declspecs->noreturn_p);
-      if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
-         && type_quals)
-       pedwarn (loc, OPT_Wpedantic,
-                "ISO C forbids const or volatile function types");
-      if (type_quals)
-       type = c_build_qualified_type (type, type_quals);
-      return type;
-    }
-
-  if (pedantic && decl_context == FIELD
-      && variably_modified_type_p (type, NULL_TREE))
-    {
-      /* C99 6.7.2.1p8 */
-      pedwarn (loc, OPT_Wpedantic, "a member of a structure or union cannot "
-              "have a variably modified type");
-    }
-
-  /* Aside from typedefs and type names (handle above),
-     `void' at top level (not within pointer)
-     is allowed only in public variables.
-     We don't complain about parms either, but that is because
-     a better error message can be made later.  */
-
-  if (VOID_TYPE_P (type) && decl_context != PARM
-      && !((decl_context != FIELD && TREE_CODE (type) != FUNCTION_TYPE)
-           && (storage_class == csc_extern
-               || (current_scope == file_scope
-                   && !(storage_class == csc_static
-                        || storage_class == csc_register)))))
-    {
-      error_at (loc, "variable or field %qE declared void", name);
-      type = integer_type_node;
-    }
-
-  /* Now create the decl, which may be a VAR_DECL, a PARM_DECL
-     or a FUNCTION_DECL, depending on DECL_CONTEXT and TYPE.  */
-
-  {
-    tree decl;
-
-    if (decl_context == PARM)
-      {
-       tree promoted_type;
-
-       /* A parameter declared as an array of T is really a pointer to T.
-          One declared as a function is really a pointer to a function.  */
-
-       if (TREE_CODE (type) == ARRAY_TYPE)
-         {
-           /* Transfer const-ness of array into that of type pointed to.  */
-           type = TREE_TYPE (type);
-           if (type_quals)
-             type = c_build_qualified_type (type, type_quals);
-           type = c_build_pointer_type (type);
-           type_quals = array_ptr_quals;
-           if (type_quals)
-             type = c_build_qualified_type (type, type_quals);
-
-           /* We don't yet implement attributes in this context.  */
-           if (array_ptr_attrs != NULL_TREE)
-             warning_at (loc, OPT_Wattributes,
-                         "attributes in parameter array declarator ignored");
-
-           size_varies = false;
-         }
-       else if (TREE_CODE (type) == FUNCTION_TYPE)
-         {
-           if (type_quals)
-             pedwarn (loc, OPT_Wpedantic,
-                      "ISO C forbids qualified function types");
-           if (type_quals)
-             type = c_build_qualified_type (type, type_quals);
-           type = c_build_pointer_type (type);
-           type_quals = TYPE_UNQUALIFIED;
-         }
-       else if (type_quals)
-         type = c_build_qualified_type (type, type_quals);
-
-       decl = build_decl (declarator->id_loc,
-                          PARM_DECL, declarator->u.id, type);
-       if (size_varies)
-         C_DECL_VARIABLE_SIZE (decl) = 1;
-
-       /* Compute the type actually passed in the parmlist,
-          for the case where there is no prototype.
-          (For example, shorts and chars are passed as ints.)
-          When there is a prototype, this is overridden later.  */
-
-       if (type == error_mark_node)
-         promoted_type = type;
-       else
-         promoted_type = c_type_promotes_to (type);
-
-       DECL_ARG_TYPE (decl) = promoted_type;
-       if (declspecs->inline_p)
-         pedwarn (loc, 0, "parameter %q+D declared %<inline%>", decl);
-       if (declspecs->noreturn_p)
-         pedwarn (loc, 0, "parameter %q+D declared %<_Noreturn%>", decl);
-      }
-    else if (decl_context == FIELD)
-      {
-       /* Note that the grammar rejects storage classes in typenames
-          and fields.  */
-       gcc_assert (storage_class == csc_none && !threadp
-                   && !declspecs->inline_p && !declspecs->noreturn_p);
-
-       /* Structure field.  It may not be a function.  */
-
-       if (TREE_CODE (type) == FUNCTION_TYPE)
-         {
-           error_at (loc, "field %qE declared as a function", name);
-           type = build_pointer_type (type);
-         }
-       else if (TREE_CODE (type) != ERROR_MARK
-                && !COMPLETE_OR_UNBOUND_ARRAY_TYPE_P (type))
-         {
-           if (name)
-             error_at (loc, "field %qE has incomplete type", name);
-           else
-             error_at (loc, "unnamed field has incomplete type");
-           type = error_mark_node;
-         }
-       type = c_build_qualified_type (type, type_quals);
-       decl = build_decl (declarator->id_loc,
-                          FIELD_DECL, declarator->u.id, type);
-       DECL_NONADDRESSABLE_P (decl) = bitfield;
-       if (bitfield && !declarator->u.id)
-         TREE_NO_WARNING (decl) = 1;
-
-       if (size_varies)
-         C_DECL_VARIABLE_SIZE (decl) = 1;
-      }
-    else if (TREE_CODE (type) == FUNCTION_TYPE)
-      {
-       if (storage_class == csc_register || threadp)
-         {
-           error_at (loc, "invalid storage class for function %qE", name);
-         }
-       else if (current_scope != file_scope)
-         {
-           /* Function declaration not at file scope.  Storage
-              classes other than `extern' are not allowed, C99
-              6.7.1p5, and `extern' makes no difference.  However,
-              GCC allows 'auto', perhaps with 'inline', to support
-              nested functions.  */
-           if (storage_class == csc_auto)
-               pedwarn (loc, OPT_Wpedantic,
-                        "invalid storage class for function %qE", name);
-           else if (storage_class == csc_static)
-             {
-               error_at (loc, "invalid storage class for function %qE", name);
-               if (funcdef_flag)
-                 storage_class = declspecs->storage_class = csc_none;
-               else
-                 return 0;
-             }
-         }
-
-       decl = build_decl (declarator->id_loc,
-                          FUNCTION_DECL, declarator->u.id, type);
-       decl = build_decl_attribute_variant (decl, decl_attr);
-
-       if (pedantic && type_quals && !DECL_IN_SYSTEM_HEADER (decl))
-         pedwarn (loc, OPT_Wpedantic,
-                  "ISO C forbids qualified function types");
-
-       /* Every function declaration is an external reference
-          (DECL_EXTERNAL) except for those which are not at file
-          scope and are explicitly declared "auto".  This is
-          forbidden by standard C (C99 6.7.1p5) and is interpreted by
-          GCC to signify a forward declaration of a nested function.  */
-       if (storage_class == csc_auto && current_scope != file_scope)
-         DECL_EXTERNAL (decl) = 0;
-       /* In C99, a function which is declared 'inline' with 'extern'
-          is not an external reference (which is confusing).  It
-          means that the later definition of the function must be output
-          in this file, C99 6.7.4p6.  In GNU C89, a function declared
-          'extern inline' is an external reference.  */
-       else if (declspecs->inline_p && storage_class != csc_static)
-         DECL_EXTERNAL (decl) = ((storage_class == csc_extern)
-                                 == flag_gnu89_inline);
-       else
-         DECL_EXTERNAL (decl) = !initialized;
-
-       /* Record absence of global scope for `static' or `auto'.  */
-       TREE_PUBLIC (decl)
-         = !(storage_class == csc_static || storage_class == csc_auto);
-
-       /* For a function definition, record the argument information
-          block where store_parm_decls will look for it.  */
-       if (funcdef_flag)
-         current_function_arg_info = arg_info;
-
-       if (declspecs->default_int_p)
-         C_FUNCTION_IMPLICIT_INT (decl) = 1;
-
-       /* Record presence of `inline' and `_Noreturn', if it is
-          reasonable.  */
-       if (flag_hosted && MAIN_NAME_P (declarator->u.id))
-         {
-           if (declspecs->inline_p)
-             pedwarn (loc, 0, "cannot inline function %<main%>");
-           if (declspecs->noreturn_p)
-             pedwarn (loc, 0, "%<main%> declared %<_Noreturn%>");
-         }
-       else
-         {
-           if (declspecs->inline_p)
-             /* Record that the function is declared `inline'.  */
-             DECL_DECLARED_INLINE_P (decl) = 1;
-           if (declspecs->noreturn_p)
-             {
-               if (!flag_isoc11)
-                 {
-                   if (flag_isoc99)
-                     pedwarn (loc, OPT_Wpedantic,
-                              "ISO C99 does not support %<_Noreturn%>");
-                   else
-                     pedwarn (loc, OPT_Wpedantic,
-                              "ISO C90 does not support %<_Noreturn%>");
-                 }
-               TREE_THIS_VOLATILE (decl) = 1;
-             }
-         }
-      }
-    else
-      {
-       /* It's a variable.  */
-       /* An uninitialized decl with `extern' is a reference.  */
-       int extern_ref = !initialized && storage_class == csc_extern;
-
-       type = c_build_qualified_type (type, type_quals);
-
-       /* C99 6.2.2p7: It is invalid (compile-time undefined
-          behavior) to create an 'extern' declaration for a
-          variable if there is a global declaration that is
-          'static' and the global declaration is not visible.
-          (If the static declaration _is_ currently visible,
-          the 'extern' declaration is taken to refer to that decl.) */
-       if (extern_ref && current_scope != file_scope)
-         {
-           tree global_decl  = identifier_global_value (declarator->u.id);
-           tree visible_decl = lookup_name (declarator->u.id);
-
-           if (global_decl
-               && global_decl != visible_decl
-               && TREE_CODE (global_decl) == VAR_DECL
-               && !TREE_PUBLIC (global_decl))
-             error_at (loc, "variable previously declared %<static%> "
-                       "redeclared %<extern%>");
-         }
-
-       decl = build_decl (declarator->id_loc,
-                          VAR_DECL, declarator->u.id, type);
-       if (size_varies)
-         C_DECL_VARIABLE_SIZE (decl) = 1;
-
-       if (declspecs->inline_p)
-         pedwarn (loc, 0, "variable %q+D declared %<inline%>", decl);
-       if (declspecs->noreturn_p)
-         pedwarn (loc, 0, "variable %q+D declared %<_Noreturn%>", decl);
-
-       /* At file scope, an initialized extern declaration may follow
-          a static declaration.  In that case, DECL_EXTERNAL will be
-          reset later in start_decl.  */
-       DECL_EXTERNAL (decl) = (storage_class == csc_extern);
-
-       /* At file scope, the presence of a `static' or `register' storage
-          class specifier, or the absence of all storage class specifiers
-          makes this declaration a definition (perhaps tentative).  Also,
-          the absence of `static' makes it public.  */
-       if (current_scope == file_scope)
-         {
-           TREE_PUBLIC (decl) = storage_class != csc_static;
-           TREE_STATIC (decl) = !extern_ref;
-         }
-       /* Not at file scope, only `static' makes a static definition.  */
-       else
-         {
-           TREE_STATIC (decl) = (storage_class == csc_static);
-           TREE_PUBLIC (decl) = extern_ref;
-         }
-
-       if (threadp)
-         DECL_TLS_MODEL (decl) = decl_default_tls_model (decl);
-      }
-
-    if ((storage_class == csc_extern
-        || (storage_class == csc_none
-            && TREE_CODE (type) == FUNCTION_TYPE
-            && !funcdef_flag))
-       && variably_modified_type_p (type, NULL_TREE))
-      {
-       /* C99 6.7.5.2p2 */
-       if (TREE_CODE (type) == FUNCTION_TYPE)
-         error_at (loc, "non-nested function with variably modified type");
-       else
-         error_at (loc, "object with variably modified type must have "
-                   "no linkage");
-      }
-
-    /* Record `register' declaration for warnings on &
-       and in case doing stupid register allocation.  */
-
-    if (storage_class == csc_register)
-      {
-       C_DECL_REGISTER (decl) = 1;
-       DECL_REGISTER (decl) = 1;
-      }
-
-    /* Record constancy and volatility.  */
-    c_apply_type_quals_to_decl (type_quals, decl);
-
-    /* Apply _Alignas specifiers.  */
-    if (alignas_align)
-      {
-       DECL_ALIGN (decl) = alignas_align * BITS_PER_UNIT;
-       DECL_USER_ALIGN (decl) = 1;
-      }
-
-    /* If a type has volatile components, it should be stored in memory.
-       Otherwise, the fact that those components are volatile
-       will be ignored, and would even crash the compiler.
-       Of course, this only makes sense on  VAR,PARM, and RESULT decl's.   */
-    if (C_TYPE_FIELDS_VOLATILE (TREE_TYPE (decl))
-       && (TREE_CODE (decl) == VAR_DECL ||  TREE_CODE (decl) == PARM_DECL
-         || TREE_CODE (decl) == RESULT_DECL))
-      {
-       /* It is not an error for a structure with volatile fields to
-          be declared register, but reset DECL_REGISTER since it
-          cannot actually go in a register.  */
-       int was_reg = C_DECL_REGISTER (decl);
-       C_DECL_REGISTER (decl) = 0;
-       DECL_REGISTER (decl) = 0;
-       c_mark_addressable (decl);
-       C_DECL_REGISTER (decl) = was_reg;
-      }
-
-  /* This is the earliest point at which we might know the assembler
-     name of a variable.  Thus, if it's known before this, die horribly.  */
-    gcc_assert (!DECL_ASSEMBLER_NAME_SET_P (decl));
-
-    if (warn_cxx_compat
-       && TREE_CODE (decl) == VAR_DECL
-       && TREE_PUBLIC (decl)
-       && TREE_STATIC (decl)
-       && (TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE
-           || TREE_CODE (TREE_TYPE (decl)) == UNION_TYPE
-           || TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE)
-       && TYPE_NAME (TREE_TYPE (decl)) == NULL_TREE)
-      warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wc___compat,
-                 ("non-local variable %qD with anonymous type is "
-                  "questionable in C++"),
-                 decl);
-
-    return decl;
-  }
-}
-\f
-/* Decode the parameter-list info for a function type or function definition.
-   The argument is the value returned by `get_parm_info' (or made in c-parse.c
-   if there is an identifier list instead of a parameter decl list).
-   These two functions are separate because when a function returns
-   or receives functions then each is called multiple times but the order
-   of calls is different.  The last call to `grokparms' is always the one
-   that contains the formal parameter names of a function definition.
-
-   Return a list of arg types to use in the FUNCTION_TYPE for this function.
-
-   FUNCDEF_FLAG is true for a function definition, false for
-   a mere declaration.  A nonempty identifier-list gets an error message
-   when FUNCDEF_FLAG is false.  */
-
-static tree
-grokparms (struct c_arg_info *arg_info, bool funcdef_flag)
-{
-  tree arg_types = arg_info->types;
-
-  if (funcdef_flag && arg_info->had_vla_unspec)
-    {
-      /* A function definition isn't function prototype scope C99 6.2.1p4.  */
-      /* C99 6.7.5.2p4 */
-      error ("%<[*]%> not allowed in other than function prototype scope");
-    }
-
-  if (arg_types == 0 && !funcdef_flag && !in_system_header)
-    warning (OPT_Wstrict_prototypes,
-            "function declaration isn%'t a prototype");
-
-  if (arg_types == error_mark_node)
-    return 0;  /* don't set TYPE_ARG_TYPES in this case */
-
-  else if (arg_types && TREE_CODE (TREE_VALUE (arg_types)) == IDENTIFIER_NODE)
-    {
-      if (!funcdef_flag)
-       {
-         pedwarn (input_location, 0, "parameter names (without types) in function declaration");
-         arg_info->parms = NULL_TREE;
-       }
-      else
-       arg_info->parms = arg_info->types;
-
-      arg_info->types = 0;
-      return 0;
-    }
-  else
-    {
-      tree parm, type, typelt;
-      unsigned int parmno;
-      const char *errmsg;
-
-      /* If there is a parameter of incomplete type in a definition,
-        this is an error.  In a declaration this is valid, and a
-        struct or union type may be completed later, before any calls
-        or definition of the function.  In the case where the tag was
-        first declared within the parameter list, a warning has
-        already been given.  If a parameter has void type, then
-        however the function cannot be defined or called, so
-        warn.  */
-
-      for (parm = arg_info->parms, typelt = arg_types, parmno = 1;
-          parm;
-          parm = DECL_CHAIN (parm), typelt = TREE_CHAIN (typelt), parmno++)
-       {
-         type = TREE_VALUE (typelt);
-         if (type == error_mark_node)
-           continue;
-
-         if (!COMPLETE_TYPE_P (type))
-           {
-             if (funcdef_flag)
-               {
-                 if (DECL_NAME (parm))
-                   error_at (input_location,
-                             "parameter %u (%q+D) has incomplete type",
-                             parmno, parm);
-                 else
-                   error_at (DECL_SOURCE_LOCATION (parm),
-                             "parameter %u has incomplete type",
-                             parmno);
-
-                 TREE_VALUE (typelt) = error_mark_node;
-                 TREE_TYPE (parm) = error_mark_node;
-                 arg_types = NULL_TREE;
-               }
-             else if (VOID_TYPE_P (type))
-               {
-                 if (DECL_NAME (parm))
-                   warning_at (input_location, 0,
-                               "parameter %u (%q+D) has void type",
-                               parmno, parm);
-                 else
-                   warning_at (DECL_SOURCE_LOCATION (parm), 0,
-                               "parameter %u has void type",
-                               parmno);
-               }
-           }
-
-         errmsg = targetm.invalid_parameter_type (type);
-         if (errmsg)
-           {
-             error (errmsg);
-             TREE_VALUE (typelt) = error_mark_node;
-             TREE_TYPE (parm) = error_mark_node;
-             arg_types = NULL_TREE;
-           }
-
-         if (DECL_NAME (parm) && TREE_USED (parm))
-           warn_if_shadowing (parm);
-       }
-      return arg_types;
-    }
-}
-
-/* Allocate and initialize a c_arg_info structure from the parser's
-   obstack.  */
-
-struct c_arg_info *
-build_arg_info (void)
-{
-  struct c_arg_info *ret = XOBNEW (&parser_obstack, struct c_arg_info);
-  ret->parms = NULL_TREE;
-  ret->tags = NULL;
-  ret->types = NULL_TREE;
-  ret->others = NULL_TREE;
-  ret->pending_sizes = NULL;
-  ret->had_vla_unspec = 0;
-  return ret;
-}
-
-/* Take apart the current scope and return a c_arg_info structure with
-   info on a parameter list just parsed.
-
-   This structure is later fed to 'grokparms' and 'store_parm_decls'.
-
-   ELLIPSIS being true means the argument list ended in '...' so don't
-   append a sentinel (void_list_node) to the end of the type-list.
-
-   EXPR is NULL or an expression that needs to be evaluated for the
-   side effects of array size expressions in the parameters.  */
-
-struct c_arg_info *
-get_parm_info (bool ellipsis, tree expr)
-{
-  struct c_binding *b = current_scope->bindings;
-  struct c_arg_info *arg_info = build_arg_info ();
-
-  tree parms    = 0;
-  VEC(c_arg_tag,gc) *tags = NULL;
-  tree types    = 0;
-  tree others   = 0;
-
-  static bool explained_incomplete_types = false;
-  bool gave_void_only_once_err = false;
-
-  arg_info->had_vla_unspec = current_scope->had_vla_unspec;
-
-  /* The bindings in this scope must not get put into a block.
-     We will take care of deleting the binding nodes.  */
-  current_scope->bindings = 0;
-
-  /* This function is only called if there was *something* on the
-     parameter list.  */
-  gcc_assert (b);
-
-  /* A parameter list consisting solely of 'void' indicates that the
-     function takes no arguments.  But if the 'void' is qualified
-     (by 'const' or 'volatile'), or has a storage class specifier
-     ('register'), then the behavior is undefined; issue an error.
-     Typedefs for 'void' are OK (see DR#157).  */
-  if (b->prev == 0                         /* one binding */
-      && TREE_CODE (b->decl) == PARM_DECL   /* which is a parameter */
-      && !DECL_NAME (b->decl)               /* anonymous */
-      && VOID_TYPE_P (TREE_TYPE (b->decl))) /* of void type */
-    {
-      if (TREE_THIS_VOLATILE (b->decl)
-         || TREE_READONLY (b->decl)
-         || C_DECL_REGISTER (b->decl))
-       error ("%<void%> as only parameter may not be qualified");
-
-      /* There cannot be an ellipsis.  */
-      if (ellipsis)
-       error ("%<void%> must be the only parameter");
-
-      arg_info->types = void_list_node;
-      return arg_info;
-    }
-
-  if (!ellipsis)
-    types = void_list_node;
-
-  /* Break up the bindings list into parms, tags, types, and others;
-     apply sanity checks; purge the name-to-decl bindings.  */
-  while (b)
-    {
-      tree decl = b->decl;
-      tree type = TREE_TYPE (decl);
-      c_arg_tag *tag;
-      const char *keyword;
-
-      switch (TREE_CODE (decl))
-       {
-       case PARM_DECL:
-         if (b->id)
-           {
-             gcc_assert (I_SYMBOL_BINDING (b->id) == b);
-             I_SYMBOL_BINDING (b->id) = b->shadowed;
-           }
-
-         /* Check for forward decls that never got their actual decl.  */
-         if (TREE_ASM_WRITTEN (decl))
-           error ("parameter %q+D has just a forward declaration", decl);
-         /* Check for (..., void, ...) and issue an error.  */
-         else if (VOID_TYPE_P (type) && !DECL_NAME (decl))
-           {
-             if (!gave_void_only_once_err)
-               {
-                 error ("%<void%> must be the only parameter");
-                 gave_void_only_once_err = true;
-               }
-           }
-         else
-           {
-             /* Valid parameter, add it to the list.  */
-             DECL_CHAIN (decl) = parms;
-             parms = decl;
-
-             /* Since there is a prototype, args are passed in their
-                declared types.  The back end may override this later.  */
-             DECL_ARG_TYPE (decl) = type;
-             types = tree_cons (0, type, types);
-           }
-         break;
-
-       case ENUMERAL_TYPE: keyword = "enum"; goto tag;
-       case UNION_TYPE:    keyword = "union"; goto tag;
-       case RECORD_TYPE:   keyword = "struct"; goto tag;
-       tag:
-         /* Types may not have tag-names, in which case the type
-            appears in the bindings list with b->id NULL.  */
-         if (b->id)
-           {
-             gcc_assert (I_TAG_BINDING (b->id) == b);
-             I_TAG_BINDING (b->id) = b->shadowed;
-           }
-
-         /* Warn about any struct, union or enum tags defined in a
-            parameter list.  The scope of such types is limited to
-            the parameter list, which is rarely if ever desirable
-            (it's impossible to call such a function with type-
-            correct arguments).  An anonymous union parm type is
-            meaningful as a GNU extension, so don't warn for that.  */
-         if (TREE_CODE (decl) != UNION_TYPE || b->id != 0)
-           {
-             if (b->id)
-               /* The %s will be one of 'struct', 'union', or 'enum'.  */
-               warning (0, "%<%s %E%> declared inside parameter list",
-                        keyword, b->id);
-             else
-               /* The %s will be one of 'struct', 'union', or 'enum'.  */
-               warning (0, "anonymous %s declared inside parameter list",
-                        keyword);
-
-             if (!explained_incomplete_types)
-               {
-                 warning (0, "its scope is only this definition or declaration,"
-                          " which is probably not what you want");
-                 explained_incomplete_types = true;
-               }
-           }
-
-         tag = VEC_safe_push (c_arg_tag, gc, tags, NULL);
-         tag->id = b->id;
-         tag->type = decl;
-         break;
-
-       case CONST_DECL:
-       case TYPE_DECL:
-       case FUNCTION_DECL:
-         /* CONST_DECLs appear here when we have an embedded enum,
-            and TYPE_DECLs appear here when we have an embedded struct
-            or union.  No warnings for this - we already warned about the
-            type itself.  FUNCTION_DECLs appear when there is an implicit
-            function declaration in the parameter list.  */
-
-         /* When we reinsert this decl in the function body, we need
-            to reconstruct whether it was marked as nested.  */
-         gcc_assert (TREE_CODE (decl) == FUNCTION_DECL
-                     ? b->nested
-                     : !b->nested);
-         DECL_CHAIN (decl) = others;
-         others = decl;
-         /* fall through */
-
-       case ERROR_MARK:
-         /* error_mark_node appears here when we have an undeclared
-            variable.  Just throw it away.  */
-         if (b->id)
-           {
-             gcc_assert (I_SYMBOL_BINDING (b->id) == b);
-             I_SYMBOL_BINDING (b->id) = b->shadowed;
-           }
-         break;
-
-         /* Other things that might be encountered.  */
-       case LABEL_DECL:
-       case VAR_DECL:
-       default:
-         gcc_unreachable ();
-       }
-
-      b = free_binding_and_advance (b);
-    }
-
-  arg_info->parms = parms;
-  arg_info->tags = tags;
-  arg_info->types = types;
-  arg_info->others = others;
-  arg_info->pending_sizes = expr;
-  return arg_info;
-}
-\f
-/* Get the struct, enum or union (CODE says which) with tag NAME.
-   Define the tag as a forward-reference with location LOC if it is
-   not defined.  Return a c_typespec structure for the type
-   specifier.  */
-
-struct c_typespec
-parser_xref_tag (location_t loc, enum tree_code code, tree name)
-{
-  struct c_typespec ret;
-  tree ref;
-  location_t refloc;
-
-  ret.expr = NULL_TREE;
-  ret.expr_const_operands = true;
-
-  /* If a cross reference is requested, look up the type
-     already defined for this tag and return it.  */
-
-  ref = lookup_tag (code, name, 0, &refloc);
-  /* If this is the right type of tag, return what we found.
-     (This reference will be shadowed by shadow_tag later if appropriate.)
-     If this is the wrong type of tag, do not return it.  If it was the
-     wrong type in the same scope, we will have had an error
-     message already; if in a different scope and declaring
-     a name, pending_xref_error will give an error message; but if in a
-     different scope and not declaring a name, this tag should
-     shadow the previous declaration of a different type of tag, and
-     this would not work properly if we return the reference found.
-     (For example, with "struct foo" in an outer scope, "union foo;"
-     must shadow that tag with a new one of union type.)  */
-  ret.kind = (ref ? ctsk_tagref : ctsk_tagfirstref);
-  if (ref && TREE_CODE (ref) == code)
-    {
-      if (C_TYPE_DEFINED_IN_STRUCT (ref)
-         && loc != UNKNOWN_LOCATION
-         && warn_cxx_compat)
-       {
-         switch (code)
-           {
-           case ENUMERAL_TYPE:
-             warning_at (loc, OPT_Wc___compat,
-                         ("enum type defined in struct or union "
-                          "is not visible in C++"));
-             inform (refloc, "enum type defined here");
-             break;
-           case RECORD_TYPE:
-             warning_at (loc, OPT_Wc___compat,
-                         ("struct defined in struct or union "
-                          "is not visible in C++"));
-             inform (refloc, "struct defined here");
-             break;
-           case UNION_TYPE:
-             warning_at (loc, OPT_Wc___compat,
-                         ("union defined in struct or union "
-                          "is not visible in C++"));
-             inform (refloc, "union defined here");
-             break;
-           default:
-             gcc_unreachable();
-           }
-       }
-
-      ret.spec = ref;
-      return ret;
-    }
-
-  /* If no such tag is yet defined, create a forward-reference node
-     and record it as the "definition".
-     When a real declaration of this type is found,
-     the forward-reference will be altered into a real type.  */
-
-  ref = make_node (code);
-  if (code == ENUMERAL_TYPE)
-    {
-      /* Give the type a default layout like unsigned int
-        to avoid crashing if it does not get defined.  */
-      SET_TYPE_MODE (ref, TYPE_MODE (unsigned_type_node));
-      TYPE_ALIGN (ref) = TYPE_ALIGN (unsigned_type_node);
-      TYPE_USER_ALIGN (ref) = 0;
-      TYPE_UNSIGNED (ref) = 1;
-      TYPE_PRECISION (ref) = TYPE_PRECISION (unsigned_type_node);
-      TYPE_MIN_VALUE (ref) = TYPE_MIN_VALUE (unsigned_type_node);
-      TYPE_MAX_VALUE (ref) = TYPE_MAX_VALUE (unsigned_type_node);
-    }
-
-  pushtag (loc, name, ref);
-
-  ret.spec = ref;
-  return ret;
-}
-
-/* Get the struct, enum or union (CODE says which) with tag NAME.
-   Define the tag as a forward-reference if it is not defined.
-   Return a tree for the type.  */
-
-tree
-xref_tag (enum tree_code code, tree name)
-{
-  return parser_xref_tag (input_location, code, name).spec;
-}
-\f
-/* Make sure that the tag NAME is defined *in the current scope*
-   at least as a forward reference.
-   LOC is the location of the struct's definition.
-   CODE says which kind of tag NAME ought to be.
-
-   This stores the current value of the file static STRUCT_PARSE_INFO
-   in *ENCLOSING_STRUCT_PARSE_INFO, and points STRUCT_PARSE_INFO at a
-   new c_struct_parse_info structure.  The old value of
-   STRUCT_PARSE_INFO is restored in finish_struct.  */
-
-tree
-start_struct (location_t loc, enum tree_code code, tree name,
-             struct c_struct_parse_info **enclosing_struct_parse_info)
-{
-  /* If there is already a tag defined at this scope
-     (as a forward reference), just return it.  */
-
-  tree ref = NULL_TREE;
-  location_t refloc = UNKNOWN_LOCATION;
-
-  if (name != NULL_TREE)
-    ref = lookup_tag (code, name, 1, &refloc);
-  if (ref && TREE_CODE (ref) == code)
-    {
-      if (TYPE_SIZE (ref))
-       {
-         if (code == UNION_TYPE)
-           error_at (loc, "redefinition of %<union %E%>", name);
-         else
-           error_at (loc, "redefinition of %<struct %E%>", name);
-         if (refloc != UNKNOWN_LOCATION)
-           inform (refloc, "originally defined here");
-         /* Don't create structures using a name already in use.  */
-         ref = NULL_TREE;
-       }
-      else if (C_TYPE_BEING_DEFINED (ref))
-       {
-         if (code == UNION_TYPE)
-           error_at (loc, "nested redefinition of %<union %E%>", name);
-         else
-           error_at (loc, "nested redefinition of %<struct %E%>", name);
-         /* Don't bother to report "originally defined here" for a
-            nested redefinition; the original definition should be
-            obvious.  */
-         /* Don't create structures that contain themselves.  */
-         ref = NULL_TREE;
-       }
-    }
-
-  /* Otherwise create a forward-reference just so the tag is in scope.  */
-
-  if (ref == NULL_TREE || TREE_CODE (ref) != code)
-    {
-      ref = make_node (code);
-      pushtag (loc, name, ref);
-    }
-
-  C_TYPE_BEING_DEFINED (ref) = 1;
-  TYPE_PACKED (ref) = flag_pack_struct;
-
-  *enclosing_struct_parse_info = struct_parse_info;
-  struct_parse_info = XNEW (struct c_struct_parse_info);
-  struct_parse_info->struct_types = VEC_alloc (tree, heap, 0);
-  struct_parse_info->fields = VEC_alloc (c_binding_ptr, heap, 0);
-  struct_parse_info->typedefs_seen = VEC_alloc (tree, heap, 0);
-
-  /* FIXME: This will issue a warning for a use of a type defined
-     within a statement expr used within sizeof, et. al.  This is not
-     terribly serious as C++ doesn't permit statement exprs within
-     sizeof anyhow.  */
-  if (warn_cxx_compat && (in_sizeof || in_typeof || in_alignof))
-    warning_at (loc, OPT_Wc___compat,
-               "defining type in %qs expression is invalid in C++",
-               (in_sizeof
-                ? "sizeof"
-                : (in_typeof ? "typeof" : "alignof")));
-
-  return ref;
-}
-
-/* Process the specs, declarator and width (NULL if omitted)
-   of a structure component, returning a FIELD_DECL node.
-   WIDTH is non-NULL for bit-fields only, and is an INTEGER_CST node.
-   DECL_ATTRS is as for grokdeclarator.
-
-   LOC is the location of the structure component.
-
-   This is done during the parsing of the struct declaration.
-   The FIELD_DECL nodes are chained together and the lot of them
-   are ultimately passed to `build_struct' to make the RECORD_TYPE node.  */
-
-tree
-grokfield (location_t loc,
-          struct c_declarator *declarator, struct c_declspecs *declspecs,
-          tree width, tree *decl_attrs)
-{
-  tree value;
-
-  if (declarator->kind == cdk_id && declarator->u.id == NULL_TREE
-      && width == NULL_TREE)
-    {
-      /* This is an unnamed decl.
-
-        If we have something of the form "union { list } ;" then this
-        is the anonymous union extension.  Similarly for struct.
-
-        If this is something of the form "struct foo;", then
-          If MS or Plan 9 extensions are enabled, this is handled as
-            an anonymous struct.
-          Otherwise this is a forward declaration of a structure tag.
-
-        If this is something of the form "foo;" and foo is a TYPE_DECL, then
-          If foo names a structure or union without a tag, then this
-            is an anonymous struct (this is permitted by C11).
-          If MS or Plan 9 extensions are enabled and foo names a
-            structure, then again this is an anonymous struct.
-          Otherwise this is an error.
-
-        Oh what a horrid tangled web we weave.  I wonder if MS consciously
-        took this from Plan 9 or if it was an accident of implementation
-        that took root before someone noticed the bug...  */
-
-      tree type = declspecs->type;
-      bool type_ok = (TREE_CODE (type) == RECORD_TYPE
-                     || TREE_CODE (type) == UNION_TYPE);
-      bool ok = false;
-
-      if (type_ok
-         && (flag_ms_extensions
-             || flag_plan9_extensions
-             || !declspecs->typedef_p))
-       {
-         if (flag_ms_extensions || flag_plan9_extensions)
-           ok = true;
-         else if (TYPE_NAME (type) == NULL)
-           ok = true;
-         else
-           ok = false;
-       }
-      if (!ok)
-       {
-         pedwarn (loc, 0, "declaration does not declare anything");
-         return NULL_TREE;
-       }
-      if (!flag_isoc11)
-       {
-         if (flag_isoc99)
-           pedwarn (loc, OPT_Wpedantic,
-                    "ISO C99 doesn%'t support unnamed structs/unions");
-         else
-           pedwarn (loc, OPT_Wpedantic,
-                    "ISO C90 doesn%'t support unnamed structs/unions");
-       }
-    }
-
-  value = grokdeclarator (declarator, declspecs, FIELD, false,
-                         width ? &width : NULL, decl_attrs, NULL, NULL,
-                         DEPRECATED_NORMAL);
-
-  finish_decl (value, loc, NULL_TREE, NULL_TREE, NULL_TREE);
-  DECL_INITIAL (value) = width;
-
-  if (warn_cxx_compat && DECL_NAME (value) != NULL_TREE)
-    {
-      /* If we currently have a binding for this field, set the
-        in_struct field in the binding, so that we warn about lookups
-        which find it.  */
-      struct c_binding *b = I_SYMBOL_BINDING (DECL_NAME (value));
-      if (b != NULL)
-       {
-         /* If the in_struct field is not yet set, push it on a list
-            to be cleared when this struct is finished.  */
-         if (!b->in_struct)
-           {
-             VEC_safe_push (c_binding_ptr, heap,
-                            struct_parse_info->fields, b);
-             b->in_struct = 1;
-           }
-       }
-    }
-
-  return value;
-}
-\f
-/* Subroutine of detect_field_duplicates: return whether X and Y,
-   which are both fields in the same struct, have duplicate field
-   names.  */
-
-static bool
-is_duplicate_field (tree x, tree y)
-{
-  if (DECL_NAME (x) != NULL_TREE && DECL_NAME (x) == DECL_NAME (y))
-    return true;
-
-  /* When using -fplan9-extensions, an anonymous field whose name is a
-     typedef can duplicate a field name.  */
-  if (flag_plan9_extensions
-      && (DECL_NAME (x) == NULL_TREE || DECL_NAME (y) == NULL_TREE))
-    {
-      tree xt, xn, yt, yn;
-
-      xt = TREE_TYPE (x);
-      if (DECL_NAME (x) != NULL_TREE)
-       xn = DECL_NAME (x);
-      else if ((TREE_CODE (xt) == RECORD_TYPE || TREE_CODE (xt) == UNION_TYPE)
-              && TYPE_NAME (xt) != NULL_TREE
-              && TREE_CODE (TYPE_NAME (xt)) == TYPE_DECL)
-       xn = DECL_NAME (TYPE_NAME (xt));
-      else
-       xn = NULL_TREE;
-
-      yt = TREE_TYPE (y);
-      if (DECL_NAME (y) != NULL_TREE)
-       yn = DECL_NAME (y);
-      else if ((TREE_CODE (yt) == RECORD_TYPE || TREE_CODE (yt) == UNION_TYPE)
-              && TYPE_NAME (yt) != NULL_TREE
-              && TREE_CODE (TYPE_NAME (yt)) == TYPE_DECL)
-       yn = DECL_NAME (TYPE_NAME (yt));
-      else
-       yn = NULL_TREE;
-
-      if (xn != NULL_TREE && xn == yn)
-       return true;
-    }
-
-  return false;
-}
-
-/* Subroutine of detect_field_duplicates: add the fields of FIELDLIST
-   to HTAB, giving errors for any duplicates.  */
-
-static void
-detect_field_duplicates_hash (tree fieldlist, htab_t htab)
-{
-  tree x, y;
-  void **slot;
-
-  for (x = fieldlist; x ; x = DECL_CHAIN (x))
-    if ((y = DECL_NAME (x)) != 0)
-      {
-       slot = htab_find_slot (htab, y, INSERT);
-       if (*slot)
-         {
-           error ("duplicate member %q+D", x);
-           DECL_NAME (x) = NULL_TREE;
-         }
-       *slot = y;
-      }
-    else if (TREE_CODE (TREE_TYPE (x)) == RECORD_TYPE
-            || TREE_CODE (TREE_TYPE (x)) == UNION_TYPE)
-      {
-       detect_field_duplicates_hash (TYPE_FIELDS (TREE_TYPE (x)), htab);
-
-       /* When using -fplan9-extensions, an anonymous field whose
-          name is a typedef can duplicate a field name.  */
-       if (flag_plan9_extensions
-           && TYPE_NAME (TREE_TYPE (x)) != NULL_TREE
-           && TREE_CODE (TYPE_NAME (TREE_TYPE (x))) == TYPE_DECL)
-         {
-           tree xn = DECL_NAME (TYPE_NAME (TREE_TYPE (x)));
-           slot = htab_find_slot (htab, xn, INSERT);
-           if (*slot)
-             error ("duplicate member %q+D", TYPE_NAME (TREE_TYPE (x)));
-           *slot = xn;
-         }
-      }
-}
-
-/* Generate an error for any duplicate field names in FIELDLIST.  Munge
-   the list such that this does not present a problem later.  */
-
-static void
-detect_field_duplicates (tree fieldlist)
-{
-  tree x, y;
-  int timeout = 10;
-
-  /* If the struct is the list of instance variables of an Objective-C
-     class, then we need to check all the instance variables of
-     superclasses when checking for duplicates (since you can't have
-     an instance variable in a subclass with the same name as an
-     instance variable in a superclass).  We pass on this job to the
-     Objective-C compiler.  objc_detect_field_duplicates() will return
-     false if we are not checking the list of instance variables and
-     the C frontend should proceed with the standard field duplicate
-     checks.  If we are checking the list of instance variables, the
-     ObjC frontend will do the check, emit the errors if needed, and
-     then return true.  */
-  if (c_dialect_objc ())
-    if (objc_detect_field_duplicates (false))
-      return;
-
-  /* First, see if there are more than "a few" fields.
-     This is trivially true if there are zero or one fields.  */
-  if (!fieldlist || !DECL_CHAIN (fieldlist))
-    return;
-  x = fieldlist;
-  do {
-    timeout--;
-    if (DECL_NAME (x) == NULL_TREE
-       && (TREE_CODE (TREE_TYPE (x)) == RECORD_TYPE
-           || TREE_CODE (TREE_TYPE (x)) == UNION_TYPE))
-      timeout = 0;
-    x = DECL_CHAIN (x);
-  } while (timeout > 0 && x);
-
-  /* If there were "few" fields and no anonymous structures or unions,
-     avoid the overhead of allocating a hash table.  Instead just do
-     the nested traversal thing.  */
-  if (timeout > 0)
-    {
-      for (x = DECL_CHAIN (fieldlist); x; x = DECL_CHAIN (x))
-       /* When using -fplan9-extensions, we can have duplicates
-          between typedef names and fields.  */
-       if (DECL_NAME (x)
-           || (flag_plan9_extensions
-               && DECL_NAME (x) == NULL_TREE
-               && (TREE_CODE (TREE_TYPE (x)) == RECORD_TYPE
-                   || TREE_CODE (TREE_TYPE (x)) == UNION_TYPE)
-               && TYPE_NAME (TREE_TYPE (x)) != NULL_TREE
-               && TREE_CODE (TYPE_NAME (TREE_TYPE (x))) == TYPE_DECL))
-         {
-           for (y = fieldlist; y != x; y = TREE_CHAIN (y))
-             if (is_duplicate_field (y, x))
-               {
-                 error ("duplicate member %q+D", x);
-                 DECL_NAME (x) = NULL_TREE;
-               }
-         }
-    }
-  else
-    {
-      htab_t htab = htab_create (37, htab_hash_pointer, htab_eq_pointer, NULL);
-
-      detect_field_duplicates_hash (fieldlist, htab);
-      htab_delete (htab);
-    }
-}
-
-/* Finish up struct info used by -Wc++-compat.  */
-
-static void
-warn_cxx_compat_finish_struct (tree fieldlist)
-{
-  unsigned int ix;
-  tree x;
-  struct c_binding *b;
-
-  /* Set the C_TYPE_DEFINED_IN_STRUCT flag for each type defined in
-     the current struct.  We do this now at the end of the struct
-     because the flag is used to issue visibility warnings, and we
-     only want to issue those warnings if the type is referenced
-     outside of the struct declaration.  */
-  FOR_EACH_VEC_ELT (tree, struct_parse_info->struct_types, ix, x)
-    C_TYPE_DEFINED_IN_STRUCT (x) = 1;
-
-  /* The TYPEDEFS_SEEN field of STRUCT_PARSE_INFO is a list of
-     typedefs used when declaring fields in this struct.  If the name
-     of any of the fields is also a typedef name then the struct would
-     not parse in C++, because the C++ lookup rules say that the
-     typedef name would be looked up in the context of the struct, and
-     would thus be the field rather than the typedef.  */
-  if (!VEC_empty (tree, struct_parse_info->typedefs_seen)
-      && fieldlist != NULL_TREE)
-    {
-      /* Use a pointer_set using the name of the typedef.  We can use
-        a pointer_set because identifiers are interned.  */
-      struct pointer_set_t *tset = pointer_set_create ();
-
-      FOR_EACH_VEC_ELT (tree, struct_parse_info->typedefs_seen, ix, x)
-       pointer_set_insert (tset, DECL_NAME (x));
-
-      for (x = fieldlist; x != NULL_TREE; x = DECL_CHAIN (x))
-       {
-         if (DECL_NAME (x) != NULL_TREE
-             && pointer_set_contains (tset, DECL_NAME (x)))
-           {
-             warning_at (DECL_SOURCE_LOCATION (x), OPT_Wc___compat,
-                         ("using %qD as both field and typedef name is "
-                          "invalid in C++"),
-                         x);
-             /* FIXME: It would be nice to report the location where
-                the typedef name is used.  */
-           }
-       }
-
-      pointer_set_destroy (tset);
-    }
-
-  /* For each field which has a binding and which was not defined in
-     an enclosing struct, clear the in_struct field.  */
-  FOR_EACH_VEC_ELT (c_binding_ptr, struct_parse_info->fields, ix, b)
-    b->in_struct = 0;
-}
-
-/* Fill in the fields of a RECORD_TYPE or UNION_TYPE node, T.
-   LOC is the location of the RECORD_TYPE or UNION_TYPE's definition.
-   FIELDLIST is a chain of FIELD_DECL nodes for the fields.
-   ATTRIBUTES are attributes to be applied to the structure.
-
-   ENCLOSING_STRUCT_PARSE_INFO is the value of STRUCT_PARSE_INFO when
-   the struct was started.  */
-
-tree
-finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
-              struct c_struct_parse_info *enclosing_struct_parse_info)
-{
-  tree x;
-  bool toplevel = file_scope == current_scope;
-  int saw_named_field;
-
-  /* If this type was previously laid out as a forward reference,
-     make sure we lay it out again.  */
-
-  TYPE_SIZE (t) = 0;
-
-  decl_attributes (&t, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE);
-
-  if (pedantic)
-    {
-      for (x = fieldlist; x; x = DECL_CHAIN (x))
-       {
-         if (DECL_NAME (x) != 0)
-           break;
-         if (flag_isoc11
-             && (TREE_CODE (TREE_TYPE (x)) == RECORD_TYPE
-                 || TREE_CODE (TREE_TYPE (x)) == UNION_TYPE))
-           break;
-       }
-
-      if (x == 0)
-       {
-         if (TREE_CODE (t) == UNION_TYPE)
-           {
-             if (fieldlist)
-               pedwarn (loc, OPT_Wpedantic, "union has no named members");
-             else
-               pedwarn (loc, OPT_Wpedantic, "union has no members");
-           }
-         else
-           {
-             if (fieldlist)
-               pedwarn (loc, OPT_Wpedantic, "struct has no named members");
-             else
-               pedwarn (loc, OPT_Wpedantic, "struct has no members");
-           }
-       }
-    }
-
-  /* Install struct as DECL_CONTEXT of each field decl.
-     Also process specified field sizes, found in the DECL_INITIAL,
-     storing 0 there after the type has been changed to precision equal
-     to its width, rather than the precision of the specified standard
-     type.  (Correct layout requires the original type to have been preserved
-     until now.)  */
-
-  saw_named_field = 0;
-  for (x = fieldlist; x; x = DECL_CHAIN (x))
-    {
-      if (TREE_TYPE (x) == error_mark_node)
-       continue;
-
-      DECL_CONTEXT (x) = t;
-
-      /* If any field is const, the structure type is pseudo-const.  */
-      if (TREE_READONLY (x))
-       C_TYPE_FIELDS_READONLY (t) = 1;
-      else
-       {
-         /* A field that is pseudo-const makes the structure likewise.  */
-         tree t1 = strip_array_types (TREE_TYPE (x));
-         if ((TREE_CODE (t1) == RECORD_TYPE || TREE_CODE (t1) == UNION_TYPE)
-             && C_TYPE_FIELDS_READONLY (t1))
-           C_TYPE_FIELDS_READONLY (t) = 1;
-       }
-
-      /* Any field that is volatile means variables of this type must be
-        treated in some ways as volatile.  */
-      if (TREE_THIS_VOLATILE (x))
-       C_TYPE_FIELDS_VOLATILE (t) = 1;
-
-      /* Any field of nominal variable size implies structure is too.  */
-      if (C_DECL_VARIABLE_SIZE (x))
-       C_TYPE_VARIABLE_SIZE (t) = 1;
-
-      if (DECL_INITIAL (x))
-       {
-         unsigned HOST_WIDE_INT width = tree_low_cst (DECL_INITIAL (x), 1);
-         DECL_SIZE (x) = bitsize_int (width);
-         DECL_BIT_FIELD (x) = 1;
-         SET_DECL_C_BIT_FIELD (x);
-       }
-
-      if (TYPE_PACKED (t)
-         && (DECL_BIT_FIELD (x)
-             || TYPE_ALIGN (TREE_TYPE (x)) > BITS_PER_UNIT))
-       DECL_PACKED (x) = 1;
-
-      /* Detect flexible array member in an invalid context.  */
-      if (TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE
-         && TYPE_SIZE (TREE_TYPE (x)) == NULL_TREE
-         && TYPE_DOMAIN (TREE_TYPE (x)) != NULL_TREE
-         && TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (x))) == NULL_TREE)
-       {
-         if (TREE_CODE (t) == UNION_TYPE)
-           {
-             error_at (DECL_SOURCE_LOCATION (x),
-                       "flexible array member in union");
-             TREE_TYPE (x) = error_mark_node;
-           }
-         else if (DECL_CHAIN (x) != NULL_TREE)
-           {
-             error_at (DECL_SOURCE_LOCATION (x),
-                       "flexible array member not at end of struct");
-             TREE_TYPE (x) = error_mark_node;
-           }
-         else if (!saw_named_field)
-           {
-             error_at (DECL_SOURCE_LOCATION (x),
-                       "flexible array member in otherwise empty struct");
-             TREE_TYPE (x) = error_mark_node;
-           }
-       }
-
-      if (pedantic && TREE_CODE (t) == RECORD_TYPE
-         && flexible_array_type_p (TREE_TYPE (x)))
-       pedwarn (DECL_SOURCE_LOCATION (x), OPT_Wpedantic,
-                "invalid use of structure with flexible array member");
-
-      if (DECL_NAME (x)
-         || TREE_CODE (TREE_TYPE (x)) == RECORD_TYPE
-         || TREE_CODE (TREE_TYPE (x)) == UNION_TYPE)
-       saw_named_field = 1;
-    }
-
-  detect_field_duplicates (fieldlist);
-
-  /* Now we have the nearly final fieldlist.  Record it,
-     then lay out the structure or union (including the fields).  */
-
-  TYPE_FIELDS (t) = fieldlist;
-
-  layout_type (t);
-
-  /* Give bit-fields their proper types.  */
-  {
-    tree *fieldlistp = &fieldlist;
-    while (*fieldlistp)
-      if (TREE_CODE (*fieldlistp) == FIELD_DECL && DECL_INITIAL (*fieldlistp)
-         && TREE_TYPE (*fieldlistp) != error_mark_node)
-       {
-         unsigned HOST_WIDE_INT width
-           = tree_low_cst (DECL_INITIAL (*fieldlistp), 1);
-         tree type = TREE_TYPE (*fieldlistp);
-         if (width != TYPE_PRECISION (type))
-           {
-             TREE_TYPE (*fieldlistp)
-               = c_build_bitfield_integer_type (width, TYPE_UNSIGNED (type));
-             DECL_MODE (*fieldlistp) = TYPE_MODE (TREE_TYPE (*fieldlistp));
-           }
-         DECL_INITIAL (*fieldlistp) = 0;
-       }
-      else
-       fieldlistp = &DECL_CHAIN (*fieldlistp);
-  }
-
-  /* Now we have the truly final field list.
-     Store it in this type and in the variants.  */
-
-  TYPE_FIELDS (t) = fieldlist;
-
-  /* If there are lots of fields, sort so we can look through them fast.
-     We arbitrarily consider 16 or more elts to be "a lot".  */
-
-  {
-    int len = 0;
-
-    for (x = fieldlist; x; x = DECL_CHAIN (x))
-      {
-       if (len > 15 || DECL_NAME (x) == NULL)
-         break;
-       len += 1;
-      }
-
-    if (len > 15)
-      {
-       tree *field_array;
-       struct lang_type *space;
-       struct sorted_fields_type *space2;
-
-       len += list_length (x);
-
-       /* Use the same allocation policy here that make_node uses, to
-         ensure that this lives as long as the rest of the struct decl.
-         All decls in an inline function need to be saved.  */
-
-       space = ggc_alloc_cleared_lang_type (sizeof (struct lang_type));
-       space2 = ggc_alloc_sorted_fields_type
-         (sizeof (struct sorted_fields_type) + len * sizeof (tree));
-
-       len = 0;
-       space->s = space2;
-       field_array = &space2->elts[0];
-       for (x = fieldlist; x; x = DECL_CHAIN (x))
-         {
-           field_array[len++] = x;
-
-           /* If there is anonymous struct or union, break out of the loop.  */
-           if (DECL_NAME (x) == NULL)
-             break;
-         }
-       /* Found no anonymous struct/union.  Add the TYPE_LANG_SPECIFIC.  */
-       if (x == NULL)
-         {
-           TYPE_LANG_SPECIFIC (t) = space;
-           TYPE_LANG_SPECIFIC (t)->s->len = len;
-           field_array = TYPE_LANG_SPECIFIC (t)->s->elts;
-           qsort (field_array, len, sizeof (tree), field_decl_cmp);
-         }
-      }
-  }
-
-  for (x = TYPE_MAIN_VARIANT (t); x; x = TYPE_NEXT_VARIANT (x))
-    {
-      TYPE_FIELDS (x) = TYPE_FIELDS (t);
-      TYPE_LANG_SPECIFIC (x) = TYPE_LANG_SPECIFIC (t);
-      C_TYPE_FIELDS_READONLY (x) = C_TYPE_FIELDS_READONLY (t);
-      C_TYPE_FIELDS_VOLATILE (x) = C_TYPE_FIELDS_VOLATILE (t);
-      C_TYPE_VARIABLE_SIZE (x) = C_TYPE_VARIABLE_SIZE (t);
-    }
-
-  /* If this was supposed to be a transparent union, but we can't
-     make it one, warn and turn off the flag.  */
-  if (TREE_CODE (t) == UNION_TYPE
-      && TYPE_TRANSPARENT_AGGR (t)
-      && (!TYPE_FIELDS (t) || TYPE_MODE (t) != DECL_MODE (TYPE_FIELDS (t))))
-    {
-      TYPE_TRANSPARENT_AGGR (t) = 0;
-      warning_at (loc, 0, "union cannot be made transparent");
-    }
-
-  /* If this structure or union completes the type of any previous
-     variable declaration, lay it out and output its rtl.  */
-  for (x = C_TYPE_INCOMPLETE_VARS (TYPE_MAIN_VARIANT (t));
-       x;
-       x = TREE_CHAIN (x))
-    {
-      tree decl = TREE_VALUE (x);
-      if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
-       layout_array_type (TREE_TYPE (decl));
-      if (TREE_CODE (decl) != TYPE_DECL)
-       {
-         layout_decl (decl, 0);
-         if (c_dialect_objc ())
-           objc_check_decl (decl);
-         rest_of_decl_compilation (decl, toplevel, 0);
-       }
-    }
-  C_TYPE_INCOMPLETE_VARS (TYPE_MAIN_VARIANT (t)) = 0;
-
-  /* Update type location to the one of the definition, instead of e.g.
-     a forward declaration.  */
-  if (TYPE_STUB_DECL (t))
-    DECL_SOURCE_LOCATION (TYPE_STUB_DECL (t)) = loc;
-
-  /* Finish debugging output for this type.  */
-  rest_of_type_compilation (t, toplevel);
-
-  /* If we're inside a function proper, i.e. not file-scope and not still
-     parsing parameters, then arrange for the size of a variable sized type
-     to be bound now.  */
-  if (building_stmt_list_p () && variably_modified_type_p (t, NULL_TREE))
-    add_stmt (build_stmt (loc,
-                         DECL_EXPR, build_decl (loc, TYPE_DECL, NULL, t)));
-
-  if (warn_cxx_compat)
-    warn_cxx_compat_finish_struct (fieldlist);
-
-  VEC_free (tree, heap, struct_parse_info->struct_types);
-  VEC_free (c_binding_ptr, heap, struct_parse_info->fields);
-  VEC_free (tree, heap, struct_parse_info->typedefs_seen);
-  XDELETE (struct_parse_info);
-
-  struct_parse_info = enclosing_struct_parse_info;
-
-  /* If this struct is defined inside a struct, add it to
-     struct_types.  */
-  if (warn_cxx_compat
-      && struct_parse_info != NULL
-      && !in_sizeof && !in_typeof && !in_alignof)
-    VEC_safe_push (tree, heap, struct_parse_info->struct_types, t);
-
-  return t;
-}
-
-/* Lay out the type T, and its element type, and so on.  */
-
-static void
-layout_array_type (tree t)
-{
-  if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE)
-    layout_array_type (TREE_TYPE (t));
-  layout_type (t);
-}
-\f
-/* Begin compiling the definition of an enumeration type.
-   NAME is its name (or null if anonymous).
-   LOC is the enum's location.
-   Returns the type object, as yet incomplete.
-   Also records info about it so that build_enumerator
-   may be used to declare the individual values as they are read.  */
-
-tree
-start_enum (location_t loc, struct c_enum_contents *the_enum, tree name)
-{
-  tree enumtype = NULL_TREE;
-  location_t enumloc = UNKNOWN_LOCATION;
-
-  /* If this is the real definition for a previous forward reference,
-     fill in the contents in the same object that used to be the
-     forward reference.  */
-
-  if (name != NULL_TREE)
-    enumtype = lookup_tag (ENUMERAL_TYPE, name, 1, &enumloc);
-
-  if (enumtype == 0 || TREE_CODE (enumtype) != ENUMERAL_TYPE)
-    {
-      enumtype = make_node (ENUMERAL_TYPE);
-      pushtag (loc, name, enumtype);
-    }
-
-  if (C_TYPE_BEING_DEFINED (enumtype))
-    error_at (loc, "nested redefinition of %<enum %E%>", name);
-
-  C_TYPE_BEING_DEFINED (enumtype) = 1;
-
-  if (TYPE_VALUES (enumtype) != 0)
-    {
-      /* This enum is a named one that has been declared already.  */
-      error_at (loc, "redeclaration of %<enum %E%>", name);
-      if (enumloc != UNKNOWN_LOCATION)
-       inform (enumloc, "originally defined here");
-
-      /* Completely replace its old definition.
-        The old enumerators remain defined, however.  */
-      TYPE_VALUES (enumtype) = 0;
-    }
-
-  the_enum->enum_next_value = integer_zero_node;
-  the_enum->enum_overflow = 0;
-
-  if (flag_short_enums)
-    TYPE_PACKED (enumtype) = 1;
-
-  /* FIXME: This will issue a warning for a use of a type defined
-     within sizeof in a statement expr.  This is not terribly serious
-     as C++ doesn't permit statement exprs within sizeof anyhow.  */
-  if (warn_cxx_compat && (in_sizeof || in_typeof || in_alignof))
-    warning_at (loc, OPT_Wc___compat,
-               "defining type in %qs expression is invalid in C++",
-               (in_sizeof
-                ? "sizeof"
-                : (in_typeof ? "typeof" : "alignof")));
-
-  return enumtype;
-}
-
-/* After processing and defining all the values of an enumeration type,
-   install their decls in the enumeration type and finish it off.
-   ENUMTYPE is the type object, VALUES a list of decl-value pairs,
-   and ATTRIBUTES are the specified attributes.
-   Returns ENUMTYPE.  */
-
-tree
-finish_enum (tree enumtype, tree values, tree attributes)
-{
-  tree pair, tem;
-  tree minnode = 0, maxnode = 0;
-  int precision, unsign;
-  bool toplevel = (file_scope == current_scope);
-  struct lang_type *lt;
-
-  decl_attributes (&enumtype, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE);
-
-  /* Calculate the maximum value of any enumerator in this type.  */
-
-  if (values == error_mark_node)
-    minnode = maxnode = integer_zero_node;
-  else
-    {
-      minnode = maxnode = TREE_VALUE (values);
-      for (pair = TREE_CHAIN (values); pair; pair = TREE_CHAIN (pair))
-       {
-         tree value = TREE_VALUE (pair);
-         if (tree_int_cst_lt (maxnode, value))
-           maxnode = value;
-         if (tree_int_cst_lt (value, minnode))
-           minnode = value;
-       }
-    }
-
-  /* Construct the final type of this enumeration.  It is the same
-     as one of the integral types - the narrowest one that fits, except
-     that normally we only go as narrow as int - and signed iff any of
-     the values are negative.  */
-  unsign = (tree_int_cst_sgn (minnode) >= 0);
-  precision = MAX (tree_int_cst_min_precision (minnode, unsign),
-                  tree_int_cst_min_precision (maxnode, unsign));
-
-  if (TYPE_PACKED (enumtype) || precision > TYPE_PRECISION (integer_type_node))
-    {
-      tem = c_common_type_for_size (precision, unsign);
-      if (tem == NULL)
-       {
-         warning (0, "enumeration values exceed range of largest integer");
-         tem = long_long_integer_type_node;
-       }
-    }
-  else
-    tem = unsign ? unsigned_type_node : integer_type_node;
-
-  TYPE_MIN_VALUE (enumtype) = TYPE_MIN_VALUE (tem);
-  TYPE_MAX_VALUE (enumtype) = TYPE_MAX_VALUE (tem);
-  TYPE_UNSIGNED (enumtype) = TYPE_UNSIGNED (tem);
-  TYPE_SIZE (enumtype) = 0;
-
-  /* If the precision of the type was specific with an attribute and it
-     was too small, give an error.  Otherwise, use it.  */
-  if (TYPE_PRECISION (enumtype))
-    {
-      if (precision > TYPE_PRECISION (enumtype))
-       error ("specified mode too small for enumeral values");
-    }
-  else
-    TYPE_PRECISION (enumtype) = TYPE_PRECISION (tem);
-
-  layout_type (enumtype);
-
-  if (values != error_mark_node)
-    {
-      /* Change the type of the enumerators to be the enum type.  We
-        need to do this irrespective of the size of the enum, for
-        proper type checking.  Replace the DECL_INITIALs of the
-        enumerators, and the value slots of the list, with copies
-        that have the enum type; they cannot be modified in place
-        because they may be shared (e.g.  integer_zero_node) Finally,
-        change the purpose slots to point to the names of the decls.  */
-      for (pair = values; pair; pair = TREE_CHAIN (pair))
-       {
-         tree enu = TREE_PURPOSE (pair);
-         tree ini = DECL_INITIAL (enu);
-
-         TREE_TYPE (enu) = enumtype;
-
-         /* The ISO C Standard mandates enumerators to have type int,
-            even though the underlying type of an enum type is
-            unspecified.  However, GCC allows enumerators of any
-            integer type as an extensions.  build_enumerator()
-            converts any enumerators that fit in an int to type int,
-            to avoid promotions to unsigned types when comparing
-            integers with enumerators that fit in the int range.
-            When -pedantic is given, build_enumerator() would have
-            already warned about those that don't fit. Here we
-            convert the rest to the enumerator type. */
-         if (TREE_TYPE (ini) != integer_type_node)
-           ini = convert (enumtype, ini);
-
-         DECL_INITIAL (enu) = ini;
-         TREE_PURPOSE (pair) = DECL_NAME (enu);
-         TREE_VALUE (pair) = ini;
-       }
-
-      TYPE_VALUES (enumtype) = values;
-    }
-
-  /* Record the min/max values so that we can warn about bit-field
-     enumerations that are too small for the values.  */
-  lt = ggc_alloc_cleared_lang_type (sizeof (struct lang_type));
-  lt->enum_min = minnode;
-  lt->enum_max = maxnode;
-  TYPE_LANG_SPECIFIC (enumtype) = lt;
-
-  /* Fix up all variant types of this enum type.  */
-  for (tem = TYPE_MAIN_VARIANT (enumtype); tem; tem = TYPE_NEXT_VARIANT (tem))
-    {
-      if (tem == enumtype)
-       continue;
-      TYPE_VALUES (tem) = TYPE_VALUES (enumtype);
-      TYPE_MIN_VALUE (tem) = TYPE_MIN_VALUE (enumtype);
-      TYPE_MAX_VALUE (tem) = TYPE_MAX_VALUE (enumtype);
-      TYPE_SIZE (tem) = TYPE_SIZE (enumtype);
-      TYPE_SIZE_UNIT (tem) = TYPE_SIZE_UNIT (enumtype);
-      SET_TYPE_MODE (tem, TYPE_MODE (enumtype));
-      TYPE_PRECISION (tem) = TYPE_PRECISION (enumtype);
-      TYPE_ALIGN (tem) = TYPE_ALIGN (enumtype);
-      TYPE_USER_ALIGN (tem) = TYPE_USER_ALIGN (enumtype);
-      TYPE_UNSIGNED (tem) = TYPE_UNSIGNED (enumtype);
-      TYPE_LANG_SPECIFIC (tem) = TYPE_LANG_SPECIFIC (enumtype);
-    }
-
-  /* Finish debugging output for this type.  */
-  rest_of_type_compilation (enumtype, toplevel);
-
-  /* If this enum is defined inside a struct, add it to
-     struct_types.  */
-  if (warn_cxx_compat
-      && struct_parse_info != NULL
-      && !in_sizeof && !in_typeof && !in_alignof)
-    VEC_safe_push (tree, heap, struct_parse_info->struct_types, enumtype);
-
-  return enumtype;
-}
-
-/* Build and install a CONST_DECL for one value of the
-   current enumeration type (one that was begun with start_enum).
-   DECL_LOC is the location of the enumerator.
-   LOC is the location of the '=' operator if any, DECL_LOC otherwise.
-   Return a tree-list containing the CONST_DECL and its value.
-   Assignment of sequential values by default is handled here.  */
-
-tree
-build_enumerator (location_t decl_loc, location_t loc,
-                 struct c_enum_contents *the_enum, tree name, tree value)
-{
-  tree decl, type;
-
-  /* Validate and default VALUE.  */
-
-  if (value != 0)
-    {
-      /* Don't issue more errors for error_mark_node (i.e. an
-        undeclared identifier) - just ignore the value expression.  */
-      if (value == error_mark_node)
-       value = 0;
-      else if (!INTEGRAL_TYPE_P (TREE_TYPE (value)))
-       {
-         error_at (loc, "enumerator value for %qE is not an integer constant",
-                   name);
-         value = 0;
-       }
-      else
-       {
-         if (TREE_CODE (value) != INTEGER_CST)
-           {
-             value = c_fully_fold (value, false, NULL);
-             if (TREE_CODE (value) == INTEGER_CST)
-               pedwarn (loc, OPT_Wpedantic,
-                        "enumerator value for %qE is not an integer "
-                        "constant expression", name);
-           }
-         if (TREE_CODE (value) != INTEGER_CST)
-           {
-             error ("enumerator value for %qE is not an integer constant",
-                    name);
-             value = 0;
-           }
-         else
-           {
-             value = default_conversion (value);
-             constant_expression_warning (value);
-           }
-       }
-    }
-
-  /* Default based on previous value.  */
-  /* It should no longer be possible to have NON_LVALUE_EXPR
-     in the default.  */
-  if (value == 0)
-    {
-      value = the_enum->enum_next_value;
-      if (the_enum->enum_overflow)
-       error_at (loc, "overflow in enumeration values");
-    }
-  /* Even though the underlying type of an enum is unspecified, the
-     type of enumeration constants is explicitly defined as int
-     (6.4.4.3/2 in the C99 Standard).  GCC allows any integer type as
-     an extension.  */
-  else if (!int_fits_type_p (value, integer_type_node))
-    pedwarn (loc, OPT_Wpedantic,
-            "ISO C restricts enumerator values to range of %<int%>");
-
-  /* The ISO C Standard mandates enumerators to have type int, even
-     though the underlying type of an enum type is unspecified.
-     However, GCC allows enumerators of any integer type as an
-     extensions.  Here we convert any enumerators that fit in an int
-     to type int, to avoid promotions to unsigned types when comparing
-     integers with enumerators that fit in the int range.  When
-     -pedantic is given, we would have already warned about those that
-     don't fit. We have to do this here rather than in finish_enum
-     because this value may be used to define more enumerators.  */
-  if (int_fits_type_p (value, integer_type_node))
-    value = convert (integer_type_node, value);
-
-  /* Set basis for default for next value.  */
-  the_enum->enum_next_value
-    = build_binary_op (EXPR_LOC_OR_HERE (value),
-                      PLUS_EXPR, value, integer_one_node, 0);
-  the_enum->enum_overflow = tree_int_cst_lt (the_enum->enum_next_value, value);
-
-  /* Now create a declaration for the enum value name.  */
-
-  type = TREE_TYPE (value);
-  type = c_common_type_for_size (MAX (TYPE_PRECISION (type),
-                                     TYPE_PRECISION (integer_type_node)),
-                                (TYPE_PRECISION (type)
-                                 >= TYPE_PRECISION (integer_type_node)
-                                 && TYPE_UNSIGNED (type)));
-
-  decl = build_decl (decl_loc, CONST_DECL, name, type);
-  DECL_INITIAL (decl) = convert (type, value);
-  pushdecl (decl);
-
-  return tree_cons (decl, value, NULL_TREE);
-}
-
-\f
-/* Create the FUNCTION_DECL for a function definition.
-   DECLSPECS, DECLARATOR and ATTRIBUTES are the parts of
-   the declaration; they describe the function's name and the type it returns,
-   but twisted together in a fashion that parallels the syntax of C.
-
-   This function creates a binding context for the function body
-   as well as setting up the FUNCTION_DECL in current_function_decl.
-
-   Returns 1 on success.  If the DECLARATOR is not suitable for a function
-   (it defines a datum instead), we return 0, which tells
-   yyparse to report a parse error.  */
-
-int
-start_function (struct c_declspecs *declspecs, struct c_declarator *declarator,
-               tree attributes)
-{
-  tree decl1, old_decl;
-  tree restype, resdecl;
-  location_t loc;
-
-  current_function_returns_value = 0;  /* Assume, until we see it does.  */
-  current_function_returns_null = 0;
-  current_function_returns_abnormally = 0;
-  warn_about_return_type = 0;
-  c_switch_stack = NULL;
-
-  /* Indicate no valid break/continue context by setting these variables
-     to some non-null, non-label value.  We'll notice and emit the proper
-     error message in c_finish_bc_stmt.  */
-  c_break_label = c_cont_label = size_zero_node;
-
-  decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, true, NULL,
-                         &attributes, NULL, NULL, DEPRECATED_NORMAL);
-
-  /* If the declarator is not suitable for a function definition,
-     cause a syntax error.  */
-  if (decl1 == 0
-      || TREE_CODE (decl1) != FUNCTION_DECL)
-    return 0;
-
-  loc = DECL_SOURCE_LOCATION (decl1);
-
-  decl_attributes (&decl1, attributes, 0);
-
-  if (DECL_DECLARED_INLINE_P (decl1)
-      && DECL_UNINLINABLE (decl1)
-      && lookup_attribute ("noinline", DECL_ATTRIBUTES (decl1)))
-    warning_at (loc, OPT_Wattributes,
-               "inline function %qD given attribute noinline",
-               decl1);
-
-  /* Handle gnu_inline attribute.  */
-  if (declspecs->inline_p
-      && !flag_gnu89_inline
-      && TREE_CODE (decl1) == FUNCTION_DECL
-      && (lookup_attribute ("gnu_inline", DECL_ATTRIBUTES (decl1))
-         || current_function_decl))
-    {
-      if (declspecs->storage_class != csc_static)
-       DECL_EXTERNAL (decl1) = !DECL_EXTERNAL (decl1);
-    }
-
-  announce_function (decl1);
-
-  if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl1))))
-    {
-      error_at (loc, "return type is an incomplete type");
-      /* Make it return void instead.  */
-      TREE_TYPE (decl1)
-       = build_function_type (void_type_node,
-                              TYPE_ARG_TYPES (TREE_TYPE (decl1)));
-    }
-
-  if (warn_about_return_type)
-    pedwarn_c99 (loc, flag_isoc99 ? 0
-                : (warn_return_type ? OPT_Wreturn_type : OPT_Wimplicit_int),
-                "return type defaults to %<int%>");
-
-  /* Make the init_value nonzero so pushdecl knows this is not tentative.
-     error_mark_node is replaced below (in pop_scope) with the BLOCK.  */
-  DECL_INITIAL (decl1) = error_mark_node;
-
-  /* A nested function is not global.  */
-  if (current_function_decl != 0)
-    TREE_PUBLIC (decl1) = 0;
-
-  /* If this definition isn't a prototype and we had a prototype declaration
-     before, copy the arg type info from that prototype.  */
-  old_decl = lookup_name_in_scope (DECL_NAME (decl1), current_scope);
-  if (old_decl && TREE_CODE (old_decl) != FUNCTION_DECL)
-    old_decl = 0;
-  current_function_prototype_locus = UNKNOWN_LOCATION;
-  current_function_prototype_built_in = false;
-  current_function_prototype_arg_types = NULL_TREE;
-  if (!prototype_p (TREE_TYPE (decl1)))
-    {
-      if (old_decl != 0 && TREE_CODE (TREE_TYPE (old_decl)) == FUNCTION_TYPE
-         && comptypes (TREE_TYPE (TREE_TYPE (decl1)),
-                       TREE_TYPE (TREE_TYPE (old_decl))))
-       {
-         TREE_TYPE (decl1) = composite_type (TREE_TYPE (old_decl),
-                                             TREE_TYPE (decl1));
-         current_function_prototype_locus = DECL_SOURCE_LOCATION (old_decl);
-         current_function_prototype_built_in
-           = C_DECL_BUILTIN_PROTOTYPE (old_decl);
-         current_function_prototype_arg_types
-           = TYPE_ARG_TYPES (TREE_TYPE (decl1));
-       }
-      if (TREE_PUBLIC (decl1))
-       {
-         /* If there is an external prototype declaration of this
-            function, record its location but do not copy information
-            to this decl.  This may be an invisible declaration
-            (built-in or in a scope which has finished) or simply
-            have more refined argument types than any declaration
-            found above.  */
-         struct c_binding *b;
-         for (b = I_SYMBOL_BINDING (DECL_NAME (decl1)); b; b = b->shadowed)
-           if (B_IN_SCOPE (b, external_scope))
-             break;
-         if (b)
-           {
-             tree ext_decl, ext_type;
-             ext_decl = b->decl;
-             ext_type = b->u.type ? b->u.type : TREE_TYPE (ext_decl);
-             if (TREE_CODE (ext_type) == FUNCTION_TYPE
-                 && comptypes (TREE_TYPE (TREE_TYPE (decl1)),
-                               TREE_TYPE (ext_type)))
-               {
-                 current_function_prototype_locus
-                   = DECL_SOURCE_LOCATION (ext_decl);
-                 current_function_prototype_built_in
-                   = C_DECL_BUILTIN_PROTOTYPE (ext_decl);
-                 current_function_prototype_arg_types
-                   = TYPE_ARG_TYPES (ext_type);
-               }
-           }
-       }
-    }
-
-  /* Optionally warn of old-fashioned def with no previous prototype.  */
-  if (warn_strict_prototypes
-      && old_decl != error_mark_node
-      && !prototype_p (TREE_TYPE (decl1))
-      && C_DECL_ISNT_PROTOTYPE (old_decl))
-    warning_at (loc, OPT_Wstrict_prototypes,
-               "function declaration isn%'t a prototype");
-  /* Optionally warn of any global def with no previous prototype.  */
-  else if (warn_missing_prototypes
-          && old_decl != error_mark_node
-          && TREE_PUBLIC (decl1)
-          && !MAIN_NAME_P (DECL_NAME (decl1))
-          && C_DECL_ISNT_PROTOTYPE (old_decl))
-    warning_at (loc, OPT_Wmissing_prototypes,
-               "no previous prototype for %qD", decl1);
-  /* Optionally warn of any def with no previous prototype
-     if the function has already been used.  */
-  else if (warn_missing_prototypes
-          && old_decl != 0
-          && old_decl != error_mark_node
-          && TREE_USED (old_decl)
-          && !prototype_p (TREE_TYPE (old_decl)))
-    warning_at (loc, OPT_Wmissing_prototypes,
-               "%qD was used with no prototype before its definition", decl1);
-  /* Optionally warn of any global def with no previous declaration.  */
-  else if (warn_missing_declarations
-          && TREE_PUBLIC (decl1)
-          && old_decl == 0
-          && !MAIN_NAME_P (DECL_NAME (decl1)))
-    warning_at (loc, OPT_Wmissing_declarations,
-               "no previous declaration for %qD",
-               decl1);
-  /* Optionally warn of any def with no previous declaration
-     if the function has already been used.  */
-  else if (warn_missing_declarations
-          && old_decl != 0
-          && old_decl != error_mark_node
-          && TREE_USED (old_decl)
-          && C_DECL_IMPLICIT (old_decl))
-    warning_at (loc, OPT_Wmissing_declarations,
-               "%qD was used with no declaration before its definition", decl1);
-
-  /* This function exists in static storage.
-     (This does not mean `static' in the C sense!)  */
-  TREE_STATIC (decl1) = 1;
-
-  /* This is the earliest point at which we might know the assembler
-     name of the function.  Thus, if it's set before this, die horribly.  */
-  gcc_assert (!DECL_ASSEMBLER_NAME_SET_P (decl1));
-
-  /* If #pragma weak was used, mark the decl weak now.  */
-  if (current_scope == file_scope)
-    maybe_apply_pragma_weak (decl1);
-
-  /* Warn for unlikely, improbable, or stupid declarations of `main'.  */
-  if (warn_main && MAIN_NAME_P (DECL_NAME (decl1)))
-    {
-      if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (decl1)))
-         != integer_type_node)
-       pedwarn (loc, OPT_Wmain, "return type of %qD is not %<int%>", decl1);
-
-      check_main_parameter_types (decl1);
-
-      if (!TREE_PUBLIC (decl1))
-       pedwarn (loc, OPT_Wmain,
-                "%qD is normally a non-static function", decl1);
-    }
-
-  /* Record the decl so that the function name is defined.
-     If we already have a decl for this name, and it is a FUNCTION_DECL,
-     use the old decl.  */
-
-  current_function_decl = pushdecl (decl1);
-
-  push_scope ();
-  declare_parm_level ();
-
-  restype = TREE_TYPE (TREE_TYPE (current_function_decl));
-  resdecl = build_decl (loc, RESULT_DECL, NULL_TREE, restype);
-  DECL_ARTIFICIAL (resdecl) = 1;
-  DECL_IGNORED_P (resdecl) = 1;
-  DECL_RESULT (current_function_decl) = resdecl;
-
-  start_fname_decls ();
-
-  return 1;
-}
-\f
-/* Subroutine of store_parm_decls which handles new-style function
-   definitions (prototype format). The parms already have decls, so we
-   need only record them as in effect and complain if any redundant
-   old-style parm decls were written.  */
-static void
-store_parm_decls_newstyle (tree fndecl, const struct c_arg_info *arg_info)
-{
-  tree decl;
-  c_arg_tag *tag;
-  unsigned ix;
-
-  if (current_scope->bindings)
-    {
-      error_at (DECL_SOURCE_LOCATION (fndecl),
-               "old-style parameter declarations in prototyped "
-               "function definition");
-
-      /* Get rid of the old-style declarations.  */
-      pop_scope ();
-      push_scope ();
-    }
-  /* Don't issue this warning for nested functions, and don't issue this
-     warning if we got here because ARG_INFO_TYPES was error_mark_node
-     (this happens when a function definition has just an ellipsis in
-     its parameter list).  */
-  else if (!in_system_header && !current_function_scope
-          && arg_info->types != error_mark_node)
-    warning_at (DECL_SOURCE_LOCATION (fndecl), OPT_Wtraditional,
-               "traditional C rejects ISO C style function definitions");
-
-  /* Now make all the parameter declarations visible in the function body.
-     We can bypass most of the grunt work of pushdecl.  */
-  for (decl = arg_info->parms; decl; decl = DECL_CHAIN (decl))
-    {
-      DECL_CONTEXT (decl) = current_function_decl;
-      if (DECL_NAME (decl))
-       {
-         bind (DECL_NAME (decl), decl, current_scope,
-               /*invisible=*/false, /*nested=*/false,
-               UNKNOWN_LOCATION);
-         if (!TREE_USED (decl))
-           warn_if_shadowing (decl);
-       }
-      else
-       error_at (DECL_SOURCE_LOCATION (decl), "parameter name omitted");
-    }
-
-  /* Record the parameter list in the function declaration.  */
-  DECL_ARGUMENTS (fndecl) = arg_info->parms;
-
-  /* Now make all the ancillary declarations visible, likewise.  */
-  for (decl = arg_info->others; decl; decl = DECL_CHAIN (decl))
-    {
-      DECL_CONTEXT (decl) = current_function_decl;
-      if (DECL_NAME (decl))
-       bind (DECL_NAME (decl), decl, current_scope,
-             /*invisible=*/false,
-             /*nested=*/(TREE_CODE (decl) == FUNCTION_DECL),
-             UNKNOWN_LOCATION);
-    }
-
-  /* And all the tag declarations.  */
-  FOR_EACH_VEC_ELT_REVERSE (c_arg_tag, arg_info->tags, ix, tag)
-    if (tag->id)
-      bind (tag->id, tag->type, current_scope,
-           /*invisible=*/false, /*nested=*/false, UNKNOWN_LOCATION);
-}
-
-/* Subroutine of store_parm_decls which handles old-style function
-   definitions (separate parameter list and declarations).  */
-
-static void
-store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
-{
-  struct c_binding *b;
-  tree parm, decl, last;
-  tree parmids = arg_info->parms;
-  struct pointer_set_t *seen_args = pointer_set_create ();
-
-  if (!in_system_header)
-    warning_at (DECL_SOURCE_LOCATION (fndecl),
-               OPT_Wold_style_definition, "old-style function definition");
-
-  /* Match each formal parameter name with its declaration.  Save each
-     decl in the appropriate TREE_PURPOSE slot of the parmids chain.  */
-  for (parm = parmids; parm; parm = TREE_CHAIN (parm))
-    {
-      if (TREE_VALUE (parm) == 0)
-       {
-         error_at (DECL_SOURCE_LOCATION (fndecl),
-                   "parameter name missing from parameter list");
-         TREE_PURPOSE (parm) = 0;
-         continue;
-       }
-
-      b = I_SYMBOL_BINDING (TREE_VALUE (parm));
-      if (b && B_IN_CURRENT_SCOPE (b))
-       {
-         decl = b->decl;
-         /* Skip erroneous parameters.  */
-         if (decl == error_mark_node)
-           continue;
-         /* If we got something other than a PARM_DECL it is an error.  */
-         if (TREE_CODE (decl) != PARM_DECL)
-           error_at (DECL_SOURCE_LOCATION (decl),
-                     "%qD declared as a non-parameter", decl);
-         /* If the declaration is already marked, we have a duplicate
-            name.  Complain and ignore the duplicate.  */
-         else if (pointer_set_contains (seen_args, decl))
-           {
-             error_at (DECL_SOURCE_LOCATION (decl),
-                       "multiple parameters named %qD", decl);
-             TREE_PURPOSE (parm) = 0;
-             continue;
-           }
-         /* If the declaration says "void", complain and turn it into
-            an int.  */
-         else if (VOID_TYPE_P (TREE_TYPE (decl)))
-           {
-             error_at (DECL_SOURCE_LOCATION (decl),
-                       "parameter %qD declared with void type", decl);
-             TREE_TYPE (decl) = integer_type_node;
-             DECL_ARG_TYPE (decl) = integer_type_node;
-             layout_decl (decl, 0);
-           }
-         warn_if_shadowing (decl);
-       }
-      /* If no declaration found, default to int.  */
-      else
-       {
-         /* FIXME diagnostics: This should be the location of the argument,
-            not the FNDECL.  E.g., for an old-style declaration
-
-              int f10(v) { blah; }
-
-            We should use the location of the V, not the F10.
-            Unfortunately, the V is an IDENTIFIER_NODE which has no
-            location.  In the future we need locations for c_arg_info
-            entries.
-
-            See gcc.dg/Wshadow-3.c for an example of this problem. */
-         decl = build_decl (DECL_SOURCE_LOCATION (fndecl),
-                            PARM_DECL, TREE_VALUE (parm), integer_type_node);
-         DECL_ARG_TYPE (decl) = TREE_TYPE (decl);
-         pushdecl (decl);
-         warn_if_shadowing (decl);
-
-         if (flag_isoc99)
-           pedwarn (DECL_SOURCE_LOCATION (decl),
-                    0, "type of %qD defaults to %<int%>", decl);
-         else
-           warning_at (DECL_SOURCE_LOCATION (decl),
-                       OPT_Wmissing_parameter_type,
-                       "type of %qD defaults to %<int%>", decl);
-       }
-
-      TREE_PURPOSE (parm) = decl;
-      pointer_set_insert (seen_args, decl);
-    }
-
-  /* Now examine the parms chain for incomplete declarations
-     and declarations with no corresponding names.  */
-
-  for (b = current_scope->bindings; b; b = b->prev)
-    {
-      parm = b->decl;
-      if (TREE_CODE (parm) != PARM_DECL)
-       continue;
-
-      if (TREE_TYPE (parm) != error_mark_node
-         && !COMPLETE_TYPE_P (TREE_TYPE (parm)))
-       {
-         error_at (DECL_SOURCE_LOCATION (parm),
-                   "parameter %qD has incomplete type", parm);
-         TREE_TYPE (parm) = error_mark_node;
-       }
-
-      if (!pointer_set_contains (seen_args, parm))
-       {
-         error_at (DECL_SOURCE_LOCATION (parm),
-                   "declaration for parameter %qD but no such parameter",
-                   parm);
-
-         /* Pretend the parameter was not missing.
-            This gets us to a standard state and minimizes
-            further error messages.  */
-         parmids = chainon (parmids, tree_cons (parm, 0, 0));
-       }
-    }
-
-  /* Chain the declarations together in the order of the list of
-     names.  Store that chain in the function decl, replacing the
-     list of names.  Update the current scope to match.  */
-  DECL_ARGUMENTS (fndecl) = 0;
-
-  for (parm = parmids; parm; parm = TREE_CHAIN (parm))
-    if (TREE_PURPOSE (parm))
-      break;
-  if (parm && TREE_PURPOSE (parm))
-    {
-      last = TREE_PURPOSE (parm);
-      DECL_ARGUMENTS (fndecl) = last;
-
-      for (parm = TREE_CHAIN (parm); parm; parm = TREE_CHAIN (parm))
-       if (TREE_PURPOSE (parm))
-         {
-           DECL_CHAIN (last) = TREE_PURPOSE (parm);
-           last = TREE_PURPOSE (parm);
-         }
-      DECL_CHAIN (last) = 0;
-    }
-
-  pointer_set_destroy (seen_args);
-
-  /* If there was a previous prototype,
-     set the DECL_ARG_TYPE of each argument according to
-     the type previously specified, and report any mismatches.  */
-
-  if (current_function_prototype_arg_types)
-    {
-      tree type;
-      for (parm = DECL_ARGUMENTS (fndecl),
-            type = current_function_prototype_arg_types;
-          parm || (type && TREE_VALUE (type) != error_mark_node
-                   && (TYPE_MAIN_VARIANT (TREE_VALUE (type)) != void_type_node));
-          parm = DECL_CHAIN (parm), type = TREE_CHAIN (type))
-       {
-         if (parm == 0 || type == 0
-             || TYPE_MAIN_VARIANT (TREE_VALUE (type)) == void_type_node)
-           {
-             if (current_function_prototype_built_in)
-               warning_at (DECL_SOURCE_LOCATION (fndecl),
-                           0, "number of arguments doesn%'t match "
-                           "built-in prototype");
-             else
-               {
-                 /* FIXME diagnostics: This should be the location of
-                    FNDECL, but there is bug when a prototype is
-                    declared inside function context, but defined
-                    outside of it (e.g., gcc.dg/pr15698-2.c).  In
-                    which case FNDECL gets the location of the
-                    prototype, not the definition.  */
-                 error_at (input_location,
-                           "number of arguments doesn%'t match prototype");
-
-                 error_at (current_function_prototype_locus,
-                           "prototype declaration");
-               }
-             break;
-           }
-         /* Type for passing arg must be consistent with that
-            declared for the arg.  ISO C says we take the unqualified
-            type for parameters declared with qualified type.  */
-         if (TREE_TYPE (parm) != error_mark_node
-             && TREE_TYPE (type) != error_mark_node
-             && !comptypes (TYPE_MAIN_VARIANT (DECL_ARG_TYPE (parm)),
-                            TYPE_MAIN_VARIANT (TREE_VALUE (type))))
-           {
-             if (TYPE_MAIN_VARIANT (TREE_TYPE (parm))
-                 == TYPE_MAIN_VARIANT (TREE_VALUE (type)))
-               {
-                 /* Adjust argument to match prototype.  E.g. a previous
-                    `int foo(float);' prototype causes
-                    `int foo(x) float x; {...}' to be treated like
-                    `int foo(float x) {...}'.  This is particularly
-                    useful for argument types like uid_t.  */
-                 DECL_ARG_TYPE (parm) = TREE_TYPE (parm);
-
-                 if (targetm.calls.promote_prototypes (TREE_TYPE (current_function_decl))
-                     && INTEGRAL_TYPE_P (TREE_TYPE (parm))
-                     && TYPE_PRECISION (TREE_TYPE (parm))
-                     < TYPE_PRECISION (integer_type_node))
-                   DECL_ARG_TYPE (parm) = integer_type_node;
-
-                 /* ??? Is it possible to get here with a
-                    built-in prototype or will it always have
-                    been diagnosed as conflicting with an
-                    old-style definition and discarded?  */
-                 if (current_function_prototype_built_in)
-                   warning_at (DECL_SOURCE_LOCATION (parm),
-                               OPT_Wpedantic, "promoted argument %qD "
-                               "doesn%'t match built-in prototype", parm);
-                 else
-                   {
-                     pedwarn (DECL_SOURCE_LOCATION (parm),
-                              OPT_Wpedantic, "promoted argument %qD "
-                              "doesn%'t match prototype", parm);
-                     pedwarn (current_function_prototype_locus, OPT_Wpedantic,
-                              "prototype declaration");
-                   }
-               }
-             else
-               {
-                 if (current_function_prototype_built_in)
-                   warning_at (DECL_SOURCE_LOCATION (parm),
-                               0, "argument %qD doesn%'t match "
-                               "built-in prototype", parm);
-                 else
-                   {
-                     error_at (DECL_SOURCE_LOCATION (parm),
-                               "argument %qD doesn%'t match prototype", parm);
-                     error_at (current_function_prototype_locus,
-                               "prototype declaration");
-                   }
-               }
-           }
-       }
-      TYPE_ACTUAL_ARG_TYPES (TREE_TYPE (fndecl)) = 0;
-    }
-
-  /* Otherwise, create a prototype that would match.  */
-
-  else
-    {
-      tree actual = 0, last = 0, type;
-
-      for (parm = DECL_ARGUMENTS (fndecl); parm; parm = DECL_CHAIN (parm))
-       {
-         type = tree_cons (NULL_TREE, DECL_ARG_TYPE (parm), NULL_TREE);
-         if (last)
-           TREE_CHAIN (last) = type;
-         else
-           actual = type;
-         last = type;
-       }
-      type = tree_cons (NULL_TREE, void_type_node, NULL_TREE);
-      if (last)
-       TREE_CHAIN (last) = type;
-      else
-       actual = type;
-
-      /* We are going to assign a new value for the TYPE_ACTUAL_ARG_TYPES
-        of the type of this function, but we need to avoid having this
-        affect the types of other similarly-typed functions, so we must
-        first force the generation of an identical (but separate) type
-        node for the relevant function type.  The new node we create
-        will be a variant of the main variant of the original function
-        type.  */
-
-      TREE_TYPE (fndecl) = build_variant_type_copy (TREE_TYPE (fndecl));
-
-      TYPE_ACTUAL_ARG_TYPES (TREE_TYPE (fndecl)) = actual;
-    }
-}
-
-/* Store parameter declarations passed in ARG_INFO into the current
-   function declaration.  */
-
-void
-store_parm_decls_from (struct c_arg_info *arg_info)
-{
-  current_function_arg_info = arg_info;
-  store_parm_decls ();
-}
-
-/* Store the parameter declarations into the current function declaration.
-   This is called after parsing the parameter declarations, before
-   digesting the body of the function.
-
-   For an old-style definition, construct a prototype out of the old-style
-   parameter declarations and inject it into the function's type.  */
-
-void
-store_parm_decls (void)
-{
-  tree fndecl = current_function_decl;
-  bool proto;
-
-  /* The argument information block for FNDECL.  */
-  struct c_arg_info *arg_info = current_function_arg_info;
-  current_function_arg_info = 0;
-
-  /* True if this definition is written with a prototype.  Note:
-     despite C99 6.7.5.3p14, we can *not* treat an empty argument
-     list in a function definition as equivalent to (void) -- an
-     empty argument list specifies the function has no parameters,
-     but only (void) sets up a prototype for future calls.  */
-  proto = arg_info->types != 0;
-
-  if (proto)
-    store_parm_decls_newstyle (fndecl, arg_info);
-  else
-    store_parm_decls_oldstyle (fndecl, arg_info);
-
-  /* The next call to push_scope will be a function body.  */
-
-  next_is_function_body = true;
-
-  /* Write a record describing this function definition to the prototypes
-     file (if requested).  */
-
-  gen_aux_info_record (fndecl, 1, 0, proto);
-
-  /* Initialize the RTL code for the function.  */
-  allocate_struct_function (fndecl, false);
-
-  if (warn_unused_local_typedefs)
-    cfun->language = ggc_alloc_cleared_language_function ();
-
-  /* Begin the statement tree for this function.  */
-  DECL_SAVED_TREE (fndecl) = push_stmt_list ();
-
-  /* ??? Insert the contents of the pending sizes list into the function
-     to be evaluated.  The only reason left to have this is
-       void foo(int n, int array[n++])
-     because we throw away the array type in favor of a pointer type, and
-     thus won't naturally see the SAVE_EXPR containing the increment.  All
-     other pending sizes would be handled by gimplify_parameters.  */
-  if (arg_info->pending_sizes)
-    add_stmt (arg_info->pending_sizes);
-}
-\f
-
-/* Finish up a function declaration and compile that function
-   all the way to assembler language output.  Then free the storage
-   for the function definition.
-
-   This is called after parsing the body of the function definition.  */
-
-void
-finish_function (void)
-{
-  tree fndecl = current_function_decl;
-  
-  if (c_dialect_objc ())
-    objc_finish_function ();
-
-  if (TREE_CODE (fndecl) == FUNCTION_DECL
-      && targetm.calls.promote_prototypes (TREE_TYPE (fndecl)))
-    {
-      tree args = DECL_ARGUMENTS (fndecl);
-      for (; args; args = DECL_CHAIN (args))
-       {
-         tree type = TREE_TYPE (args);
-         if (INTEGRAL_TYPE_P (type)
-             && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
-           DECL_ARG_TYPE (args) = integer_type_node;
-       }
-    }
-
-  if (DECL_INITIAL (fndecl) && DECL_INITIAL (fndecl) != error_mark_node)
-    BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
-
-  /* Must mark the RESULT_DECL as being in this function.  */
-
-  if (DECL_RESULT (fndecl) && DECL_RESULT (fndecl) != error_mark_node)
-    DECL_CONTEXT (DECL_RESULT (fndecl)) = fndecl;
-
-  if (MAIN_NAME_P (DECL_NAME (fndecl)) && flag_hosted
-      && TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (fndecl)))
-      == integer_type_node && flag_isoc99)
-    {
-      /* Hack.  We don't want the middle-end to warn that this return
-        is unreachable, so we mark its location as special.  Using
-        UNKNOWN_LOCATION has the problem that it gets clobbered in
-        annotate_one_with_locus.  A cleaner solution might be to
-        ensure ! should_carry_locus_p (stmt), but that needs a flag.
-      */
-      c_finish_return (BUILTINS_LOCATION, integer_zero_node, NULL_TREE);
-    }
-
-  /* Tie off the statement tree for this function.  */
-  DECL_SAVED_TREE (fndecl) = pop_stmt_list (DECL_SAVED_TREE (fndecl));
-
-  finish_fname_decls ();
-
-  /* Complain if there's just no return statement.  */
-  if (warn_return_type
-      && TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE
-      && !current_function_returns_value && !current_function_returns_null
-      /* Don't complain if we are no-return.  */
-      && !current_function_returns_abnormally
-      /* Don't complain if we are declared noreturn.  */
-      && !TREE_THIS_VOLATILE (fndecl)
-      /* Don't warn for main().  */
-      && !MAIN_NAME_P (DECL_NAME (fndecl))
-      /* Or if they didn't actually specify a return type.  */
-      && !C_FUNCTION_IMPLICIT_INT (fndecl)
-      /* Normally, with -Wreturn-type, flow will complain, but we might
-         optimize out static functions.  */
-      && !TREE_PUBLIC (fndecl))
-    {
-      warning (OPT_Wreturn_type,
-              "no return statement in function returning non-void");
-      TREE_NO_WARNING (fndecl) = 1;
-    }
-
-  /* Complain about parameters that are only set, but never otherwise used.  */
-  if (warn_unused_but_set_parameter)
-    {
-      tree decl;
-
-      for (decl = DECL_ARGUMENTS (fndecl);
-          decl;
-          decl = DECL_CHAIN (decl))
-       if (TREE_USED (decl)
-           && TREE_CODE (decl) == PARM_DECL
-           && !DECL_READ_P (decl)
-           && DECL_NAME (decl)
-           && !DECL_ARTIFICIAL (decl)
-           && !TREE_NO_WARNING (decl))
-         warning_at (DECL_SOURCE_LOCATION (decl),
-                     OPT_Wunused_but_set_parameter,
-                     "parameter %qD set but not used", decl);
-    }
-
-  /* Complain about locally defined typedefs that are not used in this
-     function.  */
-  maybe_warn_unused_local_typedefs ();
-
-  /* Store the end of the function, so that we get good line number
-     info for the epilogue.  */
-  cfun->function_end_locus = input_location;
-
-  /* Finalize the ELF visibility for the function.  */
-  c_determine_visibility (fndecl);
-
-  /* For GNU C extern inline functions disregard inline limits.  */
-  if (DECL_EXTERNAL (fndecl)
-      && DECL_DECLARED_INLINE_P (fndecl))
-    DECL_DISREGARD_INLINE_LIMITS (fndecl) = 1;
-
-  /* Genericize before inlining.  Delay genericizing nested functions
-     until their parent function is genericized.  Since finalizing
-     requires GENERIC, delay that as well.  */
-
-  if (DECL_INITIAL (fndecl) && DECL_INITIAL (fndecl) != error_mark_node
-      && !undef_nested_function)
-    {
-      if (!decl_function_context (fndecl))
-       {
-         invoke_plugin_callbacks (PLUGIN_PRE_GENERICIZE, fndecl);
-         c_genericize (fndecl);
-
-         /* ??? Objc emits functions after finalizing the compilation unit.
-            This should be cleaned up later and this conditional removed.  */
-         if (cgraph_global_info_ready)
-           {
-             cgraph_add_new_function (fndecl, false);
-             return;
-           }
-         cgraph_finalize_function (fndecl, false);
-       }
-      else
-       {
-         /* Register this function with cgraph just far enough to get it
-           added to our parent's nested function list.  Handy, since the
-           C front end doesn't have such a list.  */
-         (void) cgraph_get_create_node (fndecl);
-       }
-    }
-
-  if (!decl_function_context (fndecl))
-    undef_nested_function = false;
-
-  if (cfun->language != NULL)
-    {
-      ggc_free (cfun->language);
-      cfun->language = NULL;
-    }
-
-  /* We're leaving the context of this function, so zap cfun.
-     It's still in DECL_STRUCT_FUNCTION, and we'll restore it in
-     tree_rest_of_compilation.  */
-  set_cfun (NULL);
-  current_function_decl = NULL;
-}
-\f
-/* Check the declarations given in a for-loop for satisfying the C99
-   constraints.  If exactly one such decl is found, return it.  LOC is
-   the location of the opening parenthesis of the for loop.  The last
-   parameter allows you to control the "for loop initial declarations
-   are only allowed in C99 mode".  Normally, you should pass
-   flag_isoc99 as that parameter.  But in some cases (Objective-C
-   foreach loop, for example) we want to run the checks in this
-   function even if not in C99 mode, so we allow the caller to turn
-   off the error about not being in C99 mode.
-*/
-
-tree
-check_for_loop_decls (location_t loc, bool turn_off_iso_c99_error)
-{
-  struct c_binding *b;
-  tree one_decl = NULL_TREE;
-  int n_decls = 0;
-
-  if (!turn_off_iso_c99_error)
-    {
-      static bool hint = true;
-      /* If we get here, declarations have been used in a for loop without
-        the C99 for loop scope.  This doesn't make much sense, so don't
-        allow it.  */
-      error_at (loc, "%<for%> loop initial declarations "
-               "are only allowed in C99 mode");
-      if (hint)
-       {
-         inform (loc,
-                 "use option -std=c99 or -std=gnu99 to compile your code");
-         hint = false;
-       }
-      return NULL_TREE;
-    }
-  /* C99 subclause 6.8.5 paragraph 3:
-
-       [#3]  The  declaration  part  of  a for statement shall only
-       declare identifiers for objects having storage class auto or
-       register.
-
-     It isn't clear whether, in this sentence, "identifiers" binds to
-     "shall only declare" or to "objects" - that is, whether all identifiers
-     declared must be identifiers for objects, or whether the restriction
-     only applies to those that are.  (A question on this in comp.std.c
-     in November 2000 received no answer.)  We implement the strictest
-     interpretation, to avoid creating an extension which later causes
-     problems.  */
-
-  for (b = current_scope->bindings; b; b = b->prev)
-    {
-      tree id = b->id;
-      tree decl = b->decl;
-
-      if (!id)
-       continue;
-
-      switch (TREE_CODE (decl))
-       {
-       case VAR_DECL:
-         {
-           location_t decl_loc = DECL_SOURCE_LOCATION (decl);
-           if (TREE_STATIC (decl))
-             error_at (decl_loc,
-                       "declaration of static variable %qD in %<for%> loop "
-                       "initial declaration", decl);
-           else if (DECL_EXTERNAL (decl))
-             error_at (decl_loc,
-                       "declaration of %<extern%> variable %qD in %<for%> loop "
-                       "initial declaration", decl);
-         }
-         break;
-
-       case RECORD_TYPE:
-         error_at (loc,
-                   "%<struct %E%> declared in %<for%> loop initial "
-                   "declaration", id);
-         break;
-       case UNION_TYPE:
-         error_at (loc,
-                   "%<union %E%> declared in %<for%> loop initial declaration",
-                   id);
-         break;
-       case ENUMERAL_TYPE:
-         error_at (loc, "%<enum %E%> declared in %<for%> loop "
-                   "initial declaration", id);
-         break;
-       default:
-         error_at (loc, "declaration of non-variable "
-                   "%qD in %<for%> loop initial declaration", decl);
-       }
-
-      n_decls++;
-      one_decl = decl;
-    }
-
-  return n_decls == 1 ? one_decl : NULL_TREE;
-}
-\f
-/* Save and reinitialize the variables
-   used during compilation of a C function.  */
-
-void
-c_push_function_context (void)
-{
-  struct language_function *p = cfun->language;
-  /* cfun->language might have been already allocated by the use of
-     -Wunused-local-typedefs.  In that case, just re-use it.  */
-  if (p == NULL)
-    cfun->language = p = ggc_alloc_cleared_language_function ();
-
-  p->base.x_stmt_tree = c_stmt_tree;
-  c_stmt_tree.x_cur_stmt_list
-    = VEC_copy (tree, gc, c_stmt_tree.x_cur_stmt_list);
-  p->x_break_label = c_break_label;
-  p->x_cont_label = c_cont_label;
-  p->x_switch_stack = c_switch_stack;
-  p->arg_info = current_function_arg_info;
-  p->returns_value = current_function_returns_value;
-  p->returns_null = current_function_returns_null;
-  p->returns_abnormally = current_function_returns_abnormally;
-  p->warn_about_return_type = warn_about_return_type;
-
-  push_function_context ();
-}
-
-/* Restore the variables used during compilation of a C function.  */
-
-void
-c_pop_function_context (void)
-{
-  struct language_function *p;
-
-  pop_function_context ();
-  p = cfun->language;
-
-  /* When -Wunused-local-typedefs is in effect, cfun->languages is
-     used to store data throughout the life time of the current cfun,
-     So don't deallocate it.  */
-  if (!warn_unused_local_typedefs)
-    cfun->language = NULL;
-
-  if (DECL_STRUCT_FUNCTION (current_function_decl) == 0
-      && DECL_SAVED_TREE (current_function_decl) == NULL_TREE)
-    {
-      /* Stop pointing to the local nodes about to be freed.  */
-      /* But DECL_INITIAL must remain nonzero so we know this
-        was an actual function definition.  */
-      DECL_INITIAL (current_function_decl) = error_mark_node;
-      DECL_ARGUMENTS (current_function_decl) = 0;
-    }
-
-  c_stmt_tree = p->base.x_stmt_tree;
-  p->base.x_stmt_tree.x_cur_stmt_list = NULL;
-  c_break_label = p->x_break_label;
-  c_cont_label = p->x_cont_label;
-  c_switch_stack = p->x_switch_stack;
-  current_function_arg_info = p->arg_info;
-  current_function_returns_value = p->returns_value;
-  current_function_returns_null = p->returns_null;
-  current_function_returns_abnormally = p->returns_abnormally;
-  warn_about_return_type = p->warn_about_return_type;
-}
-
-/* The functions below are required for functionality of doing
-   function at once processing in the C front end. Currently these
-   functions are not called from anywhere in the C front end, but as
-   these changes continue, that will change.  */
-
-/* Returns the stmt_tree (if any) to which statements are currently
-   being added.  If there is no active statement-tree, NULL is
-   returned.  */
-
-stmt_tree
-current_stmt_tree (void)
-{
-  return &c_stmt_tree;
-}
-
-/* Return the global value of T as a symbol.  */
-
-tree
-identifier_global_value        (tree t)
-{
-  struct c_binding *b;
-
-  for (b = I_SYMBOL_BINDING (t); b; b = b->shadowed)
-    if (B_IN_FILE_SCOPE (b) || B_IN_EXTERNAL_SCOPE (b))
-      return b->decl;
-
-  return 0;
-}
-
-/* In C, the only C-linkage public declaration is at file scope.  */
-
-tree
-c_linkage_bindings (tree name)
-{
-  return identifier_global_value (name);
-}
-
-/* Record a builtin type for C.  If NAME is non-NULL, it is the name used;
-   otherwise the name is found in ridpointers from RID_INDEX.  */
-
-void
-record_builtin_type (enum rid rid_index, const char *name, tree type)
-{
-  tree id, decl;
-  if (name == 0)
-    id = ridpointers[(int) rid_index];
-  else
-    id = get_identifier (name);
-  decl = build_decl (UNKNOWN_LOCATION, TYPE_DECL, id, type);
-  pushdecl (decl);
-  if (debug_hooks->type_decl)
-    debug_hooks->type_decl (decl, false);
-}
-
-/* Build the void_list_node (void_type_node having been created).  */
-tree
-build_void_list_node (void)
-{
-  tree t = build_tree_list (NULL_TREE, void_type_node);
-  return t;
-}
-
-/* Return a c_parm structure with the given SPECS, ATTRS and DECLARATOR.  */
-
-struct c_parm *
-build_c_parm (struct c_declspecs *specs, tree attrs,
-             struct c_declarator *declarator)
-{
-  struct c_parm *ret = XOBNEW (&parser_obstack, struct c_parm);
-  ret->specs = specs;
-  ret->attrs = attrs;
-  ret->declarator = declarator;
-  return ret;
-}
-
-/* Return a declarator with nested attributes.  TARGET is the inner
-   declarator to which these attributes apply.  ATTRS are the
-   attributes.  */
-
-struct c_declarator *
-build_attrs_declarator (tree attrs, struct c_declarator *target)
-{
-  struct c_declarator *ret = XOBNEW (&parser_obstack, struct c_declarator);
-  ret->kind = cdk_attrs;
-  ret->declarator = target;
-  ret->u.attrs = attrs;
-  return ret;
-}
-
-/* Return a declarator for a function with arguments specified by ARGS
-   and return type specified by TARGET.  */
-
-struct c_declarator *
-build_function_declarator (struct c_arg_info *args,
-                          struct c_declarator *target)
-{
-  struct c_declarator *ret = XOBNEW (&parser_obstack, struct c_declarator);
-  ret->kind = cdk_function;
-  ret->declarator = target;
-  ret->u.arg_info = args;
-  return ret;
-}
-
-/* Return a declarator for the identifier IDENT (which may be
-   NULL_TREE for an abstract declarator).  */
-
-struct c_declarator *
-build_id_declarator (tree ident)
-{
-  struct c_declarator *ret = XOBNEW (&parser_obstack, struct c_declarator);
-  ret->kind = cdk_id;
-  ret->declarator = 0;
-  ret->u.id = ident;
-  /* Default value - may get reset to a more precise location. */
-  ret->id_loc = input_location;
-  return ret;
-}
-
-/* Return something to represent absolute declarators containing a *.
-   TARGET is the absolute declarator that the * contains.
-   TYPE_QUALS_ATTRS is a structure for type qualifiers and attributes
-   to apply to the pointer type.  */
-
-struct c_declarator *
-make_pointer_declarator (struct c_declspecs *type_quals_attrs,
-                        struct c_declarator *target)
-{
-  tree attrs;
-  int quals = 0;
-  struct c_declarator *itarget = target;
-  struct c_declarator *ret = XOBNEW (&parser_obstack, struct c_declarator);
-  if (type_quals_attrs)
-    {
-      attrs = type_quals_attrs->attrs;
-      quals = quals_from_declspecs (type_quals_attrs);
-      if (attrs != NULL_TREE)
-       itarget = build_attrs_declarator (attrs, target);
-    }
-  ret->kind = cdk_pointer;
-  ret->declarator = itarget;
-  ret->u.pointer_quals = quals;
-  return ret;
-}
-
-/* Return a pointer to a structure for an empty list of declaration
-   specifiers.  */
-
-struct c_declspecs *
-build_null_declspecs (void)
-{
-  struct c_declspecs *ret = XOBNEW (&parser_obstack, struct c_declspecs);
-  memset (&ret->locations, 0, cdw_number_of_elements);
-  ret->type = 0;
-  ret->expr = 0;
-  ret->decl_attr = 0;
-  ret->attrs = 0;
-  ret->align_log = -1;
-  ret->typespec_word = cts_none;
-  ret->storage_class = csc_none;
-  ret->expr_const_operands = true;
-  ret->declspecs_seen_p = false;
-  ret->typespec_kind = ctsk_none;
-  ret->non_sc_seen_p = false;
-  ret->typedef_p = false;
-  ret->explicit_signed_p = false;
-  ret->deprecated_p = false;
-  ret->default_int_p = false;
-  ret->long_p = false;
-  ret->long_long_p = false;
-  ret->short_p = false;
-  ret->signed_p = false;
-  ret->unsigned_p = false;
-  ret->complex_p = false;
-  ret->inline_p = false;
-  ret->noreturn_p = false;
-  ret->thread_p = false;
-  ret->const_p = false;
-  ret->volatile_p = false;
-  ret->restrict_p = false;
-  ret->saturating_p = false;
-  ret->alignas_p = false;
-  ret->address_space = ADDR_SPACE_GENERIC;
-  return ret;
-}
-
-/* Add the address space ADDRSPACE to the declaration specifiers
-   SPECS, returning SPECS.  */
-
-struct c_declspecs *
-declspecs_add_addrspace (source_location location,
-                        struct c_declspecs *specs, addr_space_t as)
-{
-  specs->non_sc_seen_p = true;
-  specs->declspecs_seen_p = true;
-
-  if (!ADDR_SPACE_GENERIC_P (specs->address_space)
-      && specs->address_space != as)
-    error ("incompatible address space qualifiers %qs and %qs",
-          c_addr_space_name (as),
-          c_addr_space_name (specs->address_space));
-  else
-    {
-      specs->address_space = as;
-      specs->locations[cdw_address_space] = location;
-    }
-  return specs;
-}
-
-/* Add the type qualifier QUAL to the declaration specifiers SPECS,
-   returning SPECS.  */
-
-struct c_declspecs *
-declspecs_add_qual (source_location loc,
-                   struct c_declspecs *specs, tree qual)
-{
-  enum rid i;
-  bool dupe = false;
-  specs->non_sc_seen_p = true;
-  specs->declspecs_seen_p = true;
-  gcc_assert (TREE_CODE (qual) == IDENTIFIER_NODE
-             && C_IS_RESERVED_WORD (qual));
-  i = C_RID_CODE (qual);
-  switch (i)
-    {
-    case RID_CONST:
-      dupe = specs->const_p;
-      specs->const_p = true;
-      specs->locations[cdw_const] = loc;
-      break;
-    case RID_VOLATILE:
-      dupe = specs->volatile_p;
-      specs->volatile_p = true;
-      specs->locations[cdw_volatile] = loc;
-      break;
-    case RID_RESTRICT:
-      dupe = specs->restrict_p;
-      specs->restrict_p = true;
-      specs->locations[cdw_restrict] = loc;
-      break;
-    default:
-      gcc_unreachable ();
-    }
-  if (dupe && !flag_isoc99)
-    pedwarn (loc, OPT_Wpedantic, "duplicate %qE", qual);
-  return specs;
-}
-
-/* Add the type specifier TYPE to the declaration specifiers SPECS,
-   returning SPECS.  */
-
-struct c_declspecs *
-declspecs_add_type (location_t loc, struct c_declspecs *specs,
-                   struct c_typespec spec)
-{
-  tree type = spec.spec;
-  specs->non_sc_seen_p = true;
-  specs->declspecs_seen_p = true;
-  specs->typespec_kind = spec.kind;
-  if (TREE_DEPRECATED (type))
-    specs->deprecated_p = true;
-
-  /* Handle type specifier keywords.  */
-  if (TREE_CODE (type) == IDENTIFIER_NODE
-      && C_IS_RESERVED_WORD (type)
-      && C_RID_CODE (type) != RID_CXX_COMPAT_WARN)
-    {
-      enum rid i = C_RID_CODE (type);
-      if (specs->type)
-       {
-         error_at (loc, "two or more data types in declaration specifiers");
-         return specs;
-       }
-      if ((int) i <= (int) RID_LAST_MODIFIER)
-       {
-         /* "long", "short", "signed", "unsigned", "_Complex" or "_Sat".  */
-         bool dupe = false;
-         switch (i)
-           {
-           case RID_LONG:
-             if (specs->long_long_p)
-               {
-                 error_at (loc, "%<long long long%> is too long for GCC");
-                 break;
-               }
-             if (specs->long_p)
-               {
-                 if (specs->typespec_word == cts_double)
-                   {
-                     error_at (loc,
-                               ("both %<long long%> and %<double%> in "
-                                "declaration specifiers"));
-                     break;
-                   }
-                 pedwarn_c90 (loc, OPT_Wlong_long,
-                              "ISO C90 does not support %<long long%>");
-                 specs->long_long_p = 1;
-                 specs->locations[cdw_long_long] = loc;
-                 break;
-               }
-             if (specs->short_p)
-               error_at (loc,
-                         ("both %<long%> and %<short%> in "
-                          "declaration specifiers"));
-             else if (specs->typespec_word == cts_void)
-               error_at (loc,
-                         ("both %<long%> and %<void%> in "
-                          "declaration specifiers"));
-             else if (specs->typespec_word == cts_int128)
-                 error_at (loc,
-                           ("both %<long%> and %<__int128%> in "
-                            "declaration specifiers"));
-             else if (specs->typespec_word == cts_bool)
-               error_at (loc,
-                         ("both %<long%> and %<_Bool%> in "
-                          "declaration specifiers"));
-             else if (specs->typespec_word == cts_char)
-               error_at (loc,
-                         ("both %<long%> and %<char%> in "
-                          "declaration specifiers"));
-             else if (specs->typespec_word == cts_float)
-               error_at (loc,
-                         ("both %<long%> and %<float%> in "
-                          "declaration specifiers"));
-             else if (specs->typespec_word == cts_dfloat32)
-               error_at (loc,
-                         ("both %<long%> and %<_Decimal32%> in "
-                          "declaration specifiers"));
-             else if (specs->typespec_word == cts_dfloat64)
-               error_at (loc,
-                         ("both %<long%> and %<_Decimal64%> in "
-                          "declaration specifiers"));
-             else if (specs->typespec_word == cts_dfloat128)
-               error_at (loc,
-                         ("both %<long%> and %<_Decimal128%> in "
-                          "declaration specifiers"));
-             else
-               {
-                 specs->long_p = true;
-                 specs->locations[cdw_long] = loc;
-               }
-             break;
-           case RID_SHORT:
-             dupe = specs->short_p;
-             if (specs->long_p)
-               error_at (loc,
-                         ("both %<long%> and %<short%> in "
-                          "declaration specifiers"));
-             else if (specs->typespec_word == cts_void)
-               error_at (loc,
-                         ("both %<short%> and %<void%> in "
-                          "declaration specifiers"));
-             else if (specs->typespec_word == cts_int128)
-               error_at (loc,
-                         ("both %<short%> and %<__int128%> in "
-                          "declaration specifiers"));
-             else if (specs->typespec_word == cts_bool)
-               error_at (loc,
-                         ("both %<short%> and %<_Bool%> in "
-                          "declaration specifiers"));
-             else if (specs->typespec_word == cts_char)
-               error_at (loc,
-                         ("both %<short%> and %<char%> in "
-                          "declaration specifiers"));
-             else if (specs->typespec_word == cts_float)
-               error_at (loc,
-                         ("both %<short%> and %<float%> in "
-                          "declaration specifiers"));
-             else if (specs->typespec_word == cts_double)
-               error_at (loc,
-                         ("both %<short%> and %<double%> in "
-                          "declaration specifiers"));
-             else if (specs->typespec_word == cts_dfloat32)
-                error_at (loc,
-                         ("both %<short%> and %<_Decimal32%> in "
-                          "declaration specifiers"));
-             else if (specs->typespec_word == cts_dfloat64)
-               error_at (loc,
-                         ("both %<short%> and %<_Decimal64%> in "
-                          "declaration specifiers"));
-             else if (specs->typespec_word == cts_dfloat128)
-               error_at (loc,
-                         ("both %<short%> and %<_Decimal128%> in "
-                          "declaration specifiers"));
-             else
-               {
-                 specs->short_p = true;
-                 specs->locations[cdw_short] = loc;
-               }
-             break;
-           case RID_SIGNED:
-             dupe = specs->signed_p;
-             if (specs->unsigned_p)
-               error_at (loc,
-                         ("both %<signed%> and %<unsigned%> in "
-                          "declaration specifiers"));
-             else if (specs->typespec_word == cts_void)
-               error_at (loc,
-                         ("both %<signed%> and %<void%> in "
-                          "declaration specifiers"));
-             else if (specs->typespec_word == cts_bool)
-               error_at (loc,
-                         ("both %<signed%> and %<_Bool%> in "
-                          "declaration specifiers"));
-             else if (specs->typespec_word == cts_float)
-               error_at (loc,
-                         ("both %<signed%> and %<float%> in "
-                          "declaration specifiers"));
-             else if (specs->typespec_word == cts_double)
-               error_at (loc,
-                         ("both %<signed%> and %<double%> in "
-                          "declaration specifiers"));
-             else if (specs->typespec_word == cts_dfloat32)
-               error_at (loc,
-                         ("both %<signed%> and %<_Decimal32%> in "
-                          "declaration specifiers"));
-             else if (specs->typespec_word == cts_dfloat64)
-               error_at (loc,
-                         ("both %<signed%> and %<_Decimal64%> in "
-                          "declaration specifiers"));
-             else if (specs->typespec_word == cts_dfloat128)
-               error_at (loc,
-                         ("both %<signed%> and %<_Decimal128%> in "
-                          "declaration specifiers"));
-             else
-               {
-                 specs->signed_p = true;
-                 specs->locations[cdw_signed] = loc;
-               }
-             break;
-           case RID_UNSIGNED:
-             dupe = specs->unsigned_p;
-             if (specs->signed_p)
-               error_at (loc,
-                         ("both %<signed%> and %<unsigned%> in "
-                          "declaration specifiers"));
-             else if (specs->typespec_word == cts_void)
-               error_at (loc,
-                         ("both %<unsigned%> and %<void%> in "
-                          "declaration specifiers"));
-             else if (specs->typespec_word == cts_bool)
-               error_at (loc,
-                         ("both %<unsigned%> and %<_Bool%> in "
-                          "declaration specifiers"));
-             else if (specs->typespec_word == cts_float)
-               error_at (loc,
-                         ("both %<unsigned%> and %<float%> in "
-                          "declaration specifiers"));
-             else if (specs->typespec_word == cts_double)
-               error_at (loc,
-                         ("both %<unsigned%> and %<double%> in "
-                          "declaration specifiers"));
-              else if (specs->typespec_word == cts_dfloat32)
-               error_at (loc,
-                         ("both %<unsigned%> and %<_Decimal32%> in "
-                          "declaration specifiers"));
-             else if (specs->typespec_word == cts_dfloat64)
-               error_at (loc,
-                         ("both %<unsigned%> and %<_Decimal64%> in "
-                          "declaration specifiers"));
-             else if (specs->typespec_word == cts_dfloat128)
-               error_at (loc,
-                         ("both %<unsigned%> and %<_Decimal128%> in "
-                          "declaration specifiers"));
-             else
-               {
-                 specs->unsigned_p = true;
-                 specs->locations[cdw_unsigned] = loc;
-               }
-             break;
-           case RID_COMPLEX:
-             dupe = specs->complex_p;
-             if (!flag_isoc99 && !in_system_header_at (loc))
-               pedwarn (loc, OPT_Wpedantic,
-                        "ISO C90 does not support complex types");
-             if (specs->typespec_word == cts_void)
-               error_at (loc,
-                         ("both %<complex%> and %<void%> in "
-                          "declaration specifiers"));
-             else if (specs->typespec_word == cts_bool)
-               error_at (loc,
-                         ("both %<complex%> and %<_Bool%> in "
-                          "declaration specifiers"));
-              else if (specs->typespec_word == cts_dfloat32)
-               error_at (loc,
-                         ("both %<complex%> and %<_Decimal32%> in "
-                          "declaration specifiers"));
-             else if (specs->typespec_word == cts_dfloat64)
-               error_at (loc,
-                         ("both %<complex%> and %<_Decimal64%> in "
-                          "declaration specifiers"));
-             else if (specs->typespec_word == cts_dfloat128)
-               error_at (loc,
-                         ("both %<complex%> and %<_Decimal128%> in "
-                          "declaration specifiers"));
-             else if (specs->typespec_word == cts_fract)
-               error_at (loc,
-                         ("both %<complex%> and %<_Fract%> in "
-                          "declaration specifiers"));
-             else if (specs->typespec_word == cts_accum)
-               error_at (loc,
-                         ("both %<complex%> and %<_Accum%> in "
-                          "declaration specifiers"));
-             else if (specs->saturating_p)
-               error_at (loc,
-                         ("both %<complex%> and %<_Sat%> in "
-                          "declaration specifiers"));
-             else
-               {
-                 specs->complex_p = true;
-                 specs->locations[cdw_complex] = loc;
-               }
-             break;
-           case RID_SAT:
-             dupe = specs->saturating_p;
-             pedwarn (loc, OPT_Wpedantic,
-                      "ISO C does not support saturating types");
-             if (specs->typespec_word == cts_int128)
-               {
-                 error_at (loc,
-                           ("both %<_Sat%> and %<__int128%> in "
-                            "declaration specifiers"));
-               }
-             else if (specs->typespec_word == cts_void)
-               error_at (loc,
-                         ("both %<_Sat%> and %<void%> in "
-                          "declaration specifiers"));
-             else if (specs->typespec_word == cts_bool)
-               error_at (loc,
-                         ("both %<_Sat%> and %<_Bool%> in "
-                          "declaration specifiers"));
-             else if (specs->typespec_word == cts_char)
-               error_at (loc,
-                         ("both %<_Sat%> and %<char%> in "
-                          "declaration specifiers"));
-             else if (specs->typespec_word == cts_int)
-               error_at (loc,
-                         ("both %<_Sat%> and %<int%> in "
-                          "declaration specifiers"));
-             else if (specs->typespec_word == cts_float)
-               error_at (loc,
-                         ("both %<_Sat%> and %<float%> in "
-                          "declaration specifiers"));
-             else if (specs->typespec_word == cts_double)
-               error_at (loc,
-                         ("both %<_Sat%> and %<double%> in "
-                          "declaration specifiers"));
-              else if (specs->typespec_word == cts_dfloat32)
-               error_at (loc,
-                         ("both %<_Sat%> and %<_Decimal32%> in "
-                          "declaration specifiers"));
-             else if (specs->typespec_word == cts_dfloat64)
-               error_at (loc,
-                         ("both %<_Sat%> and %<_Decimal64%> in "
-                          "declaration specifiers"));
-             else if (specs->typespec_word == cts_dfloat128)
-               error_at (loc,
-                         ("both %<_Sat%> and %<_Decimal128%> in "
-                          "declaration specifiers"));
-             else if (specs->complex_p)
-               error_at (loc,
-                         ("both %<_Sat%> and %<complex%> in "
-                          "declaration specifiers"));
-             else
-               {
-                 specs->saturating_p = true;
-                 specs->locations[cdw_saturating] = loc;
-               }
-             break;
-           default:
-             gcc_unreachable ();
-           }
-
-         if (dupe)
-           error_at (loc, "duplicate %qE", type);
-
-         return specs;
-       }
-      else
-       {
-         /* "void", "_Bool", "char", "int", "float", "double", "_Decimal32",
-            "__int128", "_Decimal64", "_Decimal128", "_Fract" or "_Accum".  */
-         if (specs->typespec_word != cts_none)
-           {
-             error_at (loc,
-                       "two or more data types in declaration specifiers");
-             return specs;
-           }
-         switch (i)
-           {
-           case RID_INT128:
-             if (int128_integer_type_node == NULL_TREE)
-               {
-                 error_at (loc, "%<__int128%> is not supported for this target");
-                 return specs;
-               }
-             if (!in_system_header)
-               pedwarn (loc, OPT_Wpedantic,
-                        "ISO C does not support %<__int128%> type");
-
-             if (specs->long_p)
-               error_at (loc,
-                         ("both %<__int128%> and %<long%> in "
-                          "declaration specifiers"));
-             else if (specs->saturating_p)
-               error_at (loc,
-                         ("both %<_Sat%> and %<__int128%> in "
-                          "declaration specifiers"));
-             else if (specs->short_p)
-               error_at (loc,
-                         ("both %<__int128%> and %<short%> in "
-                          "declaration specifiers"));
-             else
-               {
-                 specs->typespec_word = cts_int128;
-                 specs->locations[cdw_typespec] = loc;
-               }
-             return specs;
-           case RID_VOID:
-             if (specs->long_p)
-               error_at (loc,
-                         ("both %<long%> and %<void%> in "
-                          "declaration specifiers"));
-             else if (specs->short_p)
-               error_at (loc,
-                         ("both %<short%> and %<void%> in "
-                          "declaration specifiers"));
-             else if (specs->signed_p)
-               error_at (loc,
-                         ("both %<signed%> and %<void%> in "
-                          "declaration specifiers"));
-             else if (specs->unsigned_p)
-               error_at (loc,
-                         ("both %<unsigned%> and %<void%> in "
-                          "declaration specifiers"));
-             else if (specs->complex_p)
-               error_at (loc,
-                         ("both %<complex%> and %<void%> in "
-                          "declaration specifiers"));
-             else if (specs->saturating_p)
-               error_at (loc,
-                         ("both %<_Sat%> and %<void%> in "
-                          "declaration specifiers"));
-             else
-               {
-                 specs->typespec_word = cts_void;
-                 specs->locations[cdw_typespec] = loc;
-               }
-             return specs;
-           case RID_BOOL:
-             if (specs->long_p)
-               error_at (loc,
-                         ("both %<long%> and %<_Bool%> in "
-                          "declaration specifiers"));
-             else if (specs->short_p)
-               error_at (loc,
-                         ("both %<short%> and %<_Bool%> in "
-                          "declaration specifiers"));
-             else if (specs->signed_p)
-               error_at (loc,
-                         ("both %<signed%> and %<_Bool%> in "
-                          "declaration specifiers"));
-             else if (specs->unsigned_p)
-               error_at (loc,
-                         ("both %<unsigned%> and %<_Bool%> in "
-                          "declaration specifiers"));
-             else if (specs->complex_p)
-               error_at (loc,
-                         ("both %<complex%> and %<_Bool%> in "
-                          "declaration specifiers"));
-             else if (specs->saturating_p)
-               error_at (loc,
-                         ("both %<_Sat%> and %<_Bool%> in "
-                          "declaration specifiers"));
-             else
-               {
-                 specs->typespec_word = cts_bool;
-                 specs->locations[cdw_typespec] = loc;
-               }
-             return specs;
-           case RID_CHAR:
-             if (specs->long_p)
-               error_at (loc,
-                         ("both %<long%> and %<char%> in "
-                          "declaration specifiers"));
-             else if (specs->short_p)
-               error_at (loc,
-                         ("both %<short%> and %<char%> in "
-                          "declaration specifiers"));
-             else if (specs->saturating_p)
-               error_at (loc,
-                         ("both %<_Sat%> and %<char%> in "
-                          "declaration specifiers"));
-             else
-               {
-                 specs->typespec_word = cts_char;
-                 specs->locations[cdw_typespec] = loc;
-               }
-             return specs;
-           case RID_INT:
-             if (specs->saturating_p)
-               error_at (loc,
-                         ("both %<_Sat%> and %<int%> in "
-                          "declaration specifiers"));
-             else
-               {
-                 specs->typespec_word = cts_int;
-                 specs->locations[cdw_typespec] = loc;
-               }
-             return specs;
-           case RID_FLOAT:
-             if (specs->long_p)
-               error_at (loc,
-                         ("both %<long%> and %<float%> in "
-                          "declaration specifiers"));
-             else if (specs->short_p)
-               error_at (loc,
-                         ("both %<short%> and %<float%> in "
-                          "declaration specifiers"));
-             else if (specs->signed_p)
-               error_at (loc,
-                         ("both %<signed%> and %<float%> in "
-                          "declaration specifiers"));
-             else if (specs->unsigned_p)
-               error_at (loc,
-                         ("both %<unsigned%> and %<float%> in "
-                          "declaration specifiers"));
-             else if (specs->saturating_p)
-               error_at (loc,
-                         ("both %<_Sat%> and %<float%> in "
-                          "declaration specifiers"));
-             else
-               {
-                 specs->typespec_word = cts_float;
-                 specs->locations[cdw_typespec] = loc;
-               }
-             return specs;
-           case RID_DOUBLE:
-             if (specs->long_long_p)
-               error_at (loc,
-                         ("both %<long long%> and %<double%> in "
-                          "declaration specifiers"));
-             else if (specs->short_p)
-               error_at (loc,
-                         ("both %<short%> and %<double%> in "
-                          "declaration specifiers"));
-             else if (specs->signed_p)
-               error_at (loc,
-                         ("both %<signed%> and %<double%> in "
-                          "declaration specifiers"));
-             else if (specs->unsigned_p)
-               error_at (loc,
-                         ("both %<unsigned%> and %<double%> in "
-                          "declaration specifiers"));
-             else if (specs->saturating_p)
-               error_at (loc,
-                         ("both %<_Sat%> and %<double%> in "
-                          "declaration specifiers"));
-             else
-               {
-                 specs->typespec_word = cts_double;
-                 specs->locations[cdw_typespec] = loc;
-               }
-             return specs;
-           case RID_DFLOAT32:
-           case RID_DFLOAT64:
-           case RID_DFLOAT128:
-             {
-               const char *str;
-               if (i == RID_DFLOAT32)
-                 str = "_Decimal32";
-               else if (i == RID_DFLOAT64)
-                 str = "_Decimal64";
-               else
-                 str = "_Decimal128";
-               if (specs->long_long_p)
-                 error_at (loc,
-                           ("both %<long long%> and %<%s%> in "
-                            "declaration specifiers"),
-                           str);
-               if (specs->long_p)
-                 error_at (loc,
-                           ("both %<long%> and %<%s%> in "
-                            "declaration specifiers"),
-                           str);
-               else if (specs->short_p)
-                 error_at (loc,
-                           ("both %<short%> and %<%s%> in "
-                            "declaration specifiers"),
-                           str);
-               else if (specs->signed_p)
-                 error_at (loc,
-                           ("both %<signed%> and %<%s%> in "
-                            "declaration specifiers"),
-                           str);
-               else if (specs->unsigned_p)
-                 error_at (loc,
-                           ("both %<unsigned%> and %<%s%> in "
-                            "declaration specifiers"),
-                           str);
-                else if (specs->complex_p)
-                  error_at (loc,
-                           ("both %<complex%> and %<%s%> in "
-                            "declaration specifiers"),
-                           str);
-                else if (specs->saturating_p)
-                  error_at (loc,
-                           ("both %<_Sat%> and %<%s%> in "
-                            "declaration specifiers"),
-                           str);
-               else if (i == RID_DFLOAT32)
-                 specs->typespec_word = cts_dfloat32;
-               else if (i == RID_DFLOAT64)
-                 specs->typespec_word = cts_dfloat64;
-               else
-                 specs->typespec_word = cts_dfloat128;
-               specs->locations[cdw_typespec] = loc;
-             }
-             if (!targetm.decimal_float_supported_p ())
-               error_at (loc,
-                         ("decimal floating point not supported "
-                          "for this target"));
-             pedwarn (loc, OPT_Wpedantic,
-                      "ISO C does not support decimal floating point");
-             return specs;
-           case RID_FRACT:
-           case RID_ACCUM:
-             {
-               const char *str;
-               if (i == RID_FRACT)
-                 str = "_Fract";
-               else
-                 str = "_Accum";
-                if (specs->complex_p)
-                  error_at (loc,
-                           ("both %<complex%> and %<%s%> in "
-                            "declaration specifiers"),
-                           str);
-               else if (i == RID_FRACT)
-                   specs->typespec_word = cts_fract;
-               else
-                   specs->typespec_word = cts_accum;
-               specs->locations[cdw_typespec] = loc;
-             }
-             if (!targetm.fixed_point_supported_p ())
-               error_at (loc,
-                         "fixed-point types not supported for this target");
-             pedwarn (loc, OPT_Wpedantic,
-                      "ISO C does not support fixed-point types");
-             return specs;
-           default:
-             /* ObjC reserved word "id", handled below.  */
-             break;
-           }
-       }
-    }
-
-  /* Now we have a typedef (a TYPE_DECL node), an identifier (some
-     form of ObjC type, cases such as "int" and "long" being handled
-     above), a TYPE (struct, union, enum and typeof specifiers) or an
-     ERROR_MARK.  In none of these cases may there have previously
-     been any type specifiers.  */
-  if (specs->type || specs->typespec_word != cts_none
-      || specs->long_p || specs->short_p || specs->signed_p
-      || specs->unsigned_p || specs->complex_p)
-    error_at (loc, "two or more data types in declaration specifiers");
-  else if (TREE_CODE (type) == TYPE_DECL)
-    {
-      if (TREE_TYPE (type) == error_mark_node)
-       ; /* Allow the type to default to int to avoid cascading errors.  */
-      else
-       {
-         specs->type = TREE_TYPE (type);
-         specs->decl_attr = DECL_ATTRIBUTES (type);
-         specs->typedef_p = true;
-         specs->explicit_signed_p = C_TYPEDEF_EXPLICITLY_SIGNED (type);
-         specs->locations[cdw_typedef] = loc;
-
-         /* If this typedef name is defined in a struct, then a C++
-            lookup would return a different value.  */
-         if (warn_cxx_compat
-             && I_SYMBOL_BINDING (DECL_NAME (type))->in_struct)
-           warning_at (loc, OPT_Wc___compat,
-                       "C++ lookup of %qD would return a field, not a type",
-                       type);
-
-         /* If we are parsing a struct, record that a struct field
-            used a typedef.  */
-         if (warn_cxx_compat && struct_parse_info != NULL)
-           VEC_safe_push (tree, heap, struct_parse_info->typedefs_seen, type);
-       }
-    }
-  else if (TREE_CODE (type) == IDENTIFIER_NODE)
-    {
-      tree t = lookup_name (type);
-      if (!t || TREE_CODE (t) != TYPE_DECL)
-       error_at (loc, "%qE fails to be a typedef or built in type", type);
-      else if (TREE_TYPE (t) == error_mark_node)
-       ;
-      else
-       {
-         specs->type = TREE_TYPE (t);
-         specs->locations[cdw_typespec] = loc;
-       }
-    }
-  else
-    {
-      if (TREE_CODE (type) != ERROR_MARK && spec.kind == ctsk_typeof)
-       {
-         specs->typedef_p = true;
-         specs->locations[cdw_typedef] = loc;
-         if (spec.expr)
-           {
-             if (specs->expr)
-               specs->expr = build2 (COMPOUND_EXPR, TREE_TYPE (spec.expr),
-                                     specs->expr, spec.expr);
-             else
-               specs->expr = spec.expr;
-             specs->expr_const_operands &= spec.expr_const_operands;
-           }
-       }
-      specs->type = type;
-    }
-
-  return specs;
-}
-
-/* Add the storage class specifier or function specifier SCSPEC to the
-   declaration specifiers SPECS, returning SPECS.  */
-
-struct c_declspecs *
-declspecs_add_scspec (source_location loc,
-                     struct c_declspecs *specs,
-                     tree scspec)
-{
-  enum rid i;
-  enum c_storage_class n = csc_none;
-  bool dupe = false;
-  specs->declspecs_seen_p = true;
-  gcc_assert (TREE_CODE (scspec) == IDENTIFIER_NODE
-             && C_IS_RESERVED_WORD (scspec));
-  i = C_RID_CODE (scspec);
-  if (specs->non_sc_seen_p)
-    warning (OPT_Wold_style_declaration,
-             "%qE is not at beginning of declaration", scspec);
-  switch (i)
-    {
-    case RID_INLINE:
-      /* C99 permits duplicate inline.  Although of doubtful utility,
-        it seems simplest to permit it in gnu89 mode as well, as
-        there is also little utility in maintaining this as a
-        difference between gnu89 and C99 inline.  */
-      dupe = false;
-      specs->inline_p = true;
-      specs->locations[cdw_inline] = loc;
-      break;
-    case RID_NORETURN:
-      /* Duplicate _Noreturn is permitted.  */
-      dupe = false;
-      specs->noreturn_p = true;
-      specs->locations[cdw_noreturn] = loc;
-      break;
-    case RID_THREAD:
-      dupe = specs->thread_p;
-      if (specs->storage_class == csc_auto)
-       error ("%<__thread%> used with %<auto%>");
-      else if (specs->storage_class == csc_register)
-       error ("%<__thread%> used with %<register%>");
-      else if (specs->storage_class == csc_typedef)
-       error ("%<__thread%> used with %<typedef%>");
-      else
-       {
-         specs->thread_p = true;
-         specs->locations[cdw_thread] = loc;
-       }
-      break;
-    case RID_AUTO:
-      n = csc_auto;
-      break;
-    case RID_EXTERN:
-      n = csc_extern;
-      /* Diagnose "__thread extern".  */
-      if (specs->thread_p)
-       error ("%<__thread%> before %<extern%>");
-      break;
-    case RID_REGISTER:
-      n = csc_register;
-      break;
-    case RID_STATIC:
-      n = csc_static;
-      /* Diagnose "__thread static".  */
-      if (specs->thread_p)
-       error ("%<__thread%> before %<static%>");
-      break;
-    case RID_TYPEDEF:
-      n = csc_typedef;
-      break;
-    default:
-      gcc_unreachable ();
-    }
-  if (n != csc_none && n == specs->storage_class)
-    dupe = true;
-  if (dupe)
-    error ("duplicate %qE", scspec);
-  if (n != csc_none)
-    {
-      if (specs->storage_class != csc_none && n != specs->storage_class)
-       {
-         error ("multiple storage classes in declaration specifiers");
-       }
-      else
-       {
-         specs->storage_class = n;
-         specs->locations[cdw_storage_class] = loc;
-         if (n != csc_extern && n != csc_static && specs->thread_p)
-           {
-             error ("%<__thread%> used with %qE", scspec);
-             specs->thread_p = false;
-           }
-       }
-    }
-  return specs;
-}
-
-/* Add the attributes ATTRS to the declaration specifiers SPECS,
-   returning SPECS.  */
-
-struct c_declspecs *
-declspecs_add_attrs (source_location loc, struct c_declspecs *specs, tree attrs)
-{
-  specs->attrs = chainon (attrs, specs->attrs);
-  specs->locations[cdw_attributes] = loc;
-  specs->declspecs_seen_p = true;
-  return specs;
-}
-
-/* Add an _Alignas specifier (expression ALIGN, or type whose
-   alignment is ALIGN) to the declaration specifiers SPECS, returning
-   SPECS.  */
-struct c_declspecs *
-declspecs_add_alignas (source_location loc,
-                      struct c_declspecs *specs, tree align)
-{
-  int align_log;
-  specs->alignas_p = true;
-  specs->locations[cdw_alignas] = loc;
-  if (align == error_mark_node)
-    return specs;
-  align_log = check_user_alignment (align, true);
-  if (align_log > specs->align_log)
-    specs->align_log = align_log;
-  return specs;
-}
-
-/* Combine "long", "short", "signed", "unsigned" and "_Complex" type
-   specifiers with any other type specifier to determine the resulting
-   type.  This is where ISO C checks on complex types are made, since
-   "_Complex long" is a prefix of the valid ISO C type "_Complex long
-   double".  */
-
-struct c_declspecs *
-finish_declspecs (struct c_declspecs *specs)
-{
-  /* If a type was specified as a whole, we have no modifiers and are
-     done.  */
-  if (specs->type != NULL_TREE)
-    {
-      gcc_assert (!specs->long_p && !specs->long_long_p && !specs->short_p
-                 && !specs->signed_p && !specs->unsigned_p
-                 && !specs->complex_p);
-
-      /* Set a dummy type.  */
-      if (TREE_CODE (specs->type) == ERROR_MARK)
-        specs->type = integer_type_node;
-      return specs;
-    }
-
-  /* If none of "void", "_Bool", "char", "int", "float" or "double"
-     has been specified, treat it as "int" unless "_Complex" is
-     present and there are no other specifiers.  If we just have
-     "_Complex", it is equivalent to "_Complex double", but e.g.
-     "_Complex short" is equivalent to "_Complex short int".  */
-  if (specs->typespec_word == cts_none)
-    {
-      if (specs->saturating_p)
-       {
-         error_at (specs->locations[cdw_saturating],
-                   "%<_Sat%> is used without %<_Fract%> or %<_Accum%>");
-         if (!targetm.fixed_point_supported_p ())
-           error_at (specs->locations[cdw_saturating],
-                     "fixed-point types not supported for this target");
-         specs->typespec_word = cts_fract;
-       }
-      else if (specs->long_p || specs->short_p
-              || specs->signed_p || specs->unsigned_p)
-       {
-         specs->typespec_word = cts_int;
-       }
-      else if (specs->complex_p)
-       {
-         specs->typespec_word = cts_double;
-         pedwarn (specs->locations[cdw_complex], OPT_Wpedantic,
-                  "ISO C does not support plain %<complex%> meaning "
-                  "%<double complex%>");
-       }
-      else
-       {
-         specs->typespec_word = cts_int;
-         specs->default_int_p = true;
-         /* We don't diagnose this here because grokdeclarator will
-            give more specific diagnostics according to whether it is
-            a function definition.  */
-       }
-    }
-
-  /* If "signed" was specified, record this to distinguish "int" and
-     "signed int" in the case of a bit-field with
-     -funsigned-bitfields.  */
-  specs->explicit_signed_p = specs->signed_p;
-
-  /* Now compute the actual type.  */
-  switch (specs->typespec_word)
-    {
-    case cts_void:
-      gcc_assert (!specs->long_p && !specs->short_p
-                 && !specs->signed_p && !specs->unsigned_p
-                 && !specs->complex_p);
-      specs->type = void_type_node;
-      break;
-    case cts_bool:
-      gcc_assert (!specs->long_p && !specs->short_p
-                 && !specs->signed_p && !specs->unsigned_p
-                 && !specs->complex_p);
-      specs->type = boolean_type_node;
-      break;
-    case cts_char:
-      gcc_assert (!specs->long_p && !specs->short_p);
-      gcc_assert (!(specs->signed_p && specs->unsigned_p));
-      if (specs->signed_p)
-       specs->type = signed_char_type_node;
-      else if (specs->unsigned_p)
-       specs->type = unsigned_char_type_node;
-      else
-       specs->type = char_type_node;
-      if (specs->complex_p)
-       {
-         pedwarn (specs->locations[cdw_complex], OPT_Wpedantic,
-                  "ISO C does not support complex integer types");
-         specs->type = build_complex_type (specs->type);
-       }
-      break;
-    case cts_int128:
-      gcc_assert (!specs->long_p && !specs->short_p && !specs->long_long_p);
-      gcc_assert (!(specs->signed_p && specs->unsigned_p));
-      specs->type = (specs->unsigned_p
-                    ? int128_unsigned_type_node
-                    : int128_integer_type_node);
-      if (specs->complex_p)
-       {
-         pedwarn (specs->locations[cdw_complex], OPT_Wpedantic,
-                  "ISO C does not support complex integer types");
-         specs->type = build_complex_type (specs->type);
-       }
-      break;
-    case cts_int:
-      gcc_assert (!(specs->long_p && specs->short_p));
-      gcc_assert (!(specs->signed_p && specs->unsigned_p));
-      if (specs->long_long_p)
-       specs->type = (specs->unsigned_p
-                      ? long_long_unsigned_type_node
-                      : long_long_integer_type_node);
-      else if (specs->long_p)
-       specs->type = (specs->unsigned_p
-                      ? long_unsigned_type_node
-                      : long_integer_type_node);
-      else if (specs->short_p)
-       specs->type = (specs->unsigned_p
-                      ? short_unsigned_type_node
-                      : short_integer_type_node);
-      else
-       specs->type = (specs->unsigned_p
-                      ? unsigned_type_node
-                      : integer_type_node);
-      if (specs->complex_p)
-       {
-         pedwarn (specs->locations[cdw_complex], OPT_Wpedantic,
-                  "ISO C does not support complex integer types");
-         specs->type = build_complex_type (specs->type);
-       }
-      break;
-    case cts_float:
-      gcc_assert (!specs->long_p && !specs->short_p
-                 && !specs->signed_p && !specs->unsigned_p);
-      specs->type = (specs->complex_p
-                    ? complex_float_type_node
-                    : float_type_node);
-      break;
-    case cts_double:
-      gcc_assert (!specs->long_long_p && !specs->short_p
-                 && !specs->signed_p && !specs->unsigned_p);
-      if (specs->long_p)
-       {
-         specs->type = (specs->complex_p
-                        ? complex_long_double_type_node
-                        : long_double_type_node);
-       }
-      else
-       {
-         specs->type = (specs->complex_p
-                        ? complex_double_type_node
-                        : double_type_node);
-       }
-      break;
-    case cts_dfloat32:
-    case cts_dfloat64:
-    case cts_dfloat128:
-      gcc_assert (!specs->long_p && !specs->long_long_p && !specs->short_p
-                 && !specs->signed_p && !specs->unsigned_p && !specs->complex_p);
-      if (specs->typespec_word == cts_dfloat32)
-       specs->type = dfloat32_type_node;
-      else if (specs->typespec_word == cts_dfloat64)
-       specs->type = dfloat64_type_node;
-      else
-       specs->type = dfloat128_type_node;
-      break;
-    case cts_fract:
-      gcc_assert (!specs->complex_p);
-      if (!targetm.fixed_point_supported_p ())
-       specs->type = integer_type_node;
-      else if (specs->saturating_p)
-       {
-         if (specs->long_long_p)
-           specs->type = specs->unsigned_p
-                         ? sat_unsigned_long_long_fract_type_node
-                         : sat_long_long_fract_type_node;
-         else if (specs->long_p)
-           specs->type = specs->unsigned_p
-                         ? sat_unsigned_long_fract_type_node
-                         : sat_long_fract_type_node;
-         else if (specs->short_p)
-           specs->type = specs->unsigned_p
-                         ? sat_unsigned_short_fract_type_node
-                         : sat_short_fract_type_node;
-         else
-           specs->type = specs->unsigned_p
-                         ? sat_unsigned_fract_type_node
-                         : sat_fract_type_node;
-       }
-      else
-       {
-         if (specs->long_long_p)
-           specs->type = specs->unsigned_p
-                         ? unsigned_long_long_fract_type_node
-                         : long_long_fract_type_node;
-         else if (specs->long_p)
-           specs->type = specs->unsigned_p
-                         ? unsigned_long_fract_type_node
-                         : long_fract_type_node;
-         else if (specs->short_p)
-           specs->type = specs->unsigned_p
-                         ? unsigned_short_fract_type_node
-                         : short_fract_type_node;
-         else
-           specs->type = specs->unsigned_p
-                         ? unsigned_fract_type_node
-                         : fract_type_node;
-       }
-      break;
-    case cts_accum:
-      gcc_assert (!specs->complex_p);
-      if (!targetm.fixed_point_supported_p ())
-       specs->type = integer_type_node;
-      else if (specs->saturating_p)
-       {
-         if (specs->long_long_p)
-           specs->type = specs->unsigned_p
-                         ? sat_unsigned_long_long_accum_type_node
-                         : sat_long_long_accum_type_node;
-         else if (specs->long_p)
-           specs->type = specs->unsigned_p
-                         ? sat_unsigned_long_accum_type_node
-                         : sat_long_accum_type_node;
-         else if (specs->short_p)
-           specs->type = specs->unsigned_p
-                         ? sat_unsigned_short_accum_type_node
-                         : sat_short_accum_type_node;
-         else
-           specs->type = specs->unsigned_p
-                         ? sat_unsigned_accum_type_node
-                         : sat_accum_type_node;
-       }
-      else
-       {
-         if (specs->long_long_p)
-           specs->type = specs->unsigned_p
-                         ? unsigned_long_long_accum_type_node
-                         : long_long_accum_type_node;
-         else if (specs->long_p)
-           specs->type = specs->unsigned_p
-                         ? unsigned_long_accum_type_node
-                         : long_accum_type_node;
-         else if (specs->short_p)
-           specs->type = specs->unsigned_p
-                         ? unsigned_short_accum_type_node
-                         : short_accum_type_node;
-         else
-           specs->type = specs->unsigned_p
-                         ? unsigned_accum_type_node
-                         : accum_type_node;
-       }
-      break;
-    default:
-      gcc_unreachable ();
-    }
-
-  return specs;
-}
-
-/* A subroutine of c_write_global_declarations.  Perform final processing
-   on one file scope's declarations (or the external scope's declarations),
-   GLOBALS.  */
-
-static void
-c_write_global_declarations_1 (tree globals)
-{
-  tree decl;
-  bool reconsider;
-
-  /* Process the decls in the order they were written.  */
-  for (decl = globals; decl; decl = DECL_CHAIN (decl))
-    {
-      /* Check for used but undefined static functions using the C
-        standard's definition of "used", and set TREE_NO_WARNING so
-        that check_global_declarations doesn't repeat the check.  */
-      if (TREE_CODE (decl) == FUNCTION_DECL
-         && DECL_INITIAL (decl) == 0
-         && DECL_EXTERNAL (decl)
-         && !TREE_PUBLIC (decl)
-         && C_DECL_USED (decl))
-       {
-         pedwarn (input_location, 0, "%q+F used but never defined", decl);
-         TREE_NO_WARNING (decl) = 1;
-       }
-
-      wrapup_global_declaration_1 (decl);
-    }
-
-  do
-    {
-      reconsider = false;
-      for (decl = globals; decl; decl = DECL_CHAIN (decl))
-       reconsider |= wrapup_global_declaration_2 (decl);
-    }
-  while (reconsider);
-
-  for (decl = globals; decl; decl = DECL_CHAIN (decl))
-    check_global_declaration_1 (decl);
-}
-
-/* A subroutine of c_write_global_declarations Emit debug information for each
-   of the declarations in GLOBALS.  */
-
-static void
-c_write_global_declarations_2 (tree globals)
-{
-  tree decl;
-
-  for (decl = globals; decl ; decl = DECL_CHAIN (decl))
-    debug_hooks->global_decl (decl);
-}
-
-/* Callback to collect a source_ref from a DECL.  */
-
-static void
-collect_source_ref_cb (tree decl)
-{
-  if (!DECL_IS_BUILTIN (decl))
-    collect_source_ref (LOCATION_FILE (decl_sloc (decl, false)));
-}
-
-/* Preserve the external declarations scope across a garbage collect.  */
-static GTY(()) tree ext_block;
-
-/* Collect all references relevant to SOURCE_FILE.  */
-
-static void
-collect_all_refs (const char *source_file)
-{
-  tree t;
-  unsigned i;
-
-  FOR_EACH_VEC_ELT (tree, all_translation_units, i, t)
-    collect_ada_nodes (BLOCK_VARS (DECL_INITIAL (t)), source_file);
-
-  collect_ada_nodes (BLOCK_VARS (ext_block), source_file);
-}
-
-/* Iterate over all global declarations and call CALLBACK.  */
-
-static void
-for_each_global_decl (void (*callback) (tree decl))
-{
-  tree t;
-  tree decls;
-  tree decl;
-  unsigned i;
-
-  FOR_EACH_VEC_ELT (tree, all_translation_units, i, t)
-    { 
-      decls = DECL_INITIAL (t);
-      for (decl = BLOCK_VARS (decls); decl; decl = TREE_CHAIN (decl))
-       callback (decl);
-    }
-
-  for (decl = BLOCK_VARS (ext_block); decl; decl = TREE_CHAIN (decl))
-    callback (decl);
-}
-
-void
-c_write_global_declarations (void)
-{
-  tree t;
-  unsigned i;
-
-  /* We don't want to do this if generating a PCH.  */
-  if (pch_file)
-    return;
-
-  timevar_start (TV_PHASE_DEFERRED);
-
-  /* Do the Objective-C stuff.  This is where all the Objective-C
-     module stuff gets generated (symtab, class/protocol/selector
-     lists etc).  */
-  if (c_dialect_objc ())
-    objc_write_global_declarations ();
-
-  /* Close the external scope.  */
-  ext_block = pop_scope ();
-  external_scope = 0;
-  gcc_assert (!current_scope);
-
-  /* Handle -fdump-ada-spec[-slim]. */
-  if (dump_enabled_p (TDI_ada))
-    {
-      /* Build a table of files to generate specs for */
-      if (get_dump_file_info (TDI_ada)->flags & TDF_SLIM)
-       collect_source_ref (main_input_filename);
-      else
-       for_each_global_decl (collect_source_ref_cb);
-
-      dump_ada_specs (collect_all_refs, NULL);
-    }
-
-  if (ext_block)
-    {
-      tree tmp = BLOCK_VARS (ext_block);
-      int flags;
-      FILE * stream = dump_begin (TDI_tu, &flags);
-      if (stream && tmp)
-       {
-         dump_node (tmp, flags & ~TDF_SLIM, stream);
-         dump_end (TDI_tu, stream);
-       }
-    }
-
-  /* Process all file scopes in this compilation, and the external_scope,
-     through wrapup_global_declarations and check_global_declarations.  */
-  FOR_EACH_VEC_ELT (tree, all_translation_units, i, t)
-    c_write_global_declarations_1 (BLOCK_VARS (DECL_INITIAL (t)));
-  c_write_global_declarations_1 (BLOCK_VARS (ext_block));
-
-  timevar_stop (TV_PHASE_DEFERRED);
-  timevar_start (TV_PHASE_OPT_GEN);
-
-  /* We're done parsing; proceed to optimize and emit assembly.
-     FIXME: shouldn't be the front end's responsibility to call this.  */
-  finalize_compilation_unit ();
-
-  timevar_stop (TV_PHASE_OPT_GEN);
-  timevar_start (TV_PHASE_DBGINFO);
-
-  /* After cgraph has had a chance to emit everything that's going to
-     be emitted, output debug information for globals.  */
-  if (!seen_error ())
-    {
-      timevar_push (TV_SYMOUT);
-      FOR_EACH_VEC_ELT (tree, all_translation_units, i, t)
-       c_write_global_declarations_2 (BLOCK_VARS (DECL_INITIAL (t)));
-      c_write_global_declarations_2 (BLOCK_VARS (ext_block));
-      timevar_pop (TV_SYMOUT);
-    }
-
-  ext_block = NULL;
-  timevar_stop (TV_PHASE_DBGINFO);
-}
-
-/* Register reserved keyword WORD as qualifier for address space AS.  */
-
-void
-c_register_addr_space (const char *word, addr_space_t as)
-{
-  int rid = RID_FIRST_ADDR_SPACE + as;
-  tree id;
-
-  /* Address space qualifiers are only supported
-     in C with GNU extensions enabled.  */
-  if (c_dialect_objc () || flag_no_asm)
-    return;
-
-  id = get_identifier (word);
-  C_SET_RID_CODE (id, rid);
-  C_IS_RESERVED_WORD (id) = 1;
-  ridpointers [rid] = id;
-}
-
-#include "gt-c-decl.h"
diff --git a/gcc/c-errors.c b/gcc/c-errors.c
deleted file mode 100644 (file)
index bee534c..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-/* Various diagnostic subroutines for the GNU C language.
-   Copyright (C) 2000, 2001, 2003, 2007, 2008 Free Software Foundation, Inc.
-   Contributed by Gabriel Dos Reis <gdr@codesourcery.com>
-
-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/>.  */
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "tm.h"
-#include "tree.h"
-#include "c-tree.h"
-#include "tm_p.h"
-#include "flags.h"
-#include "diagnostic.h"
-
-/* Issue an ISO C99 pedantic warning MSGID.  */
-
-void
-pedwarn_c99 (location_t location, int opt, const char *gmsgid, ...)
-{
-  diagnostic_info diagnostic;
-  va_list ap;
-
-  va_start (ap, gmsgid);
-  diagnostic_set_info (&diagnostic, gmsgid, &ap, location,
-                      flag_isoc99 ? DK_PEDWARN : DK_WARNING);
-  diagnostic.option_index = opt;
-  report_diagnostic (&diagnostic);
-  va_end (ap);
-}
-
-/* Issue an ISO C90 pedantic warning MSGID.  This function is supposed to
-   be used for matters that are allowed in ISO C99 but not supported in
-   ISO C90, thus we explicitly don't pedwarn when C99 is specified.
-   (There is no flag_c90.)  */
-
-void
-pedwarn_c90 (location_t location, int opt, const char *gmsgid, ...)
-{
-  diagnostic_info diagnostic;
-  va_list ap;
-
-  va_start (ap, gmsgid);
-  diagnostic_set_info (&diagnostic, gmsgid, &ap, location,
-                      flag_isoc99 ? DK_WARNING : DK_PEDWARN);
-  diagnostic.option_index = opt;
-  report_diagnostic (&diagnostic);
-  va_end (ap);
-}
index dbab100bbf3ea178745daf26008633a215d5c79e..297439bae9a98fa56094f03964ff62d530d1c4f0 100644 (file)
@@ -1,3 +1,7 @@
+2012-06-29  Steven Bosscher  <steven@gcc.gnu.org>
+
+       * cppspec.c: Moved from gcc/ to here.
+
 2012-06-27  Kai Tietz  <ktietz@redhat.com>
 
        PR preprocessor/37215
diff --git a/gcc/c-family/cppspec.c b/gcc/c-family/cppspec.c
new file mode 100644 (file)
index 0000000..c9ff70e
--- /dev/null
@@ -0,0 +1,198 @@
+/* Specific flags and argument handling of the C preprocessor.
+   Copyright (C) 1999, 2007, 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/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "gcc.h"
+#include "opts.h"
+
+/* The `cpp' executable installed in $(bindir) and $(cpp_install_dir)
+   is a customized version of the gcc driver.  It forces -E; -S and -c
+   are errors.  It defaults to -x c for files with unrecognized
+   extensions, unless -x options appear in argv, in which case we
+   assume the user knows what they're doing.  If no explicit input is
+   mentioned, it will read stdin.  */
+
+/* Suffixes for known sorts of input files.  Note that we do not list
+   files which are normally considered to have been preprocessed already,
+   since the user's expectation is that `cpp' always preprocesses.  */
+static const char *const known_suffixes[] =
+{
+  ".c",  ".C",   ".S",   ".m",
+  ".cc", ".cxx", ".cpp", ".cp",  ".c++",
+  ".sx",
+  NULL
+};
+
+/* Filter the command line before processing by the gcc driver proper.  */
+void
+lang_specific_driver (struct cl_decoded_option **in_decoded_options,
+                     unsigned int *in_decoded_options_count,
+                     int *in_added_libraries ATTRIBUTE_UNUSED)
+{
+  struct cl_decoded_option *decoded_options = *in_decoded_options;
+  unsigned int argc = *in_decoded_options_count;
+
+  /* Do we need to read stdin? */
+  int read_stdin = 1;
+
+  /* Do we need to insert -E? */
+  int need_E = 1;
+
+  /* Have we seen an input file? */
+  int seen_input = 0;
+
+  /* Positions to insert -xc, -xassembler-with-cpp, and -o, if necessary.
+     0 means unnecessary.  */
+  unsigned int lang_c_here = 0;
+  unsigned int lang_S_here = 0;
+  unsigned int o_here = 0;
+
+  /* Do we need to fix up an input file with an unrecognized suffix? */
+  int need_fixups = 1;
+
+  unsigned int i, j;
+  struct cl_decoded_option *new_decoded_options;
+  unsigned int new_argc;
+  extern int is_cpp_driver;
+
+  is_cpp_driver = 1;
+
+  /* First pass.  If we see an -S or -c, barf.  If we see an input file,
+     turn off read_stdin.  If we see a second input file, it is actually
+     the output file.  If we see a third input file, barf.  */
+  for (i = 1; i < argc; i++)
+    {
+      switch (decoded_options[i].opt_index)
+       {
+       case OPT_E:
+         need_E = 0;
+         break;
+
+       case OPT_S:
+       case OPT_c:
+         fatal_error ("%qs is not a valid option to the preprocessor",
+                      decoded_options[i].orig_option_with_args_text);
+         return;
+
+       case OPT_x:
+         need_fixups = 0;
+         break;
+
+       case OPT_SPECIAL_input_file:
+         {
+           const char *file = decoded_options[i].arg;
+
+           if (strcmp (file, "-") == 0)
+             read_stdin = 0;
+           else
+             {
+               seen_input++;
+               if (seen_input == 3)
+                 {
+                   fatal_error ("too many input files");
+                   return;
+                 }
+               else if (seen_input == 2)
+                 {
+                   o_here = i;
+                 }
+               else
+                 {
+                   read_stdin = 0;
+                   if (need_fixups)
+                     {
+                       int l = strlen (file);
+                       int known = 0;
+                       const char *const *suff;
+
+                       for (suff = known_suffixes; *suff; suff++)
+                         if (!strcmp (*suff, &file[l - strlen(*suff)]))
+                           {
+                             known = 1;
+                             break;
+                           }
+
+                       if (! known)
+                         {
+                           /* .s files are a special case; we have to
+                              treat them like .S files so
+                              -D__ASSEMBLER__ will be in effect.  */
+                           if (!strcmp (".s", &file[l - 2]))
+                             lang_S_here = i;
+                           else
+                             lang_c_here = i;
+                         }
+                     }
+                 }
+             }
+         }
+         break;
+       }
+    }
+
+  /* If we don't need to edit the command line, we can bail early.  */
+
+  new_argc = argc + need_E + read_stdin + !!lang_c_here + !!lang_S_here;
+
+  if (new_argc == argc && !o_here)
+    return;
+
+  new_decoded_options = XNEWVEC (struct cl_decoded_option, new_argc);
+
+  new_decoded_options[0] = decoded_options[0];
+  j = 1;
+
+  if (need_E)
+    generate_option (OPT_E, NULL, 1, CL_DRIVER, &new_decoded_options[j++]);
+
+  for (i = 1; i < argc; i++, j++)
+    {
+      if (i == lang_c_here)
+       generate_option (OPT_x, "c", 1, CL_DRIVER, &new_decoded_options[j++]);
+      else if (i == lang_S_here)
+       generate_option (OPT_x, "assembler-with-cpp", 1, CL_DRIVER,
+                        &new_decoded_options[j++]);
+      else if (i == o_here)
+       {
+         generate_option (OPT_o, decoded_options[i].arg, 1, CL_DRIVER,
+                          &new_decoded_options[j]);
+         continue;
+       }
+
+      new_decoded_options[j] = decoded_options[i];
+    }
+
+  if (read_stdin)
+    generate_option_input_file ("-", &new_decoded_options[j++]);
+
+  *in_decoded_options_count = new_argc;
+  *in_decoded_options = new_decoded_options;
+}
+
+/* Called before linking.  Returns 0 on success and -1 on failure.  */
+int lang_specific_pre_link (void)
+{
+  return 0;  /* Not used for cpp.  */
+}
+
+/* Number of extra output files that lang_specific_pre_link may generate.  */
+int lang_specific_extra_outfiles = 0;  /* Not used for cpp.  */
diff --git a/gcc/c-lang.c b/gcc/c-lang.c
deleted file mode 100644 (file)
index ae1b081..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/* Language-specific hook definitions for C front end.
-   Copyright (C) 1991, 1995, 1997, 1998,
-   1999, 2000, 2001, 2003, 2004, 2005, 2007, 2008, 2009, 2010
-   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/>.  */
-
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "tm.h"
-#include "tree.h"
-#include "c-tree.h"
-#include "c-family/c-common.h"
-#include "langhooks.h"
-#include "langhooks-def.h"
-#include "tree-inline.h"
-#include "diagnostic-core.h"
-#include "c-objc-common.h"
-#include "c-family/c-pragma.h"
-
-enum c_language_kind c_language = clk_c;
-
-/* Lang hooks common to C and ObjC are declared in c-objc-common.h;
-   consequently, there should be very few hooks below.  */
-
-#undef LANG_HOOKS_NAME
-#define LANG_HOOKS_NAME "GNU C"
-#undef LANG_HOOKS_INIT
-#define LANG_HOOKS_INIT c_objc_common_init
-#undef LANG_HOOKS_INIT_TS
-#define LANG_HOOKS_INIT_TS c_common_init_ts
-
-/* Each front end provides its own lang hook initializer.  */
-struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
-
-#include "gtype-c.h"
diff --git a/gcc/c-lang.h b/gcc/c-lang.h
deleted file mode 100644 (file)
index 256a269..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-/* Definitions for C language specific types.
-   Copyright (C) 2009, 2010
-   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 GCC_C_LANG_H
-#define GCC_C_LANG_H
-
-#include "c-family/c-common.h"
-#include "ggc.h"
-
-struct GTY((variable_size)) lang_type {
-  /* In a RECORD_TYPE, a sorted array of the fields of the type.  */
-  struct sorted_fields_type * GTY ((reorder ("resort_sorted_fields"))) s;
-  /* In an ENUMERAL_TYPE, the min and max values.  */
-  tree enum_min;
-  tree enum_max;
-  /* In a RECORD_TYPE, information specific to Objective-C, such
-     as a list of adopted protocols or a pointer to a corresponding
-     @interface.  See objc/objc-act.h for details.  */
-  tree objc_info;
-};
-
-struct GTY(()) lang_decl {
-  char dummy;
-};
-
-/* Save and restore the variables in this file and elsewhere
-   that keep track of the progress of compilation of the current function.
-   Used for nested functions.  */
-
-struct GTY(()) language_function {
-  struct c_language_function base;
-  tree x_break_label;
-  tree x_cont_label;
-  struct c_switch * GTY((skip)) x_switch_stack;
-  struct c_arg_info * GTY((skip)) arg_info;
-  int returns_value;
-  int returns_null;
-  int returns_abnormally;
-  int warn_about_return_type;
-};
-
-
-#endif /* ! GCC_C_LANG_H */
diff --git a/gcc/c-objc-common.c b/gcc/c-objc-common.c
deleted file mode 100644 (file)
index 9351cd5..0000000
+++ /dev/null
@@ -1,214 +0,0 @@
-/* Some code common to C and ObjC front ends.
-   Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007,
-   2009, 2010 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/>.  */
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "tree.h"
-#include "c-tree.h"
-#include "intl.h"
-#include "c-family/c-pretty-print.h"
-#include "flags.h"
-#include "diagnostic.h"
-#include "tree-pretty-print.h"
-#include "langhooks.h"
-#include "c-objc-common.h"
-
-static bool c_tree_printer (pretty_printer *, text_info *, const char *,
-                           int, bool, bool, bool);
-
-bool
-c_missing_noreturn_ok_p (tree decl)
-{
-  /* A missing noreturn is not ok for freestanding implementations and
-     ok for the `main' function in hosted implementations.  */
-  return flag_hosted && MAIN_NAME_P (DECL_ASSEMBLER_NAME (decl));
-}
-
-/* Called from check_global_declarations.  */
-
-bool
-c_warn_unused_global_decl (const_tree decl)
-{
-  if (TREE_CODE (decl) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (decl))
-    return false;
-  if (DECL_IN_SYSTEM_HEADER (decl))
-    return false;
-
-  return true;
-}
-
-/* Initialization common to C and Objective-C front ends.  */
-bool
-c_objc_common_init (void)
-{
-  c_init_decl_processing ();
-
-  if (c_common_init () == false)
-    return false;
-
-  /* These were not defined in the Objective-C front end, but I'm
-     putting them here anyway.  The diagnostic format decoder might
-     want an enhanced ObjC implementation.  */
-  diagnostic_format_decoder (global_dc) = &c_tree_printer;
-
-  return true;
-}
-
-/* Called during diagnostic message formatting process to print a
-   source-level entity onto BUFFER.  The meaning of the format specifiers
-   is as follows:
-   %D: a general decl,
-   %E: an identifier or expression,
-   %F: a function declaration,
-   %T: a type.
-   %V: a list of type qualifiers from a tree.
-   %v: an explicit list of type qualifiers
-   %#v: an explicit list of type qualifiers of a function type.
-
-   Please notice when called, the `%' part was already skipped by the
-   diagnostic machinery.  */
-static bool
-c_tree_printer (pretty_printer *pp, text_info *text, const char *spec,
-               int precision, bool wide, bool set_locus, bool hash)
-{
-  tree t = NULL_TREE;
-  tree name;
-  c_pretty_printer *cpp = (c_pretty_printer *) pp;
-  pp->padding = pp_none;
-
-  if (precision != 0 || wide)
-    return false;
-
-  if (*spec == 'K')
-    {
-      percent_K_format (text);
-      return true;
-    }
-
-  if (*spec != 'v')
-    {
-      t = va_arg (*text->args_ptr, tree);
-      if (set_locus && text->locus)
-       *text->locus = DECL_SOURCE_LOCATION (t);
-    }
-
-  switch (*spec)
-    {
-    case 'D':
-      if (DECL_DEBUG_EXPR_IS_FROM (t) && DECL_DEBUG_EXPR (t))
-       {
-         t = DECL_DEBUG_EXPR (t);
-         if (!DECL_P (t))
-           {
-             pp_c_expression (cpp, t);
-             return true;
-           }
-       }
-      /* FALLTHRU */
-
-    case 'F':
-      if (DECL_NAME (t))
-       {
-         pp_identifier (cpp, lang_hooks.decl_printable_name (t, 2));
-         return true;
-       }
-      break;
-
-    case 'T':
-      gcc_assert (TYPE_P (t));
-      name = TYPE_NAME (t);
-
-      if (name && TREE_CODE (name) == TYPE_DECL)
-       {
-         if (DECL_NAME (name))
-           pp_identifier (cpp, lang_hooks.decl_printable_name (name, 2));
-         else
-           pp_type_id (cpp, t);
-         return true;
-       }
-      else
-       {
-         pp_type_id (cpp, t);
-         return true;
-       }
-      break;
-
-    case 'E':
-      if (TREE_CODE (t) == IDENTIFIER_NODE)
-       pp_identifier (cpp, IDENTIFIER_POINTER (t));
-      else
-       pp_expression (cpp, t);
-      return true;
-
-    case 'V':
-      pp_c_type_qualifier_list (cpp, t);
-      return true;
-
-    case 'v':
-      pp_c_cv_qualifiers (cpp, va_arg (*text->args_ptr, int), hash);
-      return true;
-
-    default:
-      return false;
-    }
-
-  pp_string (cpp, _("({anonymous})"));
-  return true;
-}
-
-/* In C and ObjC, all decls have "C" linkage.  */
-bool
-has_c_linkage (const_tree decl ATTRIBUTE_UNUSED)
-{
-  return true;
-}
-
-void
-c_initialize_diagnostics (diagnostic_context *context)
-{
-  pretty_printer *base;
-  c_pretty_printer *pp;
-
-  c_common_initialize_diagnostics (context);
-
-  base = context->printer;
-  pp = XNEW (c_pretty_printer);
-  memcpy (pp_base (pp), base, sizeof (pretty_printer));
-  pp_c_pretty_printer_init (pp);
-  context->printer = (pretty_printer *) pp;
-
-  /* It is safe to free this object because it was previously XNEW()'d.  */
-  XDELETE (base);
-}
-
-int
-c_types_compatible_p (tree x, tree y)
-{
-  return comptypes (TYPE_MAIN_VARIANT (x), TYPE_MAIN_VARIANT (y));
-}
-
-/* Determine if the type is a vla type for the backend.  */
-
-bool
-c_vla_unspec_p (tree x, tree fn ATTRIBUTE_UNUSED)
-{
-  return c_vla_type_p (x);
-}
diff --git a/gcc/c-objc-common.h b/gcc/c-objc-common.h
deleted file mode 100644 (file)
index dbbd50a..0000000
+++ /dev/null
@@ -1,109 +0,0 @@
-/* Language hooks common to C and ObjC front ends.
-   Copyright (C) 2004, 2005, 2007, 2008, 2009, 2010
-   Free Software Foundation, Inc.
-   Contributed by Ziemowit Laski  <zlaski@apple.com>
-
-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 GCC_C_OBJC_COMMON
-#define GCC_C_OBJC_COMMON
-
-/* Lang hooks that are shared between C and ObjC are defined here.  Hooks
-   specific to C or ObjC go in c-lang.c and objc/objc-lang.c, respectively.  */
-
-#undef LANG_HOOKS_IDENTIFIER_SIZE
-#define LANG_HOOKS_IDENTIFIER_SIZE C_SIZEOF_STRUCT_LANG_IDENTIFIER
-#undef LANG_HOOKS_FINISH
-#define LANG_HOOKS_FINISH c_common_finish
-#undef LANG_HOOKS_OPTION_LANG_MASK
-#define LANG_HOOKS_OPTION_LANG_MASK c_common_option_lang_mask
-#undef LANG_HOOKS_COMPLAIN_WRONG_LANG_P
-#define LANG_HOOKS_COMPLAIN_WRONG_LANG_P c_common_complain_wrong_lang_p
-#undef LANG_HOOKS_INIT_OPTIONS_STRUCT
-#define LANG_HOOKS_INIT_OPTIONS_STRUCT c_common_init_options_struct
-#undef LANG_HOOKS_INIT_OPTIONS
-#define LANG_HOOKS_INIT_OPTIONS c_common_init_options
-#undef LANG_HOOKS_INITIALIZE_DIAGNOSTICS
-#define LANG_HOOKS_INITIALIZE_DIAGNOSTICS c_initialize_diagnostics
-#undef LANG_HOOKS_HANDLE_OPTION
-#define LANG_HOOKS_HANDLE_OPTION c_common_handle_option
-#undef LANG_HOOKS_POST_OPTIONS
-#define LANG_HOOKS_POST_OPTIONS c_common_post_options
-#undef LANG_HOOKS_GET_ALIAS_SET
-#define LANG_HOOKS_GET_ALIAS_SET c_common_get_alias_set
-#undef LANG_HOOKS_PARSE_FILE
-#define LANG_HOOKS_PARSE_FILE c_common_parse_file
-#undef LANG_HOOKS_FINISH_INCOMPLETE_DECL
-#define LANG_HOOKS_FINISH_INCOMPLETE_DECL c_finish_incomplete_decl
-#undef LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL
-#define LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL c_warn_unused_global_decl
-#undef LANG_HOOKS_PRINT_IDENTIFIER
-#define LANG_HOOKS_PRINT_IDENTIFIER c_print_identifier
-#undef LANG_HOOKS_TYPES_COMPATIBLE_P
-#define LANG_HOOKS_TYPES_COMPATIBLE_P c_types_compatible_p
-#undef LANG_HOOKS_MISSING_NORETURN_OK_P
-#define LANG_HOOKS_MISSING_NORETURN_OK_P c_missing_noreturn_ok_p
-#undef  LANG_HOOKS_BUILTIN_FUNCTION
-#define LANG_HOOKS_BUILTIN_FUNCTION c_builtin_function
-#undef  LANG_HOOKS_BUILTIN_FUNCTION_EXT_SCOPE
-#define LANG_HOOKS_BUILTIN_FUNCTION_EXT_SCOPE c_builtin_function_ext_scope
-
-/* Attribute hooks.  */
-#undef LANG_HOOKS_COMMON_ATTRIBUTE_TABLE
-#define LANG_HOOKS_COMMON_ATTRIBUTE_TABLE c_common_attribute_table
-#undef LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE
-#define LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE c_common_format_attribute_table
-
-#undef LANG_HOOKS_TREE_DUMP_DUMP_TREE_FN
-#define LANG_HOOKS_TREE_DUMP_DUMP_TREE_FN c_dump_tree
-
-#undef LANG_HOOKS_TYPE_FOR_MODE
-#define LANG_HOOKS_TYPE_FOR_MODE c_common_type_for_mode
-#undef LANG_HOOKS_TYPE_FOR_SIZE
-#define LANG_HOOKS_TYPE_FOR_SIZE c_common_type_for_size
-#undef LANG_HOOKS_INCOMPLETE_TYPE_ERROR
-#define LANG_HOOKS_INCOMPLETE_TYPE_ERROR c_incomplete_type_error
-#undef LANG_HOOKS_TYPE_PROMOTES_TO
-#define LANG_HOOKS_TYPE_PROMOTES_TO c_type_promotes_to
-#undef LANG_HOOKS_REGISTER_BUILTIN_TYPE
-#define LANG_HOOKS_REGISTER_BUILTIN_TYPE c_register_builtin_type
-#undef LANG_HOOKS_TO_TARGET_CHARSET
-#define LANG_HOOKS_TO_TARGET_CHARSET c_common_to_target_charset
-#undef LANG_HOOKS_EXPR_TO_DECL
-#define LANG_HOOKS_EXPR_TO_DECL c_expr_to_decl
-
-/* The C front end's scoping structure is very different from
-   that expected by the language-independent code; it is best
-   to disable getdecls.
-   This means it must also provide its own write_globals.  */
-
-#undef LANG_HOOKS_GETDECLS
-#define LANG_HOOKS_GETDECLS lhd_return_null_tree_v
-#undef LANG_HOOKS_WRITE_GLOBALS
-#define LANG_HOOKS_WRITE_GLOBALS c_write_global_declarations
-
-/* Hooks for tree gimplification.  */
-#undef LANG_HOOKS_GIMPLIFY_EXPR
-#define LANG_HOOKS_GIMPLIFY_EXPR c_gimplify_expr
-
-#undef LANG_HOOKS_OMP_PREDETERMINED_SHARING
-#define LANG_HOOKS_OMP_PREDETERMINED_SHARING c_omp_predetermined_sharing
-
-#undef LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P
-#define LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P c_vla_unspec_p
-
-#endif /* GCC_C_OBJC_COMMON */
diff --git a/gcc/c-parser.c b/gcc/c-parser.c
deleted file mode 100644 (file)
index b4135ee..0000000
+++ /dev/null
@@ -1,10840 +0,0 @@
-/* Parser for C and Objective-C.
-   Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011,
-   2012 Free Software Foundation, Inc.
-
-   Parser actions based on the old Bison parser; structure somewhat
-   influenced by and fragments based on the C++ parser.
-
-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/>.  */
-
-/* TODO:
-
-   Make sure all relevant comments, and all relevant code from all
-   actions, brought over from old parser.  Verify exact correspondence
-   of syntax accepted.
-
-   Add testcases covering every input symbol in every state in old and
-   new parsers.
-
-   Include full syntax for GNU C, including erroneous cases accepted
-   with error messages, in syntax productions in comments.
-
-   Make more diagnostics in the front end generally take an explicit
-   location rather than implicitly using input_location.  */
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "tm.h"                        /* For rtl.h: needs enum reg_class.  */
-#include "tree.h"
-#include "langhooks.h"
-#include "input.h"
-#include "cpplib.h"
-#include "timevar.h"
-#include "c-family/c-pragma.h"
-#include "c-tree.h"
-#include "flags.h"
-#include "ggc.h"
-#include "c-family/c-common.h"
-#include "c-family/c-objc.h"
-#include "vec.h"
-#include "target.h"
-#include "cgraph.h"
-#include "plugin.h"
-
-\f
-/* Initialization routine for this file.  */
-
-void
-c_parse_init (void)
-{
-  /* The only initialization required is of the reserved word
-     identifiers.  */
-  unsigned int i;
-  tree id;
-  int mask = 0;
-
-  /* Make sure RID_MAX hasn't grown past the 8 bits used to hold the keyword in
-     the c_token structure.  */
-  gcc_assert (RID_MAX <= 255);
-
-  mask |= D_CXXONLY;
-  if (!flag_isoc99)
-    mask |= D_C99;
-  if (flag_no_asm)
-    {
-      mask |= D_ASM | D_EXT;
-      if (!flag_isoc99)
-       mask |= D_EXT89;
-    }
-  if (!c_dialect_objc ())
-    mask |= D_OBJC | D_CXX_OBJC;
-
-  ridpointers = ggc_alloc_cleared_vec_tree ((int) RID_MAX);
-  for (i = 0; i < num_c_common_reswords; i++)
-    {
-      /* If a keyword is disabled, do not enter it into the table
-        and so create a canonical spelling that isn't a keyword.  */
-      if (c_common_reswords[i].disable & mask)
-       {
-         if (warn_cxx_compat
-             && (c_common_reswords[i].disable & D_CXXWARN))
-           {
-             id = get_identifier (c_common_reswords[i].word);
-             C_SET_RID_CODE (id, RID_CXX_COMPAT_WARN);
-             C_IS_RESERVED_WORD (id) = 1;
-           }
-         continue;
-       }
-
-      id = get_identifier (c_common_reswords[i].word);
-      C_SET_RID_CODE (id, c_common_reswords[i].rid);
-      C_IS_RESERVED_WORD (id) = 1;
-      ridpointers [(int) c_common_reswords[i].rid] = id;
-    }
-}
-\f
-/* The C lexer intermediates between the lexer in cpplib and c-lex.c
-   and the C parser.  Unlike the C++ lexer, the parser structure
-   stores the lexer information instead of using a separate structure.
-   Identifiers are separated into ordinary identifiers, type names,
-   keywords and some other Objective-C types of identifiers, and some
-   look-ahead is maintained.
-
-   ??? It might be a good idea to lex the whole file up front (as for
-   C++).  It would then be possible to share more of the C and C++
-   lexer code, if desired.  */
-
-/* The following local token type is used.  */
-
-/* A keyword.  */
-#define CPP_KEYWORD ((enum cpp_ttype) (N_TTYPES + 1))
-
-/* More information about the type of a CPP_NAME token.  */
-typedef enum c_id_kind {
-  /* An ordinary identifier.  */
-  C_ID_ID,
-  /* An identifier declared as a typedef name.  */
-  C_ID_TYPENAME,
-  /* An identifier declared as an Objective-C class name.  */
-  C_ID_CLASSNAME,
-  /* An address space identifier.  */
-  C_ID_ADDRSPACE,
-  /* Not an identifier.  */
-  C_ID_NONE
-} c_id_kind;
-
-/* A single C token after string literal concatenation and conversion
-   of preprocessing tokens to tokens.  */
-typedef struct GTY (()) c_token {
-  /* The kind of token.  */
-  ENUM_BITFIELD (cpp_ttype) type : 8;
-  /* If this token is a CPP_NAME, this value indicates whether also
-     declared as some kind of type.  Otherwise, it is C_ID_NONE.  */
-  ENUM_BITFIELD (c_id_kind) id_kind : 8;
-  /* If this token is a keyword, this value indicates which keyword.
-     Otherwise, this value is RID_MAX.  */
-  ENUM_BITFIELD (rid) keyword : 8;
-  /* If this token is a CPP_PRAGMA, this indicates the pragma that
-     was seen.  Otherwise it is PRAGMA_NONE.  */
-  ENUM_BITFIELD (pragma_kind) pragma_kind : 8;
-  /* The location at which this token was found.  */
-  location_t location;
-  /* The value associated with this token, if any.  */
-  tree value;
-} c_token;
-
-/* A parser structure recording information about the state and
-   context of parsing.  Includes lexer information with up to two
-   tokens of look-ahead; more are not needed for C.  */
-typedef struct GTY(()) c_parser {
-  /* The look-ahead tokens.  */
-  c_token tokens[2];
-  /* How many look-ahead tokens are available (0, 1 or 2).  */
-  short tokens_avail;
-  /* True if a syntax error is being recovered from; false otherwise.
-     c_parser_error sets this flag.  It should clear this flag when
-     enough tokens have been consumed to recover from the error.  */
-  BOOL_BITFIELD error : 1;
-  /* True if we're processing a pragma, and shouldn't automatically
-     consume CPP_PRAGMA_EOL.  */
-  BOOL_BITFIELD in_pragma : 1;
-  /* True if we're parsing the outermost block of an if statement.  */
-  BOOL_BITFIELD in_if_block : 1;
-  /* True if we want to lex an untranslated string.  */
-  BOOL_BITFIELD lex_untranslated_string : 1;
-
-  /* Objective-C specific parser/lexer information.  */
-
-  /* True if we are in a context where the Objective-C "PQ" keywords
-     are considered keywords.  */
-  BOOL_BITFIELD objc_pq_context : 1;
-  /* True if we are parsing a (potential) Objective-C foreach
-     statement.  This is set to true after we parsed 'for (' and while
-     we wait for 'in' or ';' to decide if it's a standard C for loop or an
-     Objective-C foreach loop.  */
-  BOOL_BITFIELD objc_could_be_foreach_context : 1;
-  /* The following flag is needed to contextualize Objective-C lexical
-     analysis.  In some cases (e.g., 'int NSObject;'), it is
-     undesirable to bind an identifier to an Objective-C class, even
-     if a class with that name exists.  */
-  BOOL_BITFIELD objc_need_raw_identifier : 1;
-  /* Nonzero if we're processing a __transaction statement.  The value
-     is 1 | TM_STMT_ATTR_*.  */
-  unsigned int in_transaction : 4;
-  /* True if we are in a context where the Objective-C "Property attribute"
-     keywords are valid.  */
-  BOOL_BITFIELD objc_property_attr_context : 1;
-} c_parser;
-
-
-/* The actual parser and external interface.  ??? Does this need to be
-   garbage-collected?  */
-
-static GTY (()) c_parser *the_parser;
-
-/* Read in and lex a single token, storing it in *TOKEN.  */
-
-static void
-c_lex_one_token (c_parser *parser, c_token *token)
-{
-  timevar_push (TV_LEX);
-
-  token->type = c_lex_with_flags (&token->value, &token->location, NULL,
-                                 (parser->lex_untranslated_string
-                                  ? C_LEX_STRING_NO_TRANSLATE : 0));
-  token->id_kind = C_ID_NONE;
-  token->keyword = RID_MAX;
-  token->pragma_kind = PRAGMA_NONE;
-
-  switch (token->type)
-    {
-    case CPP_NAME:
-      {
-       tree decl;
-
-       bool objc_force_identifier = parser->objc_need_raw_identifier;
-       if (c_dialect_objc ())
-         parser->objc_need_raw_identifier = false;
-
-       if (C_IS_RESERVED_WORD (token->value))
-         {
-           enum rid rid_code = C_RID_CODE (token->value);
-
-           if (rid_code == RID_CXX_COMPAT_WARN)
-             {
-               warning_at (token->location,
-                           OPT_Wc___compat,
-                           "identifier %qE conflicts with C++ keyword",
-                           token->value);
-             }
-           else if (rid_code >= RID_FIRST_ADDR_SPACE
-                    && rid_code <= RID_LAST_ADDR_SPACE)
-             {
-               token->id_kind = C_ID_ADDRSPACE;
-               token->keyword = rid_code;
-               break;
-             }
-           else if (c_dialect_objc () && OBJC_IS_PQ_KEYWORD (rid_code))
-             {
-               /* We found an Objective-C "pq" keyword (in, out,
-                  inout, bycopy, byref, oneway).  They need special
-                  care because the interpretation depends on the
-                  context.  */
-               if (parser->objc_pq_context)
-                 {
-                   token->type = CPP_KEYWORD;
-                   token->keyword = rid_code;
-                   break;
-                 }
-               else if (parser->objc_could_be_foreach_context
-                        && rid_code == RID_IN)
-                 {
-                   /* We are in Objective-C, inside a (potential)
-                      foreach context (which means after having
-                      parsed 'for (', but before having parsed ';'),
-                      and we found 'in'.  We consider it the keyword
-                      which terminates the declaration at the
-                      beginning of a foreach-statement.  Note that
-                      this means you can't use 'in' for anything else
-                      in that context; in particular, in Objective-C
-                      you can't use 'in' as the name of the running
-                      variable in a C for loop.  We could potentially
-                      try to add code here to disambiguate, but it
-                      seems a reasonable limitation.  */
-                   token->type = CPP_KEYWORD;
-                   token->keyword = rid_code;
-                   break;
-                 }
-               /* Else, "pq" keywords outside of the "pq" context are
-                  not keywords, and we fall through to the code for
-                  normal tokens.  */
-             }
-           else if (c_dialect_objc () && OBJC_IS_PATTR_KEYWORD (rid_code))
-             {
-               /* We found an Objective-C "property attribute"
-                  keyword (getter, setter, readonly, etc). These are
-                  only valid in the property context.  */
-               if (parser->objc_property_attr_context)
-                 {
-                   token->type = CPP_KEYWORD;
-                   token->keyword = rid_code;
-                   break;
-                 }
-               /* Else they are not special keywords.
-               */
-             }
-           else if (c_dialect_objc () 
-                    && (OBJC_IS_AT_KEYWORD (rid_code)
-                        || OBJC_IS_CXX_KEYWORD (rid_code)))
-             {
-               /* We found one of the Objective-C "@" keywords (defs,
-                  selector, synchronized, etc) or one of the
-                  Objective-C "cxx" keywords (class, private,
-                  protected, public, try, catch, throw) without a
-                  preceding '@' sign.  Do nothing and fall through to
-                  the code for normal tokens (in C++ we would still
-                  consider the CXX ones keywords, but not in C).  */
-               ;
-             }
-           else
-             {
-               token->type = CPP_KEYWORD;
-               token->keyword = rid_code;
-               break;
-             }
-         }
-
-       decl = lookup_name (token->value);
-       if (decl)
-         {
-           if (TREE_CODE (decl) == TYPE_DECL)
-             {
-               token->id_kind = C_ID_TYPENAME;
-               break;
-             }
-         }
-       else if (c_dialect_objc ())
-         {
-           tree objc_interface_decl = objc_is_class_name (token->value);
-           /* Objective-C class names are in the same namespace as
-              variables and typedefs, and hence are shadowed by local
-              declarations.  */
-           if (objc_interface_decl
-                && (!objc_force_identifier || global_bindings_p ()))
-             {
-               token->value = objc_interface_decl;
-               token->id_kind = C_ID_CLASSNAME;
-               break;
-             }
-         }
-        token->id_kind = C_ID_ID;
-      }
-      break;
-    case CPP_AT_NAME:
-      /* This only happens in Objective-C; it must be a keyword.  */
-      token->type = CPP_KEYWORD;
-      switch (C_RID_CODE (token->value))
-       {
-         /* Replace 'class' with '@class', 'private' with '@private',
-            etc.  This prevents confusion with the C++ keyword
-            'class', and makes the tokens consistent with other
-            Objective-C 'AT' keywords.  For example '@class' is
-            reported as RID_AT_CLASS which is consistent with
-            '@synchronized', which is reported as
-            RID_AT_SYNCHRONIZED.
-         */
-       case RID_CLASS:     token->keyword = RID_AT_CLASS; break;
-       case RID_PRIVATE:   token->keyword = RID_AT_PRIVATE; break;
-       case RID_PROTECTED: token->keyword = RID_AT_PROTECTED; break;
-       case RID_PUBLIC:    token->keyword = RID_AT_PUBLIC; break;
-       case RID_THROW:     token->keyword = RID_AT_THROW; break;
-       case RID_TRY:       token->keyword = RID_AT_TRY; break;
-       case RID_CATCH:     token->keyword = RID_AT_CATCH; break;
-       default:            token->keyword = C_RID_CODE (token->value);
-       }
-      break;
-    case CPP_COLON:
-    case CPP_COMMA:
-    case CPP_CLOSE_PAREN:
-    case CPP_SEMICOLON:
-      /* These tokens may affect the interpretation of any identifiers
-        following, if doing Objective-C.  */
-      if (c_dialect_objc ())
-       parser->objc_need_raw_identifier = false;
-      break;
-    case CPP_PRAGMA:
-      /* We smuggled the cpp_token->u.pragma value in an INTEGER_CST.  */
-      token->pragma_kind = (enum pragma_kind) TREE_INT_CST_LOW (token->value);
-      token->value = NULL;
-      break;
-    default:
-      break;
-    }
-  timevar_pop (TV_LEX);
-}
-
-/* Return a pointer to the next token from PARSER, reading it in if
-   necessary.  */
-
-static inline c_token *
-c_parser_peek_token (c_parser *parser)
-{
-  if (parser->tokens_avail == 0)
-    {
-      c_lex_one_token (parser, &parser->tokens[0]);
-      parser->tokens_avail = 1;
-    }
-  return &parser->tokens[0];
-}
-
-/* Return true if the next token from PARSER has the indicated
-   TYPE.  */
-
-static inline bool
-c_parser_next_token_is (c_parser *parser, enum cpp_ttype type)
-{
-  return c_parser_peek_token (parser)->type == type;
-}
-
-/* Return true if the next token from PARSER does not have the
-   indicated TYPE.  */
-
-static inline bool
-c_parser_next_token_is_not (c_parser *parser, enum cpp_ttype type)
-{
-  return !c_parser_next_token_is (parser, type);
-}
-
-/* Return true if the next token from PARSER is the indicated
-   KEYWORD.  */
-
-static inline bool
-c_parser_next_token_is_keyword (c_parser *parser, enum rid keyword)
-{
-  return c_parser_peek_token (parser)->keyword == keyword;
-}
-
-/* Return a pointer to the next-but-one token from PARSER, reading it
-   in if necessary.  The next token is already read in.  */
-
-static c_token *
-c_parser_peek_2nd_token (c_parser *parser)
-{
-  if (parser->tokens_avail >= 2)
-    return &parser->tokens[1];
-  gcc_assert (parser->tokens_avail == 1);
-  gcc_assert (parser->tokens[0].type != CPP_EOF);
-  gcc_assert (parser->tokens[0].type != CPP_PRAGMA_EOL);
-  c_lex_one_token (parser, &parser->tokens[1]);
-  parser->tokens_avail = 2;
-  return &parser->tokens[1];
-}
-
-/* Return true if TOKEN can start a type name,
-   false otherwise.  */
-static bool
-c_token_starts_typename (c_token *token)
-{
-  switch (token->type)
-    {
-    case CPP_NAME:
-      switch (token->id_kind)
-       {
-       case C_ID_ID:
-         return false;
-       case C_ID_ADDRSPACE:
-         return true;
-       case C_ID_TYPENAME:
-         return true;
-       case C_ID_CLASSNAME:
-         gcc_assert (c_dialect_objc ());
-         return true;
-       default:
-         gcc_unreachable ();
-       }
-    case CPP_KEYWORD:
-      switch (token->keyword)
-       {
-       case RID_UNSIGNED:
-       case RID_LONG:
-       case RID_INT128:
-       case RID_SHORT:
-       case RID_SIGNED:
-       case RID_COMPLEX:
-       case RID_INT:
-       case RID_CHAR:
-       case RID_FLOAT:
-       case RID_DOUBLE:
-       case RID_VOID:
-       case RID_DFLOAT32:
-       case RID_DFLOAT64:
-       case RID_DFLOAT128:
-       case RID_BOOL:
-       case RID_ENUM:
-       case RID_STRUCT:
-       case RID_UNION:
-       case RID_TYPEOF:
-       case RID_CONST:
-       case RID_VOLATILE:
-       case RID_RESTRICT:
-       case RID_ATTRIBUTE:
-       case RID_FRACT:
-       case RID_ACCUM:
-       case RID_SAT:
-         return true;
-       default:
-         return false;
-       }
-    case CPP_LESS:
-      if (c_dialect_objc ())
-       return true;
-      return false;
-    default:
-      return false;
-    }
-}
-
-enum c_lookahead_kind {
-  /* Always treat unknown identifiers as typenames.  */
-  cla_prefer_type,
-
-  /* Could be parsing a nonabstract declarator.  Only treat an identifier
-     as a typename if followed by another identifier or a star.  */
-  cla_nonabstract_decl,
-
-  /* Never treat identifiers as typenames.  */
-  cla_prefer_id
-};
-
-/* Return true if the next token from PARSER can start a type name,
-   false otherwise.  LA specifies how to do lookahead in order to
-   detect unknown type names.  If unsure, pick CLA_PREFER_ID.  */
-
-static inline bool
-c_parser_next_tokens_start_typename (c_parser *parser, enum c_lookahead_kind la)
-{
-  c_token *token = c_parser_peek_token (parser);
-  if (c_token_starts_typename (token))
-    return true;
-
-  /* Try a bit harder to detect an unknown typename.  */
-  if (la != cla_prefer_id
-      && token->type == CPP_NAME
-      && token->id_kind == C_ID_ID
-
-      /* Do not try too hard when we could have "object in array".  */
-      && !parser->objc_could_be_foreach_context
-
-      && (la == cla_prefer_type
-         || c_parser_peek_2nd_token (parser)->type == CPP_NAME
-         || c_parser_peek_2nd_token (parser)->type == CPP_MULT)
-
-      /* Only unknown identifiers.  */
-      && !lookup_name (token->value))
-    return true;
-
-  return false;
-}
-
-/* Return true if TOKEN is a type qualifier, false otherwise.  */
-static bool
-c_token_is_qualifier (c_token *token)
-{
-  switch (token->type)
-    {
-    case CPP_NAME:
-      switch (token->id_kind)
-       {
-       case C_ID_ADDRSPACE:
-         return true;
-       default:
-         return false;
-       }
-    case CPP_KEYWORD:
-      switch (token->keyword)
-       {
-       case RID_CONST:
-       case RID_VOLATILE:
-       case RID_RESTRICT:
-       case RID_ATTRIBUTE:
-         return true;
-       default:
-         return false;
-       }
-    case CPP_LESS:
-      return false;
-    default:
-      gcc_unreachable ();
-    }
-}
-
-/* Return true if the next token from PARSER is a type qualifier,
-   false otherwise.  */
-static inline bool
-c_parser_next_token_is_qualifier (c_parser *parser)
-{
-  c_token *token = c_parser_peek_token (parser);
-  return c_token_is_qualifier (token);
-}
-
-/* Return true if TOKEN can start declaration specifiers, false
-   otherwise.  */
-static bool
-c_token_starts_declspecs (c_token *token)
-{
-  switch (token->type)
-    {
-    case CPP_NAME:
-      switch (token->id_kind)
-       {
-       case C_ID_ID:
-         return false;
-       case C_ID_ADDRSPACE:
-         return true;
-       case C_ID_TYPENAME:
-         return true;
-       case C_ID_CLASSNAME:
-         gcc_assert (c_dialect_objc ());
-         return true;
-       default:
-         gcc_unreachable ();
-       }
-    case CPP_KEYWORD:
-      switch (token->keyword)
-       {
-       case RID_STATIC:
-       case RID_EXTERN:
-       case RID_REGISTER:
-       case RID_TYPEDEF:
-       case RID_INLINE:
-       case RID_NORETURN:
-       case RID_AUTO:
-       case RID_THREAD:
-       case RID_UNSIGNED:
-       case RID_LONG:
-       case RID_INT128:
-       case RID_SHORT:
-       case RID_SIGNED:
-       case RID_COMPLEX:
-       case RID_INT:
-       case RID_CHAR:
-       case RID_FLOAT:
-       case RID_DOUBLE:
-       case RID_VOID:
-       case RID_DFLOAT32:
-       case RID_DFLOAT64:
-       case RID_DFLOAT128:
-       case RID_BOOL:
-       case RID_ENUM:
-       case RID_STRUCT:
-       case RID_UNION:
-       case RID_TYPEOF:
-       case RID_CONST:
-       case RID_VOLATILE:
-       case RID_RESTRICT:
-       case RID_ATTRIBUTE:
-       case RID_FRACT:
-       case RID_ACCUM:
-       case RID_SAT:
-       case RID_ALIGNAS:
-         return true;
-       default:
-         return false;
-       }
-    case CPP_LESS:
-      if (c_dialect_objc ())
-       return true;
-      return false;
-    default:
-      return false;
-    }
-}
-
-
-/* Return true if TOKEN can start declaration specifiers or a static
-   assertion, false otherwise.  */
-static bool
-c_token_starts_declaration (c_token *token)
-{
-  if (c_token_starts_declspecs (token)
-      || token->keyword == RID_STATIC_ASSERT)
-    return true;
-  else
-    return false;
-}
-
-/* Return true if the next token from PARSER can start declaration
-   specifiers, false otherwise.  */
-static inline bool
-c_parser_next_token_starts_declspecs (c_parser *parser)
-{
-  c_token *token = c_parser_peek_token (parser);
-
-  /* In Objective-C, a classname normally starts a declspecs unless it
-     is immediately followed by a dot.  In that case, it is the
-     Objective-C 2.0 "dot-syntax" for class objects, ie, calls the
-     setter/getter on the class.  c_token_starts_declspecs() can't
-     differentiate between the two cases because it only checks the
-     current token, so we have a special check here.  */
-  if (c_dialect_objc () 
-      && token->type == CPP_NAME
-      && token->id_kind == C_ID_CLASSNAME 
-      && c_parser_peek_2nd_token (parser)->type == CPP_DOT)
-    return false;
-
-  return c_token_starts_declspecs (token);
-}
-
-/* Return true if the next tokens from PARSER can start declaration
-   specifiers or a static assertion, false otherwise.  */
-static inline bool
-c_parser_next_tokens_start_declaration (c_parser *parser)
-{
-  c_token *token = c_parser_peek_token (parser);
-
-  /* Same as above.  */
-  if (c_dialect_objc () 
-      && token->type == CPP_NAME
-      && token->id_kind == C_ID_CLASSNAME 
-      && c_parser_peek_2nd_token (parser)->type == CPP_DOT)
-    return false;
-
-  /* Labels do not start declarations.  */
-  if (token->type == CPP_NAME
-      && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
-    return false;
-
-  if (c_token_starts_declaration (token))
-    return true;
-
-  if (c_parser_next_tokens_start_typename (parser, cla_nonabstract_decl))
-    return true;
-
-  return false;
-}
-
-/* Consume the next token from PARSER.  */
-
-static void
-c_parser_consume_token (c_parser *parser)
-{
-  gcc_assert (parser->tokens_avail >= 1);
-  gcc_assert (parser->tokens[0].type != CPP_EOF);
-  gcc_assert (!parser->in_pragma || parser->tokens[0].type != CPP_PRAGMA_EOL);
-  gcc_assert (parser->error || parser->tokens[0].type != CPP_PRAGMA);
-  if (parser->tokens_avail == 2)
-    parser->tokens[0] = parser->tokens[1];
-  parser->tokens_avail--;
-}
-
-/* Expect the current token to be a #pragma.  Consume it and remember
-   that we've begun parsing a pragma.  */
-
-static void
-c_parser_consume_pragma (c_parser *parser)
-{
-  gcc_assert (!parser->in_pragma);
-  gcc_assert (parser->tokens_avail >= 1);
-  gcc_assert (parser->tokens[0].type == CPP_PRAGMA);
-  if (parser->tokens_avail == 2)
-    parser->tokens[0] = parser->tokens[1];
-  parser->tokens_avail--;
-  parser->in_pragma = true;
-}
-
-/* Update the globals input_location and in_system_header from
-   TOKEN.  */
-static inline void
-c_parser_set_source_position_from_token (c_token *token)
-{
-  if (token->type != CPP_EOF)
-    {
-      input_location = token->location;
-    }
-}
-
-/* Issue a diagnostic of the form
-      FILE:LINE: MESSAGE before TOKEN
-   where TOKEN is the next token in the input stream of PARSER.
-   MESSAGE (specified by the caller) is usually of the form "expected
-   OTHER-TOKEN".
-
-   Do not issue a diagnostic if still recovering from an error.
-
-   ??? This is taken from the C++ parser, but building up messages in
-   this way is not i18n-friendly and some other approach should be
-   used.  */
-
-static void
-c_parser_error (c_parser *parser, const char *gmsgid)
-{
-  c_token *token = c_parser_peek_token (parser);
-  if (parser->error)
-    return;
-  parser->error = true;
-  if (!gmsgid)
-    return;
-  /* This diagnostic makes more sense if it is tagged to the line of
-     the token we just peeked at.  */
-  c_parser_set_source_position_from_token (token);
-  c_parse_error (gmsgid,
-                /* Because c_parse_error does not understand
-                   CPP_KEYWORD, keywords are treated like
-                   identifiers.  */
-                (token->type == CPP_KEYWORD ? CPP_NAME : token->type),
-                /* ??? The C parser does not save the cpp flags of a
-                   token, we need to pass 0 here and we will not get
-                   the source spelling of some tokens but rather the
-                   canonical spelling.  */
-                token->value, /*flags=*/0);
-}
-
-/* If the next token is of the indicated TYPE, consume it.  Otherwise,
-   issue the error MSGID.  If MSGID is NULL then a message has already
-   been produced and no message will be produced this time.  Returns
-   true if found, false otherwise.  */
-
-static bool
-c_parser_require (c_parser *parser,
-                 enum cpp_ttype type,
-                 const char *msgid)
-{
-  if (c_parser_next_token_is (parser, type))
-    {
-      c_parser_consume_token (parser);
-      return true;
-    }
-  else
-    {
-      c_parser_error (parser, msgid);
-      return false;
-    }
-}
-
-/* If the next token is the indicated keyword, consume it.  Otherwise,
-   issue the error MSGID.  Returns true if found, false otherwise.  */
-
-static bool
-c_parser_require_keyword (c_parser *parser,
-                         enum rid keyword,
-                         const char *msgid)
-{
-  if (c_parser_next_token_is_keyword (parser, keyword))
-    {
-      c_parser_consume_token (parser);
-      return true;
-    }
-  else
-    {
-      c_parser_error (parser, msgid);
-      return false;
-    }
-}
-
-/* Like c_parser_require, except that tokens will be skipped until the
-   desired token is found.  An error message is still produced if the
-   next token is not as expected.  If MSGID is NULL then a message has
-   already been produced and no message will be produced this
-   time.  */
-
-static void
-c_parser_skip_until_found (c_parser *parser,
-                          enum cpp_ttype type,
-                          const char *msgid)
-{
-  unsigned nesting_depth = 0;
-
-  if (c_parser_require (parser, type, msgid))
-    return;
-
-  /* Skip tokens until the desired token is found.  */
-  while (true)
-    {
-      /* Peek at the next token.  */
-      c_token *token = c_parser_peek_token (parser);
-      /* If we've reached the token we want, consume it and stop.  */
-      if (token->type == type && !nesting_depth)
-       {
-         c_parser_consume_token (parser);
-         break;
-       }
-
-      /* If we've run out of tokens, stop.  */
-      if (token->type == CPP_EOF)
-       return;
-      if (token->type == CPP_PRAGMA_EOL && parser->in_pragma)
-       return;
-      if (token->type == CPP_OPEN_BRACE
-         || token->type == CPP_OPEN_PAREN
-         || token->type == CPP_OPEN_SQUARE)
-       ++nesting_depth;
-      else if (token->type == CPP_CLOSE_BRACE
-              || token->type == CPP_CLOSE_PAREN
-              || token->type == CPP_CLOSE_SQUARE)
-       {
-         if (nesting_depth-- == 0)
-           break;
-       }
-      /* Consume this token.  */
-      c_parser_consume_token (parser);
-    }
-  parser->error = false;
-}
-
-/* Skip tokens until the end of a parameter is found, but do not
-   consume the comma, semicolon or closing delimiter.  */
-
-static void
-c_parser_skip_to_end_of_parameter (c_parser *parser)
-{
-  unsigned nesting_depth = 0;
-
-  while (true)
-    {
-      c_token *token = c_parser_peek_token (parser);
-      if ((token->type == CPP_COMMA || token->type == CPP_SEMICOLON)
-         && !nesting_depth)
-       break;
-      /* If we've run out of tokens, stop.  */
-      if (token->type == CPP_EOF)
-       return;
-      if (token->type == CPP_PRAGMA_EOL && parser->in_pragma)
-       return;
-      if (token->type == CPP_OPEN_BRACE
-         || token->type == CPP_OPEN_PAREN
-         || token->type == CPP_OPEN_SQUARE)
-       ++nesting_depth;
-      else if (token->type == CPP_CLOSE_BRACE
-              || token->type == CPP_CLOSE_PAREN
-              || token->type == CPP_CLOSE_SQUARE)
-       {
-         if (nesting_depth-- == 0)
-           break;
-       }
-      /* Consume this token.  */
-      c_parser_consume_token (parser);
-    }
-  parser->error = false;
-}
-
-/* Expect to be at the end of the pragma directive and consume an
-   end of line marker.  */
-
-static void
-c_parser_skip_to_pragma_eol (c_parser *parser)
-{
-  gcc_assert (parser->in_pragma);
-  parser->in_pragma = false;
-
-  if (!c_parser_require (parser, CPP_PRAGMA_EOL, "expected end of line"))
-    while (true)
-      {
-       c_token *token = c_parser_peek_token (parser);
-       if (token->type == CPP_EOF)
-         break;
-       if (token->type == CPP_PRAGMA_EOL)
-         {
-           c_parser_consume_token (parser);
-           break;
-         }
-       c_parser_consume_token (parser);
-      }
-
-  parser->error = false;
-}
-
-/* Skip tokens until we have consumed an entire block, or until we
-   have consumed a non-nested ';'.  */
-
-static void
-c_parser_skip_to_end_of_block_or_statement (c_parser *parser)
-{
-  unsigned nesting_depth = 0;
-  bool save_error = parser->error;
-
-  while (true)
-    {
-      c_token *token;
-
-      /* Peek at the next token.  */
-      token = c_parser_peek_token (parser);
-
-      switch (token->type)
-       {
-       case CPP_EOF:
-         return;
-
-       case CPP_PRAGMA_EOL:
-         if (parser->in_pragma)
-           return;
-         break;
-
-       case CPP_SEMICOLON:
-         /* If the next token is a ';', we have reached the
-            end of the statement.  */
-         if (!nesting_depth)
-           {
-             /* Consume the ';'.  */
-             c_parser_consume_token (parser);
-             goto finished;
-           }
-         break;
-
-       case CPP_CLOSE_BRACE:
-         /* If the next token is a non-nested '}', then we have
-            reached the end of the current block.  */
-         if (nesting_depth == 0 || --nesting_depth == 0)
-           {
-             c_parser_consume_token (parser);
-             goto finished;
-           }
-         break;
-
-       case CPP_OPEN_BRACE:
-         /* If it the next token is a '{', then we are entering a new
-            block.  Consume the entire block.  */
-         ++nesting_depth;
-         break;
-
-       case CPP_PRAGMA:
-         /* If we see a pragma, consume the whole thing at once.  We
-            have some safeguards against consuming pragmas willy-nilly.
-            Normally, we'd expect to be here with parser->error set,
-            which disables these safeguards.  But it's possible to get
-            here for secondary error recovery, after parser->error has
-            been cleared.  */
-         c_parser_consume_pragma (parser);
-         c_parser_skip_to_pragma_eol (parser);
-         parser->error = save_error;
-         continue;
-
-       default:
-         break;
-       }
-
-      c_parser_consume_token (parser);
-    }
-
- finished:
-  parser->error = false;
-}
-
-/* CPP's options (initialized by c-opts.c).  */
-extern cpp_options *cpp_opts;
-
-/* Save the warning flags which are controlled by __extension__.  */
-
-static inline int
-disable_extension_diagnostics (void)
-{
-  int ret = (pedantic
-            | (warn_pointer_arith << 1)
-            | (warn_traditional << 2)
-            | (flag_iso << 3)
-            | (warn_long_long << 4)
-            | (warn_cxx_compat << 5)
-            | (warn_overlength_strings << 6));
-  cpp_opts->cpp_pedantic = pedantic = 0;
-  warn_pointer_arith = 0;
-  cpp_opts->cpp_warn_traditional = warn_traditional = 0;
-  flag_iso = 0;
-  cpp_opts->cpp_warn_long_long = warn_long_long = 0;
-  warn_cxx_compat = 0;
-  warn_overlength_strings = 0;
-  return ret;
-}
-
-/* Restore the warning flags which are controlled by __extension__.
-   FLAGS is the return value from disable_extension_diagnostics.  */
-
-static inline void
-restore_extension_diagnostics (int flags)
-{
-  cpp_opts->cpp_pedantic = pedantic = flags & 1;
-  warn_pointer_arith = (flags >> 1) & 1;
-  cpp_opts->cpp_warn_traditional = warn_traditional = (flags >> 2) & 1;
-  flag_iso = (flags >> 3) & 1;
-  cpp_opts->cpp_warn_long_long = warn_long_long = (flags >> 4) & 1;
-  warn_cxx_compat = (flags >> 5) & 1;
-  warn_overlength_strings = (flags >> 6) & 1;
-}
-
-/* Possibly kinds of declarator to parse.  */
-typedef enum c_dtr_syn {
-  /* A normal declarator with an identifier.  */
-  C_DTR_NORMAL,
-  /* An abstract declarator (maybe empty).  */
-  C_DTR_ABSTRACT,
-  /* A parameter declarator: may be either, but after a type name does
-     not redeclare a typedef name as an identifier if it can
-     alternatively be interpreted as a typedef name; see DR#009,
-     applied in C90 TC1, omitted from C99 and reapplied in C99 TC2
-     following DR#249.  For example, given a typedef T, "int T" and
-     "int *T" are valid parameter declarations redeclaring T, while
-     "int (T)" and "int * (T)" and "int (T[])" and "int (T (int))" are
-     abstract declarators rather than involving redundant parentheses;
-     the same applies with attributes inside the parentheses before
-     "T".  */
-  C_DTR_PARM
-} c_dtr_syn;
-
-/* The binary operation precedence levels, where 0 is a dummy lowest level
-   used for the bottom of the stack.  */
-enum c_parser_prec {
-  PREC_NONE,
-  PREC_LOGOR,
-  PREC_LOGAND,
-  PREC_BITOR,
-  PREC_BITXOR,
-  PREC_BITAND,
-  PREC_EQ,
-  PREC_REL,
-  PREC_SHIFT,
-  PREC_ADD,
-  PREC_MULT,
-  NUM_PRECS
-};
-
-static void c_parser_external_declaration (c_parser *);
-static void c_parser_asm_definition (c_parser *);
-static void c_parser_declaration_or_fndef (c_parser *, bool, bool, bool,
-                                          bool, bool, tree *);
-static void c_parser_static_assert_declaration_no_semi (c_parser *);
-static void c_parser_static_assert_declaration (c_parser *);
-static void c_parser_declspecs (c_parser *, struct c_declspecs *, bool, bool,
-                               bool, enum c_lookahead_kind);
-static struct c_typespec c_parser_enum_specifier (c_parser *);
-static struct c_typespec c_parser_struct_or_union_specifier (c_parser *);
-static tree c_parser_struct_declaration (c_parser *);
-static struct c_typespec c_parser_typeof_specifier (c_parser *);
-static tree c_parser_alignas_specifier (c_parser *);
-static struct c_declarator *c_parser_declarator (c_parser *, bool, c_dtr_syn,
-                                                bool *);
-static struct c_declarator *c_parser_direct_declarator (c_parser *, bool,
-                                                       c_dtr_syn, bool *);
-static struct c_declarator *c_parser_direct_declarator_inner (c_parser *,
-                                                             bool,
-                                                             struct c_declarator *);
-static struct c_arg_info *c_parser_parms_declarator (c_parser *, bool, tree);
-static struct c_arg_info *c_parser_parms_list_declarator (c_parser *, tree,
-                                                         tree);
-static struct c_parm *c_parser_parameter_declaration (c_parser *, tree);
-static tree c_parser_simple_asm_expr (c_parser *);
-static tree c_parser_attributes (c_parser *);
-static struct c_type_name *c_parser_type_name (c_parser *);
-static struct c_expr c_parser_initializer (c_parser *);
-static struct c_expr c_parser_braced_init (c_parser *, tree, bool);
-static void c_parser_initelt (c_parser *, struct obstack *);
-static void c_parser_initval (c_parser *, struct c_expr *,
-                             struct obstack *);
-static tree c_parser_compound_statement (c_parser *);
-static void c_parser_compound_statement_nostart (c_parser *);
-static void c_parser_label (c_parser *);
-static void c_parser_statement (c_parser *);
-static void c_parser_statement_after_labels (c_parser *);
-static void c_parser_if_statement (c_parser *);
-static void c_parser_switch_statement (c_parser *);
-static void c_parser_while_statement (c_parser *);
-static void c_parser_do_statement (c_parser *);
-static void c_parser_for_statement (c_parser *);
-static tree c_parser_asm_statement (c_parser *);
-static tree c_parser_asm_operands (c_parser *, bool);
-static tree c_parser_asm_goto_operands (c_parser *);
-static tree c_parser_asm_clobbers (c_parser *);
-static struct c_expr c_parser_expr_no_commas (c_parser *, struct c_expr *);
-static struct c_expr c_parser_conditional_expression (c_parser *,
-                                                     struct c_expr *);
-static struct c_expr c_parser_binary_expression (c_parser *, struct c_expr *,
-                                                enum c_parser_prec);
-static struct c_expr c_parser_cast_expression (c_parser *, struct c_expr *);
-static struct c_expr c_parser_unary_expression (c_parser *);
-static struct c_expr c_parser_sizeof_expression (c_parser *);
-static struct c_expr c_parser_alignof_expression (c_parser *);
-static struct c_expr c_parser_postfix_expression (c_parser *);
-static struct c_expr c_parser_postfix_expression_after_paren_type (c_parser *,
-                                                                  struct c_type_name *,
-                                                                  location_t);
-static struct c_expr c_parser_postfix_expression_after_primary (c_parser *,
-                                                               location_t loc,
-                                                               struct c_expr);
-static tree c_parser_transaction (c_parser *, enum rid);
-static struct c_expr c_parser_transaction_expression (c_parser *, enum rid);
-static tree c_parser_transaction_cancel (c_parser *);
-static struct c_expr c_parser_expression (c_parser *);
-static struct c_expr c_parser_expression_conv (c_parser *);
-static VEC(tree,gc) *c_parser_expr_list (c_parser *, bool, bool,
-                                        VEC(tree,gc) **);
-static void c_parser_omp_construct (c_parser *);
-static void c_parser_omp_threadprivate (c_parser *);
-static void c_parser_omp_barrier (c_parser *);
-static void c_parser_omp_flush (c_parser *);
-static void c_parser_omp_taskwait (c_parser *);
-static void c_parser_omp_taskyield (c_parser *);
-
-enum pragma_context { pragma_external, pragma_stmt, pragma_compound };
-static bool c_parser_pragma (c_parser *, enum pragma_context);
-
-/* These Objective-C parser functions are only ever called when
-   compiling Objective-C.  */
-static void c_parser_objc_class_definition (c_parser *, tree);
-static void c_parser_objc_class_instance_variables (c_parser *);
-static void c_parser_objc_class_declaration (c_parser *);
-static void c_parser_objc_alias_declaration (c_parser *);
-static void c_parser_objc_protocol_definition (c_parser *, tree);
-static bool c_parser_objc_method_type (c_parser *);
-static void c_parser_objc_method_definition (c_parser *);
-static void c_parser_objc_methodprotolist (c_parser *);
-static void c_parser_objc_methodproto (c_parser *);
-static tree c_parser_objc_method_decl (c_parser *, bool, tree *, tree *);
-static tree c_parser_objc_type_name (c_parser *);
-static tree c_parser_objc_protocol_refs (c_parser *);
-static void c_parser_objc_try_catch_finally_statement (c_parser *);
-static void c_parser_objc_synchronized_statement (c_parser *);
-static tree c_parser_objc_selector (c_parser *);
-static tree c_parser_objc_selector_arg (c_parser *);
-static tree c_parser_objc_receiver (c_parser *);
-static tree c_parser_objc_message_args (c_parser *);
-static tree c_parser_objc_keywordexpr (c_parser *);
-static void c_parser_objc_at_property_declaration (c_parser *);
-static void c_parser_objc_at_synthesize_declaration (c_parser *);
-static void c_parser_objc_at_dynamic_declaration (c_parser *);
-static bool c_parser_objc_diagnose_bad_element_prefix
-  (c_parser *, struct c_declspecs *);
-
-/* Parse a translation unit (C90 6.7, C99 6.9).
-
-   translation-unit:
-     external-declarations
-
-   external-declarations:
-     external-declaration
-     external-declarations external-declaration
-
-   GNU extensions:
-
-   translation-unit:
-     empty
-*/
-
-static void
-c_parser_translation_unit (c_parser *parser)
-{
-  if (c_parser_next_token_is (parser, CPP_EOF))
-    {
-      pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic,
-              "ISO C forbids an empty translation unit");
-    }
-  else
-    {
-      void *obstack_position = obstack_alloc (&parser_obstack, 0);
-      mark_valid_location_for_stdc_pragma (false);
-      do
-       {
-         ggc_collect ();
-         c_parser_external_declaration (parser);
-         obstack_free (&parser_obstack, obstack_position);
-       }
-      while (c_parser_next_token_is_not (parser, CPP_EOF));
-    }
-}
-
-/* Parse an external declaration (C90 6.7, C99 6.9).
-
-   external-declaration:
-     function-definition
-     declaration
-
-   GNU extensions:
-
-   external-declaration:
-     asm-definition
-     ;
-     __extension__ external-declaration
-
-   Objective-C:
-
-   external-declaration:
-     objc-class-definition
-     objc-class-declaration
-     objc-alias-declaration
-     objc-protocol-definition
-     objc-method-definition
-     @end
-*/
-
-static void
-c_parser_external_declaration (c_parser *parser)
-{
-  int ext;
-  switch (c_parser_peek_token (parser)->type)
-    {
-    case CPP_KEYWORD:
-      switch (c_parser_peek_token (parser)->keyword)
-       {
-       case RID_EXTENSION:
-         ext = disable_extension_diagnostics ();
-         c_parser_consume_token (parser);
-         c_parser_external_declaration (parser);
-         restore_extension_diagnostics (ext);
-         break;
-       case RID_ASM:
-         c_parser_asm_definition (parser);
-         break;
-       case RID_AT_INTERFACE:
-       case RID_AT_IMPLEMENTATION:
-         gcc_assert (c_dialect_objc ());
-         c_parser_objc_class_definition (parser, NULL_TREE);
-         break;
-       case RID_AT_CLASS:
-         gcc_assert (c_dialect_objc ());
-         c_parser_objc_class_declaration (parser);
-         break;
-       case RID_AT_ALIAS:
-         gcc_assert (c_dialect_objc ());
-         c_parser_objc_alias_declaration (parser);
-         break;
-       case RID_AT_PROTOCOL:
-         gcc_assert (c_dialect_objc ());
-         c_parser_objc_protocol_definition (parser, NULL_TREE);
-         break;
-       case RID_AT_PROPERTY:
-         gcc_assert (c_dialect_objc ());
-         c_parser_objc_at_property_declaration (parser);
-         break;
-       case RID_AT_SYNTHESIZE:
-         gcc_assert (c_dialect_objc ());
-         c_parser_objc_at_synthesize_declaration (parser);
-         break;
-       case RID_AT_DYNAMIC:
-         gcc_assert (c_dialect_objc ());
-         c_parser_objc_at_dynamic_declaration (parser);
-         break;
-       case RID_AT_END:
-         gcc_assert (c_dialect_objc ());
-         c_parser_consume_token (parser);
-         objc_finish_implementation ();
-         break;
-       default:
-         goto decl_or_fndef;
-       }
-      break;
-    case CPP_SEMICOLON:
-      pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic,
-              "ISO C does not allow extra %<;%> outside of a function");
-      c_parser_consume_token (parser);
-      break;
-    case CPP_PRAGMA:
-      mark_valid_location_for_stdc_pragma (true);
-      c_parser_pragma (parser, pragma_external);
-      mark_valid_location_for_stdc_pragma (false);
-      break;
-    case CPP_PLUS:
-    case CPP_MINUS:
-      if (c_dialect_objc ())
-       {
-         c_parser_objc_method_definition (parser);
-         break;
-       }
-      /* Else fall through, and yield a syntax error trying to parse
-        as a declaration or function definition.  */
-    default:
-    decl_or_fndef:
-      /* A declaration or a function definition (or, in Objective-C,
-        an @interface or @protocol with prefix attributes).  We can
-        only tell which after parsing the declaration specifiers, if
-        any, and the first declarator.  */
-      c_parser_declaration_or_fndef (parser, true, true, true, false, true, NULL);
-      break;
-    }
-}
-
-/* Parse a declaration or function definition (C90 6.5, 6.7.1, C99
-   6.7, 6.9.1).  If FNDEF_OK is true, a function definition is
-   accepted; otherwise (old-style parameter declarations) only other
-   declarations are accepted.  If STATIC_ASSERT_OK is true, a static
-   assertion is accepted; otherwise (old-style parameter declarations)
-   it is not.  If NESTED is true, we are inside a function or parsing
-   old-style parameter declarations; any functions encountered are
-   nested functions and declaration specifiers are required; otherwise
-   we are at top level and functions are normal functions and
-   declaration specifiers may be optional.  If EMPTY_OK is true, empty
-   declarations are OK (subject to all other constraints); otherwise
-   (old-style parameter declarations) they are diagnosed.  If
-   START_ATTR_OK is true, the declaration specifiers may start with
-   attributes; otherwise they may not.
-   OBJC_FOREACH_OBJECT_DECLARATION can be used to get back the parsed
-   declaration when parsing an Objective-C foreach statement.
-
-   declaration:
-     declaration-specifiers init-declarator-list[opt] ;
-     static_assert-declaration
-
-   function-definition:
-     declaration-specifiers[opt] declarator declaration-list[opt]
-       compound-statement
-
-   declaration-list:
-     declaration
-     declaration-list declaration
-
-   init-declarator-list:
-     init-declarator
-     init-declarator-list , init-declarator
-
-   init-declarator:
-     declarator simple-asm-expr[opt] attributes[opt]
-     declarator simple-asm-expr[opt] attributes[opt] = initializer
-
-   GNU extensions:
-
-   nested-function-definition:
-     declaration-specifiers declarator declaration-list[opt]
-       compound-statement
-
-   Objective-C:
-     attributes objc-class-definition
-     attributes objc-category-definition
-     attributes objc-protocol-definition
-
-   The simple-asm-expr and attributes are GNU extensions.
-
-   This function does not handle __extension__; that is handled in its
-   callers.  ??? Following the old parser, __extension__ may start
-   external declarations, declarations in functions and declarations
-   at the start of "for" loops, but not old-style parameter
-   declarations.
-
-   C99 requires declaration specifiers in a function definition; the
-   absence is diagnosed through the diagnosis of implicit int.  In GNU
-   C we also allow but diagnose declarations without declaration
-   specifiers, but only at top level (elsewhere they conflict with
-   other syntax).
-
-   In Objective-C, declarations of the looping variable in a foreach
-   statement are exceptionally terminated by 'in' (for example, 'for
-   (NSObject *object in array) { ... }').
-
-   OpenMP:
-
-   declaration:
-     threadprivate-directive  */
-
-static void
-c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
-                              bool static_assert_ok, bool empty_ok,
-                              bool nested, bool start_attr_ok,
-                              tree *objc_foreach_object_declaration)
-{
-  struct c_declspecs *specs;
-  tree prefix_attrs;
-  tree all_prefix_attrs;
-  bool diagnosed_no_specs = false;
-  location_t here = c_parser_peek_token (parser)->location;
-
-  if (static_assert_ok
-      && c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT))
-    {
-      c_parser_static_assert_declaration (parser);
-      return;
-    }
-  specs = build_null_declspecs ();
-
-  /* Try to detect an unknown type name when we have "A B" or "A *B".  */
-  if (c_parser_peek_token (parser)->type == CPP_NAME
-      && c_parser_peek_token (parser)->id_kind == C_ID_ID
-      && (c_parser_peek_2nd_token (parser)->type == CPP_NAME
-          || c_parser_peek_2nd_token (parser)->type == CPP_MULT)
-      && (!nested || !lookup_name (c_parser_peek_token (parser)->value)))
-    {
-      error_at (here, "unknown type name %qE",
-                c_parser_peek_token (parser)->value);
-
-      /* Parse declspecs normally to get a correct pointer type, but avoid
-         a further "fails to be a type name" error.  Refuse nested functions
-         since it is not how the user likely wants us to recover.  */
-      c_parser_peek_token (parser)->type = CPP_KEYWORD;
-      c_parser_peek_token (parser)->keyword = RID_VOID;
-      c_parser_peek_token (parser)->value = error_mark_node;
-      fndef_ok = !nested;
-    }
-
-  c_parser_declspecs (parser, specs, true, true, start_attr_ok, cla_nonabstract_decl);
-  if (parser->error)
-    {
-      c_parser_skip_to_end_of_block_or_statement (parser);
-      return;
-    }
-  if (nested && !specs->declspecs_seen_p)
-    {
-      c_parser_error (parser, "expected declaration specifiers");
-      c_parser_skip_to_end_of_block_or_statement (parser);
-      return;
-    }
-  finish_declspecs (specs);
-  if (c_parser_next_token_is (parser, CPP_SEMICOLON))
-    {
-      if (empty_ok)
-       shadow_tag (specs);
-      else
-       {
-         shadow_tag_warned (specs, 1);
-         pedwarn (here, 0, "empty declaration");
-       }
-      c_parser_consume_token (parser);
-      return;
-    }
-
-  /* Provide better error recovery.  Note that a type name here is usually
-     better diagnosed as a redeclaration.  */
-  if (empty_ok
-      && specs->typespec_kind == ctsk_tagdef
-      && c_parser_next_token_starts_declspecs (parser)
-      && !c_parser_next_token_is (parser, CPP_NAME))
-    {
-      c_parser_error (parser, "expected %<;%>, identifier or %<(%>");
-      parser->error = false;
-      shadow_tag_warned (specs, 1);
-      return;
-    }
-  else if (c_dialect_objc ())
-    {
-      /* Prefix attributes are an error on method decls.  */
-      switch (c_parser_peek_token (parser)->type)
-       {
-         case CPP_PLUS:
-         case CPP_MINUS:
-           if (c_parser_objc_diagnose_bad_element_prefix (parser, specs))
-             return;
-           if (specs->attrs)
-             {
-               warning_at (c_parser_peek_token (parser)->location, 
-                           OPT_Wattributes,
-                           "prefix attributes are ignored for methods");
-               specs->attrs = NULL_TREE;
-             }
-           if (fndef_ok)
-             c_parser_objc_method_definition (parser);
-           else
-             c_parser_objc_methodproto (parser);
-           return;
-           break;
-         default:
-           break;
-       }
-      /* This is where we parse 'attributes @interface ...',
-        'attributes @implementation ...', 'attributes @protocol ...'
-        (where attributes could be, for example, __attribute__
-        ((deprecated)).
-      */
-      switch (c_parser_peek_token (parser)->keyword)
-       {
-       case RID_AT_INTERFACE:
-         {
-           if (c_parser_objc_diagnose_bad_element_prefix (parser, specs))
-             return;
-           c_parser_objc_class_definition (parser, specs->attrs);
-           return;
-         }
-         break;
-       case RID_AT_IMPLEMENTATION:
-         {
-           if (c_parser_objc_diagnose_bad_element_prefix (parser, specs))
-             return;
-           if (specs->attrs)
-             {
-               warning_at (c_parser_peek_token (parser)->location, 
-                       OPT_Wattributes,
-                       "prefix attributes are ignored for implementations");
-               specs->attrs = NULL_TREE;
-             }
-           c_parser_objc_class_definition (parser, NULL_TREE);     
-           return;
-         }
-         break;
-       case RID_AT_PROTOCOL:
-         {
-           if (c_parser_objc_diagnose_bad_element_prefix (parser, specs))
-             return;
-           c_parser_objc_protocol_definition (parser, specs->attrs);
-           return;
-         }
-         break;
-       case RID_AT_ALIAS:
-       case RID_AT_CLASS:
-       case RID_AT_END:
-       case RID_AT_PROPERTY:
-         if (specs->attrs)
-           {
-             c_parser_error (parser, "unexpected attribute");
-             specs->attrs = NULL;
-           }
-         break;
-       default:
-         break;
-       }
-    }
-  
-  pending_xref_error ();
-  prefix_attrs = specs->attrs;
-  all_prefix_attrs = prefix_attrs;
-  specs->attrs = NULL_TREE;
-  while (true)
-    {
-      struct c_declarator *declarator;
-      bool dummy = false;
-      timevar_id_t tv;
-      tree fnbody;
-      /* Declaring either one or more declarators (in which case we
-        should diagnose if there were no declaration specifiers) or a
-        function definition (in which case the diagnostic for
-        implicit int suffices).  */
-      declarator = c_parser_declarator (parser, 
-                                       specs->typespec_kind != ctsk_none,
-                                       C_DTR_NORMAL, &dummy);
-      if (declarator == NULL)
-       {
-         c_parser_skip_to_end_of_block_or_statement (parser);
-         return;
-       }
-      if (c_parser_next_token_is (parser, CPP_EQ)
-         || c_parser_next_token_is (parser, CPP_COMMA)
-         || c_parser_next_token_is (parser, CPP_SEMICOLON)
-         || c_parser_next_token_is_keyword (parser, RID_ASM)
-         || c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE)
-         || c_parser_next_token_is_keyword (parser, RID_IN))
-       {
-         tree asm_name = NULL_TREE;
-         tree postfix_attrs = NULL_TREE;
-         if (!diagnosed_no_specs && !specs->declspecs_seen_p)
-           {
-             diagnosed_no_specs = true;
-             pedwarn (here, 0, "data definition has no type or storage class");
-           }
-         /* Having seen a data definition, there cannot now be a
-            function definition.  */
-         fndef_ok = false;
-         if (c_parser_next_token_is_keyword (parser, RID_ASM))
-           asm_name = c_parser_simple_asm_expr (parser);
-         if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
-           postfix_attrs = c_parser_attributes (parser);
-         if (c_parser_next_token_is (parser, CPP_EQ))
-           {
-             tree d;
-             struct c_expr init;
-             location_t init_loc;
-             c_parser_consume_token (parser);
-             /* The declaration of the variable is in effect while
-                its initializer is parsed.  */
-             d = start_decl (declarator, specs, true,
-                             chainon (postfix_attrs, all_prefix_attrs));
-             if (!d)
-               d = error_mark_node;
-             start_init (d, asm_name, global_bindings_p ());
-             init_loc = c_parser_peek_token (parser)->location;
-             init = c_parser_initializer (parser);
-             finish_init ();
-             if (d != error_mark_node)
-               {
-                 maybe_warn_string_init (TREE_TYPE (d), init);
-                 finish_decl (d, init_loc, init.value,
-                              init.original_type, asm_name);
-               }
-           }
-         else
-           {
-             tree d = start_decl (declarator, specs, false,
-                                  chainon (postfix_attrs,
-                                           all_prefix_attrs));
-             if (d)
-               finish_decl (d, UNKNOWN_LOCATION, NULL_TREE,
-                            NULL_TREE, asm_name);
-             
-             if (c_parser_next_token_is_keyword (parser, RID_IN))
-               {
-                 if (d)
-                   *objc_foreach_object_declaration = d;
-                 else
-                   *objc_foreach_object_declaration = error_mark_node;             
-               }
-           }
-         if (c_parser_next_token_is (parser, CPP_COMMA))
-           {
-             c_parser_consume_token (parser);
-             if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
-               all_prefix_attrs = chainon (c_parser_attributes (parser),
-                                           prefix_attrs);
-             else
-               all_prefix_attrs = prefix_attrs;
-             continue;
-           }
-         else if (c_parser_next_token_is (parser, CPP_SEMICOLON))
-           {
-             c_parser_consume_token (parser);
-             return;
-           }
-         else if (c_parser_next_token_is_keyword (parser, RID_IN))
-           {
-             /* This can only happen in Objective-C: we found the
-                'in' that terminates the declaration inside an
-                Objective-C foreach statement.  Do not consume the
-                token, so that the caller can use it to determine
-                that this indeed is a foreach context.  */
-             return;
-           }
-         else
-           {
-             c_parser_error (parser, "expected %<,%> or %<;%>");
-             c_parser_skip_to_end_of_block_or_statement (parser);
-             return;
-           }
-       }
-      else if (!fndef_ok)
-       {
-         c_parser_error (parser, "expected %<=%>, %<,%>, %<;%>, "
-                         "%<asm%> or %<__attribute__%>");
-         c_parser_skip_to_end_of_block_or_statement (parser);
-         return;
-       }
-      /* Function definition (nested or otherwise).  */
-      if (nested)
-       {
-         pedwarn (here, OPT_Wpedantic, "ISO C forbids nested functions");
-         c_push_function_context ();
-       }
-      if (!start_function (specs, declarator, all_prefix_attrs))
-       {
-         /* This can appear in many cases looking nothing like a
-            function definition, so we don't give a more specific
-            error suggesting there was one.  */
-         c_parser_error (parser, "expected %<=%>, %<,%>, %<;%>, %<asm%> "
-                         "or %<__attribute__%>");
-         if (nested)
-           c_pop_function_context ();
-         break;
-       }
-
-      if (DECL_DECLARED_INLINE_P (current_function_decl))
-        tv = TV_PARSE_INLINE;
-      else
-        tv = TV_PARSE_FUNC;
-      timevar_push (tv);
-
-      /* Parse old-style parameter declarations.  ??? Attributes are
-        not allowed to start declaration specifiers here because of a
-        syntax conflict between a function declaration with attribute
-        suffix and a function definition with an attribute prefix on
-        first old-style parameter declaration.  Following the old
-        parser, they are not accepted on subsequent old-style
-        parameter declarations either.  However, there is no
-        ambiguity after the first declaration, nor indeed on the
-        first as long as we don't allow postfix attributes after a
-        declarator with a nonempty identifier list in a definition;
-        and postfix attributes have never been accepted here in
-        function definitions either.  */
-      while (c_parser_next_token_is_not (parser, CPP_EOF)
-            && c_parser_next_token_is_not (parser, CPP_OPEN_BRACE))
-       c_parser_declaration_or_fndef (parser, false, false, false,
-                                      true, false, NULL);
-      store_parm_decls ();
-      DECL_STRUCT_FUNCTION (current_function_decl)->function_start_locus
-       = c_parser_peek_token (parser)->location;
-      fnbody = c_parser_compound_statement (parser);
-      if (nested)
-       {
-         tree decl = current_function_decl;
-         /* Mark nested functions as needing static-chain initially.
-            lower_nested_functions will recompute it but the
-            DECL_STATIC_CHAIN flag is also used before that happens,
-            by initializer_constant_valid_p.  See gcc.dg/nested-fn-2.c.  */
-         DECL_STATIC_CHAIN (decl) = 1;
-         add_stmt (fnbody);
-         finish_function ();
-         c_pop_function_context ();
-         add_stmt (build_stmt (DECL_SOURCE_LOCATION (decl), DECL_EXPR, decl));
-       }
-      else
-       {
-         add_stmt (fnbody);
-         finish_function ();
-       }
-
-      timevar_pop (tv);
-      break;
-    }
-}
-
-/* Parse an asm-definition (asm() outside a function body).  This is a
-   GNU extension.
-
-   asm-definition:
-     simple-asm-expr ;
-*/
-
-static void
-c_parser_asm_definition (c_parser *parser)
-{
-  tree asm_str = c_parser_simple_asm_expr (parser);
-  if (asm_str)
-    add_asm_node (asm_str);
-  c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
-}
-
-/* Parse a static assertion (C11 6.7.10).
-
-   static_assert-declaration:
-     static_assert-declaration-no-semi ;
-*/
-
-static void
-c_parser_static_assert_declaration (c_parser *parser)
-{
-  c_parser_static_assert_declaration_no_semi (parser);
-  if (parser->error
-      || !c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
-    c_parser_skip_to_end_of_block_or_statement (parser);
-}
-
-/* Parse a static assertion (C11 6.7.10), without the trailing
-   semicolon.
-
-   static_assert-declaration-no-semi:
-     _Static_assert ( constant-expression , string-literal )
-*/
-
-static void
-c_parser_static_assert_declaration_no_semi (c_parser *parser)
-{
-  location_t assert_loc, value_loc;
-  tree value;
-  tree string;
-
-  gcc_assert (c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT));
-  assert_loc = c_parser_peek_token (parser)->location;
-  if (!flag_isoc11)
-    {
-      if (flag_isoc99)
-       pedwarn (assert_loc, OPT_Wpedantic,
-                "ISO C99 does not support %<_Static_assert%>");
-      else
-       pedwarn (assert_loc, OPT_Wpedantic,
-                "ISO C90 does not support %<_Static_assert%>");
-    }
-  c_parser_consume_token (parser);
-  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
-    return;
-  value_loc = c_parser_peek_token (parser)->location;
-  value = c_parser_expr_no_commas (parser, NULL).value;
-  parser->lex_untranslated_string = true;
-  if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
-    {
-      parser->lex_untranslated_string = false;
-      return;
-    }
-  switch (c_parser_peek_token (parser)->type)
-    {
-    case CPP_STRING:
-    case CPP_STRING16:
-    case CPP_STRING32:
-    case CPP_WSTRING:
-    case CPP_UTF8STRING:
-      string = c_parser_peek_token (parser)->value;
-      c_parser_consume_token (parser);
-      parser->lex_untranslated_string = false;
-      break;
-    default:
-      c_parser_error (parser, "expected string literal");
-      parser->lex_untranslated_string = false;
-      return;
-    }
-  c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>");
-
-  if (!INTEGRAL_TYPE_P (TREE_TYPE (value)))
-    {
-      error_at (value_loc, "expression in static assertion is not an integer");
-      return;
-    }
-  if (TREE_CODE (value) != INTEGER_CST)
-    {
-      value = c_fully_fold (value, false, NULL);
-      if (TREE_CODE (value) == INTEGER_CST)
-       pedwarn (value_loc, OPT_Wpedantic, "expression in static assertion "
-                "is not an integer constant expression");
-    }
-  if (TREE_CODE (value) != INTEGER_CST)
-    {
-      error_at (value_loc, "expression in static assertion is not constant");
-      return;
-    }
-  constant_expression_warning (value);
-  if (integer_zerop (value))
-    error_at (assert_loc, "static assertion failed: %E", string);
-}
-
-/* Parse some declaration specifiers (possibly none) (C90 6.5, C99
-   6.7), adding them to SPECS (which may already include some).
-   Storage class specifiers are accepted iff SCSPEC_OK; type
-   specifiers are accepted iff TYPESPEC_OK; attributes are accepted at
-   the start iff START_ATTR_OK.
-
-   declaration-specifiers:
-     storage-class-specifier declaration-specifiers[opt]
-     type-specifier declaration-specifiers[opt]
-     type-qualifier declaration-specifiers[opt]
-     function-specifier declaration-specifiers[opt]
-     alignment-specifier declaration-specifiers[opt]
-
-   Function specifiers (inline) are from C99, and are currently
-   handled as storage class specifiers, as is __thread.  Alignment
-   specifiers are from C11.
-
-   C90 6.5.1, C99 6.7.1:
-   storage-class-specifier:
-     typedef
-     extern
-     static
-     auto
-     register
-
-   C99 6.7.4:
-   function-specifier:
-     inline
-     _Noreturn
-
-   (_Noreturn is new in C11.)
-
-   C90 6.5.2, C99 6.7.2:
-   type-specifier:
-     void
-     char
-     short
-     int
-     long
-     float
-     double
-     signed
-     unsigned
-     _Bool
-     _Complex
-     [_Imaginary removed in C99 TC2]
-     struct-or-union-specifier
-     enum-specifier
-     typedef-name
-
-   (_Bool and _Complex are new in C99.)
-
-   C90 6.5.3, C99 6.7.3:
-
-   type-qualifier:
-     const
-     restrict
-     volatile
-     address-space-qualifier
-
-   (restrict is new in C99.)
-
-   GNU extensions:
-
-   declaration-specifiers:
-     attributes declaration-specifiers[opt]
-
-   type-qualifier:
-     address-space
-
-   address-space:
-     identifier recognized by the target
-
-   storage-class-specifier:
-     __thread
-
-   type-specifier:
-     typeof-specifier
-     __int128
-     _Decimal32
-     _Decimal64
-     _Decimal128
-     _Fract
-     _Accum
-     _Sat
-
-  (_Fract, _Accum, and _Sat are new from ISO/IEC DTR 18037:
-   http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1169.pdf)
-
-   Objective-C:
-
-   type-specifier:
-     class-name objc-protocol-refs[opt]
-     typedef-name objc-protocol-refs
-     objc-protocol-refs
-*/
-
-static void
-c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
-                   bool scspec_ok, bool typespec_ok, bool start_attr_ok,
-                   enum c_lookahead_kind la)
-{
-  bool attrs_ok = start_attr_ok;
-  bool seen_type = specs->typespec_kind != ctsk_none;
-
-  if (!typespec_ok)
-    gcc_assert (la == cla_prefer_id);
-
-  while (c_parser_next_token_is (parser, CPP_NAME)
-        || c_parser_next_token_is (parser, CPP_KEYWORD)
-        || (c_dialect_objc () && c_parser_next_token_is (parser, CPP_LESS)))
-    {
-      struct c_typespec t;
-      tree attrs;
-      tree align;
-      location_t loc = c_parser_peek_token (parser)->location;
-
-      /* If we cannot accept a type, exit if the next token must start
-        one.  Also, if we already have seen a tagged definition,
-        a typename would be an error anyway and likely the user
-        has simply forgotten a semicolon, so we exit.  */
-      if ((!typespec_ok || specs->typespec_kind == ctsk_tagdef)
-         && c_parser_next_tokens_start_typename (parser, la)
-         && !c_parser_next_token_is_qualifier (parser))
-       break;
-
-      if (c_parser_next_token_is (parser, CPP_NAME))
-       {
-         c_token *name_token = c_parser_peek_token (parser);
-         tree value = name_token->value;
-         c_id_kind kind = name_token->id_kind;
-
-         if (kind == C_ID_ADDRSPACE)
-           {
-             addr_space_t as
-               = name_token->keyword - RID_FIRST_ADDR_SPACE;
-             declspecs_add_addrspace (name_token->location, specs, as);
-             c_parser_consume_token (parser);
-             attrs_ok = true;
-             continue;
-           }
-
-         gcc_assert (!c_parser_next_token_is_qualifier (parser));
-
-         /* If we cannot accept a type, and the next token must start one,
-            exit.  Do the same if we already have seen a tagged definition,
-            since it would be an error anyway and likely the user has simply
-            forgotten a semicolon.  */
-         if (seen_type || !c_parser_next_tokens_start_typename (parser, la))
-           break;
-
-         /* Now at an unknown typename (C_ID_ID), a C_ID_TYPENAME or
-            a C_ID_CLASSNAME.  */
-         c_parser_consume_token (parser);
-         seen_type = true;
-         attrs_ok = true;
-         if (kind == C_ID_ID)
-           {
-             error ("unknown type name %qE", value);
-             t.kind = ctsk_typedef;
-             t.spec = error_mark_node;
-           }
-         else if (kind == C_ID_TYPENAME
-                  && (!c_dialect_objc ()
-                      || c_parser_next_token_is_not (parser, CPP_LESS)))
-           {
-             t.kind = ctsk_typedef;
-             /* For a typedef name, record the meaning, not the name.
-                In case of 'foo foo, bar;'.  */
-             t.spec = lookup_name (value);
-           }
-         else
-           {
-             tree proto = NULL_TREE;
-             gcc_assert (c_dialect_objc ());
-             t.kind = ctsk_objc;
-             if (c_parser_next_token_is (parser, CPP_LESS))
-               proto = c_parser_objc_protocol_refs (parser);
-             t.spec = objc_get_protocol_qualified_type (value, proto);
-           }
-         t.expr = NULL_TREE;
-         t.expr_const_operands = true;
-         declspecs_add_type (name_token->location, specs, t);
-         continue;
-       }
-      if (c_parser_next_token_is (parser, CPP_LESS))
-       {
-         /* Make "<SomeProtocol>" equivalent to "id <SomeProtocol>" -
-            nisse@lysator.liu.se.  */
-         tree proto;
-         gcc_assert (c_dialect_objc ());
-         if (!typespec_ok || seen_type)
-           break;
-         proto = c_parser_objc_protocol_refs (parser);
-         t.kind = ctsk_objc;
-         t.spec = objc_get_protocol_qualified_type (NULL_TREE, proto);
-         t.expr = NULL_TREE;
-         t.expr_const_operands = true;
-         declspecs_add_type (loc, specs, t);
-         continue;
-       }
-      gcc_assert (c_parser_next_token_is (parser, CPP_KEYWORD));
-      switch (c_parser_peek_token (parser)->keyword)
-       {
-       case RID_STATIC:
-       case RID_EXTERN:
-       case RID_REGISTER:
-       case RID_TYPEDEF:
-       case RID_INLINE:
-       case RID_NORETURN:
-       case RID_AUTO:
-       case RID_THREAD:
-         if (!scspec_ok)
-           goto out;
-         attrs_ok = true;
-         /* TODO: Distinguish between function specifiers (inline, noreturn)
-            and storage class specifiers, either here or in
-            declspecs_add_scspec.  */
-         declspecs_add_scspec (loc, specs,
-                               c_parser_peek_token (parser)->value);
-         c_parser_consume_token (parser);
-         break;
-       case RID_UNSIGNED:
-       case RID_LONG:
-       case RID_INT128:
-       case RID_SHORT:
-       case RID_SIGNED:
-       case RID_COMPLEX:
-       case RID_INT:
-       case RID_CHAR:
-       case RID_FLOAT:
-       case RID_DOUBLE:
-       case RID_VOID:
-       case RID_DFLOAT32:
-       case RID_DFLOAT64:
-       case RID_DFLOAT128:
-       case RID_BOOL:
-       case RID_FRACT:
-       case RID_ACCUM:
-       case RID_SAT:
-         if (!typespec_ok)
-           goto out;
-         attrs_ok = true;
-         seen_type = true;
-         if (c_dialect_objc ())
-           parser->objc_need_raw_identifier = true;
-         t.kind = ctsk_resword;
-         t.spec = c_parser_peek_token (parser)->value;
-         t.expr = NULL_TREE;
-         t.expr_const_operands = true;
-         declspecs_add_type (loc, specs, t);
-         c_parser_consume_token (parser);
-         break;
-       case RID_ENUM:
-         if (!typespec_ok)
-           goto out;
-         attrs_ok = true;
-         seen_type = true;
-         t = c_parser_enum_specifier (parser);
-         declspecs_add_type (loc, specs, t);
-         break;
-       case RID_STRUCT:
-       case RID_UNION:
-         if (!typespec_ok)
-           goto out;
-         attrs_ok = true;
-         seen_type = true;
-         t = c_parser_struct_or_union_specifier (parser);
-          invoke_plugin_callbacks (PLUGIN_FINISH_TYPE, t.spec);
-         declspecs_add_type (loc, specs, t);
-         break;
-       case RID_TYPEOF:
-         /* ??? The old parser rejected typeof after other type
-            specifiers, but is a syntax error the best way of
-            handling this?  */
-         if (!typespec_ok || seen_type)
-           goto out;
-         attrs_ok = true;
-         seen_type = true;
-         t = c_parser_typeof_specifier (parser);
-         declspecs_add_type (loc, specs, t);
-         break;
-       case RID_CONST:
-       case RID_VOLATILE:
-       case RID_RESTRICT:
-         attrs_ok = true;
-         declspecs_add_qual (loc, specs, c_parser_peek_token (parser)->value);
-         c_parser_consume_token (parser);
-         break;
-       case RID_ATTRIBUTE:
-         if (!attrs_ok)
-           goto out;
-         attrs = c_parser_attributes (parser);
-         declspecs_add_attrs (loc, specs, attrs);
-         break;
-       case RID_ALIGNAS:
-         align = c_parser_alignas_specifier (parser);
-         declspecs_add_alignas (loc, specs, align);
-         break;
-       default:
-         goto out;
-       }
-    }
- out: ;
-}
-
-/* Parse an enum specifier (C90 6.5.2.2, C99 6.7.2.2).
-
-   enum-specifier:
-     enum attributes[opt] identifier[opt] { enumerator-list } attributes[opt]
-     enum attributes[opt] identifier[opt] { enumerator-list , } attributes[opt]
-     enum attributes[opt] identifier
-
-   The form with trailing comma is new in C99.  The forms with
-   attributes are GNU extensions.  In GNU C, we accept any expression
-   without commas in the syntax (assignment expressions, not just
-   conditional expressions); assignment expressions will be diagnosed
-   as non-constant.
-
-   enumerator-list:
-     enumerator
-     enumerator-list , enumerator
-
-   enumerator:
-     enumeration-constant
-     enumeration-constant = constant-expression
-*/
-
-static struct c_typespec
-c_parser_enum_specifier (c_parser *parser)
-{
-  struct c_typespec ret;
-  tree attrs;
-  tree ident = NULL_TREE;
-  location_t enum_loc;
-  location_t ident_loc = UNKNOWN_LOCATION;  /* Quiet warning.  */
-  gcc_assert (c_parser_next_token_is_keyword (parser, RID_ENUM));
-  enum_loc = c_parser_peek_token (parser)->location;
-  c_parser_consume_token (parser);
-  attrs = c_parser_attributes (parser);
-  enum_loc = c_parser_peek_token (parser)->location;
-  /* Set the location in case we create a decl now.  */
-  c_parser_set_source_position_from_token (c_parser_peek_token (parser));
-  if (c_parser_next_token_is (parser, CPP_NAME))
-    {
-      ident = c_parser_peek_token (parser)->value;
-      ident_loc = c_parser_peek_token (parser)->location;
-      enum_loc = ident_loc;
-      c_parser_consume_token (parser);
-    }
-  if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
-    {
-      /* Parse an enum definition.  */
-      struct c_enum_contents the_enum;
-      tree type;
-      tree postfix_attrs;
-      /* We chain the enumerators in reverse order, then put them in
-        forward order at the end.  */
-      tree values;
-      timevar_push (TV_PARSE_ENUM);
-      type = start_enum (enum_loc, &the_enum, ident);
-      values = NULL_TREE;
-      c_parser_consume_token (parser);
-      while (true)
-       {
-         tree enum_id;
-         tree enum_value;
-         tree enum_decl;
-         bool seen_comma;
-         c_token *token;
-         location_t comma_loc = UNKNOWN_LOCATION;  /* Quiet warning.  */
-         location_t decl_loc, value_loc;
-         if (c_parser_next_token_is_not (parser, CPP_NAME))
-           {
-             c_parser_error (parser, "expected identifier");
-             c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
-             values = error_mark_node;
-             break;
-           }
-         token = c_parser_peek_token (parser);
-         enum_id = token->value;
-         /* Set the location in case we create a decl now.  */
-         c_parser_set_source_position_from_token (token);
-         decl_loc = value_loc = token->location;
-         c_parser_consume_token (parser);
-         if (c_parser_next_token_is (parser, CPP_EQ))
-           {
-             c_parser_consume_token (parser);
-             value_loc = c_parser_peek_token (parser)->location;
-             enum_value = c_parser_expr_no_commas (parser, NULL).value;
-           }
-         else
-           enum_value = NULL_TREE;
-         enum_decl = build_enumerator (decl_loc, value_loc,
-                                       &the_enum, enum_id, enum_value);
-         TREE_CHAIN (enum_decl) = values;
-         values = enum_decl;
-         seen_comma = false;
-         if (c_parser_next_token_is (parser, CPP_COMMA))
-           {
-             comma_loc = c_parser_peek_token (parser)->location;
-             seen_comma = true;
-             c_parser_consume_token (parser);
-           }
-         if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
-           {
-             if (seen_comma && !flag_isoc99)
-               pedwarn (comma_loc, OPT_Wpedantic, "comma at end of enumerator list");
-             c_parser_consume_token (parser);
-             break;
-           }
-         if (!seen_comma)
-           {
-             c_parser_error (parser, "expected %<,%> or %<}%>");
-             c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
-             values = error_mark_node;
-             break;
-           }
-       }
-      postfix_attrs = c_parser_attributes (parser);
-      ret.spec = finish_enum (type, nreverse (values),
-                             chainon (attrs, postfix_attrs));
-      ret.kind = ctsk_tagdef;
-      ret.expr = NULL_TREE;
-      ret.expr_const_operands = true;
-      timevar_pop (TV_PARSE_ENUM);
-      return ret;
-    }
-  else if (!ident)
-    {
-      c_parser_error (parser, "expected %<{%>");
-      ret.spec = error_mark_node;
-      ret.kind = ctsk_tagref;
-      ret.expr = NULL_TREE;
-      ret.expr_const_operands = true;
-      return ret;
-    }
-  ret = parser_xref_tag (ident_loc, ENUMERAL_TYPE, ident);
-  /* In ISO C, enumerated types can be referred to only if already
-     defined.  */
-  if (pedantic && !COMPLETE_TYPE_P (ret.spec))
-    {
-      gcc_assert (ident);
-      pedwarn (enum_loc, OPT_Wpedantic,
-              "ISO C forbids forward references to %<enum%> types");
-    }
-  return ret;
-}
-
-/* Parse a struct or union specifier (C90 6.5.2.1, C99 6.7.2.1).
-
-   struct-or-union-specifier:
-     struct-or-union attributes[opt] identifier[opt]
-       { struct-contents } attributes[opt]
-     struct-or-union attributes[opt] identifier
-
-   struct-contents:
-     struct-declaration-list
-
-   struct-declaration-list:
-     struct-declaration ;
-     struct-declaration-list struct-declaration ;
-
-   GNU extensions:
-
-   struct-contents:
-     empty
-     struct-declaration
-     struct-declaration-list struct-declaration
-
-   struct-declaration-list:
-     struct-declaration-list ;
-     ;
-
-   (Note that in the syntax here, unlike that in ISO C, the semicolons
-   are included here rather than in struct-declaration, in order to
-   describe the syntax with extra semicolons and missing semicolon at
-   end.)
-
-   Objective-C:
-
-   struct-declaration-list:
-     @defs ( class-name )
-
-   (Note this does not include a trailing semicolon, but can be
-   followed by further declarations, and gets a pedwarn-if-pedantic
-   when followed by a semicolon.)  */
-
-static struct c_typespec
-c_parser_struct_or_union_specifier (c_parser *parser)
-{
-  struct c_typespec ret;
-  tree attrs;
-  tree ident = NULL_TREE;
-  location_t struct_loc;
-  location_t ident_loc = UNKNOWN_LOCATION;
-  enum tree_code code;
-  switch (c_parser_peek_token (parser)->keyword)
-    {
-    case RID_STRUCT:
-      code = RECORD_TYPE;
-      break;
-    case RID_UNION:
-      code = UNION_TYPE;
-      break;
-    default:
-      gcc_unreachable ();
-    }
-  struct_loc = c_parser_peek_token (parser)->location;
-  c_parser_consume_token (parser);
-  attrs = c_parser_attributes (parser);
-
-  /* Set the location in case we create a decl now.  */
-  c_parser_set_source_position_from_token (c_parser_peek_token (parser));
-
-  if (c_parser_next_token_is (parser, CPP_NAME))
-    {
-      ident = c_parser_peek_token (parser)->value;
-      ident_loc = c_parser_peek_token (parser)->location;
-      struct_loc = ident_loc;
-      c_parser_consume_token (parser);
-    }
-  if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
-    {
-      /* Parse a struct or union definition.  Start the scope of the
-        tag before parsing components.  */
-      struct c_struct_parse_info *struct_info;
-      tree type = start_struct (struct_loc, code, ident, &struct_info);
-      tree postfix_attrs;
-      /* We chain the components in reverse order, then put them in
-        forward order at the end.  Each struct-declaration may
-        declare multiple components (comma-separated), so we must use
-        chainon to join them, although when parsing each
-        struct-declaration we can use TREE_CHAIN directly.
-
-        The theory behind all this is that there will be more
-        semicolon separated fields than comma separated fields, and
-        so we'll be minimizing the number of node traversals required
-        by chainon.  */
-      tree contents;
-      timevar_push (TV_PARSE_STRUCT);
-      contents = NULL_TREE;
-      c_parser_consume_token (parser);
-      /* Handle the Objective-C @defs construct,
-        e.g. foo(sizeof(struct{ @defs(ClassName) }));.  */
-      if (c_parser_next_token_is_keyword (parser, RID_AT_DEFS))
-       {
-         tree name;
-         gcc_assert (c_dialect_objc ());
-         c_parser_consume_token (parser);
-         if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
-           goto end_at_defs;
-         if (c_parser_next_token_is (parser, CPP_NAME)
-             && c_parser_peek_token (parser)->id_kind == C_ID_CLASSNAME)
-           {
-             name = c_parser_peek_token (parser)->value;
-             c_parser_consume_token (parser);
-           }
-         else
-           {
-             c_parser_error (parser, "expected class name");
-             c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
-             goto end_at_defs;
-           }
-         c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
-                                    "expected %<)%>");
-         contents = nreverse (objc_get_class_ivars (name));
-       }
-    end_at_defs:
-      /* Parse the struct-declarations and semicolons.  Problems with
-        semicolons are diagnosed here; empty structures are diagnosed
-        elsewhere.  */
-      while (true)
-       {
-         tree decls;
-         /* Parse any stray semicolon.  */
-         if (c_parser_next_token_is (parser, CPP_SEMICOLON))
-           {
-             pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic,
-                      "extra semicolon in struct or union specified");
-             c_parser_consume_token (parser);
-             continue;
-           }
-         /* Stop if at the end of the struct or union contents.  */
-         if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
-           {
-             c_parser_consume_token (parser);
-             break;
-           }
-         /* Accept #pragmas at struct scope.  */
-         if (c_parser_next_token_is (parser, CPP_PRAGMA))
-           {
-             c_parser_pragma (parser, pragma_external);
-             continue;
-           }
-         /* Parse some comma-separated declarations, but not the
-            trailing semicolon if any.  */
-         decls = c_parser_struct_declaration (parser);
-         contents = chainon (decls, contents);
-         /* If no semicolon follows, either we have a parse error or
-            are at the end of the struct or union and should
-            pedwarn.  */
-         if (c_parser_next_token_is (parser, CPP_SEMICOLON))
-           c_parser_consume_token (parser);
-         else
-           {
-             if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
-               pedwarn (c_parser_peek_token (parser)->location, 0,
-                        "no semicolon at end of struct or union");
-             else if (parser->error
-                      || !c_parser_next_token_starts_declspecs (parser))
-               {
-                 c_parser_error (parser, "expected %<;%>");
-                 c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
-                 break;
-               }
-
-             /* If we come here, we have already emitted an error
-                for an expected `;', identifier or `(', and we also
-                recovered already.  Go on with the next field. */
-           }
-       }
-      postfix_attrs = c_parser_attributes (parser);
-      ret.spec = finish_struct (struct_loc, type, nreverse (contents),
-                               chainon (attrs, postfix_attrs), struct_info);
-      ret.kind = ctsk_tagdef;
-      ret.expr = NULL_TREE;
-      ret.expr_const_operands = true;
-      timevar_pop (TV_PARSE_STRUCT);
-      return ret;
-    }
-  else if (!ident)
-    {
-      c_parser_error (parser, "expected %<{%>");
-      ret.spec = error_mark_node;
-      ret.kind = ctsk_tagref;
-      ret.expr = NULL_TREE;
-      ret.expr_const_operands = true;
-      return ret;
-    }
-  ret = parser_xref_tag (ident_loc, code, ident);
-  return ret;
-}
-
-/* Parse a struct-declaration (C90 6.5.2.1, C99 6.7.2.1), *without*
-   the trailing semicolon.
-
-   struct-declaration:
-     specifier-qualifier-list struct-declarator-list
-     static_assert-declaration-no-semi
-
-   specifier-qualifier-list:
-     type-specifier specifier-qualifier-list[opt]
-     type-qualifier specifier-qualifier-list[opt]
-     attributes specifier-qualifier-list[opt]
-
-   struct-declarator-list:
-     struct-declarator
-     struct-declarator-list , attributes[opt] struct-declarator
-
-   struct-declarator:
-     declarator attributes[opt]
-     declarator[opt] : constant-expression attributes[opt]
-
-   GNU extensions:
-
-   struct-declaration:
-     __extension__ struct-declaration
-     specifier-qualifier-list
-
-   Unlike the ISO C syntax, semicolons are handled elsewhere.  The use
-   of attributes where shown is a GNU extension.  In GNU C, we accept
-   any expression without commas in the syntax (assignment
-   expressions, not just conditional expressions); assignment
-   expressions will be diagnosed as non-constant.  */
-
-static tree
-c_parser_struct_declaration (c_parser *parser)
-{
-  struct c_declspecs *specs;
-  tree prefix_attrs;
-  tree all_prefix_attrs;
-  tree decls;
-  location_t decl_loc;
-  if (c_parser_next_token_is_keyword (parser, RID_EXTENSION))
-    {
-      int ext;
-      tree decl;
-      ext = disable_extension_diagnostics ();
-      c_parser_consume_token (parser);
-      decl = c_parser_struct_declaration (parser);
-      restore_extension_diagnostics (ext);
-      return decl;
-    }
-  if (c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT))
-    {
-      c_parser_static_assert_declaration_no_semi (parser);
-      return NULL_TREE;
-    }
-  specs = build_null_declspecs ();
-  decl_loc = c_parser_peek_token (parser)->location;
-  c_parser_declspecs (parser, specs, false, true, true, cla_nonabstract_decl);
-  if (parser->error)
-    return NULL_TREE;
-  if (!specs->declspecs_seen_p)
-    {
-      c_parser_error (parser, "expected specifier-qualifier-list");
-      return NULL_TREE;
-    }
-  finish_declspecs (specs);
-  if (c_parser_next_token_is (parser, CPP_SEMICOLON)
-      || c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
-    {
-      tree ret;
-      if (specs->typespec_kind == ctsk_none)
-       {
-         pedwarn (decl_loc, OPT_Wpedantic,
-                  "ISO C forbids member declarations with no members");
-         shadow_tag_warned (specs, pedantic);
-         ret = NULL_TREE;
-       }
-      else
-       {
-         /* Support for unnamed structs or unions as members of
-            structs or unions (which is [a] useful and [b] supports
-            MS P-SDK).  */
-         tree attrs = NULL;
-
-         ret = grokfield (c_parser_peek_token (parser)->location,
-                          build_id_declarator (NULL_TREE), specs,
-                          NULL_TREE, &attrs);
-         if (ret)
-           decl_attributes (&ret, attrs, 0);
-       }
-      return ret;
-    }
-
-  /* Provide better error recovery.  Note that a type name here is valid,
-     and will be treated as a field name.  */
-  if (specs->typespec_kind == ctsk_tagdef
-      && TREE_CODE (specs->type) != ENUMERAL_TYPE
-      && c_parser_next_token_starts_declspecs (parser)
-      && !c_parser_next_token_is (parser, CPP_NAME))
-    {
-      c_parser_error (parser, "expected %<;%>, identifier or %<(%>");
-      parser->error = false;
-      return NULL_TREE;
-    }
-
-  pending_xref_error ();
-  prefix_attrs = specs->attrs;
-  all_prefix_attrs = prefix_attrs;
-  specs->attrs = NULL_TREE;
-  decls = NULL_TREE;
-  while (true)
-    {
-      /* Declaring one or more declarators or un-named bit-fields.  */
-      struct c_declarator *declarator;
-      bool dummy = false;
-      if (c_parser_next_token_is (parser, CPP_COLON))
-       declarator = build_id_declarator (NULL_TREE);
-      else
-       declarator = c_parser_declarator (parser,
-                                         specs->typespec_kind != ctsk_none,
-                                         C_DTR_NORMAL, &dummy);
-      if (declarator == NULL)
-       {
-         c_parser_skip_to_end_of_block_or_statement (parser);
-         break;
-       }
-      if (c_parser_next_token_is (parser, CPP_COLON)
-         || c_parser_next_token_is (parser, CPP_COMMA)
-         || c_parser_next_token_is (parser, CPP_SEMICOLON)
-         || c_parser_next_token_is (parser, CPP_CLOSE_BRACE)
-         || c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
-       {
-         tree postfix_attrs = NULL_TREE;
-         tree width = NULL_TREE;
-         tree d;
-         if (c_parser_next_token_is (parser, CPP_COLON))
-           {
-             c_parser_consume_token (parser);
-             width = c_parser_expr_no_commas (parser, NULL).value;
-           }
-         if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
-           postfix_attrs = c_parser_attributes (parser);
-         d = grokfield (c_parser_peek_token (parser)->location,
-                        declarator, specs, width, &all_prefix_attrs);
-         decl_attributes (&d, chainon (postfix_attrs,
-                                       all_prefix_attrs), 0);
-         DECL_CHAIN (d) = decls;
-         decls = d;
-         if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
-           all_prefix_attrs = chainon (c_parser_attributes (parser),
-                                       prefix_attrs);
-         else
-           all_prefix_attrs = prefix_attrs;
-         if (c_parser_next_token_is (parser, CPP_COMMA))
-           c_parser_consume_token (parser);
-         else if (c_parser_next_token_is (parser, CPP_SEMICOLON)
-                  || c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
-           {
-             /* Semicolon consumed in caller.  */
-             break;
-           }
-         else
-           {
-             c_parser_error (parser, "expected %<,%>, %<;%> or %<}%>");
-             break;
-           }
-       }
-      else
-       {
-         c_parser_error (parser,
-                         "expected %<:%>, %<,%>, %<;%>, %<}%> or "
-                         "%<__attribute__%>");
-         break;
-       }
-    }
-  return decls;
-}
-
-/* Parse a typeof specifier (a GNU extension).
-
-   typeof-specifier:
-     typeof ( expression )
-     typeof ( type-name )
-*/
-
-static struct c_typespec
-c_parser_typeof_specifier (c_parser *parser)
-{
-  struct c_typespec ret;
-  ret.kind = ctsk_typeof;
-  ret.spec = error_mark_node;
-  ret.expr = NULL_TREE;
-  ret.expr_const_operands = true;
-  gcc_assert (c_parser_next_token_is_keyword (parser, RID_TYPEOF));
-  c_parser_consume_token (parser);
-  c_inhibit_evaluation_warnings++;
-  in_typeof++;
-  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
-    {
-      c_inhibit_evaluation_warnings--;
-      in_typeof--;
-      return ret;
-    }
-  if (c_parser_next_tokens_start_typename (parser, cla_prefer_id))
-    {
-      struct c_type_name *type = c_parser_type_name (parser);
-      c_inhibit_evaluation_warnings--;
-      in_typeof--;
-      if (type != NULL)
-       {
-         ret.spec = groktypename (type, &ret.expr, &ret.expr_const_operands);
-         pop_maybe_used (variably_modified_type_p (ret.spec, NULL_TREE));
-       }
-    }
-  else
-    {
-      bool was_vm;
-      location_t here = c_parser_peek_token (parser)->location;
-      struct c_expr expr = c_parser_expression (parser);
-      c_inhibit_evaluation_warnings--;
-      in_typeof--;
-      if (TREE_CODE (expr.value) == COMPONENT_REF
-         && DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1)))
-       error_at (here, "%<typeof%> applied to a bit-field");
-      mark_exp_read (expr.value);
-      ret.spec = TREE_TYPE (expr.value);
-      was_vm = variably_modified_type_p (ret.spec, NULL_TREE);
-      /* This is returned with the type so that when the type is
-        evaluated, this can be evaluated.  */
-      if (was_vm)
-       ret.expr = c_fully_fold (expr.value, false, &ret.expr_const_operands);
-      pop_maybe_used (was_vm);
-    }
-  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
-  return ret;
-}
-
-/* Parse an alignment-specifier.
-
-   C11 6.7.5:
-
-   alignment-specifier:
-     _Alignas ( type-name )
-     _Alignas ( constant-expression )
-*/
-
-static tree
-c_parser_alignas_specifier (c_parser * parser)
-{
-  tree ret = error_mark_node;
-  location_t loc = c_parser_peek_token (parser)->location;
-  gcc_assert (c_parser_next_token_is_keyword (parser, RID_ALIGNAS));
-  c_parser_consume_token (parser);
-  if (!flag_isoc11)
-    {
-      if (flag_isoc99)
-       pedwarn (loc, OPT_Wpedantic,
-                "ISO C99 does not support %<_Alignas%>");
-      else
-       pedwarn (loc, OPT_Wpedantic,
-                "ISO C90 does not support %<_Alignas%>");
-    }
-  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
-    return ret;
-  if (c_parser_next_tokens_start_typename (parser, cla_prefer_id))
-    {
-      struct c_type_name *type = c_parser_type_name (parser);
-      if (type != NULL)
-       ret = c_alignof (loc, groktypename (type, NULL, NULL));
-    }
-  else
-    ret = c_parser_expr_no_commas (parser, NULL).value;
-  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
-  return ret;
-}
-
-/* Parse a declarator, possibly an abstract declarator (C90 6.5.4,
-   6.5.5, C99 6.7.5, 6.7.6).  If TYPE_SEEN_P then a typedef name may
-   be redeclared; otherwise it may not.  KIND indicates which kind of
-   declarator is wanted.  Returns a valid declarator except in the
-   case of a syntax error in which case NULL is returned.  *SEEN_ID is
-   set to true if an identifier being declared is seen; this is used
-   to diagnose bad forms of abstract array declarators and to
-   determine whether an identifier list is syntactically permitted.
-
-   declarator:
-     pointer[opt] direct-declarator
-
-   direct-declarator:
-     identifier
-     ( attributes[opt] declarator )
-     direct-declarator array-declarator
-     direct-declarator ( parameter-type-list )
-     direct-declarator ( identifier-list[opt] )
-
-   pointer:
-     * type-qualifier-list[opt]
-     * type-qualifier-list[opt] pointer
-
-   type-qualifier-list:
-     type-qualifier
-     attributes
-     type-qualifier-list type-qualifier
-     type-qualifier-list attributes
-
-   parameter-type-list:
-     parameter-list
-     parameter-list , ...
-
-   parameter-list:
-     parameter-declaration
-     parameter-list , parameter-declaration
-
-   parameter-declaration:
-     declaration-specifiers declarator attributes[opt]
-     declaration-specifiers abstract-declarator[opt] attributes[opt]
-
-   identifier-list:
-     identifier
-     identifier-list , identifier
-
-   abstract-declarator:
-     pointer
-     pointer[opt] direct-abstract-declarator
-
-   direct-abstract-declarator:
-     ( attributes[opt] abstract-declarator )
-     direct-abstract-declarator[opt] array-declarator
-     direct-abstract-declarator[opt] ( parameter-type-list[opt] )
-
-   GNU extensions:
-
-   direct-declarator:
-     direct-declarator ( parameter-forward-declarations
-                        parameter-type-list[opt] )
-
-   direct-abstract-declarator:
-     direct-abstract-declarator[opt] ( parameter-forward-declarations
-                                      parameter-type-list[opt] )
-
-   parameter-forward-declarations:
-     parameter-list ;
-     parameter-forward-declarations parameter-list ;
-
-   The uses of attributes shown above are GNU extensions.
-
-   Some forms of array declarator are not included in C99 in the
-   syntax for abstract declarators; these are disallowed elsewhere.
-   This may be a defect (DR#289).
-
-   This function also accepts an omitted abstract declarator as being
-   an abstract declarator, although not part of the formal syntax.  */
-
-static struct c_declarator *
-c_parser_declarator (c_parser *parser, bool type_seen_p, c_dtr_syn kind,
-                    bool *seen_id)
-{
-  /* Parse any initial pointer part.  */
-  if (c_parser_next_token_is (parser, CPP_MULT))
-    {
-      struct c_declspecs *quals_attrs = build_null_declspecs ();
-      struct c_declarator *inner;
-      c_parser_consume_token (parser);
-      c_parser_declspecs (parser, quals_attrs, false, false, true, cla_prefer_id);
-      inner = c_parser_declarator (parser, type_seen_p, kind, seen_id);
-      if (inner == NULL)
-       return NULL;
-      else
-       return make_pointer_declarator (quals_attrs, inner);
-    }
-  /* Now we have a direct declarator, direct abstract declarator or
-     nothing (which counts as a direct abstract declarator here).  */
-  return c_parser_direct_declarator (parser, type_seen_p, kind, seen_id);
-}
-
-/* Parse a direct declarator or direct abstract declarator; arguments
-   as c_parser_declarator.  */
-
-static struct c_declarator *
-c_parser_direct_declarator (c_parser *parser, bool type_seen_p, c_dtr_syn kind,
-                           bool *seen_id)
-{
-  /* The direct declarator must start with an identifier (possibly
-     omitted) or a parenthesized declarator (possibly abstract).  In
-     an ordinary declarator, initial parentheses must start a
-     parenthesized declarator.  In an abstract declarator or parameter
-     declarator, they could start a parenthesized declarator or a
-     parameter list.  To tell which, the open parenthesis and any
-     following attributes must be read.  If a declaration specifier
-     follows, then it is a parameter list; if the specifier is a
-     typedef name, there might be an ambiguity about redeclaring it,
-     which is resolved in the direction of treating it as a typedef
-     name.  If a close parenthesis follows, it is also an empty
-     parameter list, as the syntax does not permit empty abstract
-     declarators.  Otherwise, it is a parenthesized declarator (in
-     which case the analysis may be repeated inside it, recursively).
-
-     ??? There is an ambiguity in a parameter declaration "int
-     (__attribute__((foo)) x)", where x is not a typedef name: it
-     could be an abstract declarator for a function, or declare x with
-     parentheses.  The proper resolution of this ambiguity needs
-     documenting.  At present we follow an accident of the old
-     parser's implementation, whereby the first parameter must have
-     some declaration specifiers other than just attributes.  Thus as
-     a parameter declaration it is treated as a parenthesized
-     parameter named x, and as an abstract declarator it is
-     rejected.
-
-     ??? Also following the old parser, attributes inside an empty
-     parameter list are ignored, making it a list not yielding a
-     prototype, rather than giving an error or making it have one
-     parameter with implicit type int.
-
-     ??? Also following the old parser, typedef names may be
-     redeclared in declarators, but not Objective-C class names.  */
-
-  if (kind != C_DTR_ABSTRACT
-      && c_parser_next_token_is (parser, CPP_NAME)
-      && ((type_seen_p
-          && (c_parser_peek_token (parser)->id_kind == C_ID_TYPENAME
-              || c_parser_peek_token (parser)->id_kind == C_ID_CLASSNAME))
-         || c_parser_peek_token (parser)->id_kind == C_ID_ID))
-    {
-      struct c_declarator *inner
-       = build_id_declarator (c_parser_peek_token (parser)->value);
-      *seen_id = true;
-      inner->id_loc = c_parser_peek_token (parser)->location;
-      c_parser_consume_token (parser);
-      return c_parser_direct_declarator_inner (parser, *seen_id, inner);
-    }
-
-  if (kind != C_DTR_NORMAL
-      && c_parser_next_token_is (parser, CPP_OPEN_SQUARE))
-    {
-      struct c_declarator *inner = build_id_declarator (NULL_TREE);
-      return c_parser_direct_declarator_inner (parser, *seen_id, inner);
-    }
-
-  /* Either we are at the end of an abstract declarator, or we have
-     parentheses.  */
-
-  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
-    {
-      tree attrs;
-      struct c_declarator *inner;
-      c_parser_consume_token (parser);
-      attrs = c_parser_attributes (parser);
-      if (kind != C_DTR_NORMAL
-         && (c_parser_next_token_starts_declspecs (parser)
-             || c_parser_next_token_is (parser, CPP_CLOSE_PAREN)))
-       {
-         struct c_arg_info *args
-           = c_parser_parms_declarator (parser, kind == C_DTR_NORMAL,
-                                        attrs);
-         if (args == NULL)
-           return NULL;
-         else
-           {
-             inner
-               = build_function_declarator (args,
-                                            build_id_declarator (NULL_TREE));
-             return c_parser_direct_declarator_inner (parser, *seen_id,
-                                                      inner);
-           }
-       }
-      /* A parenthesized declarator.  */
-      inner = c_parser_declarator (parser, type_seen_p, kind, seen_id);
-      if (inner != NULL && attrs != NULL)
-       inner = build_attrs_declarator (attrs, inner);
-      if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
-       {
-         c_parser_consume_token (parser);
-         if (inner == NULL)
-           return NULL;
-         else
-           return c_parser_direct_declarator_inner (parser, *seen_id, inner);
-       }
-      else
-       {
-         c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
-                                    "expected %<)%>");
-         return NULL;
-       }
-    }
-  else
-    {
-      if (kind == C_DTR_NORMAL)
-       {
-         c_parser_error (parser, "expected identifier or %<(%>");
-         return NULL;
-       }
-      else
-       return build_id_declarator (NULL_TREE);
-    }
-}
-
-/* Parse part of a direct declarator or direct abstract declarator,
-   given that some (in INNER) has already been parsed; ID_PRESENT is
-   true if an identifier is present, false for an abstract
-   declarator.  */
-
-static struct c_declarator *
-c_parser_direct_declarator_inner (c_parser *parser, bool id_present,
-                                 struct c_declarator *inner)
-{
-  /* Parse a sequence of array declarators and parameter lists.  */
-  if (c_parser_next_token_is (parser, CPP_OPEN_SQUARE))
-    {
-      location_t brace_loc = c_parser_peek_token (parser)->location;
-      struct c_declarator *declarator;
-      struct c_declspecs *quals_attrs = build_null_declspecs ();
-      bool static_seen;
-      bool star_seen;
-      tree dimen;
-      c_parser_consume_token (parser);
-      c_parser_declspecs (parser, quals_attrs, false, false, true, cla_prefer_id);
-      static_seen = c_parser_next_token_is_keyword (parser, RID_STATIC);
-      if (static_seen)
-       c_parser_consume_token (parser);
-      if (static_seen && !quals_attrs->declspecs_seen_p)
-       c_parser_declspecs (parser, quals_attrs, false, false, true, cla_prefer_id);
-      if (!quals_attrs->declspecs_seen_p)
-       quals_attrs = NULL;
-      /* If "static" is present, there must be an array dimension.
-        Otherwise, there may be a dimension, "*", or no
-        dimension.  */
-      if (static_seen)
-       {
-         star_seen = false;
-         dimen = c_parser_expr_no_commas (parser, NULL).value;
-       }
-      else
-       {
-         if (c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
-           {
-             dimen = NULL_TREE;
-             star_seen = false;
-           }
-         else if (c_parser_next_token_is (parser, CPP_MULT))
-           {
-             if (c_parser_peek_2nd_token (parser)->type == CPP_CLOSE_SQUARE)
-               {
-                 dimen = NULL_TREE;
-                 star_seen = true;
-                 c_parser_consume_token (parser);
-               }
-             else
-               {
-                 star_seen = false;
-                 dimen = c_parser_expr_no_commas (parser, NULL).value;
-               }
-           }
-         else
-           {
-             star_seen = false;
-             dimen = c_parser_expr_no_commas (parser, NULL).value;
-           }
-       }
-      if (c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
-       c_parser_consume_token (parser);
-      else
-       {
-         c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
-                                    "expected %<]%>");
-         return NULL;
-       }
-      if (dimen)
-       mark_exp_read (dimen);
-      declarator = build_array_declarator (brace_loc, dimen, quals_attrs,
-                                          static_seen, star_seen);
-      if (declarator == NULL)
-       return NULL;
-      inner = set_array_declarator_inner (declarator, inner);
-      return c_parser_direct_declarator_inner (parser, id_present, inner);
-    }
-  else if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
-    {
-      tree attrs;
-      struct c_arg_info *args;
-      c_parser_consume_token (parser);
-      attrs = c_parser_attributes (parser);
-      args = c_parser_parms_declarator (parser, id_present, attrs);
-      if (args == NULL)
-       return NULL;
-      else
-       {
-         inner = build_function_declarator (args, inner);
-         return c_parser_direct_declarator_inner (parser, id_present, inner);
-       }
-    }
-  return inner;
-}
-
-/* Parse a parameter list or identifier list, including the closing
-   parenthesis but not the opening one.  ATTRS are the attributes at
-   the start of the list.  ID_LIST_OK is true if an identifier list is
-   acceptable; such a list must not have attributes at the start.  */
-
-static struct c_arg_info *
-c_parser_parms_declarator (c_parser *parser, bool id_list_ok, tree attrs)
-{
-  push_scope ();
-  declare_parm_level ();
-  /* If the list starts with an identifier, it is an identifier list.
-     Otherwise, it is either a prototype list or an empty list.  */
-  if (id_list_ok
-      && !attrs
-      && c_parser_next_token_is (parser, CPP_NAME)
-      && c_parser_peek_token (parser)->id_kind == C_ID_ID
-      
-      /* Look ahead to detect typos in type names.  */
-      && c_parser_peek_2nd_token (parser)->type != CPP_NAME
-      && c_parser_peek_2nd_token (parser)->type != CPP_MULT
-      && c_parser_peek_2nd_token (parser)->type != CPP_OPEN_PAREN
-      && c_parser_peek_2nd_token (parser)->type != CPP_OPEN_SQUARE)
-    {
-      tree list = NULL_TREE, *nextp = &list;
-      while (c_parser_next_token_is (parser, CPP_NAME)
-            && c_parser_peek_token (parser)->id_kind == C_ID_ID)
-       {
-         *nextp = build_tree_list (NULL_TREE,
-                                   c_parser_peek_token (parser)->value);
-         nextp = & TREE_CHAIN (*nextp);
-         c_parser_consume_token (parser);
-         if (c_parser_next_token_is_not (parser, CPP_COMMA))
-           break;
-         c_parser_consume_token (parser);
-         if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
-           {
-             c_parser_error (parser, "expected identifier");
-             break;
-           }
-       }
-      if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
-       {
-         struct c_arg_info *ret = build_arg_info ();
-         ret->types = list;
-         c_parser_consume_token (parser);
-         pop_scope ();
-         return ret;
-       }
-      else
-       {
-         c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
-                                    "expected %<)%>");
-         pop_scope ();
-         return NULL;
-       }
-    }
-  else
-    {
-      struct c_arg_info *ret = c_parser_parms_list_declarator (parser, attrs,
-                                                              NULL);
-      pop_scope ();
-      return ret;
-    }
-}
-
-/* Parse a parameter list (possibly empty), including the closing
-   parenthesis but not the opening one.  ATTRS are the attributes at
-   the start of the list.  EXPR is NULL or an expression that needs to
-   be evaluated for the side effects of array size expressions in the
-   parameters.  */
-
-static struct c_arg_info *
-c_parser_parms_list_declarator (c_parser *parser, tree attrs, tree expr)
-{
-  bool bad_parm = false;
-
-  /* ??? Following the old parser, forward parameter declarations may
-     use abstract declarators, and if no real parameter declarations
-     follow the forward declarations then this is not diagnosed.  Also
-     note as above that attributes are ignored as the only contents of
-     the parentheses, or as the only contents after forward
-     declarations.  */
-  if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
-    {
-      struct c_arg_info *ret = build_arg_info ();
-      c_parser_consume_token (parser);
-      return ret;
-    }
-  if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
-    {
-      struct c_arg_info *ret = build_arg_info ();
-
-      if (flag_allow_parameterless_variadic_functions)
-        {
-          /* F (...) is allowed.  */
-          ret->types = NULL_TREE;
-        }
-      else
-        {
-          /* Suppress -Wold-style-definition for this case.  */
-          ret->types = error_mark_node;
-          error_at (c_parser_peek_token (parser)->location,
-                    "ISO C requires a named argument before %<...%>");
-        }
-      c_parser_consume_token (parser);
-      if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
-       {
-         c_parser_consume_token (parser);
-         return ret;
-       }
-      else
-       {
-         c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
-                                    "expected %<)%>");
-         return NULL;
-       }
-    }
-  /* Nonempty list of parameters, either terminated with semicolon
-     (forward declarations; recurse) or with close parenthesis (normal
-     function) or with ", ... )" (variadic function).  */
-  while (true)
-    {
-      /* Parse a parameter.  */
-      struct c_parm *parm = c_parser_parameter_declaration (parser, attrs);
-      attrs = NULL_TREE;
-      if (parm == NULL)
-       bad_parm = true;
-      else
-       push_parm_decl (parm, &expr);
-      if (c_parser_next_token_is (parser, CPP_SEMICOLON))
-       {
-         tree new_attrs;
-         c_parser_consume_token (parser);
-         mark_forward_parm_decls ();
-         new_attrs = c_parser_attributes (parser);
-         return c_parser_parms_list_declarator (parser, new_attrs, expr);
-       }
-      if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
-       {
-         c_parser_consume_token (parser);
-         if (bad_parm)
-           return NULL;
-         else
-           return get_parm_info (false, expr);
-       }
-      if (!c_parser_require (parser, CPP_COMMA,
-                            "expected %<;%>, %<,%> or %<)%>"))
-       {
-         c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
-         return NULL;
-       }
-      if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
-       {
-         c_parser_consume_token (parser);
-         if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
-           {
-             c_parser_consume_token (parser);
-             if (bad_parm)
-               return NULL;
-             else
-               return get_parm_info (true, expr);
-           }
-         else
-           {
-             c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
-                                        "expected %<)%>");
-             return NULL;
-           }
-       }
-    }
-}
-
-/* Parse a parameter declaration.  ATTRS are the attributes at the
-   start of the declaration if it is the first parameter.  */
-
-static struct c_parm *
-c_parser_parameter_declaration (c_parser *parser, tree attrs)
-{
-  struct c_declspecs *specs;
-  struct c_declarator *declarator;
-  tree prefix_attrs;
-  tree postfix_attrs = NULL_TREE;
-  bool dummy = false;
-
-  /* Accept #pragmas between parameter declarations.  */
-  while (c_parser_next_token_is (parser, CPP_PRAGMA))
-    c_parser_pragma (parser, pragma_external);
-
-  if (!c_parser_next_token_starts_declspecs (parser))
-    {
-      c_token *token = c_parser_peek_token (parser);
-      if (parser->error)
-       return NULL;
-      c_parser_set_source_position_from_token (token);
-      if (c_parser_next_tokens_start_typename (parser, cla_prefer_type))
-       {
-         error ("unknown type name %qE", token->value);
-         parser->error = true;
-       }
-      /* ??? In some Objective-C cases '...' isn't applicable so there
-        should be a different message.  */
-      else
-       c_parser_error (parser,
-                       "expected declaration specifiers or %<...%>");
-      c_parser_skip_to_end_of_parameter (parser);
-      return NULL;
-    }
-  specs = build_null_declspecs ();
-  if (attrs)
-    {
-      declspecs_add_attrs (input_location, specs, attrs);
-      attrs = NULL_TREE;
-    }
-  c_parser_declspecs (parser, specs, true, true, true, cla_nonabstract_decl);
-  finish_declspecs (specs);
-  pending_xref_error ();
-  prefix_attrs = specs->attrs;
-  specs->attrs = NULL_TREE;
-  declarator = c_parser_declarator (parser,
-                                   specs->typespec_kind != ctsk_none,
-                                   C_DTR_PARM, &dummy);
-  if (declarator == NULL)
-    {
-      c_parser_skip_until_found (parser, CPP_COMMA, NULL);
-      return NULL;
-    }
-  if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
-    postfix_attrs = c_parser_attributes (parser);
-  return build_c_parm (specs, chainon (postfix_attrs, prefix_attrs),
-                      declarator);
-}
-
-/* Parse a string literal in an asm expression.  It should not be
-   translated, and wide string literals are an error although
-   permitted by the syntax.  This is a GNU extension.
-
-   asm-string-literal:
-     string-literal
-
-   ??? At present, following the old parser, the caller needs to have
-   set lex_untranslated_string to 1.  It would be better to follow the
-   C++ parser rather than using this kludge.  */
-
-static tree
-c_parser_asm_string_literal (c_parser *parser)
-{
-  tree str;
-  int save_flag = warn_overlength_strings;
-  warn_overlength_strings = 0;
-  if (c_parser_next_token_is (parser, CPP_STRING))
-    {
-      str = c_parser_peek_token (parser)->value;
-      c_parser_consume_token (parser);
-    }
-  else if (c_parser_next_token_is (parser, CPP_WSTRING))
-    {
-      error_at (c_parser_peek_token (parser)->location,
-               "wide string literal in %<asm%>");
-      str = build_string (1, "");
-      c_parser_consume_token (parser);
-    }
-  else
-    {
-      c_parser_error (parser, "expected string literal");
-      str = NULL_TREE;
-    }
-  warn_overlength_strings = save_flag;
-  return str;
-}
-
-/* Parse a simple asm expression.  This is used in restricted
-   contexts, where a full expression with inputs and outputs does not
-   make sense.  This is a GNU extension.
-
-   simple-asm-expr:
-     asm ( asm-string-literal )
-*/
-
-static tree
-c_parser_simple_asm_expr (c_parser *parser)
-{
-  tree str;
-  gcc_assert (c_parser_next_token_is_keyword (parser, RID_ASM));
-  /* ??? Follow the C++ parser rather than using the
-     lex_untranslated_string kludge.  */
-  parser->lex_untranslated_string = true;
-  c_parser_consume_token (parser);
-  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
-    {
-      parser->lex_untranslated_string = false;
-      return NULL_TREE;
-    }
-  str = c_parser_asm_string_literal (parser);
-  parser->lex_untranslated_string = false;
-  if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
-    {
-      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
-      return NULL_TREE;
-    }
-  return str;
-}
-
-static tree
-c_parser_attribute_any_word (c_parser *parser)
-{
-  tree attr_name = NULL_TREE;
-
-  if (c_parser_next_token_is (parser, CPP_KEYWORD))
-    {
-      /* ??? See comment above about what keywords are accepted here.  */
-      bool ok;
-      switch (c_parser_peek_token (parser)->keyword)
-       {
-       case RID_STATIC:
-       case RID_UNSIGNED:
-       case RID_LONG:
-       case RID_INT128:
-       case RID_CONST:
-       case RID_EXTERN:
-       case RID_REGISTER:
-       case RID_TYPEDEF:
-       case RID_SHORT:
-       case RID_INLINE:
-       case RID_NORETURN:
-       case RID_VOLATILE:
-       case RID_SIGNED:
-       case RID_AUTO:
-       case RID_RESTRICT:
-       case RID_COMPLEX:
-       case RID_THREAD:
-       case RID_INT:
-       case RID_CHAR:
-       case RID_FLOAT:
-       case RID_DOUBLE:
-       case RID_VOID:
-       case RID_DFLOAT32:
-       case RID_DFLOAT64:
-       case RID_DFLOAT128:
-       case RID_BOOL:
-       case RID_FRACT:
-       case RID_ACCUM:
-       case RID_SAT:
-       case RID_TRANSACTION_ATOMIC:
-       case RID_TRANSACTION_CANCEL:
-         ok = true;
-         break;
-       default:
-         ok = false;
-         break;
-       }
-      if (!ok)
-       return NULL_TREE;
-
-      /* Accept __attribute__((__const)) as __attribute__((const)) etc.  */
-      attr_name = ridpointers[(int) c_parser_peek_token (parser)->keyword];
-    }
-  else if (c_parser_next_token_is (parser, CPP_NAME))
-    attr_name = c_parser_peek_token (parser)->value;
-
-  return attr_name;
-}
-
-/* Parse (possibly empty) attributes.  This is a GNU extension.
-
-   attributes:
-     empty
-     attributes attribute
-
-   attribute:
-     __attribute__ ( ( attribute-list ) )
-
-   attribute-list:
-     attrib
-     attribute_list , attrib
-
-   attrib:
-     empty
-     any-word
-     any-word ( identifier )
-     any-word ( identifier , nonempty-expr-list )
-     any-word ( expr-list )
-
-   where the "identifier" must not be declared as a type, and
-   "any-word" may be any identifier (including one declared as a
-   type), a reserved word storage class specifier, type specifier or
-   type qualifier.  ??? This still leaves out most reserved keywords
-   (following the old parser), shouldn't we include them, and why not
-   allow identifiers declared as types to start the arguments?  */
-
-static tree
-c_parser_attributes (c_parser *parser)
-{
-  tree attrs = NULL_TREE;
-  while (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
-    {
-      /* ??? Follow the C++ parser rather than using the
-        lex_untranslated_string kludge.  */
-      parser->lex_untranslated_string = true;
-      c_parser_consume_token (parser);
-      if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
-       {
-         parser->lex_untranslated_string = false;
-         return attrs;
-       }
-      if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
-       {
-         parser->lex_untranslated_string = false;
-         c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
-         return attrs;
-       }
-      /* Parse the attribute list.  */
-      while (c_parser_next_token_is (parser, CPP_COMMA)
-            || c_parser_next_token_is (parser, CPP_NAME)
-            || c_parser_next_token_is (parser, CPP_KEYWORD))
-       {
-         tree attr, attr_name, attr_args;
-         VEC(tree,gc) *expr_list;
-         if (c_parser_next_token_is (parser, CPP_COMMA))
-           {
-             c_parser_consume_token (parser);
-             continue;
-           }
-
-         attr_name = c_parser_attribute_any_word (parser);
-         if (attr_name == NULL)
-           break;
-         c_parser_consume_token (parser);
-         if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN))
-           {
-             attr = build_tree_list (attr_name, NULL_TREE);
-             attrs = chainon (attrs, attr);
-             continue;
-           }
-         c_parser_consume_token (parser);
-         /* Parse the attribute contents.  If they start with an
-            identifier which is followed by a comma or close
-            parenthesis, then the arguments start with that
-            identifier; otherwise they are an expression list.  
-            In objective-c the identifier may be a classname.  */
-         if (c_parser_next_token_is (parser, CPP_NAME)
-             && (c_parser_peek_token (parser)->id_kind == C_ID_ID
-                 || (c_dialect_objc () 
-                     && c_parser_peek_token (parser)->id_kind == C_ID_CLASSNAME))
-             && ((c_parser_peek_2nd_token (parser)->type == CPP_COMMA)
-                 || (c_parser_peek_2nd_token (parser)->type
-                     == CPP_CLOSE_PAREN)))
-           {
-             tree arg1 = c_parser_peek_token (parser)->value;
-             c_parser_consume_token (parser);
-             if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
-               attr_args = build_tree_list (NULL_TREE, arg1);
-             else
-               {
-                 tree tree_list;
-                 c_parser_consume_token (parser);
-                 expr_list = c_parser_expr_list (parser, false, true, NULL);
-                 tree_list = build_tree_list_vec (expr_list);
-                 attr_args = tree_cons (NULL_TREE, arg1, tree_list);
-                 release_tree_vector (expr_list);
-               }
-           }
-         else
-           {
-             if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
-               attr_args = NULL_TREE;
-             else
-               {
-                 expr_list = c_parser_expr_list (parser, false, true, NULL);
-                 attr_args = build_tree_list_vec (expr_list);
-                 release_tree_vector (expr_list);
-               }
-           }
-         attr = build_tree_list (attr_name, attr_args);
-         if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
-           c_parser_consume_token (parser);
-         else
-           {
-             parser->lex_untranslated_string = false;
-             c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
-                                        "expected %<)%>");
-             return attrs;
-           }
-         attrs = chainon (attrs, attr);
-       }
-      if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
-       c_parser_consume_token (parser);
-      else
-       {
-         parser->lex_untranslated_string = false;
-         c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
-                                    "expected %<)%>");
-         return attrs;
-       }
-      if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
-       c_parser_consume_token (parser);
-      else
-       {
-         parser->lex_untranslated_string = false;
-         c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
-                                    "expected %<)%>");
-         return attrs;
-       }
-      parser->lex_untranslated_string = false;
-    }
-  return attrs;
-}
-
-/* Parse a type name (C90 6.5.5, C99 6.7.6).
-
-   type-name:
-     specifier-qualifier-list abstract-declarator[opt]
-*/
-
-static struct c_type_name *
-c_parser_type_name (c_parser *parser)
-{
-  struct c_declspecs *specs = build_null_declspecs ();
-  struct c_declarator *declarator;
-  struct c_type_name *ret;
-  bool dummy = false;
-  c_parser_declspecs (parser, specs, false, true, true, cla_prefer_type);
-  if (!specs->declspecs_seen_p)
-    {
-      c_parser_error (parser, "expected specifier-qualifier-list");
-      return NULL;
-    }
-  if (specs->type != error_mark_node)
-    {
-      pending_xref_error ();
-      finish_declspecs (specs);
-    }
-  declarator = c_parser_declarator (parser,
-                                   specs->typespec_kind != ctsk_none,
-                                   C_DTR_ABSTRACT, &dummy);
-  if (declarator == NULL)
-    return NULL;
-  ret = XOBNEW (&parser_obstack, struct c_type_name);
-  ret->specs = specs;
-  ret->declarator = declarator;
-  return ret;
-}
-
-/* Parse an initializer (C90 6.5.7, C99 6.7.8).
-
-   initializer:
-     assignment-expression
-     { initializer-list }
-     { initializer-list , }
-
-   initializer-list:
-     designation[opt] initializer
-     initializer-list , designation[opt] initializer
-
-   designation:
-     designator-list =
-
-   designator-list:
-     designator
-     designator-list designator
-
-   designator:
-     array-designator
-     . identifier
-
-   array-designator:
-     [ constant-expression ]
-
-   GNU extensions:
-
-   initializer:
-     { }
-
-   designation:
-     array-designator
-     identifier :
-
-   array-designator:
-     [ constant-expression ... constant-expression ]
-
-   Any expression without commas is accepted in the syntax for the
-   constant-expressions, with non-constant expressions rejected later.
-
-   This function is only used for top-level initializers; for nested
-   ones, see c_parser_initval.  */
-
-static struct c_expr
-c_parser_initializer (c_parser *parser)
-{
-  if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
-    return c_parser_braced_init (parser, NULL_TREE, false);
-  else
-    {
-      struct c_expr ret;
-      location_t loc = c_parser_peek_token (parser)->location;
-      ret = c_parser_expr_no_commas (parser, NULL);
-      if (TREE_CODE (ret.value) != STRING_CST
-         && TREE_CODE (ret.value) != COMPOUND_LITERAL_EXPR)
-       ret = default_function_array_read_conversion (loc, ret);
-      return ret;
-    }
-}
-
-/* Parse a braced initializer list.  TYPE is the type specified for a
-   compound literal, and NULL_TREE for other initializers and for
-   nested braced lists.  NESTED_P is true for nested braced lists,
-   false for the list of a compound literal or the list that is the
-   top-level initializer in a declaration.  */
-
-static struct c_expr
-c_parser_braced_init (c_parser *parser, tree type, bool nested_p)
-{
-  struct c_expr ret;
-  struct obstack braced_init_obstack;
-  location_t brace_loc = c_parser_peek_token (parser)->location;
-  gcc_obstack_init (&braced_init_obstack);
-  gcc_assert (c_parser_next_token_is (parser, CPP_OPEN_BRACE));
-  c_parser_consume_token (parser);
-  if (nested_p)
-    push_init_level (0, &braced_init_obstack);
-  else
-    really_start_incremental_init (type);
-  if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
-    {
-      pedwarn (brace_loc, OPT_Wpedantic, "ISO C forbids empty initializer braces");
-    }
-  else
-    {
-      /* Parse a non-empty initializer list, possibly with a trailing
-        comma.  */
-      while (true)
-       {
-         c_parser_initelt (parser, &braced_init_obstack);
-         if (parser->error)
-           break;
-         if (c_parser_next_token_is (parser, CPP_COMMA))
-           c_parser_consume_token (parser);
-         else
-           break;
-         if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
-           break;
-       }
-    }
-  if (c_parser_next_token_is_not (parser, CPP_CLOSE_BRACE))
-    {
-      ret.value = error_mark_node;
-      ret.original_code = ERROR_MARK;
-      ret.original_type = NULL;
-      c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, "expected %<}%>");
-      pop_init_level (0, &braced_init_obstack);
-      obstack_free (&braced_init_obstack, NULL);
-      return ret;
-    }
-  c_parser_consume_token (parser);
-  ret = pop_init_level (0, &braced_init_obstack);
-  obstack_free (&braced_init_obstack, NULL);
-  return ret;
-}
-
-/* Parse a nested initializer, including designators.  */
-
-static void
-c_parser_initelt (c_parser *parser, struct obstack * braced_init_obstack)
-{
-  /* Parse any designator or designator list.  A single array
-     designator may have the subsequent "=" omitted in GNU C, but a
-     longer list or a structure member designator may not.  */
-  if (c_parser_next_token_is (parser, CPP_NAME)
-      && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
-    {
-      /* Old-style structure member designator.  */
-      set_init_label (c_parser_peek_token (parser)->value,
-                     braced_init_obstack);
-      /* Use the colon as the error location.  */
-      pedwarn (c_parser_peek_2nd_token (parser)->location, OPT_Wpedantic,
-              "obsolete use of designated initializer with %<:%>");
-      c_parser_consume_token (parser);
-      c_parser_consume_token (parser);
-    }
-  else
-    {
-      /* des_seen is 0 if there have been no designators, 1 if there
-        has been a single array designator and 2 otherwise.  */
-      int des_seen = 0;
-      /* Location of a designator.  */
-      location_t des_loc = UNKNOWN_LOCATION;  /* Quiet warning.  */
-      while (c_parser_next_token_is (parser, CPP_OPEN_SQUARE)
-            || c_parser_next_token_is (parser, CPP_DOT))
-       {
-         int des_prev = des_seen;
-         if (!des_seen)
-           des_loc = c_parser_peek_token (parser)->location;
-         if (des_seen < 2)
-           des_seen++;
-         if (c_parser_next_token_is (parser, CPP_DOT))
-           {
-             des_seen = 2;
-             c_parser_consume_token (parser);
-             if (c_parser_next_token_is (parser, CPP_NAME))
-               {
-                 set_init_label (c_parser_peek_token (parser)->value,
-                                 braced_init_obstack);
-                 c_parser_consume_token (parser);
-               }
-             else
-               {
-                 struct c_expr init;
-                 init.value = error_mark_node;
-                 init.original_code = ERROR_MARK;
-                 init.original_type = NULL;
-                 c_parser_error (parser, "expected identifier");
-                 c_parser_skip_until_found (parser, CPP_COMMA, NULL);
-                 process_init_element (init, false, braced_init_obstack);
-                 return;
-               }
-           }
-         else
-           {
-             tree first, second;
-             location_t ellipsis_loc = UNKNOWN_LOCATION;  /* Quiet warning.  */
-             /* ??? Following the old parser, [ objc-receiver
-                objc-message-args ] is accepted as an initializer,
-                being distinguished from a designator by what follows
-                the first assignment expression inside the square
-                brackets, but after a first array designator a
-                subsequent square bracket is for Objective-C taken to
-                start an expression, using the obsolete form of
-                designated initializer without '=', rather than
-                possibly being a second level of designation: in LALR
-                terms, the '[' is shifted rather than reducing
-                designator to designator-list.  */
-             if (des_prev == 1 && c_dialect_objc ())
-               {
-                 des_seen = des_prev;
-                 break;
-               }
-             if (des_prev == 0 && c_dialect_objc ())
-               {
-                 /* This might be an array designator or an
-                    Objective-C message expression.  If the former,
-                    continue parsing here; if the latter, parse the
-                    remainder of the initializer given the starting
-                    primary-expression.  ??? It might make sense to
-                    distinguish when des_prev == 1 as well; see
-                    previous comment.  */
-                 tree rec, args;
-                 struct c_expr mexpr;
-                 c_parser_consume_token (parser);
-                 if (c_parser_peek_token (parser)->type == CPP_NAME
-                     && ((c_parser_peek_token (parser)->id_kind
-                          == C_ID_TYPENAME)
-                         || (c_parser_peek_token (parser)->id_kind
-                             == C_ID_CLASSNAME)))
-                   {
-                     /* Type name receiver.  */
-                     tree id = c_parser_peek_token (parser)->value;
-                     c_parser_consume_token (parser);
-                     rec = objc_get_class_reference (id);
-                     goto parse_message_args;
-                   }
-                 first = c_parser_expr_no_commas (parser, NULL).value;
-                 mark_exp_read (first);
-                 if (c_parser_next_token_is (parser, CPP_ELLIPSIS)
-                     || c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
-                   goto array_desig_after_first;
-                 /* Expression receiver.  So far only one part
-                    without commas has been parsed; there might be
-                    more of the expression.  */
-                 rec = first;
-                 while (c_parser_next_token_is (parser, CPP_COMMA))
-                   {
-                     struct c_expr next;
-                     location_t comma_loc, exp_loc;
-                     comma_loc = c_parser_peek_token (parser)->location;
-                     c_parser_consume_token (parser);
-                     exp_loc = c_parser_peek_token (parser)->location;
-                     next = c_parser_expr_no_commas (parser, NULL);
-                     next = default_function_array_read_conversion (exp_loc,
-                                                                    next);
-                     rec = build_compound_expr (comma_loc, rec, next.value);
-                   }
-               parse_message_args:
-                 /* Now parse the objc-message-args.  */
-                 args = c_parser_objc_message_args (parser);
-                 c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
-                                            "expected %<]%>");
-                 mexpr.value
-                   = objc_build_message_expr (rec, args);
-                 mexpr.original_code = ERROR_MARK;
-                 mexpr.original_type = NULL;
-                 /* Now parse and process the remainder of the
-                    initializer, starting with this message
-                    expression as a primary-expression.  */
-                 c_parser_initval (parser, &mexpr, braced_init_obstack);
-                 return;
-               }
-             c_parser_consume_token (parser);
-             first = c_parser_expr_no_commas (parser, NULL).value;
-             mark_exp_read (first);
-           array_desig_after_first:
-             if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
-               {
-                 ellipsis_loc = c_parser_peek_token (parser)->location;
-                 c_parser_consume_token (parser);
-                 second = c_parser_expr_no_commas (parser, NULL).value;
-                 mark_exp_read (second);
-               }
-             else
-               second = NULL_TREE;
-             if (c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
-               {
-                 c_parser_consume_token (parser);
-                 set_init_index (first, second, braced_init_obstack);
-                 if (second)
-                   pedwarn (ellipsis_loc, OPT_Wpedantic,
-                            "ISO C forbids specifying range of elements to initialize");
-               }
-             else
-               c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
-                                          "expected %<]%>");
-           }
-       }
-      if (des_seen >= 1)
-       {
-         if (c_parser_next_token_is (parser, CPP_EQ))
-           {
-             if (!flag_isoc99)
-               pedwarn (des_loc, OPT_Wpedantic,
-                        "ISO C90 forbids specifying subobject to initialize");
-             c_parser_consume_token (parser);
-           }
-         else
-           {
-             if (des_seen == 1)
-               pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic,
-                        "obsolete use of designated initializer without %<=%>");
-             else
-               {
-                 struct c_expr init;
-                 init.value = error_mark_node;
-                 init.original_code = ERROR_MARK;
-                 init.original_type = NULL;
-                 c_parser_error (parser, "expected %<=%>");
-                 c_parser_skip_until_found (parser, CPP_COMMA, NULL);
-                 process_init_element (init, false, braced_init_obstack);
-                 return;
-               }
-           }
-       }
-    }
-  c_parser_initval (parser, NULL, braced_init_obstack);
-}
-
-/* Parse a nested initializer; as c_parser_initializer but parses
-   initializers within braced lists, after any designators have been
-   applied.  If AFTER is not NULL then it is an Objective-C message
-   expression which is the primary-expression starting the
-   initializer.  */
-
-static void
-c_parser_initval (c_parser *parser, struct c_expr *after,
-                 struct obstack * braced_init_obstack)
-{
-  struct c_expr init;
-  gcc_assert (!after || c_dialect_objc ());
-  if (c_parser_next_token_is (parser, CPP_OPEN_BRACE) && !after)
-    init = c_parser_braced_init (parser, NULL_TREE, true);
-  else
-    {
-      location_t loc = c_parser_peek_token (parser)->location;
-      init = c_parser_expr_no_commas (parser, after);
-      if (init.value != NULL_TREE
-         && TREE_CODE (init.value) != STRING_CST
-         && TREE_CODE (init.value) != COMPOUND_LITERAL_EXPR)
-       init = default_function_array_read_conversion (loc, init);
-    }
-  process_init_element (init, false, braced_init_obstack);
-}
-
-/* Parse a compound statement (possibly a function body) (C90 6.6.2,
-   C99 6.8.2).
-
-   compound-statement:
-     { block-item-list[opt] }
-     { label-declarations block-item-list }
-
-   block-item-list:
-     block-item
-     block-item-list block-item
-
-   block-item:
-     nested-declaration
-     statement
-
-   nested-declaration:
-     declaration
-
-   GNU extensions:
-
-   compound-statement:
-     { label-declarations block-item-list }
-
-   nested-declaration:
-     __extension__ nested-declaration
-     nested-function-definition
-
-   label-declarations:
-     label-declaration
-     label-declarations label-declaration
-
-   label-declaration:
-     __label__ identifier-list ;
-
-   Allowing the mixing of declarations and code is new in C99.  The
-   GNU syntax also permits (not shown above) labels at the end of
-   compound statements, which yield an error.  We don't allow labels
-   on declarations; this might seem like a natural extension, but
-   there would be a conflict between attributes on the label and
-   prefix attributes on the declaration.  ??? The syntax follows the
-   old parser in requiring something after label declarations.
-   Although they are erroneous if the labels declared aren't defined,
-   is it useful for the syntax to be this way?
-
-   OpenMP:
-
-   block-item:
-     openmp-directive
-
-   openmp-directive:
-     barrier-directive
-     flush-directive  */
-
-static tree
-c_parser_compound_statement (c_parser *parser)
-{
-  tree stmt;
-  location_t brace_loc;
-  brace_loc = c_parser_peek_token (parser)->location;
-  if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
-    {
-      /* Ensure a scope is entered and left anyway to avoid confusion
-        if we have just prepared to enter a function body.  */
-      stmt = c_begin_compound_stmt (true);
-      c_end_compound_stmt (brace_loc, stmt, true);
-      return error_mark_node;
-    }
-  stmt = c_begin_compound_stmt (true);
-  c_parser_compound_statement_nostart (parser);
-  return c_end_compound_stmt (brace_loc, stmt, true);
-}
-
-/* Parse a compound statement except for the opening brace.  This is
-   used for parsing both compound statements and statement expressions
-   (which follow different paths to handling the opening).  */
-
-static void
-c_parser_compound_statement_nostart (c_parser *parser)
-{
-  bool last_stmt = false;
-  bool last_label = false;
-  bool save_valid_for_pragma = valid_location_for_stdc_pragma_p ();
-  location_t label_loc = UNKNOWN_LOCATION;  /* Quiet warning.  */
-  if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
-    {
-      c_parser_consume_token (parser);
-      return;
-    }
-  mark_valid_location_for_stdc_pragma (true);
-  if (c_parser_next_token_is_keyword (parser, RID_LABEL))
-    {
-      /* Read zero or more forward-declarations for labels that nested
-        functions can jump to.  */
-      mark_valid_location_for_stdc_pragma (false);
-      while (c_parser_next_token_is_keyword (parser, RID_LABEL))
-       {
-         label_loc = c_parser_peek_token (parser)->location;
-         c_parser_consume_token (parser);
-         /* Any identifiers, including those declared as type names,
-            are OK here.  */
-         while (true)
-           {
-             tree label;
-             if (c_parser_next_token_is_not (parser, CPP_NAME))
-               {
-                 c_parser_error (parser, "expected identifier");
-                 break;
-               }
-             label
-               = declare_label (c_parser_peek_token (parser)->value);
-             C_DECLARED_LABEL_FLAG (label) = 1;
-             add_stmt (build_stmt (label_loc, DECL_EXPR, label));
-             c_parser_consume_token (parser);
-             if (c_parser_next_token_is (parser, CPP_COMMA))
-               c_parser_consume_token (parser);
-             else
-               break;
-           }
-         c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
-       }
-      pedwarn (label_loc, OPT_Wpedantic, "ISO C forbids label declarations");
-    }
-  /* We must now have at least one statement, label or declaration.  */
-  if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
-    {
-      mark_valid_location_for_stdc_pragma (save_valid_for_pragma);
-      c_parser_error (parser, "expected declaration or statement");
-      c_parser_consume_token (parser);
-      return;
-    }
-  while (c_parser_next_token_is_not (parser, CPP_CLOSE_BRACE))
-    {
-      location_t loc = c_parser_peek_token (parser)->location;
-      if (c_parser_next_token_is_keyword (parser, RID_CASE)
-         || c_parser_next_token_is_keyword (parser, RID_DEFAULT)
-         || (c_parser_next_token_is (parser, CPP_NAME)
-             && c_parser_peek_2nd_token (parser)->type == CPP_COLON))
-       {
-         if (c_parser_next_token_is_keyword (parser, RID_CASE))
-           label_loc = c_parser_peek_2nd_token (parser)->location;
-         else
-           label_loc = c_parser_peek_token (parser)->location;
-         last_label = true;
-         last_stmt = false;
-         mark_valid_location_for_stdc_pragma (false);
-         c_parser_label (parser);
-       }
-      else if (!last_label
-              && c_parser_next_tokens_start_declaration (parser))
-       {
-         last_label = false;
-         mark_valid_location_for_stdc_pragma (false);
-         c_parser_declaration_or_fndef (parser, true, true, true, true, true, NULL);
-         if (last_stmt)
-           pedwarn_c90 (loc,
-                        (pedantic && !flag_isoc99)
-                        ? OPT_Wpedantic
-                        : OPT_Wdeclaration_after_statement,
-                        "ISO C90 forbids mixed declarations and code");
-         last_stmt = false;
-       }
-      else if (!last_label
-              && c_parser_next_token_is_keyword (parser, RID_EXTENSION))
-       {
-         /* __extension__ can start a declaration, but is also an
-            unary operator that can start an expression.  Consume all
-            but the last of a possible series of __extension__ to
-            determine which.  */
-         while (c_parser_peek_2nd_token (parser)->type == CPP_KEYWORD
-                && (c_parser_peek_2nd_token (parser)->keyword
-                    == RID_EXTENSION))
-           c_parser_consume_token (parser);
-         if (c_token_starts_declaration (c_parser_peek_2nd_token (parser)))
-           {
-             int ext;
-             ext = disable_extension_diagnostics ();
-             c_parser_consume_token (parser);
-             last_label = false;
-             mark_valid_location_for_stdc_pragma (false);
-             c_parser_declaration_or_fndef (parser, true, true, true, true,
-                                            true, NULL);
-             /* Following the old parser, __extension__ does not
-                disable this diagnostic.  */
-             restore_extension_diagnostics (ext);
-             if (last_stmt)
-               pedwarn_c90 (loc, (pedantic && !flag_isoc99)
-                            ? OPT_Wpedantic
-                            : OPT_Wdeclaration_after_statement,
-                            "ISO C90 forbids mixed declarations and code");
-             last_stmt = false;
-           }
-         else
-           goto statement;
-       }
-      else if (c_parser_next_token_is (parser, CPP_PRAGMA))
-       {
-         /* External pragmas, and some omp pragmas, are not associated
-            with regular c code, and so are not to be considered statements
-            syntactically.  This ensures that the user doesn't put them
-            places that would turn into syntax errors if the directive
-            were ignored.  */
-         if (c_parser_pragma (parser, pragma_compound))
-           last_label = false, last_stmt = true;
-       }
-      else if (c_parser_next_token_is (parser, CPP_EOF))
-       {
-         mark_valid_location_for_stdc_pragma (save_valid_for_pragma);
-         c_parser_error (parser, "expected declaration or statement");
-         return;
-       }
-      else if (c_parser_next_token_is_keyword (parser, RID_ELSE))
-        {
-          if (parser->in_if_block)
-            {
-             mark_valid_location_for_stdc_pragma (save_valid_for_pragma);
-              error_at (loc, """expected %<}%> before %<else%>");
-              return;
-            }
-          else
-            {
-              error_at (loc, "%<else%> without a previous %<if%>");
-              c_parser_consume_token (parser);
-              continue;
-            }
-        }
-      else
-       {
-       statement:
-         last_label = false;
-         last_stmt = true;
-         mark_valid_location_for_stdc_pragma (false);
-         c_parser_statement_after_labels (parser);
-       }
-
-      parser->error = false;
-    }
-  if (last_label)
-    error_at (label_loc, "label at end of compound statement");
-  c_parser_consume_token (parser);
-  /* Restore the value we started with.  */
-  mark_valid_location_for_stdc_pragma (save_valid_for_pragma);
-}
-
-/* Parse a label (C90 6.6.1, C99 6.8.1).
-
-   label:
-     identifier : attributes[opt]
-     case constant-expression :
-     default :
-
-   GNU extensions:
-
-   label:
-     case constant-expression ... constant-expression :
-
-   The use of attributes on labels is a GNU extension.  The syntax in
-   GNU C accepts any expressions without commas, non-constant
-   expressions being rejected later.  */
-
-static void
-c_parser_label (c_parser *parser)
-{
-  location_t loc1 = c_parser_peek_token (parser)->location;
-  tree label = NULL_TREE;
-  if (c_parser_next_token_is_keyword (parser, RID_CASE))
-    {
-      tree exp1, exp2;
-      c_parser_consume_token (parser);
-      exp1 = c_parser_expr_no_commas (parser, NULL).value;
-      if (c_parser_next_token_is (parser, CPP_COLON))
-       {
-         c_parser_consume_token (parser);
-         label = do_case (loc1, exp1, NULL_TREE);
-       }
-      else if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
-       {
-         c_parser_consume_token (parser);
-         exp2 = c_parser_expr_no_commas (parser, NULL).value;
-         if (c_parser_require (parser, CPP_COLON, "expected %<:%>"))
-           label = do_case (loc1, exp1, exp2);
-       }
-      else
-       c_parser_error (parser, "expected %<:%> or %<...%>");
-    }
-  else if (c_parser_next_token_is_keyword (parser, RID_DEFAULT))
-    {
-      c_parser_consume_token (parser);
-      if (c_parser_require (parser, CPP_COLON, "expected %<:%>"))
-       label = do_case (loc1, NULL_TREE, NULL_TREE);
-    }
-  else
-    {
-      tree name = c_parser_peek_token (parser)->value;
-      tree tlab;
-      tree attrs;
-      location_t loc2 = c_parser_peek_token (parser)->location;
-      gcc_assert (c_parser_next_token_is (parser, CPP_NAME));
-      c_parser_consume_token (parser);
-      gcc_assert (c_parser_next_token_is (parser, CPP_COLON));
-      c_parser_consume_token (parser);
-      attrs = c_parser_attributes (parser);
-      tlab = define_label (loc2, name);
-      if (tlab)
-       {
-         decl_attributes (&tlab, attrs, 0);
-         label = add_stmt (build_stmt (loc1, LABEL_EXPR, tlab));
-       }
-    }
-  if (label)
-    {
-      if (c_parser_next_tokens_start_declaration (parser))
-       {
-         error_at (c_parser_peek_token (parser)->location,
-                   "a label can only be part of a statement and "
-                   "a declaration is not a statement");
-         c_parser_declaration_or_fndef (parser, /*fndef_ok*/ false,
-                                        /*static_assert_ok*/ true,
-                                        /*nested*/ true, /*empty_ok*/ false,
-                                        /*start_attr_ok*/ true, NULL);
-       }
-    }
-}
-
-/* Parse a statement (C90 6.6, C99 6.8).
-
-   statement:
-     labeled-statement
-     compound-statement
-     expression-statement
-     selection-statement
-     iteration-statement
-     jump-statement
-
-   labeled-statement:
-     label statement
-
-   expression-statement:
-     expression[opt] ;
-
-   selection-statement:
-     if-statement
-     switch-statement
-
-   iteration-statement:
-     while-statement
-     do-statement
-     for-statement
-
-   jump-statement:
-     goto identifier ;
-     continue ;
-     break ;
-     return expression[opt] ;
-
-   GNU extensions:
-
-   statement:
-     asm-statement
-
-   jump-statement:
-     goto * expression ;
-
-   Objective-C:
-
-   statement:
-     objc-throw-statement
-     objc-try-catch-statement
-     objc-synchronized-statement
-
-   objc-throw-statement:
-     @throw expression ;
-     @throw ;
-
-   OpenMP:
-
-   statement:
-     openmp-construct
-
-   openmp-construct:
-     parallel-construct
-     for-construct
-     sections-construct
-     single-construct
-     parallel-for-construct
-     parallel-sections-construct
-     master-construct
-     critical-construct
-     atomic-construct
-     ordered-construct
-
-   parallel-construct:
-     parallel-directive structured-block
-
-   for-construct:
-     for-directive iteration-statement
-
-   sections-construct:
-     sections-directive section-scope
-
-   single-construct:
-     single-directive structured-block
-
-   parallel-for-construct:
-     parallel-for-directive iteration-statement
-
-   parallel-sections-construct:
-     parallel-sections-directive section-scope
-
-   master-construct:
-     master-directive structured-block
-
-   critical-construct:
-     critical-directive structured-block
-
-   atomic-construct:
-     atomic-directive expression-statement
-
-   ordered-construct:
-     ordered-directive structured-block
-
-   Transactional Memory:
-
-   statement:
-     transaction-statement
-     transaction-cancel-statement
-*/
-
-static void
-c_parser_statement (c_parser *parser)
-{
-  while (c_parser_next_token_is_keyword (parser, RID_CASE)
-        || c_parser_next_token_is_keyword (parser, RID_DEFAULT)
-        || (c_parser_next_token_is (parser, CPP_NAME)
-            && c_parser_peek_2nd_token (parser)->type == CPP_COLON))
-    c_parser_label (parser);
-  c_parser_statement_after_labels (parser);
-}
-
-/* Parse a statement, other than a labeled statement.  */
-
-static void
-c_parser_statement_after_labels (c_parser *parser)
-{
-  location_t loc = c_parser_peek_token (parser)->location;
-  tree stmt = NULL_TREE;
-  bool in_if_block = parser->in_if_block;
-  parser->in_if_block = false;
-  switch (c_parser_peek_token (parser)->type)
-    {
-    case CPP_OPEN_BRACE:
-      add_stmt (c_parser_compound_statement (parser));
-      break;
-    case CPP_KEYWORD:
-      switch (c_parser_peek_token (parser)->keyword)
-       {
-       case RID_IF:
-         c_parser_if_statement (parser);
-         break;
-       case RID_SWITCH:
-         c_parser_switch_statement (parser);
-         break;
-       case RID_WHILE:
-         c_parser_while_statement (parser);
-         break;
-       case RID_DO:
-         c_parser_do_statement (parser);
-         break;
-       case RID_FOR:
-         c_parser_for_statement (parser);
-         break;
-       case RID_GOTO:
-         c_parser_consume_token (parser);
-         if (c_parser_next_token_is (parser, CPP_NAME))
-           {
-             stmt = c_finish_goto_label (loc,
-                                         c_parser_peek_token (parser)->value);
-             c_parser_consume_token (parser);
-           }
-         else if (c_parser_next_token_is (parser, CPP_MULT))
-           {
-             tree val;
-
-             c_parser_consume_token (parser);
-             val = c_parser_expression (parser).value;
-             mark_exp_read (val);
-             stmt = c_finish_goto_ptr (loc, val);
-           }
-         else
-           c_parser_error (parser, "expected identifier or %<*%>");
-         goto expect_semicolon;
-       case RID_CONTINUE:
-         c_parser_consume_token (parser);
-         stmt = c_finish_bc_stmt (loc, &c_cont_label, false);
-         goto expect_semicolon;
-       case RID_BREAK:
-         c_parser_consume_token (parser);
-         stmt = c_finish_bc_stmt (loc, &c_break_label, true);
-         goto expect_semicolon;
-       case RID_RETURN:
-         c_parser_consume_token (parser);
-         if (c_parser_next_token_is (parser, CPP_SEMICOLON))
-           {
-             stmt = c_finish_return (loc, NULL_TREE, NULL_TREE);
-             c_parser_consume_token (parser);
-           }
-         else
-           {
-             struct c_expr expr = c_parser_expression_conv (parser);
-             mark_exp_read (expr.value);
-             stmt = c_finish_return (loc, expr.value, expr.original_type);
-             goto expect_semicolon;
-           }
-         break;
-       case RID_ASM:
-         stmt = c_parser_asm_statement (parser);
-         break;
-       case RID_TRANSACTION_ATOMIC:
-       case RID_TRANSACTION_RELAXED:
-         stmt = c_parser_transaction (parser,
-             c_parser_peek_token (parser)->keyword);
-         break;
-       case RID_TRANSACTION_CANCEL:
-         stmt = c_parser_transaction_cancel (parser);
-         goto expect_semicolon;
-       case RID_AT_THROW:
-         gcc_assert (c_dialect_objc ());
-         c_parser_consume_token (parser);
-         if (c_parser_next_token_is (parser, CPP_SEMICOLON))
-           {
-             stmt = objc_build_throw_stmt (loc, NULL_TREE);
-             c_parser_consume_token (parser);
-           }
-         else
-           {
-             tree expr = c_parser_expression (parser).value;
-             expr = c_fully_fold (expr, false, NULL);
-             stmt = objc_build_throw_stmt (loc, expr);
-             goto expect_semicolon;
-           }
-         break;
-       case RID_AT_TRY:
-         gcc_assert (c_dialect_objc ());
-         c_parser_objc_try_catch_finally_statement (parser);
-         break;
-       case RID_AT_SYNCHRONIZED:
-         gcc_assert (c_dialect_objc ());
-         c_parser_objc_synchronized_statement (parser);
-         break;
-       default:
-         goto expr_stmt;
-       }
-      break;
-    case CPP_SEMICOLON:
-      c_parser_consume_token (parser);
-      break;
-    case CPP_CLOSE_PAREN:
-    case CPP_CLOSE_SQUARE:
-      /* Avoid infinite loop in error recovery:
-        c_parser_skip_until_found stops at a closing nesting
-        delimiter without consuming it, but here we need to consume
-        it to proceed further.  */
-      c_parser_error (parser, "expected statement");
-      c_parser_consume_token (parser);
-      break;
-    case CPP_PRAGMA:
-      c_parser_pragma (parser, pragma_stmt);
-      break;
-    default:
-    expr_stmt:
-      stmt = c_finish_expr_stmt (loc, c_parser_expression_conv (parser).value);
-    expect_semicolon:
-      c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
-      break;
-    }
-  /* Two cases cannot and do not have line numbers associated: If stmt
-     is degenerate, such as "2;", then stmt is an INTEGER_CST, which
-     cannot hold line numbers.  But that's OK because the statement
-     will either be changed to a MODIFY_EXPR during gimplification of
-     the statement expr, or discarded.  If stmt was compound, but
-     without new variables, we will have skipped the creation of a
-     BIND and will have a bare STATEMENT_LIST.  But that's OK because
-     (recursively) all of the component statements should already have
-     line numbers assigned.  ??? Can we discard no-op statements
-     earlier?  */
-  if (CAN_HAVE_LOCATION_P (stmt)
-      && EXPR_LOCATION (stmt) == UNKNOWN_LOCATION)
-    SET_EXPR_LOCATION (stmt, loc);
-
-  parser->in_if_block = in_if_block;
-}
-
-/* Parse the condition from an if, do, while or for statements.  */
-
-static tree
-c_parser_condition (c_parser *parser)
-{
-  location_t loc = c_parser_peek_token (parser)->location;
-  tree cond;
-  cond = c_parser_expression_conv (parser).value;
-  cond = c_objc_common_truthvalue_conversion (loc, cond);
-  cond = c_fully_fold (cond, false, NULL);
-  if (warn_sequence_point)
-    verify_sequence_points (cond);
-  return cond;
-}
-
-/* Parse a parenthesized condition from an if, do or while statement.
-
-   condition:
-     ( expression )
-*/
-static tree
-c_parser_paren_condition (c_parser *parser)
-{
-  tree cond;
-  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
-    return error_mark_node;
-  cond = c_parser_condition (parser);
-  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
-  return cond;
-}
-
-/* Parse a statement which is a block in C99.  */
-
-static tree
-c_parser_c99_block_statement (c_parser *parser)
-{
-  tree block = c_begin_compound_stmt (flag_isoc99);
-  location_t loc = c_parser_peek_token (parser)->location;
-  c_parser_statement (parser);
-  return c_end_compound_stmt (loc, block, flag_isoc99);
-}
-
-/* Parse the body of an if statement.  This is just parsing a
-   statement but (a) it is a block in C99, (b) we track whether the
-   body is an if statement for the sake of -Wparentheses warnings, (c)
-   we handle an empty body specially for the sake of -Wempty-body
-   warnings, and (d) we call parser_compound_statement directly
-   because c_parser_statement_after_labels resets
-   parser->in_if_block.  */
-
-static tree
-c_parser_if_body (c_parser *parser, bool *if_p)
-{
-  tree block = c_begin_compound_stmt (flag_isoc99);
-  location_t body_loc = c_parser_peek_token (parser)->location;
-  while (c_parser_next_token_is_keyword (parser, RID_CASE)
-        || c_parser_next_token_is_keyword (parser, RID_DEFAULT)
-        || (c_parser_next_token_is (parser, CPP_NAME)
-            && c_parser_peek_2nd_token (parser)->type == CPP_COLON))
-    c_parser_label (parser);
-  *if_p = c_parser_next_token_is_keyword (parser, RID_IF);
-  if (c_parser_next_token_is (parser, CPP_SEMICOLON))
-    {
-      location_t loc = c_parser_peek_token (parser)->location;
-      add_stmt (build_empty_stmt (loc));
-      c_parser_consume_token (parser);
-      if (!c_parser_next_token_is_keyword (parser, RID_ELSE))
-       warning_at (loc, OPT_Wempty_body,
-                   "suggest braces around empty body in an %<if%> statement");
-    }
-  else if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
-    add_stmt (c_parser_compound_statement (parser));
-  else
-    c_parser_statement_after_labels (parser);
-  return c_end_compound_stmt (body_loc, block, flag_isoc99);
-}
-
-/* Parse the else body of an if statement.  This is just parsing a
-   statement but (a) it is a block in C99, (b) we handle an empty body
-   specially for the sake of -Wempty-body warnings.  */
-
-static tree
-c_parser_else_body (c_parser *parser)
-{
-  location_t else_loc = c_parser_peek_token (parser)->location;
-  tree block = c_begin_compound_stmt (flag_isoc99);
-  while (c_parser_next_token_is_keyword (parser, RID_CASE)
-        || c_parser_next_token_is_keyword (parser, RID_DEFAULT)
-        || (c_parser_next_token_is (parser, CPP_NAME)
-            && c_parser_peek_2nd_token (parser)->type == CPP_COLON))
-    c_parser_label (parser);
-  if (c_parser_next_token_is (parser, CPP_SEMICOLON))
-    {
-      location_t loc = c_parser_peek_token (parser)->location;
-      warning_at (loc,
-                 OPT_Wempty_body,
-                "suggest braces around empty body in an %<else%> statement");
-      add_stmt (build_empty_stmt (loc));
-      c_parser_consume_token (parser);
-    }
-  else
-    c_parser_statement_after_labels (parser);
-  return c_end_compound_stmt (else_loc, block, flag_isoc99);
-}
-
-/* Parse an if statement (C90 6.6.4, C99 6.8.4).
-
-   if-statement:
-     if ( expression ) statement
-     if ( expression ) statement else statement
-*/
-
-static void
-c_parser_if_statement (c_parser *parser)
-{
-  tree block;
-  location_t loc;
-  tree cond;
-  bool first_if = false;
-  tree first_body, second_body;
-  bool in_if_block;
-
-  gcc_assert (c_parser_next_token_is_keyword (parser, RID_IF));
-  c_parser_consume_token (parser);
-  block = c_begin_compound_stmt (flag_isoc99);
-  loc = c_parser_peek_token (parser)->location;
-  cond = c_parser_paren_condition (parser);
-  in_if_block = parser->in_if_block;
-  parser->in_if_block = true;
-  first_body = c_parser_if_body (parser, &first_if);
-  parser->in_if_block = in_if_block;
-  if (c_parser_next_token_is_keyword (parser, RID_ELSE))
-    {
-      c_parser_consume_token (parser);
-      second_body = c_parser_else_body (parser);
-    }
-  else
-    second_body = NULL_TREE;
-  c_finish_if_stmt (loc, cond, first_body, second_body, first_if);
-  add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
-}
-
-/* Parse a switch statement (C90 6.6.4, C99 6.8.4).
-
-   switch-statement:
-     switch (expression) statement
-*/
-
-static void
-c_parser_switch_statement (c_parser *parser)
-{
-  tree block, expr, body, save_break;
-  location_t switch_loc = c_parser_peek_token (parser)->location;
-  location_t switch_cond_loc;
-  gcc_assert (c_parser_next_token_is_keyword (parser, RID_SWITCH));
-  c_parser_consume_token (parser);
-  block = c_begin_compound_stmt (flag_isoc99);
-  if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
-    {
-      switch_cond_loc = c_parser_peek_token (parser)->location;
-      expr = c_parser_expression (parser).value;
-      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
-    }
-  else
-    {
-      switch_cond_loc = UNKNOWN_LOCATION;
-      expr = error_mark_node;
-    }
-  c_start_case (switch_loc, switch_cond_loc, expr);
-  save_break = c_break_label;
-  c_break_label = NULL_TREE;
-  body = c_parser_c99_block_statement (parser);
-  c_finish_case (body);
-  if (c_break_label)
-    {
-      location_t here = c_parser_peek_token (parser)->location;
-      tree t = build1 (LABEL_EXPR, void_type_node, c_break_label);
-      SET_EXPR_LOCATION (t, here);
-      add_stmt (t);
-    }
-  c_break_label = save_break;
-  add_stmt (c_end_compound_stmt (switch_loc, block, flag_isoc99));
-}
-
-/* Parse a while statement (C90 6.6.5, C99 6.8.5).
-
-   while-statement:
-      while (expression) statement
-*/
-
-static void
-c_parser_while_statement (c_parser *parser)
-{
-  tree block, cond, body, save_break, save_cont;
-  location_t loc;
-  gcc_assert (c_parser_next_token_is_keyword (parser, RID_WHILE));
-  c_parser_consume_token (parser);
-  block = c_begin_compound_stmt (flag_isoc99);
-  loc = c_parser_peek_token (parser)->location;
-  cond = c_parser_paren_condition (parser);
-  save_break = c_break_label;
-  c_break_label = NULL_TREE;
-  save_cont = c_cont_label;
-  c_cont_label = NULL_TREE;
-  body = c_parser_c99_block_statement (parser);
-  c_finish_loop (loc, cond, NULL, body, c_break_label, c_cont_label, true);
-  add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
-  c_break_label = save_break;
-  c_cont_label = save_cont;
-}
-
-/* Parse a do statement (C90 6.6.5, C99 6.8.5).
-
-   do-statement:
-     do statement while ( expression ) ;
-*/
-
-static void
-c_parser_do_statement (c_parser *parser)
-{
-  tree block, cond, body, save_break, save_cont, new_break, new_cont;
-  location_t loc;
-  gcc_assert (c_parser_next_token_is_keyword (parser, RID_DO));
-  c_parser_consume_token (parser);
-  if (c_parser_next_token_is (parser, CPP_SEMICOLON))
-    warning_at (c_parser_peek_token (parser)->location,
-               OPT_Wempty_body,
-               "suggest braces around empty body in %<do%> statement");
-  block = c_begin_compound_stmt (flag_isoc99);
-  loc = c_parser_peek_token (parser)->location;
-  save_break = c_break_label;
-  c_break_label = NULL_TREE;
-  save_cont = c_cont_label;
-  c_cont_label = NULL_TREE;
-  body = c_parser_c99_block_statement (parser);
-  c_parser_require_keyword (parser, RID_WHILE, "expected %<while%>");
-  new_break = c_break_label;
-  c_break_label = save_break;
-  new_cont = c_cont_label;
-  c_cont_label = save_cont;
-  cond = c_parser_paren_condition (parser);
-  if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
-    c_parser_skip_to_end_of_block_or_statement (parser);
-  c_finish_loop (loc, cond, NULL, body, new_break, new_cont, false);
-  add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
-}
-
-/* Parse a for statement (C90 6.6.5, C99 6.8.5).
-
-   for-statement:
-     for ( expression[opt] ; expression[opt] ; expression[opt] ) statement
-     for ( nested-declaration expression[opt] ; expression[opt] ) statement
-
-   The form with a declaration is new in C99.
-
-   ??? In accordance with the old parser, the declaration may be a
-   nested function, which is then rejected in check_for_loop_decls,
-   but does it make any sense for this to be included in the grammar?
-   Note in particular that the nested function does not include a
-   trailing ';', whereas the "declaration" production includes one.
-   Also, can we reject bad declarations earlier and cheaper than
-   check_for_loop_decls?
-
-   In Objective-C, there are two additional variants:
-
-   foreach-statement:
-     for ( expression in expresssion ) statement
-     for ( declaration in expression ) statement
-
-   This is inconsistent with C, because the second variant is allowed
-   even if c99 is not enabled.
-
-   The rest of the comment documents these Objective-C foreach-statement.
-
-   Here is the canonical example of the first variant:
-    for (object in array)    { do something with object }
-   we call the first expression ("object") the "object_expression" and 
-   the second expression ("array") the "collection_expression".
-   object_expression must be an lvalue of type "id" (a generic Objective-C
-   object) because the loop works by assigning to object_expression the
-   various objects from the collection_expression.  collection_expression
-   must evaluate to something of type "id" which responds to the method
-   countByEnumeratingWithState:objects:count:.
-
-   The canonical example of the second variant is:
-    for (id object in array)    { do something with object }
-   which is completely equivalent to
-    {
-      id object;
-      for (object in array) { do something with object }
-    }
-   Note that initizializing 'object' in some way (eg, "for ((object =
-   xxx) in array) { do something with object }") is possibly
-   technically valid, but completely pointless as 'object' will be
-   assigned to something else as soon as the loop starts.  We should
-   most likely reject it (TODO).
-
-   The beginning of the Objective-C foreach-statement looks exactly
-   like the beginning of the for-statement, and we can tell it is a
-   foreach-statement only because the initial declaration or
-   expression is terminated by 'in' instead of ';'.
-*/
-
-static void
-c_parser_for_statement (c_parser *parser)
-{
-  tree block, cond, incr, save_break, save_cont, body;
-  /* The following are only used when parsing an ObjC foreach statement.  */
-  tree object_expression;
-  /* Silence the bogus uninitialized warning.  */
-  tree collection_expression = NULL;
-  location_t loc = c_parser_peek_token (parser)->location;
-  location_t for_loc = c_parser_peek_token (parser)->location;
-  bool is_foreach_statement = false;
-  gcc_assert (c_parser_next_token_is_keyword (parser, RID_FOR));
-  c_parser_consume_token (parser);
-  /* Open a compound statement in Objective-C as well, just in case this is
-     as foreach expression.  */
-  block = c_begin_compound_stmt (flag_isoc99 || c_dialect_objc ());
-  cond = error_mark_node;
-  incr = error_mark_node;
-  if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
-    {
-      /* Parse the initialization declaration or expression.  */
-      object_expression = error_mark_node;
-      parser->objc_could_be_foreach_context = c_dialect_objc ();
-      if (c_parser_next_token_is (parser, CPP_SEMICOLON))
-       {
-         parser->objc_could_be_foreach_context = false;
-         c_parser_consume_token (parser);
-         c_finish_expr_stmt (loc, NULL_TREE);
-       }
-      else if (c_parser_next_tokens_start_declaration (parser))
-       {
-         c_parser_declaration_or_fndef (parser, true, true, true, true, true, 
-                                        &object_expression);
-         parser->objc_could_be_foreach_context = false;
-         
-         if (c_parser_next_token_is_keyword (parser, RID_IN))
-           {
-             c_parser_consume_token (parser);
-             is_foreach_statement = true;
-             if (check_for_loop_decls (for_loc, true) == NULL_TREE)
-               c_parser_error (parser, "multiple iterating variables in fast enumeration");
-           }
-         else
-           check_for_loop_decls (for_loc, flag_isoc99);
-       }
-      else if (c_parser_next_token_is_keyword (parser, RID_EXTENSION))
-       {
-         /* __extension__ can start a declaration, but is also an
-            unary operator that can start an expression.  Consume all
-            but the last of a possible series of __extension__ to
-            determine which.  */
-         while (c_parser_peek_2nd_token (parser)->type == CPP_KEYWORD
-                && (c_parser_peek_2nd_token (parser)->keyword
-                    == RID_EXTENSION))
-           c_parser_consume_token (parser);
-         if (c_token_starts_declaration (c_parser_peek_2nd_token (parser)))
-           {
-             int ext;
-             ext = disable_extension_diagnostics ();
-             c_parser_consume_token (parser);
-             c_parser_declaration_or_fndef (parser, true, true, true, true,
-                                            true, &object_expression);
-             parser->objc_could_be_foreach_context = false;
-             
-             restore_extension_diagnostics (ext);
-             if (c_parser_next_token_is_keyword (parser, RID_IN))
-               {
-                 c_parser_consume_token (parser);
-                 is_foreach_statement = true;
-                 if (check_for_loop_decls (for_loc, true) == NULL_TREE)
-                   c_parser_error (parser, "multiple iterating variables in fast enumeration");
-               }
-             else
-               check_for_loop_decls (for_loc, flag_isoc99);
-           }
-         else
-           goto init_expr;
-       }
-      else
-       {
-       init_expr:
-         {
-           tree init_expression;
-           init_expression = c_parser_expression (parser).value;
-           parser->objc_could_be_foreach_context = false;
-           if (c_parser_next_token_is_keyword (parser, RID_IN))
-             {
-               c_parser_consume_token (parser);
-               is_foreach_statement = true;
-               if (! lvalue_p (init_expression))
-                 c_parser_error (parser, "invalid iterating variable in fast enumeration");
-               object_expression = c_fully_fold (init_expression, false, NULL);
-             }
-           else
-             {
-               c_finish_expr_stmt (loc, init_expression);
-               c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
-             }
-         }
-       }
-      /* Parse the loop condition.  In the case of a foreach
-        statement, there is no loop condition.  */
-      gcc_assert (!parser->objc_could_be_foreach_context);
-      if (!is_foreach_statement)
-       {
-         if (c_parser_next_token_is (parser, CPP_SEMICOLON))
-           {
-             c_parser_consume_token (parser);
-             cond = NULL_TREE;
-           }
-         else
-           {
-             cond = c_parser_condition (parser);
-             c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
-           }
-       }
-      /* Parse the increment expression (the third expression in a
-        for-statement).  In the case of a foreach-statement, this is
-        the expression that follows the 'in'.  */
-      if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
-       {
-         if (is_foreach_statement)
-           {
-             c_parser_error (parser, "missing collection in fast enumeration");
-             collection_expression = error_mark_node;
-           }
-         else
-           incr = c_process_expr_stmt (loc, NULL_TREE);
-       }
-      else
-       {
-         if (is_foreach_statement)
-           collection_expression = c_fully_fold (c_parser_expression (parser).value,
-                                                 false, NULL);
-         else
-           incr = c_process_expr_stmt (loc, c_parser_expression (parser).value);
-       }
-      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
-    }
-  save_break = c_break_label;
-  c_break_label = NULL_TREE;
-  save_cont = c_cont_label;
-  c_cont_label = NULL_TREE;
-  body = c_parser_c99_block_statement (parser);
-  if (is_foreach_statement)
-    objc_finish_foreach_loop (loc, object_expression, collection_expression, body, c_break_label, c_cont_label);
-  else
-    c_finish_loop (loc, cond, incr, body, c_break_label, c_cont_label, true);
-  add_stmt (c_end_compound_stmt (loc, block, flag_isoc99 || c_dialect_objc ()));
-  c_break_label = save_break;
-  c_cont_label = save_cont;
-}
-
-/* Parse an asm statement, a GNU extension.  This is a full-blown asm
-   statement with inputs, outputs, clobbers, and volatile tag
-   allowed.
-
-   asm-statement:
-     asm type-qualifier[opt] ( asm-argument ) ;
-     asm type-qualifier[opt] goto ( asm-goto-argument ) ;
-
-   asm-argument:
-     asm-string-literal
-     asm-string-literal : asm-operands[opt]
-     asm-string-literal : asm-operands[opt] : asm-operands[opt]
-     asm-string-literal : asm-operands[opt] : asm-operands[opt] : asm-clobbers[opt]
-
-   asm-goto-argument:
-     asm-string-literal : : asm-operands[opt] : asm-clobbers[opt] \
-       : asm-goto-operands
-
-   Qualifiers other than volatile are accepted in the syntax but
-   warned for.  */
-
-static tree
-c_parser_asm_statement (c_parser *parser)
-{
-  tree quals, str, outputs, inputs, clobbers, labels, ret;
-  bool simple, is_goto;
-  location_t asm_loc = c_parser_peek_token (parser)->location;
-  int section, nsections;
-
-  gcc_assert (c_parser_next_token_is_keyword (parser, RID_ASM));
-  c_parser_consume_token (parser);
-  if (c_parser_next_token_is_keyword (parser, RID_VOLATILE))
-    {
-      quals = c_parser_peek_token (parser)->value;
-      c_parser_consume_token (parser);
-    }
-  else if (c_parser_next_token_is_keyword (parser, RID_CONST)
-          || c_parser_next_token_is_keyword (parser, RID_RESTRICT))
-    {
-      warning_at (c_parser_peek_token (parser)->location,
-                 0,
-                 "%E qualifier ignored on asm",
-                 c_parser_peek_token (parser)->value);
-      quals = NULL_TREE;
-      c_parser_consume_token (parser);
-    }
-  else
-    quals = NULL_TREE;
-
-  is_goto = false;
-  if (c_parser_next_token_is_keyword (parser, RID_GOTO))
-    {
-      c_parser_consume_token (parser);
-      is_goto = true;
-    }
-
-  /* ??? Follow the C++ parser rather than using the
-     lex_untranslated_string kludge.  */
-  parser->lex_untranslated_string = true;
-  ret = NULL;
-
-  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
-    goto error;
-
-  str = c_parser_asm_string_literal (parser);
-  if (str == NULL_TREE)
-    goto error_close_paren;
-
-  simple = true;
-  outputs = NULL_TREE;
-  inputs = NULL_TREE;
-  clobbers = NULL_TREE;
-  labels = NULL_TREE;
-
-  if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN) && !is_goto)
-    goto done_asm;
-
-  /* Parse each colon-delimited section of operands.  */
-  nsections = 3 + is_goto;
-  for (section = 0; section < nsections; ++section)
-    {
-      if (!c_parser_require (parser, CPP_COLON,
-                            is_goto
-                            ? "expected %<:%>"
-                            : "expected %<:%> or %<)%>"))
-       goto error_close_paren;
-
-      /* Once past any colon, we're no longer a simple asm.  */
-      simple = false;
-
-      if ((!c_parser_next_token_is (parser, CPP_COLON)
-          && !c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
-         || section == 3)
-       switch (section)
-         {
-         case 0:
-           /* For asm goto, we don't allow output operands, but reserve
-              the slot for a future extension that does allow them.  */
-           if (!is_goto)
-             outputs = c_parser_asm_operands (parser, false);
-           break;
-         case 1:
-           inputs = c_parser_asm_operands (parser, true);
-           break;
-         case 2:
-           clobbers = c_parser_asm_clobbers (parser);
-           break;
-         case 3:
-           labels = c_parser_asm_goto_operands (parser);
-           break;
-         default:
-           gcc_unreachable ();
-         }
-
-      if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN) && !is_goto)
-       goto done_asm;
-    }
-
- done_asm:
-  if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
-    {
-      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
-      goto error;
-    }
-
-  if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
-    c_parser_skip_to_end_of_block_or_statement (parser);
-
-  ret = build_asm_stmt (quals, build_asm_expr (asm_loc, str, outputs, inputs,
-                                              clobbers, labels, simple));
-
- error:
-  parser->lex_untranslated_string = false;
-  return ret;
-
- error_close_paren:
-  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
-  goto error;
-}
-
-/* Parse asm operands, a GNU extension.  If CONVERT_P (for inputs but
-   not outputs), apply the default conversion of functions and arrays
-   to pointers.
-
-   asm-operands:
-     asm-operand
-     asm-operands , asm-operand
-
-   asm-operand:
-     asm-string-literal ( expression )
-     [ identifier ] asm-string-literal ( expression )
-*/
-
-static tree
-c_parser_asm_operands (c_parser *parser, bool convert_p)
-{
-  tree list = NULL_TREE;
-  location_t loc;
-  while (true)
-    {
-      tree name, str;
-      struct c_expr expr;
-      if (c_parser_next_token_is (parser, CPP_OPEN_SQUARE))
-       {
-         c_parser_consume_token (parser);
-         if (c_parser_next_token_is (parser, CPP_NAME))
-           {
-             tree id = c_parser_peek_token (parser)->value;
-             c_parser_consume_token (parser);
-             name = build_string (IDENTIFIER_LENGTH (id),
-                                  IDENTIFIER_POINTER (id));
-           }
-         else
-           {
-             c_parser_error (parser, "expected identifier");
-             c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL);
-             return NULL_TREE;
-           }
-         c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
-                                    "expected %<]%>");
-       }
-      else
-       name = NULL_TREE;
-      str = c_parser_asm_string_literal (parser);
-      if (str == NULL_TREE)
-       return NULL_TREE;
-      parser->lex_untranslated_string = false;
-      if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
-       {
-         parser->lex_untranslated_string = true;
-         return NULL_TREE;
-       }
-      loc = c_parser_peek_token (parser)->location;
-      expr = c_parser_expression (parser);
-      mark_exp_read (expr.value);
-      if (convert_p)
-       expr = default_function_array_conversion (loc, expr);
-      expr.value = c_fully_fold (expr.value, false, NULL);
-      parser->lex_untranslated_string = true;
-      if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
-       {
-         c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
-         return NULL_TREE;
-       }
-      list = chainon (list, build_tree_list (build_tree_list (name, str),
-                                            expr.value));
-      if (c_parser_next_token_is (parser, CPP_COMMA))
-       c_parser_consume_token (parser);
-      else
-       break;
-    }
-  return list;
-}
-
-/* Parse asm clobbers, a GNU extension.
-
-   asm-clobbers:
-     asm-string-literal
-     asm-clobbers , asm-string-literal
-*/
-
-static tree
-c_parser_asm_clobbers (c_parser *parser)
-{
-  tree list = NULL_TREE;
-  while (true)
-    {
-      tree str = c_parser_asm_string_literal (parser);
-      if (str)
-       list = tree_cons (NULL_TREE, str, list);
-      else
-       return NULL_TREE;
-      if (c_parser_next_token_is (parser, CPP_COMMA))
-       c_parser_consume_token (parser);
-      else
-       break;
-    }
-  return list;
-}
-
-/* Parse asm goto labels, a GNU extension.
-
-   asm-goto-operands:
-     identifier
-     asm-goto-operands , identifier
-*/
-
-static tree
-c_parser_asm_goto_operands (c_parser *parser)
-{
-  tree list = NULL_TREE;
-  while (true)
-    {
-      tree name, label;
-
-      if (c_parser_next_token_is (parser, CPP_NAME))
-       {
-         c_token *tok = c_parser_peek_token (parser);
-         name = tok->value;
-         label = lookup_label_for_goto (tok->location, name);
-         c_parser_consume_token (parser);
-         TREE_USED (label) = 1;
-       }
-      else
-       {
-         c_parser_error (parser, "expected identifier");
-         return NULL_TREE;
-       }
-
-      name = build_string (IDENTIFIER_LENGTH (name),
-                          IDENTIFIER_POINTER (name));
-      list = tree_cons (name, label, list);
-      if (c_parser_next_token_is (parser, CPP_COMMA))
-       c_parser_consume_token (parser);
-      else
-       return nreverse (list);
-    }
-}
-
-/* Parse an expression other than a compound expression; that is, an
-   assignment expression (C90 6.3.16, C99 6.5.16).  If AFTER is not
-   NULL then it is an Objective-C message expression which is the
-   primary-expression starting the expression as an initializer.
-
-   assignment-expression:
-     conditional-expression
-     unary-expression assignment-operator assignment-expression
-
-   assignment-operator: one of
-     = *= /= %= += -= <<= >>= &= ^= |=
-
-   In GNU C we accept any conditional expression on the LHS and
-   diagnose the invalid lvalue rather than producing a syntax
-   error.  */
-
-static struct c_expr
-c_parser_expr_no_commas (c_parser *parser, struct c_expr *after)
-{
-  struct c_expr lhs, rhs, ret;
-  enum tree_code code;
-  location_t op_location, exp_location;
-  gcc_assert (!after || c_dialect_objc ());
-  lhs = c_parser_conditional_expression (parser, after);
-  op_location = c_parser_peek_token (parser)->location;
-  switch (c_parser_peek_token (parser)->type)
-    {
-    case CPP_EQ:
-      code = NOP_EXPR;
-      break;
-    case CPP_MULT_EQ:
-      code = MULT_EXPR;
-      break;
-    case CPP_DIV_EQ:
-      code = TRUNC_DIV_EXPR;
-      break;
-    case CPP_MOD_EQ:
-      code = TRUNC_MOD_EXPR;
-      break;
-    case CPP_PLUS_EQ:
-      code = PLUS_EXPR;
-      break;
-    case CPP_MINUS_EQ:
-      code = MINUS_EXPR;
-      break;
-    case CPP_LSHIFT_EQ:
-      code = LSHIFT_EXPR;
-      break;
-    case CPP_RSHIFT_EQ:
-      code = RSHIFT_EXPR;
-      break;
-    case CPP_AND_EQ:
-      code = BIT_AND_EXPR;
-      break;
-    case CPP_XOR_EQ:
-      code = BIT_XOR_EXPR;
-      break;
-    case CPP_OR_EQ:
-      code = BIT_IOR_EXPR;
-      break;
-    default:
-      return lhs;
-    }
-  c_parser_consume_token (parser);
-  exp_location = c_parser_peek_token (parser)->location;
-  rhs = c_parser_expr_no_commas (parser, NULL);
-  rhs = default_function_array_read_conversion (exp_location, rhs);
-  ret.value = build_modify_expr (op_location, lhs.value, lhs.original_type,
-                                code, exp_location, rhs.value,
-                                rhs.original_type);
-  if (code == NOP_EXPR)
-    ret.original_code = MODIFY_EXPR;
-  else
-    {
-      TREE_NO_WARNING (ret.value) = 1;
-      ret.original_code = ERROR_MARK;
-    }
-  ret.original_type = NULL;
-  return ret;
-}
-
-/* Parse a conditional expression (C90 6.3.15, C99 6.5.15).  If AFTER
-   is not NULL then it is an Objective-C message expression which is
-   the primary-expression starting the expression as an initializer.
-
-   conditional-expression:
-     logical-OR-expression
-     logical-OR-expression ? expression : conditional-expression
-
-   GNU extensions:
-
-   conditional-expression:
-     logical-OR-expression ? : conditional-expression
-*/
-
-static struct c_expr
-c_parser_conditional_expression (c_parser *parser, struct c_expr *after)
-{
-  struct c_expr cond, exp1, exp2, ret;
-  location_t cond_loc, colon_loc, middle_loc;
-
-  gcc_assert (!after || c_dialect_objc ());
-
-  cond = c_parser_binary_expression (parser, after, PREC_NONE);
-
-  if (c_parser_next_token_is_not (parser, CPP_QUERY))
-    return cond;
-  cond_loc = c_parser_peek_token (parser)->location;
-  cond = default_function_array_read_conversion (cond_loc, cond);
-  c_parser_consume_token (parser);
-  if (c_parser_next_token_is (parser, CPP_COLON))
-    {
-      tree eptype = NULL_TREE;
-
-      middle_loc = c_parser_peek_token (parser)->location;
-      pedwarn (middle_loc, OPT_Wpedantic, 
-              "ISO C forbids omitting the middle term of a ?: expression");
-      warn_for_omitted_condop (middle_loc, cond.value);
-      if (TREE_CODE (cond.value) == EXCESS_PRECISION_EXPR)
-       {
-         eptype = TREE_TYPE (cond.value);
-         cond.value = TREE_OPERAND (cond.value, 0);
-       }
-      /* Make sure first operand is calculated only once.  */
-      exp1.value = c_save_expr (default_conversion (cond.value));
-      if (eptype)
-       exp1.value = build1 (EXCESS_PRECISION_EXPR, eptype, exp1.value);
-      exp1.original_type = NULL;
-      cond.value = c_objc_common_truthvalue_conversion (cond_loc, exp1.value);
-      c_inhibit_evaluation_warnings += cond.value == truthvalue_true_node;
-    }
-  else
-    {
-      cond.value
-       = c_objc_common_truthvalue_conversion
-       (cond_loc, default_conversion (cond.value));
-      c_inhibit_evaluation_warnings += cond.value == truthvalue_false_node;
-      exp1 = c_parser_expression_conv (parser);
-      mark_exp_read (exp1.value);
-      c_inhibit_evaluation_warnings +=
-       ((cond.value == truthvalue_true_node)
-        - (cond.value == truthvalue_false_node));
-    }
-
-  colon_loc = c_parser_peek_token (parser)->location;
-  if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
-    {
-      c_inhibit_evaluation_warnings -= cond.value == truthvalue_true_node;
-      ret.value = error_mark_node;
-      ret.original_code = ERROR_MARK;
-      ret.original_type = NULL;
-      return ret;
-    }
-  {
-    location_t exp2_loc = c_parser_peek_token (parser)->location;
-    exp2 = c_parser_conditional_expression (parser, NULL);
-    exp2 = default_function_array_read_conversion (exp2_loc, exp2);
-  }
-  c_inhibit_evaluation_warnings -= cond.value == truthvalue_true_node;
-  ret.value = build_conditional_expr (colon_loc, cond.value,
-                                     cond.original_code == C_MAYBE_CONST_EXPR,
-                                     exp1.value, exp1.original_type,
-                                     exp2.value, exp2.original_type);
-  ret.original_code = ERROR_MARK;
-  if (exp1.value == error_mark_node || exp2.value == error_mark_node)
-    ret.original_type = NULL;
-  else
-    {
-      tree t1, t2;
-
-      /* If both sides are enum type, the default conversion will have
-        made the type of the result be an integer type.  We want to
-        remember the enum types we started with.  */
-      t1 = exp1.original_type ? exp1.original_type : TREE_TYPE (exp1.value);
-      t2 = exp2.original_type ? exp2.original_type : TREE_TYPE (exp2.value);
-      ret.original_type = ((t1 != error_mark_node
-                           && t2 != error_mark_node
-                           && (TYPE_MAIN_VARIANT (t1)
-                               == TYPE_MAIN_VARIANT (t2)))
-                          ? t1
-                          : NULL);
-    }
-  return ret;
-}
-
-/* Parse a binary expression; that is, a logical-OR-expression (C90
-   6.3.5-6.3.14, C99 6.5.5-6.5.14).  If AFTER is not NULL then it is
-   an Objective-C message expression which is the primary-expression
-   starting the expression as an initializer.  PREC is the starting
-   precedence, usually PREC_NONE.
-
-   multiplicative-expression:
-     cast-expression
-     multiplicative-expression * cast-expression
-     multiplicative-expression / cast-expression
-     multiplicative-expression % cast-expression
-
-   additive-expression:
-     multiplicative-expression
-     additive-expression + multiplicative-expression
-     additive-expression - multiplicative-expression
-
-   shift-expression:
-     additive-expression
-     shift-expression << additive-expression
-     shift-expression >> additive-expression
-
-   relational-expression:
-     shift-expression
-     relational-expression < shift-expression
-     relational-expression > shift-expression
-     relational-expression <= shift-expression
-     relational-expression >= shift-expression
-
-   equality-expression:
-     relational-expression
-     equality-expression == relational-expression
-     equality-expression != relational-expression
-
-   AND-expression:
-     equality-expression
-     AND-expression & equality-expression
-
-   exclusive-OR-expression:
-     AND-expression
-     exclusive-OR-expression ^ AND-expression
-
-   inclusive-OR-expression:
-     exclusive-OR-expression
-     inclusive-OR-expression | exclusive-OR-expression
-
-   logical-AND-expression:
-     inclusive-OR-expression
-     logical-AND-expression && inclusive-OR-expression
-
-   logical-OR-expression:
-     logical-AND-expression
-     logical-OR-expression || logical-AND-expression
-*/
-
-static struct c_expr
-c_parser_binary_expression (c_parser *parser, struct c_expr *after,
-                           enum c_parser_prec prec)
-{
-  /* A binary expression is parsed using operator-precedence parsing,
-     with the operands being cast expressions.  All the binary
-     operators are left-associative.  Thus a binary expression is of
-     form:
-
-     E0 op1 E1 op2 E2 ...
-
-     which we represent on a stack.  On the stack, the precedence
-     levels are strictly increasing.  When a new operator is
-     encountered of higher precedence than that at the top of the
-     stack, it is pushed; its LHS is the top expression, and its RHS
-     is everything parsed until it is popped.  When a new operator is
-     encountered with precedence less than or equal to that at the top
-     of the stack, triples E[i-1] op[i] E[i] are popped and replaced
-     by the result of the operation until the operator at the top of
-     the stack has lower precedence than the new operator or there is
-     only one element on the stack; then the top expression is the LHS
-     of the new operator.  In the case of logical AND and OR
-     expressions, we also need to adjust c_inhibit_evaluation_warnings
-     as appropriate when the operators are pushed and popped.  */
-
-  struct {
-    /* The expression at this stack level.  */
-    struct c_expr expr;
-    /* The precedence of the operator on its left, PREC_NONE at the
-       bottom of the stack.  */
-    enum c_parser_prec prec;
-    /* The operation on its left.  */
-    enum tree_code op;
-    /* The source location of this operation.  */
-    location_t loc;
-  } stack[NUM_PRECS];
-  int sp;
-  /* Location of the binary operator.  */
-  location_t binary_loc = UNKNOWN_LOCATION;  /* Quiet warning.  */
-#define POP                                                                  \
-  do {                                                                       \
-    switch (stack[sp].op)                                                    \
-      {                                                                              \
-      case TRUTH_ANDIF_EXPR:                                                 \
-       c_inhibit_evaluation_warnings -= (stack[sp - 1].expr.value            \
-                                         == truthvalue_false_node);          \
-       break;                                                                \
-      case TRUTH_ORIF_EXPR:                                                  \
-       c_inhibit_evaluation_warnings -= (stack[sp - 1].expr.value            \
-                                         == truthvalue_true_node);           \
-       break;                                                                \
-      default:                                                               \
-       break;                                                                \
-      }                                                                              \
-    stack[sp - 1].expr                                                       \
-      = default_function_array_read_conversion (stack[sp - 1].loc,           \
-                                               stack[sp - 1].expr);          \
-    stack[sp].expr                                                           \
-      = default_function_array_read_conversion (stack[sp].loc,               \
-                                               stack[sp].expr);              \
-    stack[sp - 1].expr = parser_build_binary_op (stack[sp].loc,                      \
-                                                stack[sp].op,                \
-                                                stack[sp - 1].expr,          \
-                                                stack[sp].expr);             \
-    sp--;                                                                    \
-  } while (0)
-  gcc_assert (!after || c_dialect_objc ());
-  stack[0].loc = c_parser_peek_token (parser)->location;
-  stack[0].expr = c_parser_cast_expression (parser, after);
-  stack[0].prec = prec;
-  sp = 0;
-  while (true)
-    {
-      enum c_parser_prec oprec;
-      enum tree_code ocode;
-      if (parser->error)
-       goto out;
-      switch (c_parser_peek_token (parser)->type)
-       {
-       case CPP_MULT:
-         oprec = PREC_MULT;
-         ocode = MULT_EXPR;
-         break;
-       case CPP_DIV:
-         oprec = PREC_MULT;
-         ocode = TRUNC_DIV_EXPR;
-         break;
-       case CPP_MOD:
-         oprec = PREC_MULT;
-         ocode = TRUNC_MOD_EXPR;
-         break;
-       case CPP_PLUS:
-         oprec = PREC_ADD;
-         ocode = PLUS_EXPR;
-         break;
-       case CPP_MINUS:
-         oprec = PREC_ADD;
-         ocode = MINUS_EXPR;
-         break;
-       case CPP_LSHIFT:
-         oprec = PREC_SHIFT;
-         ocode = LSHIFT_EXPR;
-         break;
-       case CPP_RSHIFT:
-         oprec = PREC_SHIFT;
-         ocode = RSHIFT_EXPR;
-         break;
-       case CPP_LESS:
-         oprec = PREC_REL;
-         ocode = LT_EXPR;
-         break;
-       case CPP_GREATER:
-         oprec = PREC_REL;
-         ocode = GT_EXPR;
-         break;
-       case CPP_LESS_EQ:
-         oprec = PREC_REL;
-         ocode = LE_EXPR;
-         break;
-       case CPP_GREATER_EQ:
-         oprec = PREC_REL;
-         ocode = GE_EXPR;
-         break;
-       case CPP_EQ_EQ:
-         oprec = PREC_EQ;
-         ocode = EQ_EXPR;
-         break;
-       case CPP_NOT_EQ:
-         oprec = PREC_EQ;
-         ocode = NE_EXPR;
-         break;
-       case CPP_AND:
-         oprec = PREC_BITAND;
-         ocode = BIT_AND_EXPR;
-         break;
-       case CPP_XOR:
-         oprec = PREC_BITXOR;
-         ocode = BIT_XOR_EXPR;
-         break;
-       case CPP_OR:
-         oprec = PREC_BITOR;
-         ocode = BIT_IOR_EXPR;
-         break;
-       case CPP_AND_AND:
-         oprec = PREC_LOGAND;
-         ocode = TRUTH_ANDIF_EXPR;
-         break;
-       case CPP_OR_OR:
-         oprec = PREC_LOGOR;
-         ocode = TRUTH_ORIF_EXPR;
-         break;
-       default:
-         /* Not a binary operator, so end of the binary
-            expression.  */
-         goto out;
-       }
-      binary_loc = c_parser_peek_token (parser)->location;
-      while (oprec <= stack[sp].prec)
-       {
-         if (sp == 0)
-           goto out;
-         POP;
-       }
-      c_parser_consume_token (parser);
-      switch (ocode)
-       {
-       case TRUTH_ANDIF_EXPR:
-         stack[sp].expr
-           = default_function_array_read_conversion (stack[sp].loc,
-                                                     stack[sp].expr);
-         stack[sp].expr.value = c_objc_common_truthvalue_conversion
-           (stack[sp].loc, default_conversion (stack[sp].expr.value));
-         c_inhibit_evaluation_warnings += (stack[sp].expr.value
-                                           == truthvalue_false_node);
-         break;
-       case TRUTH_ORIF_EXPR:
-         stack[sp].expr
-           = default_function_array_read_conversion (stack[sp].loc,
-                                                     stack[sp].expr);
-         stack[sp].expr.value = c_objc_common_truthvalue_conversion
-           (stack[sp].loc, default_conversion (stack[sp].expr.value));
-         c_inhibit_evaluation_warnings += (stack[sp].expr.value
-                                           == truthvalue_true_node);
-         break;
-       default:
-         break;
-       }
-      sp++;
-      stack[sp].loc = binary_loc;
-      stack[sp].expr = c_parser_cast_expression (parser, NULL);
-      stack[sp].prec = oprec;
-      stack[sp].op = ocode;
-      stack[sp].loc = binary_loc;
-    }
- out:
-  while (sp > 0)
-    POP;
-  return stack[0].expr;
-#undef POP
-}
-
-/* Parse a cast expression (C90 6.3.4, C99 6.5.4).  If AFTER is not
-   NULL then it is an Objective-C message expression which is the
-   primary-expression starting the expression as an initializer.
-
-   cast-expression:
-     unary-expression
-     ( type-name ) unary-expression
-*/
-
-static struct c_expr
-c_parser_cast_expression (c_parser *parser, struct c_expr *after)
-{
-  location_t cast_loc = c_parser_peek_token (parser)->location;
-  gcc_assert (!after || c_dialect_objc ());
-  if (after)
-    return c_parser_postfix_expression_after_primary (parser,
-                                                     cast_loc, *after);
-  /* If the expression begins with a parenthesized type name, it may
-     be either a cast or a compound literal; we need to see whether
-     the next character is '{' to tell the difference.  If not, it is
-     an unary expression.  Full detection of unknown typenames here
-     would require a 3-token lookahead.  */
-  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
-      && c_token_starts_typename (c_parser_peek_2nd_token (parser)))
-    {
-      struct c_type_name *type_name;
-      struct c_expr ret;
-      struct c_expr expr;
-      c_parser_consume_token (parser);
-      type_name = c_parser_type_name (parser);
-      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
-      if (type_name == NULL)
-       {
-         ret.value = error_mark_node;
-         ret.original_code = ERROR_MARK;
-         ret.original_type = NULL;
-         return ret;
-       }
-
-      /* Save casted types in the function's used types hash table.  */
-      used_types_insert (type_name->specs->type);
-
-      if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
-       return c_parser_postfix_expression_after_paren_type (parser, type_name,
-                                                            cast_loc);
-      {
-       location_t expr_loc = c_parser_peek_token (parser)->location;
-       expr = c_parser_cast_expression (parser, NULL);
-       expr = default_function_array_read_conversion (expr_loc, expr);
-      }
-      ret.value = c_cast_expr (cast_loc, type_name, expr.value);
-      ret.original_code = ERROR_MARK;
-      ret.original_type = NULL;
-      return ret;
-    }
-  else
-    return c_parser_unary_expression (parser);
-}
-
-/* Parse an unary expression (C90 6.3.3, C99 6.5.3).
-
-   unary-expression:
-     postfix-expression
-     ++ unary-expression
-     -- unary-expression
-     unary-operator cast-expression
-     sizeof unary-expression
-     sizeof ( type-name )
-
-   unary-operator: one of
-     & * + - ~ !
-
-   GNU extensions:
-
-   unary-expression:
-     __alignof__ unary-expression
-     __alignof__ ( type-name )
-     && identifier
-
-   (C11 permits _Alignof with type names only.)
-
-   unary-operator: one of
-     __extension__ __real__ __imag__
-
-   Transactional Memory:
-
-   unary-expression:
-     transaction-expression
-
-   In addition, the GNU syntax treats ++ and -- as unary operators, so
-   they may be applied to cast expressions with errors for non-lvalues
-   given later.  */
-
-static struct c_expr
-c_parser_unary_expression (c_parser *parser)
-{
-  int ext;
-  struct c_expr ret, op;
-  location_t op_loc = c_parser_peek_token (parser)->location;
-  location_t exp_loc;
-  ret.original_code = ERROR_MARK;
-  ret.original_type = NULL;
-  switch (c_parser_peek_token (parser)->type)
-    {
-    case CPP_PLUS_PLUS:
-      c_parser_consume_token (parser);
-      exp_loc = c_parser_peek_token (parser)->location;
-      op = c_parser_cast_expression (parser, NULL);
-      op = default_function_array_read_conversion (exp_loc, op);
-      return parser_build_unary_op (op_loc, PREINCREMENT_EXPR, op);
-    case CPP_MINUS_MINUS:
-      c_parser_consume_token (parser);
-      exp_loc = c_parser_peek_token (parser)->location;
-      op = c_parser_cast_expression (parser, NULL);
-      op = default_function_array_read_conversion (exp_loc, op);
-      return parser_build_unary_op (op_loc, PREDECREMENT_EXPR, op);
-    case CPP_AND:
-      c_parser_consume_token (parser);
-      op = c_parser_cast_expression (parser, NULL);
-      mark_exp_read (op.value);
-      return parser_build_unary_op (op_loc, ADDR_EXPR, op);
-    case CPP_MULT:
-      c_parser_consume_token (parser);
-      exp_loc = c_parser_peek_token (parser)->location;
-      op = c_parser_cast_expression (parser, NULL);
-      op = default_function_array_read_conversion (exp_loc, op);
-      ret.value = build_indirect_ref (op_loc, op.value, RO_UNARY_STAR);
-      return ret;
-    case CPP_PLUS:
-      if (!c_dialect_objc () && !in_system_header)
-       warning_at (op_loc,
-                   OPT_Wtraditional,
-                   "traditional C rejects the unary plus operator");
-      c_parser_consume_token (parser);
-      exp_loc = c_parser_peek_token (parser)->location;
-      op = c_parser_cast_expression (parser, NULL);
-      op = default_function_array_read_conversion (exp_loc, op);
-      return parser_build_unary_op (op_loc, CONVERT_EXPR, op);
-    case CPP_MINUS:
-      c_parser_consume_token (parser);
-      exp_loc = c_parser_peek_token (parser)->location;
-      op = c_parser_cast_expression (parser, NULL);
-      op = default_function_array_read_conversion (exp_loc, op);
-      return parser_build_unary_op (op_loc, NEGATE_EXPR, op);
-    case CPP_COMPL:
-      c_parser_consume_token (parser);
-      exp_loc = c_parser_peek_token (parser)->location;
-      op = c_parser_cast_expression (parser, NULL);
-      op = default_function_array_read_conversion (exp_loc, op);
-      return parser_build_unary_op (op_loc, BIT_NOT_EXPR, op);
-    case CPP_NOT:
-      c_parser_consume_token (parser);
-      exp_loc = c_parser_peek_token (parser)->location;
-      op = c_parser_cast_expression (parser, NULL);
-      op = default_function_array_read_conversion (exp_loc, op);
-      return parser_build_unary_op (op_loc, TRUTH_NOT_EXPR, op);
-    case CPP_AND_AND:
-      /* Refer to the address of a label as a pointer.  */
-      c_parser_consume_token (parser);
-      if (c_parser_next_token_is (parser, CPP_NAME))
-       {
-         ret.value = finish_label_address_expr
-           (c_parser_peek_token (parser)->value, op_loc);
-         c_parser_consume_token (parser);
-       }
-      else
-       {
-         c_parser_error (parser, "expected identifier");
-         ret.value = error_mark_node;
-       }
-       return ret;
-    case CPP_KEYWORD:
-      switch (c_parser_peek_token (parser)->keyword)
-       {
-       case RID_SIZEOF:
-         return c_parser_sizeof_expression (parser);
-       case RID_ALIGNOF:
-         return c_parser_alignof_expression (parser);
-       case RID_EXTENSION:
-         c_parser_consume_token (parser);
-         ext = disable_extension_diagnostics ();
-         ret = c_parser_cast_expression (parser, NULL);
-         restore_extension_diagnostics (ext);
-         return ret;
-       case RID_REALPART:
-         c_parser_consume_token (parser);
-         exp_loc = c_parser_peek_token (parser)->location;
-         op = c_parser_cast_expression (parser, NULL);
-         op = default_function_array_conversion (exp_loc, op);
-         return parser_build_unary_op (op_loc, REALPART_EXPR, op);
-       case RID_IMAGPART:
-         c_parser_consume_token (parser);
-         exp_loc = c_parser_peek_token (parser)->location;
-         op = c_parser_cast_expression (parser, NULL);
-         op = default_function_array_conversion (exp_loc, op);
-         return parser_build_unary_op (op_loc, IMAGPART_EXPR, op);
-       case RID_TRANSACTION_ATOMIC:
-       case RID_TRANSACTION_RELAXED:
-         return c_parser_transaction_expression (parser,
-             c_parser_peek_token (parser)->keyword);
-       default:
-         return c_parser_postfix_expression (parser);
-       }
-    default:
-      return c_parser_postfix_expression (parser);
-    }
-}
-
-/* Parse a sizeof expression.  */
-
-static struct c_expr
-c_parser_sizeof_expression (c_parser *parser)
-{
-  struct c_expr expr;
-  location_t expr_loc;
-  gcc_assert (c_parser_next_token_is_keyword (parser, RID_SIZEOF));
-  c_parser_consume_token (parser);
-  c_inhibit_evaluation_warnings++;
-  in_sizeof++;
-  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
-      && c_token_starts_typename (c_parser_peek_2nd_token (parser)))
-    {
-      /* Either sizeof ( type-name ) or sizeof unary-expression
-        starting with a compound literal.  */
-      struct c_type_name *type_name;
-      c_parser_consume_token (parser);
-      expr_loc = c_parser_peek_token (parser)->location;
-      type_name = c_parser_type_name (parser);
-      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
-      if (type_name == NULL)
-       {
-         struct c_expr ret;
-         c_inhibit_evaluation_warnings--;
-         in_sizeof--;
-         ret.value = error_mark_node;
-         ret.original_code = ERROR_MARK;
-         ret.original_type = NULL;
-         return ret;
-       }
-      if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
-       {
-         expr = c_parser_postfix_expression_after_paren_type (parser,
-                                                              type_name,
-                                                              expr_loc);
-         goto sizeof_expr;
-       }
-      /* sizeof ( type-name ).  */
-      c_inhibit_evaluation_warnings--;
-      in_sizeof--;
-      return c_expr_sizeof_type (expr_loc, type_name);
-    }
-  else
-    {
-      expr_loc = c_parser_peek_token (parser)->location;
-      expr = c_parser_unary_expression (parser);
-    sizeof_expr:
-      c_inhibit_evaluation_warnings--;
-      in_sizeof--;
-      mark_exp_read (expr.value);
-      if (TREE_CODE (expr.value) == COMPONENT_REF
-         && DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1)))
-       error_at (expr_loc, "%<sizeof%> applied to a bit-field");
-      return c_expr_sizeof_expr (expr_loc, expr);
-    }
-}
-
-/* Parse an alignof expression.  */
-
-static struct c_expr
-c_parser_alignof_expression (c_parser *parser)
-{
-  struct c_expr expr;
-  location_t loc = c_parser_peek_token (parser)->location;
-  tree alignof_spelling = c_parser_peek_token (parser)->value;
-  gcc_assert (c_parser_next_token_is_keyword (parser, RID_ALIGNOF));
-  /* A diagnostic is not required for the use of this identifier in
-     the implementation namespace; only diagnose it for the C11
-     spelling because of existing code using the other spellings.  */
-  if (!flag_isoc11
-      && strcmp (IDENTIFIER_POINTER (alignof_spelling), "_Alignof") == 0)
-    {
-      if (flag_isoc99)
-       pedwarn (loc, OPT_Wpedantic, "ISO C99 does not support %qE",
-                alignof_spelling);
-      else
-       pedwarn (loc, OPT_Wpedantic, "ISO C90 does not support %qE",
-                alignof_spelling);
-    }
-  c_parser_consume_token (parser);
-  c_inhibit_evaluation_warnings++;
-  in_alignof++;
-  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
-      && c_token_starts_typename (c_parser_peek_2nd_token (parser)))
-    {
-      /* Either __alignof__ ( type-name ) or __alignof__
-        unary-expression starting with a compound literal.  */
-      location_t loc;
-      struct c_type_name *type_name;
-      struct c_expr ret;
-      c_parser_consume_token (parser);
-      loc = c_parser_peek_token (parser)->location;
-      type_name = c_parser_type_name (parser);
-      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
-      if (type_name == NULL)
-       {
-         struct c_expr ret;
-         c_inhibit_evaluation_warnings--;
-         in_alignof--;
-         ret.value = error_mark_node;
-         ret.original_code = ERROR_MARK;
-         ret.original_type = NULL;
-         return ret;
-       }
-      if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
-       {
-         expr = c_parser_postfix_expression_after_paren_type (parser,
-                                                              type_name,
-                                                              loc);
-         goto alignof_expr;
-       }
-      /* alignof ( type-name ).  */
-      c_inhibit_evaluation_warnings--;
-      in_alignof--;
-      ret.value = c_alignof (loc, groktypename (type_name, NULL, NULL));
-      ret.original_code = ERROR_MARK;
-      ret.original_type = NULL;
-      return ret;
-    }
-  else
-    {
-      struct c_expr ret;
-      expr = c_parser_unary_expression (parser);
-    alignof_expr:
-      mark_exp_read (expr.value);
-      c_inhibit_evaluation_warnings--;
-      in_alignof--;
-      pedwarn (loc, OPT_Wpedantic, "ISO C does not allow %<%E (expression)%>",
-              alignof_spelling);
-      ret.value = c_alignof_expr (loc, expr.value);
-      ret.original_code = ERROR_MARK;
-      ret.original_type = NULL;
-      return ret;
-    }
-}
-
-/* Helper function to read arguments of builtins which are interfaces
-   for the middle-end nodes like COMPLEX_EXPR, VEC_PERM_EXPR and
-   others.  The name of the builtin is passed using BNAME parameter.
-   Function returns true if there were no errors while parsing and
-   stores the arguments in CEXPR_LIST.  */
-static bool
-c_parser_get_builtin_args (c_parser *parser, const char *bname,
-                          VEC(c_expr_t,gc) **ret_cexpr_list)
-{
-  location_t loc = c_parser_peek_token (parser)->location;
-  VEC (c_expr_t,gc) *cexpr_list;
-  c_expr_t expr;
-
-  *ret_cexpr_list = NULL;
-  if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN))
-    {
-      error_at (loc, "cannot take address of %qs", bname);
-      return false;
-    }
-
-  c_parser_consume_token (parser);
-
-  if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
-    {
-      c_parser_consume_token (parser);
-      return true;
-    }
-
-  expr = c_parser_expr_no_commas (parser, NULL);
-  cexpr_list = VEC_alloc (c_expr_t, gc, 1);
-  C_EXPR_APPEND (cexpr_list, expr);
-  while (c_parser_next_token_is (parser, CPP_COMMA))
-    {
-      c_parser_consume_token (parser);
-      expr = c_parser_expr_no_commas (parser, NULL);
-      C_EXPR_APPEND (cexpr_list, expr);
-    }
-
-  if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
-    return false;
-
-  *ret_cexpr_list = cexpr_list;
-  return true;
-}
-
-
-/* Parse a postfix expression (C90 6.3.1-6.3.2, C99 6.5.1-6.5.2).
-
-   postfix-expression:
-     primary-expression
-     postfix-expression [ expression ]
-     postfix-expression ( argument-expression-list[opt] )
-     postfix-expression . identifier
-     postfix-expression -> identifier
-     postfix-expression ++
-     postfix-expression --
-     ( type-name ) { initializer-list }
-     ( type-name ) { initializer-list , }
-
-   argument-expression-list:
-     argument-expression
-     argument-expression-list , argument-expression
-
-   primary-expression:
-     identifier
-     constant
-     string-literal
-     ( expression )
-
-   GNU extensions:
-
-   primary-expression:
-     __func__
-       (treated as a keyword in GNU C)
-     __FUNCTION__
-     __PRETTY_FUNCTION__
-     ( compound-statement )
-     __builtin_va_arg ( assignment-expression , type-name )
-     __builtin_offsetof ( type-name , offsetof-member-designator )
-     __builtin_choose_expr ( assignment-expression ,
-                            assignment-expression ,
-                            assignment-expression )
-     __builtin_types_compatible_p ( type-name , type-name )
-     __builtin_complex ( assignment-expression , assignment-expression )
-     __builtin_shuffle ( assignment-expression , assignment-expression )
-     __builtin_shuffle ( assignment-expression , 
-                        assignment-expression ,
-                        assignment-expression, )
-
-   offsetof-member-designator:
-     identifier
-     offsetof-member-designator . identifier
-     offsetof-member-designator [ expression ]
-
-   Objective-C:
-
-   primary-expression:
-     [ objc-receiver objc-message-args ]
-     @selector ( objc-selector-arg )
-     @protocol ( identifier )
-     @encode ( type-name )
-     objc-string-literal
-     Classname . identifier
-*/
-
-static struct c_expr
-c_parser_postfix_expression (c_parser *parser)
-{
-  struct c_expr expr, e1;
-  struct c_type_name *t1, *t2;
-  location_t loc = c_parser_peek_token (parser)->location;;
-  expr.original_code = ERROR_MARK;
-  expr.original_type = NULL;
-  switch (c_parser_peek_token (parser)->type)
-    {
-    case CPP_NUMBER:
-      expr.value = c_parser_peek_token (parser)->value;
-      loc = c_parser_peek_token (parser)->location;
-      c_parser_consume_token (parser);
-      if (TREE_CODE (expr.value) == FIXED_CST
-         && !targetm.fixed_point_supported_p ())
-       {
-         error_at (loc, "fixed-point types not supported for this target");
-         expr.value = error_mark_node;
-       }
-      break;
-    case CPP_CHAR:
-    case CPP_CHAR16:
-    case CPP_CHAR32:
-    case CPP_WCHAR:
-      expr.value = c_parser_peek_token (parser)->value;
-      c_parser_consume_token (parser);
-      break;
-    case CPP_STRING:
-    case CPP_STRING16:
-    case CPP_STRING32:
-    case CPP_WSTRING:
-    case CPP_UTF8STRING:
-      expr.value = c_parser_peek_token (parser)->value;
-      expr.original_code = STRING_CST;
-      c_parser_consume_token (parser);
-      break;
-    case CPP_OBJC_STRING:
-      gcc_assert (c_dialect_objc ());
-      expr.value
-       = objc_build_string_object (c_parser_peek_token (parser)->value);
-      c_parser_consume_token (parser);
-      break;
-    case CPP_NAME:
-      switch (c_parser_peek_token (parser)->id_kind)
-       {
-       case C_ID_ID:
-         {
-           tree id = c_parser_peek_token (parser)->value;
-           c_parser_consume_token (parser);
-           expr.value = build_external_ref (loc, id,
-                                            (c_parser_peek_token (parser)->type
-                                             == CPP_OPEN_PAREN),
-                                            &expr.original_type);
-           break;
-         }
-       case C_ID_CLASSNAME:
-         {
-           /* Here we parse the Objective-C 2.0 Class.name dot
-              syntax.  */
-           tree class_name = c_parser_peek_token (parser)->value;
-           tree component;
-           c_parser_consume_token (parser);
-           gcc_assert (c_dialect_objc ());
-           if (!c_parser_require (parser, CPP_DOT, "expected %<.%>"))
-             {
-               expr.value = error_mark_node;
-               break;
-             }
-           if (c_parser_next_token_is_not (parser, CPP_NAME))
-             {
-               c_parser_error (parser, "expected identifier");
-               expr.value = error_mark_node;
-               break;
-             }
-           component = c_parser_peek_token (parser)->value;
-           c_parser_consume_token (parser);
-           expr.value = objc_build_class_component_ref (class_name, 
-                                                        component);
-           break;
-         }
-       default:
-         c_parser_error (parser, "expected expression");
-         expr.value = error_mark_node;
-         break;
-       }
-      break;
-    case CPP_OPEN_PAREN:
-      /* A parenthesized expression, statement expression or compound
-        literal.  */
-      if (c_parser_peek_2nd_token (parser)->type == CPP_OPEN_BRACE)
-       {
-         /* A statement expression.  */
-         tree stmt;
-         location_t brace_loc;
-         c_parser_consume_token (parser);
-         brace_loc = c_parser_peek_token (parser)->location;
-         c_parser_consume_token (parser);
-         if (!building_stmt_list_p ())
-           {
-             error_at (loc, "braced-group within expression allowed "
-                       "only inside a function");
-             parser->error = true;
-             c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
-             c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
-             expr.value = error_mark_node;
-             break;
-           }
-         stmt = c_begin_stmt_expr ();
-         c_parser_compound_statement_nostart (parser);
-         c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
-                                    "expected %<)%>");
-         pedwarn (loc, OPT_Wpedantic,
-                  "ISO C forbids braced-groups within expressions");
-         expr.value = c_finish_stmt_expr (brace_loc, stmt);
-         mark_exp_read (expr.value);
-       }
-      else if (c_token_starts_typename (c_parser_peek_2nd_token (parser)))
-       {
-         /* A compound literal.  ??? Can we actually get here rather
-            than going directly to
-            c_parser_postfix_expression_after_paren_type from
-            elsewhere?  */
-         location_t loc;
-         struct c_type_name *type_name;
-         c_parser_consume_token (parser);
-         loc = c_parser_peek_token (parser)->location;
-         type_name = c_parser_type_name (parser);
-         c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
-                                    "expected %<)%>");
-         if (type_name == NULL)
-           {
-             expr.value = error_mark_node;
-           }
-         else
-           expr = c_parser_postfix_expression_after_paren_type (parser,
-                                                                type_name,
-                                                                loc);
-       }
-      else
-       {
-         /* A parenthesized expression.  */
-         c_parser_consume_token (parser);
-         expr = c_parser_expression (parser);
-         if (TREE_CODE (expr.value) == MODIFY_EXPR)
-           TREE_NO_WARNING (expr.value) = 1;
-         if (expr.original_code != C_MAYBE_CONST_EXPR)
-           expr.original_code = ERROR_MARK;
-         /* Don't change EXPR.ORIGINAL_TYPE.  */
-         c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
-                                    "expected %<)%>");
-       }
-      break;
-    case CPP_KEYWORD:
-      switch (c_parser_peek_token (parser)->keyword)
-       {
-       case RID_FUNCTION_NAME:
-       case RID_PRETTY_FUNCTION_NAME:
-       case RID_C99_FUNCTION_NAME:
-         expr.value = fname_decl (loc,
-                                  c_parser_peek_token (parser)->keyword,
-                                  c_parser_peek_token (parser)->value);
-         c_parser_consume_token (parser);
-         break;
-       case RID_VA_ARG:
-         c_parser_consume_token (parser);
-         if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
-           {
-             expr.value = error_mark_node;
-             break;
-           }
-         e1 = c_parser_expr_no_commas (parser, NULL);
-         mark_exp_read (e1.value);
-         e1.value = c_fully_fold (e1.value, false, NULL);
-         if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
-           {
-             c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
-             expr.value = error_mark_node;
-             break;
-           }
-         loc = c_parser_peek_token (parser)->location;
-         t1 = c_parser_type_name (parser);
-         c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
-                                    "expected %<)%>");
-         if (t1 == NULL)
-           {
-             expr.value = error_mark_node;
-           }
-         else
-           {
-             tree type_expr = NULL_TREE;
-             expr.value = c_build_va_arg (loc, e1.value,
-                                          groktypename (t1, &type_expr, NULL));
-             if (type_expr)
-               {
-                 expr.value = build2 (C_MAYBE_CONST_EXPR,
-                                      TREE_TYPE (expr.value), type_expr,
-                                      expr.value);
-                 C_MAYBE_CONST_EXPR_NON_CONST (expr.value) = true;
-               }
-           }
-         break;
-       case RID_OFFSETOF:
-         c_parser_consume_token (parser);
-         if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
-           {
-             expr.value = error_mark_node;
-             break;
-           }
-         t1 = c_parser_type_name (parser);
-         if (t1 == NULL)
-           parser->error = true;
-         if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
-            gcc_assert (parser->error);
-         if (parser->error)
-           {
-             c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
-             expr.value = error_mark_node;
-             break;
-           }
-
-         {
-           tree type = groktypename (t1, NULL, NULL);
-           tree offsetof_ref;
-           if (type == error_mark_node)
-             offsetof_ref = error_mark_node;
-           else
-             {
-               offsetof_ref = build1 (INDIRECT_REF, type, null_pointer_node);
-               SET_EXPR_LOCATION (offsetof_ref, loc);
-             }
-           /* Parse the second argument to __builtin_offsetof.  We
-              must have one identifier, and beyond that we want to
-              accept sub structure and sub array references.  */
-           if (c_parser_next_token_is (parser, CPP_NAME))
-             {
-               offsetof_ref = build_component_ref
-                 (loc, offsetof_ref, c_parser_peek_token (parser)->value);
-               c_parser_consume_token (parser);
-               while (c_parser_next_token_is (parser, CPP_DOT)
-                      || c_parser_next_token_is (parser,
-                                                 CPP_OPEN_SQUARE)
-                      || c_parser_next_token_is (parser,
-                                                 CPP_DEREF))
-                 {
-                   if (c_parser_next_token_is (parser, CPP_DEREF))
-                     {
-                       loc = c_parser_peek_token (parser)->location;
-                       offsetof_ref = build_array_ref (loc,
-                                                       offsetof_ref,
-                                                       integer_zero_node);
-                       goto do_dot;
-                     }
-                   else if (c_parser_next_token_is (parser, CPP_DOT))
-                     {
-                     do_dot:
-                       c_parser_consume_token (parser);
-                       if (c_parser_next_token_is_not (parser,
-                                                       CPP_NAME))
-                         {
-                           c_parser_error (parser, "expected identifier");
-                           break;
-                         }
-                       offsetof_ref = build_component_ref
-                         (loc, offsetof_ref,
-                          c_parser_peek_token (parser)->value);
-                       c_parser_consume_token (parser);
-                     }
-                   else
-                     {
-                       tree idx;
-                       loc = c_parser_peek_token (parser)->location;
-                       c_parser_consume_token (parser);
-                       idx = c_parser_expression (parser).value;
-                       idx = c_fully_fold (idx, false, NULL);
-                       c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
-                                                  "expected %<]%>");
-                       offsetof_ref = build_array_ref (loc, offsetof_ref, idx);
-                     }
-                 }
-             }
-           else
-             c_parser_error (parser, "expected identifier");
-           c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
-                                      "expected %<)%>");
-           expr.value = fold_offsetof (offsetof_ref);
-         }
-         break;
-       case RID_CHOOSE_EXPR:
-         {
-           VEC (c_expr_t, gc) *cexpr_list;
-           c_expr_t *e1_p, *e2_p, *e3_p;
-           tree c;
-
-           c_parser_consume_token (parser);
-           if (!c_parser_get_builtin_args (parser,
-                                           "__builtin_choose_expr",
-                                           &cexpr_list))
-             {
-               expr.value = error_mark_node;
-               break;
-             }
-
-           if (VEC_length (c_expr_t, cexpr_list) != 3)
-             {
-               error_at (loc, "wrong number of arguments to "
-                              "%<__builtin_choose_expr%>");
-               expr.value = error_mark_node;
-               break;
-             }
-
-           e1_p = VEC_index (c_expr_t, cexpr_list, 0);
-           e2_p = VEC_index (c_expr_t, cexpr_list, 1);
-           e3_p = VEC_index (c_expr_t, cexpr_list, 2);
-
-           c = e1_p->value;
-           mark_exp_read (e2_p->value);
-           mark_exp_read (e3_p->value);
-           if (TREE_CODE (c) != INTEGER_CST
-               || !INTEGRAL_TYPE_P (TREE_TYPE (c)))
-             error_at (loc,
-                       "first argument to %<__builtin_choose_expr%> not"
-                       " a constant");
-           constant_expression_warning (c);
-           expr = integer_zerop (c) ? *e3_p : *e2_p;
-           break;
-         }
-       case RID_TYPES_COMPATIBLE_P:
-         c_parser_consume_token (parser);
-         if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
-           {
-             expr.value = error_mark_node;
-             break;
-           }
-         t1 = c_parser_type_name (parser);
-         if (t1 == NULL)
-           {
-             expr.value = error_mark_node;
-             break;
-           }
-         if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
-           {
-             c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
-             expr.value = error_mark_node;
-             break;
-           }
-         t2 = c_parser_type_name (parser);
-         if (t2 == NULL)
-           {
-             expr.value = error_mark_node;
-             break;
-           }
-         c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
-                                    "expected %<)%>");
-         {
-           tree e1, e2;
-           e1 = groktypename (t1, NULL, NULL);
-           e2 = groktypename (t2, NULL, NULL);
-           if (e1 == error_mark_node || e2 == error_mark_node)
-             {
-               expr.value = error_mark_node;
-               break;
-             }
-
-           e1 = TYPE_MAIN_VARIANT (e1);
-           e2 = TYPE_MAIN_VARIANT (e2);
-
-           expr.value
-             = comptypes (e1, e2) ? integer_one_node : integer_zero_node;
-         }
-         break;
-       case RID_BUILTIN_COMPLEX:
-         {
-           VEC(c_expr_t, gc) *cexpr_list;
-           c_expr_t *e1_p, *e2_p;
-
-           c_parser_consume_token (parser);
-           if (!c_parser_get_builtin_args (parser,
-                                           "__builtin_complex",
-                                           &cexpr_list))
-             {
-               expr.value = error_mark_node;
-               break;
-             }
-
-           if (VEC_length (c_expr_t, cexpr_list) != 2)
-             {
-               error_at (loc, "wrong number of arguments to "
-                              "%<__builtin_complex%>");
-               expr.value = error_mark_node;
-               break;
-             }
-
-           e1_p = VEC_index (c_expr_t, cexpr_list, 0);
-           e2_p = VEC_index (c_expr_t, cexpr_list, 1);
-
-           mark_exp_read (e1_p->value);
-           if (TREE_CODE (e1_p->value) == EXCESS_PRECISION_EXPR)
-             e1_p->value = convert (TREE_TYPE (e1_p->value),
-                                    TREE_OPERAND (e1_p->value, 0));
-           mark_exp_read (e2_p->value);
-           if (TREE_CODE (e2_p->value) == EXCESS_PRECISION_EXPR)
-             e2_p->value = convert (TREE_TYPE (e2_p->value),
-                                    TREE_OPERAND (e2_p->value, 0));
-           if (!SCALAR_FLOAT_TYPE_P (TREE_TYPE (e1_p->value))
-               || DECIMAL_FLOAT_TYPE_P (TREE_TYPE (e1_p->value))
-               || !SCALAR_FLOAT_TYPE_P (TREE_TYPE (e2_p->value))
-               || DECIMAL_FLOAT_TYPE_P (TREE_TYPE (e2_p->value)))
-             {
-               error_at (loc, "%<__builtin_complex%> operand "
-                         "not of real binary floating-point type");
-               expr.value = error_mark_node;
-               break;
-             }
-           if (TYPE_MAIN_VARIANT (TREE_TYPE (e1_p->value))
-               != TYPE_MAIN_VARIANT (TREE_TYPE (e2_p->value)))
-             {
-               error_at (loc,
-                         "%<__builtin_complex%> operands of different types");
-               expr.value = error_mark_node;
-               break;
-             }
-           if (!flag_isoc99)
-             pedwarn (loc, OPT_Wpedantic,
-                      "ISO C90 does not support complex types");
-           expr.value = build2 (COMPLEX_EXPR,
-                                build_complex_type
-                                  (TYPE_MAIN_VARIANT
-                                    (TREE_TYPE (e1_p->value))),
-                                e1_p->value, e2_p->value);
-           break;
-         }
-       case RID_BUILTIN_SHUFFLE:
-         {
-           VEC(c_expr_t,gc) *cexpr_list;
-           unsigned int i;
-           c_expr_t *p;
-
-           c_parser_consume_token (parser);
-           if (!c_parser_get_builtin_args (parser,
-                                           "__builtin_shuffle",
-                                           &cexpr_list))
-             {
-               expr.value = error_mark_node;
-               break;
-             }
-
-           FOR_EACH_VEC_ELT (c_expr_t, cexpr_list, i, p)
-             mark_exp_read (p->value);
-
-           if (VEC_length (c_expr_t, cexpr_list) == 2)
-             expr.value =
-               c_build_vec_perm_expr
-                 (loc, VEC_index (c_expr_t, cexpr_list, 0)->value,
-                  NULL_TREE, VEC_index (c_expr_t, cexpr_list, 1)->value);
-
-           else if (VEC_length (c_expr_t, cexpr_list) == 3)
-             expr.value =
-               c_build_vec_perm_expr
-                 (loc, VEC_index (c_expr_t, cexpr_list, 0)->value,
-                  VEC_index (c_expr_t, cexpr_list, 1)->value,
-                  VEC_index (c_expr_t, cexpr_list, 2)->value);
-           else
-             {
-               error_at (loc, "wrong number of arguments to "
-                              "%<__builtin_shuffle%>");
-               expr.value = error_mark_node;
-             }
-           break;
-         }
-       case RID_AT_SELECTOR:
-         gcc_assert (c_dialect_objc ());
-         c_parser_consume_token (parser);
-         if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
-           {
-             expr.value = error_mark_node;
-             break;
-           }
-         {
-           tree sel = c_parser_objc_selector_arg (parser);
-           c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
-                                      "expected %<)%>");
-           expr.value = objc_build_selector_expr (loc, sel);
-         }
-         break;
-       case RID_AT_PROTOCOL:
-         gcc_assert (c_dialect_objc ());
-         c_parser_consume_token (parser);
-         if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
-           {
-             expr.value = error_mark_node;
-             break;
-           }
-         if (c_parser_next_token_is_not (parser, CPP_NAME))
-           {
-             c_parser_error (parser, "expected identifier");
-             c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
-             expr.value = error_mark_node;
-             break;
-           }
-         {
-           tree id = c_parser_peek_token (parser)->value;
-           c_parser_consume_token (parser);
-           c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
-                                      "expected %<)%>");
-           expr.value = objc_build_protocol_expr (id);
-         }
-         break;
-       case RID_AT_ENCODE:
-         /* Extension to support C-structures in the archiver.  */
-         gcc_assert (c_dialect_objc ());
-         c_parser_consume_token (parser);
-         if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
-           {
-             expr.value = error_mark_node;
-             break;
-           }
-         t1 = c_parser_type_name (parser);
-         if (t1 == NULL)
-           {
-             expr.value = error_mark_node;
-             c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
-             break;
-           }
-         c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
-                                    "expected %<)%>");
-         {
-           tree type = groktypename (t1, NULL, NULL);
-           expr.value = objc_build_encode_expr (type);
-         }
-         break;
-       default:
-         c_parser_error (parser, "expected expression");
-         expr.value = error_mark_node;
-         break;
-       }
-      break;
-    case CPP_OPEN_SQUARE:
-      if (c_dialect_objc ())
-       {
-         tree receiver, args;
-         c_parser_consume_token (parser);
-         receiver = c_parser_objc_receiver (parser);
-         args = c_parser_objc_message_args (parser);
-         c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
-                                    "expected %<]%>");
-         expr.value = objc_build_message_expr (receiver, args);
-         break;
-       }
-      /* Else fall through to report error.  */
-    default:
-      c_parser_error (parser, "expected expression");
-      expr.value = error_mark_node;
-      break;
-    }
-  return c_parser_postfix_expression_after_primary (parser, loc, expr);
-}
-
-/* Parse a postfix expression after a parenthesized type name: the
-   brace-enclosed initializer of a compound literal, possibly followed
-   by some postfix operators.  This is separate because it is not
-   possible to tell until after the type name whether a cast
-   expression has a cast or a compound literal, or whether the operand
-   of sizeof is a parenthesized type name or starts with a compound
-   literal.  TYPE_LOC is the location where TYPE_NAME starts--the
-   location of the first token after the parentheses around the type
-   name.  */
-
-static struct c_expr
-c_parser_postfix_expression_after_paren_type (c_parser *parser,
-                                             struct c_type_name *type_name,
-                                             location_t type_loc)
-{
-  tree type;
-  struct c_expr init;
-  bool non_const;
-  struct c_expr expr;
-  location_t start_loc;
-  tree type_expr = NULL_TREE;
-  bool type_expr_const = true;
-  check_compound_literal_type (type_loc, type_name);
-  start_init (NULL_TREE, NULL, 0);
-  type = groktypename (type_name, &type_expr, &type_expr_const);
-  start_loc = c_parser_peek_token (parser)->location;
-  if (type != error_mark_node && C_TYPE_VARIABLE_SIZE (type))
-    {
-      error_at (type_loc, "compound literal has variable size");
-      type = error_mark_node;
-    }
-  init = c_parser_braced_init (parser, type, false);
-  finish_init ();
-  maybe_warn_string_init (type, init);
-
-  if (type != error_mark_node
-      && !ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (type))
-      && current_function_decl)
-    {
-      error ("compound literal qualified by address-space qualifier");
-      type = error_mark_node;
-    }
-
-  if (!flag_isoc99)
-    pedwarn (start_loc, OPT_Wpedantic, "ISO C90 forbids compound literals");
-  non_const = ((init.value && TREE_CODE (init.value) == CONSTRUCTOR)
-              ? CONSTRUCTOR_NON_CONST (init.value)
-              : init.original_code == C_MAYBE_CONST_EXPR);
-  non_const |= !type_expr_const;
-  expr.value = build_compound_literal (start_loc, type, init.value, non_const);
-  expr.original_code = ERROR_MARK;
-  expr.original_type = NULL;
-  if (type_expr)
-    {
-      if (TREE_CODE (expr.value) == C_MAYBE_CONST_EXPR)
-       {
-         gcc_assert (C_MAYBE_CONST_EXPR_PRE (expr.value) == NULL_TREE);
-         C_MAYBE_CONST_EXPR_PRE (expr.value) = type_expr;
-       }
-      else
-       {
-         gcc_assert (!non_const);
-         expr.value = build2 (C_MAYBE_CONST_EXPR, type,
-                              type_expr, expr.value);
-       }
-    }
-  return c_parser_postfix_expression_after_primary (parser, start_loc, expr);
-}
-
-/* Parse a postfix expression after the initial primary or compound
-   literal; that is, parse a series of postfix operators.
-
-   EXPR_LOC is the location of the primary expression.  */
-
-static struct c_expr
-c_parser_postfix_expression_after_primary (c_parser *parser,
-                                          location_t expr_loc,
-                                          struct c_expr expr)
-{
-  struct c_expr orig_expr;
-  tree ident, idx;
-  VEC(tree,gc) *exprlist;
-  VEC(tree,gc) *origtypes;
-  while (true)
-    {
-      location_t op_loc = c_parser_peek_token (parser)->location;
-      switch (c_parser_peek_token (parser)->type)
-       {
-       case CPP_OPEN_SQUARE:
-         /* Array reference.  */
-         c_parser_consume_token (parser);
-         idx = c_parser_expression (parser).value;
-         c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
-                                    "expected %<]%>");
-         expr.value = build_array_ref (op_loc, expr.value, idx);
-         expr.original_code = ERROR_MARK;
-         expr.original_type = NULL;
-         break;
-       case CPP_OPEN_PAREN:
-         /* Function call.  */
-         c_parser_consume_token (parser);
-         if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
-           exprlist = NULL;
-         else
-           exprlist = c_parser_expr_list (parser, true, false, &origtypes);
-         c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
-                                    "expected %<)%>");
-         orig_expr = expr;
-         mark_exp_read (expr.value);
-         /* FIXME diagnostics: Ideally we want the FUNCNAME, not the
-            "(" after the FUNCNAME, which is what we have now.    */
-         expr.value = build_function_call_vec (op_loc, expr.value, exprlist,
-                                               origtypes);
-         expr.original_code = ERROR_MARK;
-         if (TREE_CODE (expr.value) == INTEGER_CST
-             && TREE_CODE (orig_expr.value) == FUNCTION_DECL
-             && DECL_BUILT_IN_CLASS (orig_expr.value) == BUILT_IN_NORMAL
-             && DECL_FUNCTION_CODE (orig_expr.value) == BUILT_IN_CONSTANT_P)
-           expr.original_code = C_MAYBE_CONST_EXPR;
-         expr.original_type = NULL;
-         if (exprlist != NULL)
-           {
-             release_tree_vector (exprlist);
-             release_tree_vector (origtypes);
-           }
-         break;
-       case CPP_DOT:
-         /* Structure element reference.  */
-         c_parser_consume_token (parser);
-         expr = default_function_array_conversion (expr_loc, expr);
-         if (c_parser_next_token_is (parser, CPP_NAME))
-           ident = c_parser_peek_token (parser)->value;
-         else
-           {
-             c_parser_error (parser, "expected identifier");
-             expr.value = error_mark_node;
-             expr.original_code = ERROR_MARK;
-              expr.original_type = NULL;
-             return expr;
-           }
-         c_parser_consume_token (parser);
-         expr.value = build_component_ref (op_loc, expr.value, ident);
-         expr.original_code = ERROR_MARK;
-         if (TREE_CODE (expr.value) != COMPONENT_REF)
-           expr.original_type = NULL;
-         else
-           {
-             /* Remember the original type of a bitfield.  */
-             tree field = TREE_OPERAND (expr.value, 1);
-             if (TREE_CODE (field) != FIELD_DECL)
-               expr.original_type = NULL;
-             else
-               expr.original_type = DECL_BIT_FIELD_TYPE (field);
-           }
-         break;
-       case CPP_DEREF:
-         /* Structure element reference.  */
-         c_parser_consume_token (parser);
-         expr = default_function_array_conversion (expr_loc, expr);
-         if (c_parser_next_token_is (parser, CPP_NAME))
-           ident = c_parser_peek_token (parser)->value;
-         else
-           {
-             c_parser_error (parser, "expected identifier");
-             expr.value = error_mark_node;
-             expr.original_code = ERROR_MARK;
-             expr.original_type = NULL;
-             return expr;
-           }
-         c_parser_consume_token (parser);
-         expr.value = build_component_ref (op_loc,
-                                           build_indirect_ref (op_loc,
-                                                               expr.value,
-                                                               RO_ARROW),
-                                           ident);
-         expr.original_code = ERROR_MARK;
-         if (TREE_CODE (expr.value) != COMPONENT_REF)
-           expr.original_type = NULL;
-         else
-           {
-             /* Remember the original type of a bitfield.  */
-             tree field = TREE_OPERAND (expr.value, 1);
-             if (TREE_CODE (field) != FIELD_DECL)
-               expr.original_type = NULL;
-             else
-               expr.original_type = DECL_BIT_FIELD_TYPE (field);
-           }
-         break;
-       case CPP_PLUS_PLUS:
-         /* Postincrement.  */
-         c_parser_consume_token (parser);
-         expr = default_function_array_read_conversion (expr_loc, expr);
-         expr.value = build_unary_op (op_loc,
-                                      POSTINCREMENT_EXPR, expr.value, 0);
-         expr.original_code = ERROR_MARK;
-         expr.original_type = NULL;
-         break;
-       case CPP_MINUS_MINUS:
-         /* Postdecrement.  */
-         c_parser_consume_token (parser);
-         expr = default_function_array_read_conversion (expr_loc, expr);
-         expr.value = build_unary_op (op_loc,
-                                      POSTDECREMENT_EXPR, expr.value, 0);
-         expr.original_code = ERROR_MARK;
-         expr.original_type = NULL;
-         break;
-       default:
-         return expr;
-       }
-    }
-}
-
-/* Parse an expression (C90 6.3.17, C99 6.5.17).
-
-   expression:
-     assignment-expression
-     expression , assignment-expression
-*/
-
-static struct c_expr
-c_parser_expression (c_parser *parser)
-{
-  struct c_expr expr;
-  expr = c_parser_expr_no_commas (parser, NULL);
-  while (c_parser_next_token_is (parser, CPP_COMMA))
-    {
-      struct c_expr next;
-      tree lhsval;
-      location_t loc = c_parser_peek_token (parser)->location;
-      location_t expr_loc;
-      c_parser_consume_token (parser);
-      expr_loc = c_parser_peek_token (parser)->location;
-      lhsval = expr.value;
-      while (TREE_CODE (lhsval) == COMPOUND_EXPR)
-       lhsval = TREE_OPERAND (lhsval, 1);
-      if (DECL_P (lhsval) || handled_component_p (lhsval))
-       mark_exp_read (lhsval);
-      next = c_parser_expr_no_commas (parser, NULL);
-      next = default_function_array_conversion (expr_loc, next);
-      expr.value = build_compound_expr (loc, expr.value, next.value);
-      expr.original_code = COMPOUND_EXPR;
-      expr.original_type = next.original_type;
-    }
-  return expr;
-}
-
-/* Parse an expression and convert functions or arrays to
-   pointers.  */
-
-static struct c_expr
-c_parser_expression_conv (c_parser *parser)
-{
-  struct c_expr expr;
-  location_t loc = c_parser_peek_token (parser)->location;
-  expr = c_parser_expression (parser);
-  expr = default_function_array_conversion (loc, expr);
-  return expr;
-}
-
-/* Parse a non-empty list of expressions.  If CONVERT_P, convert
-   functions and arrays to pointers.  If FOLD_P, fold the expressions.
-
-   nonempty-expr-list:
-     assignment-expression
-     nonempty-expr-list , assignment-expression
-*/
-
-static VEC(tree,gc) *
-c_parser_expr_list (c_parser *parser, bool convert_p, bool fold_p,
-                   VEC(tree,gc) **p_orig_types)
-{
-  VEC(tree,gc) *ret;
-  VEC(tree,gc) *orig_types;
-  struct c_expr expr;
-  location_t loc = c_parser_peek_token (parser)->location;
-
-  ret = make_tree_vector ();
-  if (p_orig_types == NULL)
-    orig_types = NULL;
-  else
-    orig_types = make_tree_vector ();
-
-  expr = c_parser_expr_no_commas (parser, NULL);
-  if (convert_p)
-    expr = default_function_array_read_conversion (loc, expr);
-  if (fold_p)
-    expr.value = c_fully_fold (expr.value, false, NULL);
-  VEC_quick_push (tree, ret, expr.value);
-  if (orig_types != NULL)
-    VEC_quick_push (tree, orig_types, expr.original_type);
-  while (c_parser_next_token_is (parser, CPP_COMMA))
-    {
-      c_parser_consume_token (parser);
-      loc = c_parser_peek_token (parser)->location;
-      expr = c_parser_expr_no_commas (parser, NULL);
-      if (convert_p)
-       expr = default_function_array_read_conversion (loc, expr);
-      if (fold_p)
-       expr.value = c_fully_fold (expr.value, false, NULL);
-      VEC_safe_push (tree, gc, ret, expr.value);
-      if (orig_types != NULL)
-       VEC_safe_push (tree, gc, orig_types, expr.original_type);
-    }
-  if (orig_types != NULL)
-    *p_orig_types = orig_types;
-  return ret;
-}
-\f
-/* Parse Objective-C-specific constructs.  */
-
-/* Parse an objc-class-definition.
-
-   objc-class-definition:
-     @interface identifier objc-superclass[opt] objc-protocol-refs[opt]
-       objc-class-instance-variables[opt] objc-methodprotolist @end
-     @implementation identifier objc-superclass[opt]
-       objc-class-instance-variables[opt]
-     @interface identifier ( identifier ) objc-protocol-refs[opt]
-       objc-methodprotolist @end
-     @interface identifier ( ) objc-protocol-refs[opt]
-       objc-methodprotolist @end
-     @implementation identifier ( identifier )
-
-   objc-superclass:
-     : identifier
-
-   "@interface identifier (" must start "@interface identifier (
-   identifier ) ...": objc-methodprotolist in the first production may
-   not start with a parenthesized identifier as a declarator of a data
-   definition with no declaration specifiers if the objc-superclass,
-   objc-protocol-refs and objc-class-instance-variables are omitted.  */
-
-static void
-c_parser_objc_class_definition (c_parser *parser, tree attributes)
-{
-  bool iface_p;
-  tree id1;
-  tree superclass;
-  if (c_parser_next_token_is_keyword (parser, RID_AT_INTERFACE))
-    iface_p = true;
-  else if (c_parser_next_token_is_keyword (parser, RID_AT_IMPLEMENTATION))
-    iface_p = false;
-  else
-    gcc_unreachable ();
-
-  c_parser_consume_token (parser);
-  if (c_parser_next_token_is_not (parser, CPP_NAME))
-    {
-      c_parser_error (parser, "expected identifier");
-      return;
-    }
-  id1 = c_parser_peek_token (parser)->value;
-  c_parser_consume_token (parser);
-  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
-    {
-      /* We have a category or class extension.  */
-      tree id2;
-      tree proto = NULL_TREE;
-      c_parser_consume_token (parser);
-      if (c_parser_next_token_is_not (parser, CPP_NAME))
-       {
-         if (iface_p && c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
-           {
-             /* We have a class extension.  */
-             id2 = NULL_TREE;
-           }
-         else
-           {
-             c_parser_error (parser, "expected identifier or %<)%>");
-             c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
-             return;
-           }
-       }
-      else
-       {
-         id2 = c_parser_peek_token (parser)->value;
-         c_parser_consume_token (parser);
-       }
-      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
-      if (!iface_p)
-       {
-         objc_start_category_implementation (id1, id2);
-         return;
-       }
-      if (c_parser_next_token_is (parser, CPP_LESS))
-       proto = c_parser_objc_protocol_refs (parser);
-      objc_start_category_interface (id1, id2, proto, attributes);
-      c_parser_objc_methodprotolist (parser);
-      c_parser_require_keyword (parser, RID_AT_END, "expected %<@end%>");
-      objc_finish_interface ();
-      return;
-    }
-  if (c_parser_next_token_is (parser, CPP_COLON))
-    {
-      c_parser_consume_token (parser);
-      if (c_parser_next_token_is_not (parser, CPP_NAME))
-       {
-         c_parser_error (parser, "expected identifier");
-         return;
-       }
-      superclass = c_parser_peek_token (parser)->value;
-      c_parser_consume_token (parser);
-    }
-  else
-    superclass = NULL_TREE;
-  if (iface_p)
-    {
-      tree proto = NULL_TREE;
-      if (c_parser_next_token_is (parser, CPP_LESS))
-       proto = c_parser_objc_protocol_refs (parser);
-      objc_start_class_interface (id1, superclass, proto, attributes);
-    }
-  else
-    objc_start_class_implementation (id1, superclass);
-  if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
-    c_parser_objc_class_instance_variables (parser);
-  if (iface_p)
-    {
-      objc_continue_interface ();
-      c_parser_objc_methodprotolist (parser);
-      c_parser_require_keyword (parser, RID_AT_END, "expected %<@end%>");
-      objc_finish_interface ();
-    }
-  else
-    {
-      objc_continue_implementation ();
-      return;
-    }
-}
-
-/* Parse objc-class-instance-variables.
-
-   objc-class-instance-variables:
-     { objc-instance-variable-decl-list[opt] }
-
-   objc-instance-variable-decl-list:
-     objc-visibility-spec
-     objc-instance-variable-decl ;
-     ;
-     objc-instance-variable-decl-list objc-visibility-spec
-     objc-instance-variable-decl-list objc-instance-variable-decl ;
-     objc-instance-variable-decl-list ;
-
-   objc-visibility-spec:
-     @private
-     @protected
-     @public
-
-   objc-instance-variable-decl:
-     struct-declaration
-*/
-
-static void
-c_parser_objc_class_instance_variables (c_parser *parser)
-{
-  gcc_assert (c_parser_next_token_is (parser, CPP_OPEN_BRACE));
-  c_parser_consume_token (parser);
-  while (c_parser_next_token_is_not (parser, CPP_EOF))
-    {
-      tree decls;
-      /* Parse any stray semicolon.  */
-      if (c_parser_next_token_is (parser, CPP_SEMICOLON))
-       {
-         pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic,
-                  "extra semicolon");
-         c_parser_consume_token (parser);
-         continue;
-       }
-      /* Stop if at the end of the instance variables.  */
-      if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
-       {
-         c_parser_consume_token (parser);
-         break;
-       }
-      /* Parse any objc-visibility-spec.  */
-      if (c_parser_next_token_is_keyword (parser, RID_AT_PRIVATE))
-       {
-         c_parser_consume_token (parser);
-         objc_set_visibility (OBJC_IVAR_VIS_PRIVATE);
-         continue;
-       }
-      else if (c_parser_next_token_is_keyword (parser, RID_AT_PROTECTED))
-       {
-         c_parser_consume_token (parser);
-         objc_set_visibility (OBJC_IVAR_VIS_PROTECTED);
-         continue;
-       }
-      else if (c_parser_next_token_is_keyword (parser, RID_AT_PUBLIC))
-       {
-         c_parser_consume_token (parser);
-         objc_set_visibility (OBJC_IVAR_VIS_PUBLIC);
-         continue;
-       }
-      else if (c_parser_next_token_is_keyword (parser, RID_AT_PACKAGE))
-       {
-         c_parser_consume_token (parser);
-         objc_set_visibility (OBJC_IVAR_VIS_PACKAGE);
-         continue;
-       }
-      else if (c_parser_next_token_is (parser, CPP_PRAGMA))
-       {
-         c_parser_pragma (parser, pragma_external);
-         continue;
-       }
-
-      /* Parse some comma-separated declarations.  */
-      decls = c_parser_struct_declaration (parser);
-      if (decls == NULL)
-       {
-         /* There is a syntax error.  We want to skip the offending
-            tokens up to the next ';' (included) or '}'
-            (excluded).  */
-         
-         /* First, skip manually a ')' or ']'.  This is because they
-            reduce the nesting level, so c_parser_skip_until_found()
-            wouldn't be able to skip past them.  */
-         c_token *token = c_parser_peek_token (parser);
-         if (token->type == CPP_CLOSE_PAREN || token->type == CPP_CLOSE_SQUARE)
-           c_parser_consume_token (parser);
-
-         /* Then, do the standard skipping.  */
-         c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
-
-         /* We hopefully recovered.  Start normal parsing again.  */
-         parser->error = false;
-         continue;
-       }
-      else
-       {
-         /* Comma-separated instance variables are chained together
-            in reverse order; add them one by one.  */
-         tree ivar = nreverse (decls);
-         for (; ivar; ivar = DECL_CHAIN (ivar))
-           objc_add_instance_variable (copy_node (ivar));
-       }
-      c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
-    }
-}
-
-/* Parse an objc-class-declaration.
-
-   objc-class-declaration:
-     @class identifier-list ;
-*/
-
-static void
-c_parser_objc_class_declaration (c_parser *parser)
-{
-  gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_CLASS));
-  c_parser_consume_token (parser);
-  /* Any identifiers, including those declared as type names, are OK
-     here.  */
-  while (true)
-    {
-      tree id;
-      if (c_parser_next_token_is_not (parser, CPP_NAME))
-       {
-         c_parser_error (parser, "expected identifier");
-         c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
-         parser->error = false;
-         return;
-       }
-      id = c_parser_peek_token (parser)->value;
-      objc_declare_class (id);
-      c_parser_consume_token (parser);
-      if (c_parser_next_token_is (parser, CPP_COMMA))
-       c_parser_consume_token (parser);
-      else
-       break;
-    }
-  c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
-}
-
-/* Parse an objc-alias-declaration.
-
-   objc-alias-declaration:
-     @compatibility_alias identifier identifier ;
-*/
-
-static void
-c_parser_objc_alias_declaration (c_parser *parser)
-{
-  tree id1, id2;
-  gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_ALIAS));
-  c_parser_consume_token (parser);
-  if (c_parser_next_token_is_not (parser, CPP_NAME))
-    {
-      c_parser_error (parser, "expected identifier");
-      c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
-      return;
-    }
-  id1 = c_parser_peek_token (parser)->value;
-  c_parser_consume_token (parser);
-  if (c_parser_next_token_is_not (parser, CPP_NAME))
-    {
-      c_parser_error (parser, "expected identifier");
-      c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
-      return;
-    }
-  id2 = c_parser_peek_token (parser)->value;
-  c_parser_consume_token (parser);
-  c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
-  objc_declare_alias (id1, id2);
-}
-
-/* Parse an objc-protocol-definition.
-
-   objc-protocol-definition:
-     @protocol identifier objc-protocol-refs[opt] objc-methodprotolist @end
-     @protocol identifier-list ;
-
-   "@protocol identifier ;" should be resolved as "@protocol
-   identifier-list ;": objc-methodprotolist may not start with a
-   semicolon in the first alternative if objc-protocol-refs are
-   omitted.  */
-
-static void
-c_parser_objc_protocol_definition (c_parser *parser, tree attributes)
-{
-  gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_PROTOCOL));
-
-  c_parser_consume_token (parser);
-  if (c_parser_next_token_is_not (parser, CPP_NAME))
-    {
-      c_parser_error (parser, "expected identifier");
-      return;
-    }
-  if (c_parser_peek_2nd_token (parser)->type == CPP_COMMA
-      || c_parser_peek_2nd_token (parser)->type == CPP_SEMICOLON)
-    {
-      /* Any identifiers, including those declared as type names, are
-        OK here.  */
-      while (true)
-       {
-         tree id;
-         if (c_parser_next_token_is_not (parser, CPP_NAME))
-           {
-             c_parser_error (parser, "expected identifier");
-             break;
-           }
-         id = c_parser_peek_token (parser)->value;
-         objc_declare_protocol (id, attributes);
-         c_parser_consume_token (parser);
-         if (c_parser_next_token_is (parser, CPP_COMMA))
-           c_parser_consume_token (parser);
-         else
-           break;
-       }
-      c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
-    }
-  else
-    {
-      tree id = c_parser_peek_token (parser)->value;
-      tree proto = NULL_TREE;
-      c_parser_consume_token (parser);
-      if (c_parser_next_token_is (parser, CPP_LESS))
-       proto = c_parser_objc_protocol_refs (parser);
-      parser->objc_pq_context = true;
-      objc_start_protocol (id, proto, attributes);
-      c_parser_objc_methodprotolist (parser);
-      c_parser_require_keyword (parser, RID_AT_END, "expected %<@end%>");
-      parser->objc_pq_context = false;
-      objc_finish_interface ();
-    }
-}
-
-/* Parse an objc-method-type.
-
-   objc-method-type:
-     +
-     -
-
-   Return true if it is a class method (+) and false if it is
-   an instance method (-).
-*/
-static inline bool
-c_parser_objc_method_type (c_parser *parser)
-{
-  switch (c_parser_peek_token (parser)->type)
-    {
-    case CPP_PLUS:
-      c_parser_consume_token (parser);
-      return true;
-    case CPP_MINUS:
-      c_parser_consume_token (parser);
-      return false;
-    default:
-      gcc_unreachable ();
-    }
-}
-
-/* Parse an objc-method-definition.
-
-   objc-method-definition:
-     objc-method-type objc-method-decl ;[opt] compound-statement
-*/
-
-static void
-c_parser_objc_method_definition (c_parser *parser)
-{
-  bool is_class_method = c_parser_objc_method_type (parser);
-  tree decl, attributes = NULL_TREE, expr = NULL_TREE;
-  parser->objc_pq_context = true;
-  decl = c_parser_objc_method_decl (parser, is_class_method, &attributes,
-                                   &expr);
-  if (decl == error_mark_node)
-    return;  /* Bail here. */
-
-  if (c_parser_next_token_is (parser, CPP_SEMICOLON))
-    {
-      c_parser_consume_token (parser);
-      pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic,
-              "extra semicolon in method definition specified");
-    }
-
-  if (!c_parser_next_token_is (parser, CPP_OPEN_BRACE))
-    {
-      c_parser_error (parser, "expected %<{%>");
-      return;
-    }
-
-  parser->objc_pq_context = false;
-  if (objc_start_method_definition (is_class_method, decl, attributes, expr))
-    {
-      add_stmt (c_parser_compound_statement (parser));
-      objc_finish_method_definition (current_function_decl);
-    }
-  else
-    {
-      /* This code is executed when we find a method definition
-        outside of an @implementation context (or invalid for other
-        reasons).  Parse the method (to keep going) but do not emit
-        any code.
-      */
-      c_parser_compound_statement (parser);
-    }
-}
-
-/* Parse an objc-methodprotolist.
-
-   objc-methodprotolist:
-     empty
-     objc-methodprotolist objc-methodproto
-     objc-methodprotolist declaration
-     objc-methodprotolist ;
-     @optional
-     @required
-
-   The declaration is a data definition, which may be missing
-   declaration specifiers under the same rules and diagnostics as
-   other data definitions outside functions, and the stray semicolon
-   is diagnosed the same way as a stray semicolon outside a
-   function.  */
-
-static void
-c_parser_objc_methodprotolist (c_parser *parser)
-{
-  while (true)
-    {
-      /* The list is terminated by @end.  */
-      switch (c_parser_peek_token (parser)->type)
-       {
-       case CPP_SEMICOLON:
-         pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic,
-                  "ISO C does not allow extra %<;%> outside of a function");
-         c_parser_consume_token (parser);
-         break;
-       case CPP_PLUS:
-       case CPP_MINUS:
-         c_parser_objc_methodproto (parser);
-         break;
-       case CPP_PRAGMA:
-         c_parser_pragma (parser, pragma_external);
-         break;
-       case CPP_EOF:
-         return;
-       default:
-         if (c_parser_next_token_is_keyword (parser, RID_AT_END))
-           return;
-         else if (c_parser_next_token_is_keyword (parser, RID_AT_PROPERTY))
-           c_parser_objc_at_property_declaration (parser);
-         else if (c_parser_next_token_is_keyword (parser, RID_AT_OPTIONAL))
-           {
-             objc_set_method_opt (true);
-             c_parser_consume_token (parser);
-           }
-         else if (c_parser_next_token_is_keyword (parser, RID_AT_REQUIRED))
-           {
-             objc_set_method_opt (false);
-             c_parser_consume_token (parser);
-           }
-         else
-           c_parser_declaration_or_fndef (parser, false, false, true,
-                                          false, true, NULL);
-         break;
-       }
-    }
-}
-
-/* Parse an objc-methodproto.
-
-   objc-methodproto:
-     objc-method-type objc-method-decl ;
-*/
-
-static void
-c_parser_objc_methodproto (c_parser *parser)
-{
-  bool is_class_method = c_parser_objc_method_type (parser);
-  tree decl, attributes = NULL_TREE;
-
-  /* Remember protocol qualifiers in prototypes.  */
-  parser->objc_pq_context = true;
-  decl = c_parser_objc_method_decl (parser, is_class_method, &attributes,
-                                   NULL);
-  /* Forget protocol qualifiers now.  */
-  parser->objc_pq_context = false;
-
-  /* Do not allow the presence of attributes to hide an erroneous 
-     method implementation in the interface section.  */
-  if (!c_parser_next_token_is (parser, CPP_SEMICOLON))
-    {
-      c_parser_error (parser, "expected %<;%>");
-      return;
-    }
-  
-  if (decl != error_mark_node)
-    objc_add_method_declaration (is_class_method, decl, attributes);
-
-  c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
-}
-
-/* If we are at a position that method attributes may be present, check that 
-   there are not any parsed already (a syntax error) and then collect any 
-   specified at the current location.  Finally, if new attributes were present,
-   check that the next token is legal ( ';' for decls and '{' for defs).  */
-   
-static bool 
-c_parser_objc_maybe_method_attributes (c_parser* parser, tree* attributes)
-{
-  bool bad = false;
-  if (*attributes)
-    {
-      c_parser_error (parser, 
-                   "method attributes must be specified at the end only");
-      *attributes = NULL_TREE;
-      bad = true;
-    }
-
-  if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
-    *attributes = c_parser_attributes (parser);
-
-  /* If there were no attributes here, just report any earlier error.  */
-  if (*attributes == NULL_TREE || bad)
-    return bad;
-
-  /* If the attributes are followed by a ; or {, then just report any earlier
-     error.  */
-  if (c_parser_next_token_is (parser, CPP_SEMICOLON)
-      || c_parser_next_token_is (parser, CPP_OPEN_BRACE))
-    return bad;
-
-  /* We've got attributes, but not at the end.  */
-  c_parser_error (parser, 
-                 "expected %<;%> or %<{%> after method attribute definition");
-  return true;
-}
-
-/* Parse an objc-method-decl.
-
-   objc-method-decl:
-     ( objc-type-name ) objc-selector
-     objc-selector
-     ( objc-type-name ) objc-keyword-selector objc-optparmlist
-     objc-keyword-selector objc-optparmlist
-     attributes
-
-   objc-keyword-selector:
-     objc-keyword-decl
-     objc-keyword-selector objc-keyword-decl
-
-   objc-keyword-decl:
-     objc-selector : ( objc-type-name ) identifier
-     objc-selector : identifier
-     : ( objc-type-name ) identifier
-     : identifier
-
-   objc-optparmlist:
-     objc-optparms objc-optellipsis
-
-   objc-optparms:
-     empty
-     objc-opt-parms , parameter-declaration
-
-   objc-optellipsis:
-     empty
-     , ...
-*/
-
-static tree
-c_parser_objc_method_decl (c_parser *parser, bool is_class_method,
-                          tree *attributes, tree *expr)
-{
-  tree type = NULL_TREE;
-  tree sel;
-  tree parms = NULL_TREE;
-  bool ellipsis = false;
-  bool attr_err = false;
-
-  *attributes = NULL_TREE;
-  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
-    {
-      c_parser_consume_token (parser);
-      type = c_parser_objc_type_name (parser);
-      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
-    }
-  sel = c_parser_objc_selector (parser);
-  /* If there is no selector, or a colon follows, we have an
-     objc-keyword-selector.  If there is a selector, and a colon does
-     not follow, that selector ends the objc-method-decl.  */
-  if (!sel || c_parser_next_token_is (parser, CPP_COLON))
-    {
-      tree tsel = sel;
-      tree list = NULL_TREE;
-      while (true)
-       {
-         tree atype = NULL_TREE, id, keyworddecl;
-         tree param_attr = NULL_TREE;
-         if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
-           break;
-         if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
-           {
-             c_parser_consume_token (parser);
-             atype = c_parser_objc_type_name (parser);
-             c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
-                                        "expected %<)%>");
-           }
-         /* New ObjC allows attributes on method parameters.  */
-         if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
-           param_attr = c_parser_attributes (parser);
-         if (c_parser_next_token_is_not (parser, CPP_NAME))
-           {
-             c_parser_error (parser, "expected identifier");
-             return error_mark_node;
-           }
-         id = c_parser_peek_token (parser)->value;
-         c_parser_consume_token (parser);
-         keyworddecl = objc_build_keyword_decl (tsel, atype, id, param_attr);
-         list = chainon (list, keyworddecl);
-         tsel = c_parser_objc_selector (parser);
-         if (!tsel && c_parser_next_token_is_not (parser, CPP_COLON))
-           break;
-       }
-
-      attr_err |= c_parser_objc_maybe_method_attributes (parser, attributes) ;
-
-      /* Parse the optional parameter list.  Optional Objective-C
-        method parameters follow the C syntax, and may include '...'
-        to denote a variable number of arguments.  */
-      parms = make_node (TREE_LIST);
-      while (c_parser_next_token_is (parser, CPP_COMMA))
-       {
-         struct c_parm *parm;
-         c_parser_consume_token (parser);
-         if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
-           {
-             ellipsis = true;
-             c_parser_consume_token (parser);
-             attr_err |= c_parser_objc_maybe_method_attributes 
-                                               (parser, attributes) ;
-             break;
-           }
-         parm = c_parser_parameter_declaration (parser, NULL_TREE);
-         if (parm == NULL)
-           break;
-         parms = chainon (parms,
-                          build_tree_list (NULL_TREE, grokparm (parm, expr)));
-       }
-      sel = list;
-    }
-  else
-    attr_err |= c_parser_objc_maybe_method_attributes (parser, attributes) ;
-
-  if (sel == NULL)
-    {
-      c_parser_error (parser, "objective-c method declaration is expected");
-      return error_mark_node;
-    }
-
-  if (attr_err)
-    return error_mark_node;
-
-  return objc_build_method_signature (is_class_method, type, sel, parms, ellipsis);
-}
-
-/* Parse an objc-type-name.
-
-   objc-type-name:
-     objc-type-qualifiers[opt] type-name
-     objc-type-qualifiers[opt]
-
-   objc-type-qualifiers:
-     objc-type-qualifier
-     objc-type-qualifiers objc-type-qualifier
-
-   objc-type-qualifier: one of
-     in out inout bycopy byref oneway
-*/
-
-static tree
-c_parser_objc_type_name (c_parser *parser)
-{
-  tree quals = NULL_TREE;
-  struct c_type_name *type_name = NULL;
-  tree type = NULL_TREE;
-  while (true)
-    {
-      c_token *token = c_parser_peek_token (parser);
-      if (token->type == CPP_KEYWORD
-         && (token->keyword == RID_IN
-             || token->keyword == RID_OUT
-             || token->keyword == RID_INOUT
-             || token->keyword == RID_BYCOPY
-             || token->keyword == RID_BYREF
-             || token->keyword == RID_ONEWAY))
-       {
-         quals = chainon (build_tree_list (NULL_TREE, token->value), quals);
-         c_parser_consume_token (parser);
-       }
-      else
-       break;
-    }
-  if (c_parser_next_tokens_start_typename (parser, cla_prefer_type))
-    type_name = c_parser_type_name (parser);
-  if (type_name)
-    type = groktypename (type_name, NULL, NULL);
-
-  /* If the type is unknown, and error has already been produced and
-     we need to recover from the error.  In that case, use NULL_TREE
-     for the type, as if no type had been specified; this will use the
-     default type ('id') which is good for error recovery.  */
-  if (type == error_mark_node)
-    type = NULL_TREE;
-
-  return build_tree_list (quals, type);
-}
-
-/* Parse objc-protocol-refs.
-
-   objc-protocol-refs:
-     < identifier-list >
-*/
-
-static tree
-c_parser_objc_protocol_refs (c_parser *parser)
-{
-  tree list = NULL_TREE;
-  gcc_assert (c_parser_next_token_is (parser, CPP_LESS));
-  c_parser_consume_token (parser);
-  /* Any identifiers, including those declared as type names, are OK
-     here.  */
-  while (true)
-    {
-      tree id;
-      if (c_parser_next_token_is_not (parser, CPP_NAME))
-       {
-         c_parser_error (parser, "expected identifier");
-         break;
-       }
-      id = c_parser_peek_token (parser)->value;
-      list = chainon (list, build_tree_list (NULL_TREE, id));
-      c_parser_consume_token (parser);
-      if (c_parser_next_token_is (parser, CPP_COMMA))
-       c_parser_consume_token (parser);
-      else
-       break;
-    }
-  c_parser_require (parser, CPP_GREATER, "expected %<>%>");
-  return list;
-}
-
-/* Parse an objc-try-catch-finally-statement.
-
-   objc-try-catch-finally-statement:
-     @try compound-statement objc-catch-list[opt]
-     @try compound-statement objc-catch-list[opt] @finally compound-statement
-
-   objc-catch-list:
-     @catch ( objc-catch-parameter-declaration ) compound-statement
-     objc-catch-list @catch ( objc-catch-parameter-declaration ) compound-statement
-
-   objc-catch-parameter-declaration:
-     parameter-declaration
-     '...'
-
-   where '...' is to be interpreted literally, that is, it means CPP_ELLIPSIS.
-
-   PS: This function is identical to cp_parser_objc_try_catch_finally_statement
-   for C++.  Keep them in sync.  */   
-
-static void
-c_parser_objc_try_catch_finally_statement (c_parser *parser)
-{
-  location_t location;
-  tree stmt;
-
-  gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_TRY));
-  c_parser_consume_token (parser);
-  location = c_parser_peek_token (parser)->location;
-  objc_maybe_warn_exceptions (location);
-  stmt = c_parser_compound_statement (parser);
-  objc_begin_try_stmt (location, stmt);
-
-  while (c_parser_next_token_is_keyword (parser, RID_AT_CATCH))
-    {
-      struct c_parm *parm;
-      tree parameter_declaration = error_mark_node;
-      bool seen_open_paren = false;
-
-      c_parser_consume_token (parser);
-      if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
-       seen_open_paren = true;
-      if (c_parser_next_token_is (parser, 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
-            '...'.  */
-         c_parser_consume_token (parser);
-         parameter_declaration = NULL_TREE;
-       }
-      else
-       {
-         /* We have "@catch (NSException *exception)" or something
-            like that.  Parse the parameter declaration.  */
-         parm = c_parser_parameter_declaration (parser, NULL_TREE);
-         if (parm == NULL)
-           parameter_declaration = error_mark_node;
-         else
-           parameter_declaration = grokparm (parm, NULL);
-       }
-      if (seen_open_paren)
-       c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>");
-      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 (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
-           c_parser_consume_token (parser);
-         
-         /* 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);
-      if (c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
-       c_parser_compound_statement_nostart (parser);
-      objc_finish_catch_clause ();
-    }
-  if (c_parser_next_token_is_keyword (parser, RID_AT_FINALLY))
-    {
-      c_parser_consume_token (parser);
-      location = c_parser_peek_token (parser)->location;
-      stmt = c_parser_compound_statement (parser);
-      objc_build_finally_clause (location, stmt);
-    }
-  objc_finish_try_stmt ();
-}
-
-/* Parse an objc-synchronized-statement.
-
-   objc-synchronized-statement:
-     @synchronized ( expression ) compound-statement
-*/
-
-static void
-c_parser_objc_synchronized_statement (c_parser *parser)
-{
-  location_t loc;
-  tree expr, stmt;
-  gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_SYNCHRONIZED));
-  c_parser_consume_token (parser);
-  loc = c_parser_peek_token (parser)->location;
-  objc_maybe_warn_exceptions (loc);
-  if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
-    {
-      expr = c_parser_expression (parser).value;
-      expr = c_fully_fold (expr, false, NULL);
-      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
-    }
-  else
-    expr = error_mark_node;
-  stmt = c_parser_compound_statement (parser);
-  objc_build_synchronized (loc, expr, stmt);
-}
-
-/* Parse an objc-selector; return NULL_TREE without an error if the
-   next token is not an objc-selector.
-
-   objc-selector:
-     identifier
-     one of
-       enum struct union if else while do for switch case default
-       break continue return goto asm sizeof typeof __alignof
-       unsigned long const short volatile signed restrict _Complex
-       in out inout bycopy byref oneway int char float double void _Bool
-
-   ??? Why this selection of keywords but not, for example, storage
-   class specifiers?  */
-
-static tree
-c_parser_objc_selector (c_parser *parser)
-{
-  c_token *token = c_parser_peek_token (parser);
-  tree value = token->value;
-  if (token->type == CPP_NAME)
-    {
-      c_parser_consume_token (parser);
-      return value;
-    }
-  if (token->type != CPP_KEYWORD)
-    return NULL_TREE;
-  switch (token->keyword)
-    {
-    case RID_ENUM:
-    case RID_STRUCT:
-    case RID_UNION:
-    case RID_IF:
-    case RID_ELSE:
-    case RID_WHILE:
-    case RID_DO:
-    case RID_FOR:
-    case RID_SWITCH:
-    case RID_CASE:
-    case RID_DEFAULT:
-    case RID_BREAK:
-    case RID_CONTINUE:
-    case RID_RETURN:
-    case RID_GOTO:
-    case RID_ASM:
-    case RID_SIZEOF:
-    case RID_TYPEOF:
-    case RID_ALIGNOF:
-    case RID_UNSIGNED:
-    case RID_LONG:
-    case RID_INT128:
-    case RID_CONST:
-    case RID_SHORT:
-    case RID_VOLATILE:
-    case RID_SIGNED:
-    case RID_RESTRICT:
-    case RID_COMPLEX:
-    case RID_IN:
-    case RID_OUT:
-    case RID_INOUT:
-    case RID_BYCOPY:
-    case RID_BYREF:
-    case RID_ONEWAY:
-    case RID_INT:
-    case RID_CHAR:
-    case RID_FLOAT:
-    case RID_DOUBLE:
-    case RID_VOID:
-    case RID_BOOL:
-      c_parser_consume_token (parser);
-      return value;
-    default:
-      return NULL_TREE;
-    }
-}
-
-/* Parse an objc-selector-arg.
-
-   objc-selector-arg:
-     objc-selector
-     objc-keywordname-list
-
-   objc-keywordname-list:
-     objc-keywordname
-     objc-keywordname-list objc-keywordname
-
-   objc-keywordname:
-     objc-selector :
-     :
-*/
-
-static tree
-c_parser_objc_selector_arg (c_parser *parser)
-{
-  tree sel = c_parser_objc_selector (parser);
-  tree list = NULL_TREE;
-  if (sel && c_parser_next_token_is_not (parser, CPP_COLON))
-    return sel;
-  while (true)
-    {
-      if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
-       return list;
-      list = chainon (list, build_tree_list (sel, NULL_TREE));
-      sel = c_parser_objc_selector (parser);
-      if (!sel && c_parser_next_token_is_not (parser, CPP_COLON))
-       break;
-    }
-  return list;
-}
-
-/* Parse an objc-receiver.
-
-   objc-receiver:
-     expression
-     class-name
-     type-name
-*/
-
-static tree
-c_parser_objc_receiver (c_parser *parser)
-{
-  if (c_parser_peek_token (parser)->type == CPP_NAME
-      && (c_parser_peek_token (parser)->id_kind == C_ID_TYPENAME
-         || c_parser_peek_token (parser)->id_kind == C_ID_CLASSNAME))
-    {
-      tree id = c_parser_peek_token (parser)->value;
-      c_parser_consume_token (parser);
-      return objc_get_class_reference (id);
-    }
-  return c_fully_fold (c_parser_expression (parser).value, false, NULL);
-}
-
-/* Parse objc-message-args.
-
-   objc-message-args:
-     objc-selector
-     objc-keywordarg-list
-
-   objc-keywordarg-list:
-     objc-keywordarg
-     objc-keywordarg-list objc-keywordarg
-
-   objc-keywordarg:
-     objc-selector : objc-keywordexpr
-     : objc-keywordexpr
-*/
-
-static tree
-c_parser_objc_message_args (c_parser *parser)
-{
-  tree sel = c_parser_objc_selector (parser);
-  tree list = NULL_TREE;
-  if (sel && c_parser_next_token_is_not (parser, CPP_COLON))
-    return sel;
-  while (true)
-    {
-      tree keywordexpr;
-      if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
-       return error_mark_node;
-      keywordexpr = c_parser_objc_keywordexpr (parser);
-      list = chainon (list, build_tree_list (sel, keywordexpr));
-      sel = c_parser_objc_selector (parser);
-      if (!sel && c_parser_next_token_is_not (parser, CPP_COLON))
-       break;
-    }
-  return list;
-}
-
-/* Parse an objc-keywordexpr.
-
-   objc-keywordexpr:
-     nonempty-expr-list
-*/
-
-static tree
-c_parser_objc_keywordexpr (c_parser *parser)
-{
-  tree ret;
-  VEC(tree,gc) *expr_list = c_parser_expr_list (parser, true, true, NULL);
-  if (VEC_length (tree, expr_list) == 1)
-    {
-      /* Just return the expression, remove a level of
-        indirection.  */
-      ret = VEC_index (tree, expr_list, 0);
-    }
-  else
-    {
-      /* We have a comma expression, we will collapse later.  */
-      ret = build_tree_list_vec (expr_list);
-    }
-  release_tree_vector (expr_list);
-  return ret;
-}
-
-/* A check, needed in several places, that ObjC interface, implementation or
-   method definitions are not prefixed by incorrect items.  */
-static bool
-c_parser_objc_diagnose_bad_element_prefix (c_parser *parser, 
-                                          struct c_declspecs *specs)
-{
-  if (!specs->declspecs_seen_p || specs->non_sc_seen_p
-      || specs->typespec_kind != ctsk_none)
-    {
-      c_parser_error (parser, 
-                     "no type or storage class may be specified here,");
-      c_parser_skip_to_end_of_block_or_statement (parser);
-      return true;
-    }
-  return false;
-}
-
-/* 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 cp_parser_objc_at_propery_declaration
-  for C++.  Keep them in sync.  */
-static void
-c_parser_objc_at_property_declaration (c_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 = c_parser_peek_token (parser)->location;
-  gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_PROPERTY));
-
-  c_parser_consume_token (parser);  /* Eat '@property'.  */
-
-  /* Parse the optional attribute list...  */
-  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
-    {
-      /* Eat the '(' */
-      c_parser_consume_token (parser);
-      
-      /* Property attribute keywords are valid now.  */
-      parser->objc_property_attr_context = true;
-
-      while (true)
-       {
-         bool syntax_error = false;
-         c_token *token = c_parser_peek_token (parser);
-         enum rid keyword;
-
-         if (token->type != CPP_KEYWORD)
-           {
-             if (token->type == CPP_CLOSE_PAREN)
-               c_parser_error (parser, "expected identifier");
-             else
-               {
-                 c_parser_consume_token (parser);
-                 c_parser_error (parser, "unknown property attribute");
-               }
-             break;
-           }
-         keyword = token->keyword;
-         c_parser_consume_token (parser);
-         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 (c_parser_next_token_is_not (parser, CPP_EQ))
-               {
-                 if (keyword == RID_GETTER)
-                   c_parser_error (parser,
-                                   "missing %<=%> (after %<getter%> attribute)");
-                 else
-                   c_parser_error (parser,
-                                   "missing %<=%> (after %<setter%> attribute)");
-                 syntax_error = true;
-                 break;
-               }
-             c_parser_consume_token (parser); /* eat the = */
-             if (c_parser_next_token_is_not (parser, CPP_NAME))
-               {
-                 c_parser_error (parser, "expected identifier");
-                 syntax_error = true;
-                 break;
-               }
-             if (keyword == RID_SETTER)
-               {
-                 if (property_setter_ident != NULL_TREE)
-                   c_parser_error (parser, "the %<setter%> attribute may only be specified once");
-                 else
-                   property_setter_ident = c_parser_peek_token (parser)->value;
-                 c_parser_consume_token (parser);
-                 if (c_parser_next_token_is_not (parser, CPP_COLON))
-                   c_parser_error (parser, "setter name must terminate with %<:%>");
-                 else
-                   c_parser_consume_token (parser);
-               }
-             else
-               {
-                 if (property_getter_ident != NULL_TREE)
-                   c_parser_error (parser, "the %<getter%> attribute may only be specified once");
-                 else
-                   property_getter_ident = c_parser_peek_token (parser)->value;
-                 c_parser_consume_token (parser);
-               }
-             break;
-           default:
-             c_parser_error (parser, "unknown property attribute");
-             syntax_error = true;
-             break;
-           }
-
-         if (syntax_error)
-           break;
-         
-         if (c_parser_next_token_is (parser, CPP_COMMA))
-           c_parser_consume_token (parser);
-         else
-           break;
-       }
-      parser->objc_property_attr_context = false;
-      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
-    }
-  /* ... and the property declaration(s).  */
-  properties = c_parser_struct_declaration (parser);
-
-  if (properties == error_mark_node)
-    {
-      c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
-      parser->error = false;
-      return;
-    }
-
-  if (properties == NULL_TREE)
-    c_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);
-    }
-
-  c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
-  parser->error = false;
-}
-
-/* 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 cp_parser_objc_at_synthesize_declaration
-  for C++.  Keep them in sync.
-*/
-static void
-c_parser_objc_at_synthesize_declaration (c_parser *parser)
-{
-  tree list = NULL_TREE;
-  location_t loc;
-  gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_SYNTHESIZE));
-  loc = c_parser_peek_token (parser)->location;
-
-  c_parser_consume_token (parser);
-  while (true)
-    {
-      tree property, ivar;
-      if (c_parser_next_token_is_not (parser, CPP_NAME))
-       {
-         c_parser_error (parser, "expected identifier");
-         c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
-         /* Once we find the semicolon, we can resume normal parsing.
-            We have to reset parser->error manually because
-            c_parser_skip_until_found() won't reset it for us if the
-            next token is precisely a semicolon.  */
-         parser->error = false;
-         return;
-       }
-      property = c_parser_peek_token (parser)->value;
-      c_parser_consume_token (parser);
-      if (c_parser_next_token_is (parser, CPP_EQ))
-       {
-         c_parser_consume_token (parser);
-         if (c_parser_next_token_is_not (parser, CPP_NAME))
-           {
-             c_parser_error (parser, "expected identifier");
-             c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
-             parser->error = false;
-             return;
-           }
-         ivar = c_parser_peek_token (parser)->value;
-         c_parser_consume_token (parser);
-       }
-      else
-       ivar = NULL_TREE;
-      list = chainon (list, build_tree_list (ivar, property));
-      if (c_parser_next_token_is (parser, CPP_COMMA))
-       c_parser_consume_token (parser);
-      else
-       break;
-    }
-  c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
-  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 cp_parser_objc_at_dynamic_declaration
-  for C++.  Keep them in sync.
-*/
-static void
-c_parser_objc_at_dynamic_declaration (c_parser *parser)
-{
-  tree list = NULL_TREE;
-  location_t loc;
-  gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_DYNAMIC));
-  loc = c_parser_peek_token (parser)->location;
-
-  c_parser_consume_token (parser);
-  while (true)
-    {
-      tree property;
-      if (c_parser_next_token_is_not (parser, CPP_NAME))
-       {
-         c_parser_error (parser, "expected identifier");
-         c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
-         parser->error = false;
-         return;
-       }
-      property = c_parser_peek_token (parser)->value;
-      list = chainon (list, build_tree_list (NULL_TREE, property));
-      c_parser_consume_token (parser);
-      if (c_parser_next_token_is (parser, CPP_COMMA))
-       c_parser_consume_token (parser);
-      else
-       break;
-    }
-  c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
-  objc_add_dynamic_declaration (loc, list);
-}
-
-\f
-/* Handle pragmas.  Some OpenMP pragmas are associated with, and therefore
-   should be considered, statements.  ALLOW_STMT is true if we're within
-   the context of a function and such pragmas are to be allowed.  Returns
-   true if we actually parsed such a pragma.  */
-
-static bool
-c_parser_pragma (c_parser *parser, enum pragma_context context)
-{
-  unsigned int id;
-
-  id = c_parser_peek_token (parser)->pragma_kind;
-  gcc_assert (id != PRAGMA_NONE);
-
-  switch (id)
-    {
-    case PRAGMA_OMP_BARRIER:
-      if (context != pragma_compound)
-       {
-         if (context == pragma_stmt)
-           c_parser_error (parser, "%<#pragma omp barrier%> may only be "
-                           "used in compound statements");
-         goto bad_stmt;
-       }
-      c_parser_omp_barrier (parser);
-      return false;
-
-    case PRAGMA_OMP_FLUSH:
-      if (context != pragma_compound)
-       {
-         if (context == pragma_stmt)
-           c_parser_error (parser, "%<#pragma omp flush%> may only be "
-                           "used in compound statements");
-         goto bad_stmt;
-       }
-      c_parser_omp_flush (parser);
-      return false;
-
-    case PRAGMA_OMP_TASKWAIT:
-      if (context != pragma_compound)
-       {
-         if (context == pragma_stmt)
-           c_parser_error (parser, "%<#pragma omp taskwait%> may only be "
-                           "used in compound statements");
-         goto bad_stmt;
-       }
-      c_parser_omp_taskwait (parser);
-      return false;
-
-    case PRAGMA_OMP_TASKYIELD:
-      if (context != pragma_compound)
-       {
-         if (context == pragma_stmt)
-           c_parser_error (parser, "%<#pragma omp taskyield%> may only be "
-                           "used in compound statements");
-         goto bad_stmt;
-       }
-      c_parser_omp_taskyield (parser);
-      return false;
-
-    case PRAGMA_OMP_THREADPRIVATE:
-      c_parser_omp_threadprivate (parser);
-      return false;
-
-    case PRAGMA_OMP_SECTION:
-      error_at (c_parser_peek_token (parser)->location,
-               "%<#pragma omp section%> may only be used in "
-               "%<#pragma omp sections%> construct");
-      c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
-      return false;
-
-    case PRAGMA_GCC_PCH_PREPROCESS:
-      c_parser_error (parser, "%<#pragma GCC pch_preprocess%> must be first");
-      c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
-      return false;
-
-    default:
-      if (id < PRAGMA_FIRST_EXTERNAL)
-       {
-         if (context == pragma_external)
-           {
-           bad_stmt:
-             c_parser_error (parser, "expected declaration specifiers");
-             c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
-             return false;
-           }
-         c_parser_omp_construct (parser);
-         return true;
-       }
-      break;
-    }
-
-  c_parser_consume_pragma (parser);
-  c_invoke_pragma_handler (id);
-
-  /* Skip to EOL, but suppress any error message.  Those will have been
-     generated by the handler routine through calling error, as opposed
-     to calling c_parser_error.  */
-  parser->error = true;
-  c_parser_skip_to_pragma_eol (parser);
-
-  return false;
-}
-
-/* The interface the pragma parsers have to the lexer.  */
-
-enum cpp_ttype
-pragma_lex (tree *value)
-{
-  c_token *tok = c_parser_peek_token (the_parser);
-  enum cpp_ttype ret = tok->type;
-
-  *value = tok->value;
-  if (ret == CPP_PRAGMA_EOL || ret == CPP_EOF)
-    ret = CPP_EOF;
-  else
-    {
-      if (ret == CPP_KEYWORD)
-       ret = CPP_NAME;
-      c_parser_consume_token (the_parser);
-    }
-
-  return ret;
-}
-
-static void
-c_parser_pragma_pch_preprocess (c_parser *parser)
-{
-  tree name = NULL;
-
-  c_parser_consume_pragma (parser);
-  if (c_parser_next_token_is (parser, CPP_STRING))
-    {
-      name = c_parser_peek_token (parser)->value;
-      c_parser_consume_token (parser);
-    }
-  else
-    c_parser_error (parser, "expected string literal");
-  c_parser_skip_to_pragma_eol (parser);
-
-  if (name)
-    c_common_pch_pragma (parse_in, TREE_STRING_POINTER (name));
-}
-\f
-/* OpenMP 2.5 parsing routines.  */
-
-/* Returns name of the next clause.
-   If the clause is not recognized PRAGMA_OMP_CLAUSE_NONE is returned and
-   the token is not consumed.  Otherwise appropriate pragma_omp_clause is
-   returned and the token is consumed.  */
-
-static pragma_omp_clause
-c_parser_omp_clause_name (c_parser *parser)
-{
-  pragma_omp_clause result = PRAGMA_OMP_CLAUSE_NONE;
-
-  if (c_parser_next_token_is_keyword (parser, RID_IF))
-    result = PRAGMA_OMP_CLAUSE_IF;
-  else if (c_parser_next_token_is_keyword (parser, RID_DEFAULT))
-    result = PRAGMA_OMP_CLAUSE_DEFAULT;
-  else if (c_parser_next_token_is (parser, CPP_NAME))
-    {
-      const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
-
-      switch (p[0])
-       {
-       case 'c':
-         if (!strcmp ("collapse", p))
-           result = PRAGMA_OMP_CLAUSE_COLLAPSE;
-         else if (!strcmp ("copyin", p))
-           result = PRAGMA_OMP_CLAUSE_COPYIN;
-          else if (!strcmp ("copyprivate", p))
-           result = PRAGMA_OMP_CLAUSE_COPYPRIVATE;
-         break;
-       case 'f':
-         if (!strcmp ("final", p))
-           result = PRAGMA_OMP_CLAUSE_FINAL;
-         else if (!strcmp ("firstprivate", p))
-           result = PRAGMA_OMP_CLAUSE_FIRSTPRIVATE;
-         break;
-       case 'l':
-         if (!strcmp ("lastprivate", p))
-           result = PRAGMA_OMP_CLAUSE_LASTPRIVATE;
-         break;
-       case 'm':
-         if (!strcmp ("mergeable", p))
-           result = PRAGMA_OMP_CLAUSE_MERGEABLE;
-         break;
-       case 'n':
-         if (!strcmp ("nowait", p))
-           result = PRAGMA_OMP_CLAUSE_NOWAIT;
-         else if (!strcmp ("num_threads", p))
-           result = PRAGMA_OMP_CLAUSE_NUM_THREADS;
-         break;
-       case 'o':
-         if (!strcmp ("ordered", p))
-           result = PRAGMA_OMP_CLAUSE_ORDERED;
-         break;
-       case 'p':
-         if (!strcmp ("private", p))
-           result = PRAGMA_OMP_CLAUSE_PRIVATE;
-         break;
-       case 'r':
-         if (!strcmp ("reduction", p))
-           result = PRAGMA_OMP_CLAUSE_REDUCTION;
-         break;
-       case 's':
-         if (!strcmp ("schedule", p))
-           result = PRAGMA_OMP_CLAUSE_SCHEDULE;
-         else if (!strcmp ("shared", p))
-           result = PRAGMA_OMP_CLAUSE_SHARED;
-         break;
-       case 'u':
-         if (!strcmp ("untied", p))
-           result = PRAGMA_OMP_CLAUSE_UNTIED;
-         break;
-       }
-    }
-
-  if (result != PRAGMA_OMP_CLAUSE_NONE)
-    c_parser_consume_token (parser);
-
-  return result;
-}
-
-/* Validate that a clause of the given type does not already exist.  */
-
-static void
-check_no_duplicate_clause (tree clauses, enum omp_clause_code code,
-                          const char *name)
-{
-  tree c;
-
-  for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
-    if (OMP_CLAUSE_CODE (c) == code)
-      {
-       location_t loc = OMP_CLAUSE_LOCATION (c);
-       error_at (loc, "too many %qs clauses", name);
-       break;
-      }
-}
-
-/* OpenMP 2.5:
-   variable-list:
-     identifier
-     variable-list , identifier
-
-   If KIND is nonzero, create the appropriate node and install the
-   decl in OMP_CLAUSE_DECL and add the node to the head of the list.
-   If KIND is nonzero, CLAUSE_LOC is the location of the clause.
-
-   If KIND is zero, create a TREE_LIST with the decl in TREE_PURPOSE;
-   return the list created.  */
-
-static tree
-c_parser_omp_variable_list (c_parser *parser,
-                           location_t clause_loc,
-                           enum omp_clause_code kind,
-                            tree list)
-{
-  if (c_parser_next_token_is_not (parser, CPP_NAME)
-      || c_parser_peek_token (parser)->id_kind != C_ID_ID)
-    c_parser_error (parser, "expected identifier");
-
-  while (c_parser_next_token_is (parser, CPP_NAME)
-        && c_parser_peek_token (parser)->id_kind == C_ID_ID)
-    {
-      tree t = lookup_name (c_parser_peek_token (parser)->value);
-
-      if (t == NULL_TREE)
-       undeclared_variable (c_parser_peek_token (parser)->location,
-                            c_parser_peek_token (parser)->value);
-      else if (t == error_mark_node)
-       ;
-      else if (kind != 0)
-       {
-         tree u = build_omp_clause (clause_loc, kind);
-         OMP_CLAUSE_DECL (u) = t;
-         OMP_CLAUSE_CHAIN (u) = list;
-         list = u;
-       }
-      else
-       list = tree_cons (t, NULL_TREE, list);
-
-      c_parser_consume_token (parser);
-
-      if (c_parser_next_token_is_not (parser, CPP_COMMA))
-       break;
-
-      c_parser_consume_token (parser);
-    }
-
-  return list;
-}
-
-/* Similarly, but expect leading and trailing parenthesis.  This is a very
-   common case for omp clauses.  */
-
-static tree
-c_parser_omp_var_list_parens (c_parser *parser, enum omp_clause_code kind,
-                             tree list)
-{
-  /* The clauses location.  */
-  location_t loc = c_parser_peek_token (parser)->location;
-
-  if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
-    {
-      list = c_parser_omp_variable_list (parser, loc, kind, list);
-      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
-    }
-  return list;
-}
-
-/* OpenMP 3.0:
-   collapse ( constant-expression ) */
-
-static tree
-c_parser_omp_clause_collapse (c_parser *parser, tree list)
-{
-  tree c, num = error_mark_node;
-  HOST_WIDE_INT n;
-  location_t loc;
-
-  check_no_duplicate_clause (list, OMP_CLAUSE_COLLAPSE, "collapse");
-
-  loc = c_parser_peek_token (parser)->location;
-  if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
-    {
-      num = c_parser_expr_no_commas (parser, NULL).value;
-      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
-    }
-  if (num == error_mark_node)
-    return list;
-  if (!INTEGRAL_TYPE_P (TREE_TYPE (num))
-      || !host_integerp (num, 0)
-      || (n = tree_low_cst (num, 0)) <= 0
-      || (int) n != n)
-    {
-      error_at (loc,
-               "collapse argument needs positive constant integer expression");
-      return list;
-    }
-  c = build_omp_clause (loc, OMP_CLAUSE_COLLAPSE);
-  OMP_CLAUSE_COLLAPSE_EXPR (c) = num;
-  OMP_CLAUSE_CHAIN (c) = list;
-  return c;
-}
-
-/* OpenMP 2.5:
-   copyin ( variable-list ) */
-
-static tree
-c_parser_omp_clause_copyin (c_parser *parser, tree list)
-{
-  return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_COPYIN, list);
-}
-
-/* OpenMP 2.5:
-   copyprivate ( variable-list ) */
-
-static tree
-c_parser_omp_clause_copyprivate (c_parser *parser, tree list)
-{
-  return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_COPYPRIVATE, list);
-}
-
-/* OpenMP 2.5:
-   default ( shared | none ) */
-
-static tree
-c_parser_omp_clause_default (c_parser *parser, tree list)
-{
-  enum omp_clause_default_kind kind = OMP_CLAUSE_DEFAULT_UNSPECIFIED;
-  location_t loc = c_parser_peek_token (parser)->location;
-  tree c;
-
-  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
-    return list;
-  if (c_parser_next_token_is (parser, CPP_NAME))
-    {
-      const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
-
-      switch (p[0])
-       {
-       case 'n':
-         if (strcmp ("none", p) != 0)
-           goto invalid_kind;
-         kind = OMP_CLAUSE_DEFAULT_NONE;
-         break;
-
-       case 's':
-         if (strcmp ("shared", p) != 0)
-           goto invalid_kind;
-         kind = OMP_CLAUSE_DEFAULT_SHARED;
-         break;
-
-       default:
-         goto invalid_kind;
-       }
-
-      c_parser_consume_token (parser);
-    }
-  else
-    {
-    invalid_kind:
-      c_parser_error (parser, "expected %<none%> or %<shared%>");
-    }
-  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
-
-  if (kind == OMP_CLAUSE_DEFAULT_UNSPECIFIED)
-    return list;
-
-  check_no_duplicate_clause (list, OMP_CLAUSE_DEFAULT, "default");
-  c = build_omp_clause (loc, OMP_CLAUSE_DEFAULT);
-  OMP_CLAUSE_CHAIN (c) = list;
-  OMP_CLAUSE_DEFAULT_KIND (c) = kind;
-
-  return c;
-}
-
-/* OpenMP 2.5:
-   firstprivate ( variable-list ) */
-
-static tree
-c_parser_omp_clause_firstprivate (c_parser *parser, tree list)
-{
-  return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_FIRSTPRIVATE, list);
-}
-
-/* OpenMP 3.1:
-   final ( expression ) */
-
-static tree
-c_parser_omp_clause_final (c_parser *parser, tree list)
-{
-  location_t loc = c_parser_peek_token (parser)->location;
-  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
-    {
-      tree t = c_parser_paren_condition (parser);
-      tree c;
-
-      check_no_duplicate_clause (list, OMP_CLAUSE_FINAL, "final");
-
-      c = build_omp_clause (loc, OMP_CLAUSE_FINAL);
-      OMP_CLAUSE_FINAL_EXPR (c) = t;
-      OMP_CLAUSE_CHAIN (c) = list;
-      list = c;
-    }
-  else
-    c_parser_error (parser, "expected %<(%>");
-
-  return list;
-}
-
-/* OpenMP 2.5:
-   if ( expression ) */
-
-static tree
-c_parser_omp_clause_if (c_parser *parser, tree list)
-{
-  location_t loc = c_parser_peek_token (parser)->location;
-  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
-    {
-      tree t = c_parser_paren_condition (parser);
-      tree c;
-
-      check_no_duplicate_clause (list, OMP_CLAUSE_IF, "if");
-
-      c = build_omp_clause (loc, OMP_CLAUSE_IF);
-      OMP_CLAUSE_IF_EXPR (c) = t;
-      OMP_CLAUSE_CHAIN (c) = list;
-      list = c;
-    }
-  else
-    c_parser_error (parser, "expected %<(%>");
-
-  return list;
-}
-
-/* OpenMP 2.5:
-   lastprivate ( variable-list ) */
-
-static tree
-c_parser_omp_clause_lastprivate (c_parser *parser, tree list)
-{
-  return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_LASTPRIVATE, list);
-}
-
-/* OpenMP 3.1:
-   mergeable */
-
-static tree
-c_parser_omp_clause_mergeable (c_parser *parser ATTRIBUTE_UNUSED, tree list)
-{
-  tree c;
-
-  /* FIXME: Should we allow duplicates?  */
-  check_no_duplicate_clause (list, OMP_CLAUSE_MERGEABLE, "mergeable");
-
-  c = build_omp_clause (c_parser_peek_token (parser)->location,
-                       OMP_CLAUSE_MERGEABLE);
-  OMP_CLAUSE_CHAIN (c) = list;
-
-  return c;
-}
-
-/* OpenMP 2.5:
-   nowait */
-
-static tree
-c_parser_omp_clause_nowait (c_parser *parser ATTRIBUTE_UNUSED, tree list)
-{
-  tree c;
-  location_t loc = c_parser_peek_token (parser)->location;
-
-  check_no_duplicate_clause (list, OMP_CLAUSE_NOWAIT, "nowait");
-
-  c = build_omp_clause (loc, OMP_CLAUSE_NOWAIT);
-  OMP_CLAUSE_CHAIN (c) = list;
-  return c;
-}
-
-/* OpenMP 2.5:
-   num_threads ( expression ) */
-
-static tree
-c_parser_omp_clause_num_threads (c_parser *parser, tree list)
-{
-  location_t num_threads_loc = c_parser_peek_token (parser)->location;
-  if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
-    {
-      location_t expr_loc = c_parser_peek_token (parser)->location;
-      tree c, t = c_parser_expression (parser).value;
-      mark_exp_read (t);
-      t = c_fully_fold (t, false, NULL);
-
-      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
-
-      if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
-       {
-         c_parser_error (parser, "expected integer expression");
-         return list;
-       }
-
-      /* Attempt to statically determine when the number isn't positive.  */
-      c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, t,
-                      build_int_cst (TREE_TYPE (t), 0));
-      if (CAN_HAVE_LOCATION_P (c))
-       SET_EXPR_LOCATION (c, expr_loc);
-      if (c == boolean_true_node)
-       {
-         warning_at (expr_loc, 0,
-                     "%<num_threads%> value must be positive");
-         t = integer_one_node;
-       }
-
-      check_no_duplicate_clause (list, OMP_CLAUSE_NUM_THREADS, "num_threads");
-
-      c = build_omp_clause (num_threads_loc, OMP_CLAUSE_NUM_THREADS);
-      OMP_CLAUSE_NUM_THREADS_EXPR (c) = t;
-      OMP_CLAUSE_CHAIN (c) = list;
-      list = c;
-    }
-
-  return list;
-}
-
-/* OpenMP 2.5:
-   ordered */
-
-static tree
-c_parser_omp_clause_ordered (c_parser *parser, tree list)
-{
-  tree c;
-
-  check_no_duplicate_clause (list, OMP_CLAUSE_ORDERED, "ordered");
-
-  c = build_omp_clause (c_parser_peek_token (parser)->location,
-                       OMP_CLAUSE_ORDERED);
-  OMP_CLAUSE_CHAIN (c) = list;
-
-  return c;
-}
-
-/* OpenMP 2.5:
-   private ( variable-list ) */
-
-static tree
-c_parser_omp_clause_private (c_parser *parser, tree list)
-{
-  return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_PRIVATE, list);
-}
-
-/* OpenMP 2.5:
-   reduction ( reduction-operator : variable-list )
-
-   reduction-operator:
-     One of: + * - & ^ | && ||
-     
-   OpenMP 3.1:
-   
-   reduction-operator:
-     One of: + * - & ^ | && || max min  */
-
-static tree
-c_parser_omp_clause_reduction (c_parser *parser, tree list)
-{
-  location_t clause_loc = c_parser_peek_token (parser)->location;
-  if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
-    {
-      enum tree_code code;
-
-      switch (c_parser_peek_token (parser)->type)
-       {
-       case CPP_PLUS:
-         code = PLUS_EXPR;
-         break;
-       case CPP_MULT:
-         code = MULT_EXPR;
-         break;
-       case CPP_MINUS:
-         code = MINUS_EXPR;
-         break;
-       case CPP_AND:
-         code = BIT_AND_EXPR;
-         break;
-       case CPP_XOR:
-         code = BIT_XOR_EXPR;
-         break;
-       case CPP_OR:
-         code = BIT_IOR_EXPR;
-         break;
-       case CPP_AND_AND:
-         code = TRUTH_ANDIF_EXPR;
-         break;
-       case CPP_OR_OR:
-         code = TRUTH_ORIF_EXPR;
-         break;
-        case CPP_NAME:
-         {
-           const char *p
-             = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
-           if (strcmp (p, "min") == 0)
-             {
-               code = MIN_EXPR;
-               break;
-             }
-           if (strcmp (p, "max") == 0)
-             {
-               code = MAX_EXPR;
-               break;
-             }
-         }
-         /* FALLTHRU */
-       default:
-         c_parser_error (parser,
-                         "expected %<+%>, %<*%>, %<-%>, %<&%>, "
-                         "%<^%>, %<|%>, %<&&%>, %<||%>, %<min%> or %<max%>");
-         c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, 0);
-         return list;
-       }
-      c_parser_consume_token (parser);
-      if (c_parser_require (parser, CPP_COLON, "expected %<:%>"))
-       {
-         tree nl, c;
-
-         nl = c_parser_omp_variable_list (parser, clause_loc,
-                                          OMP_CLAUSE_REDUCTION, list);
-         for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
-           OMP_CLAUSE_REDUCTION_CODE (c) = code;
-
-         list = nl;
-       }
-      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
-    }
-  return list;
-}
-
-/* OpenMP 2.5:
-   schedule ( schedule-kind )
-   schedule ( schedule-kind , expression )
-
-   schedule-kind:
-     static | dynamic | guided | runtime | auto
-*/
-
-static tree
-c_parser_omp_clause_schedule (c_parser *parser, tree list)
-{
-  tree c, t;
-  location_t loc = c_parser_peek_token (parser)->location;
-
-  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
-    return list;
-
-  c = build_omp_clause (loc, OMP_CLAUSE_SCHEDULE);
-
-  if (c_parser_next_token_is (parser, CPP_NAME))
-    {
-      tree kind = c_parser_peek_token (parser)->value;
-      const char *p = IDENTIFIER_POINTER (kind);
-
-      switch (p[0])
-       {
-       case 'd':
-         if (strcmp ("dynamic", p) != 0)
-           goto invalid_kind;
-         OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_DYNAMIC;
-         break;
-
-        case 'g':
-         if (strcmp ("guided", p) != 0)
-           goto invalid_kind;
-         OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_GUIDED;
-         break;
-
-       case 'r':
-         if (strcmp ("runtime", p) != 0)
-           goto invalid_kind;
-         OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_RUNTIME;
-         break;
-
-       default:
-         goto invalid_kind;
-       }
-    }
-  else if (c_parser_next_token_is_keyword (parser, RID_STATIC))
-    OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_STATIC;
-  else if (c_parser_next_token_is_keyword (parser, RID_AUTO))
-    OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_AUTO;
-  else
-    goto invalid_kind;
-
-  c_parser_consume_token (parser);
-  if (c_parser_next_token_is (parser, CPP_COMMA))
-    {
-      location_t here;
-      c_parser_consume_token (parser);
-
-      here = c_parser_peek_token (parser)->location;
-      t = c_parser_expr_no_commas (parser, NULL).value;
-      mark_exp_read (t);
-      t = c_fully_fold (t, false, NULL);
-
-      if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_RUNTIME)
-       error_at (here, "schedule %<runtime%> does not take "
-                 "a %<chunk_size%> parameter");
-      else if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_AUTO)
-       error_at (here,
-                 "schedule %<auto%> does not take "
-                 "a %<chunk_size%> parameter");
-      else if (TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE)
-       OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = t;
-      else
-       c_parser_error (parser, "expected integer expression");
-
-      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
-    }
-  else
-    c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
-                              "expected %<,%> or %<)%>");
-
-  check_no_duplicate_clause (list, OMP_CLAUSE_SCHEDULE, "schedule");
-  OMP_CLAUSE_CHAIN (c) = list;
-  return c;
-
- invalid_kind:
-  c_parser_error (parser, "invalid schedule kind");
-  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, 0);
-  return list;
-}
-
-/* OpenMP 2.5:
-   shared ( variable-list ) */
-
-static tree
-c_parser_omp_clause_shared (c_parser *parser, tree list)
-{
-  return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_SHARED, list);
-}
-
-/* OpenMP 3.0:
-   untied */
-
-static tree
-c_parser_omp_clause_untied (c_parser *parser ATTRIBUTE_UNUSED, tree list)
-{
-  tree c;
-
-  /* FIXME: Should we allow duplicates?  */
-  check_no_duplicate_clause (list, OMP_CLAUSE_UNTIED, "untied");
-
-  c = build_omp_clause (c_parser_peek_token (parser)->location,
-                       OMP_CLAUSE_UNTIED);
-  OMP_CLAUSE_CHAIN (c) = list;
-
-  return c;
-}
-
-/* Parse all OpenMP clauses.  The set clauses allowed by the directive
-   is a bitmask in MASK.  Return the list of clauses found; the result
-   of clause default goes in *pdefault.  */
-
-static tree
-c_parser_omp_all_clauses (c_parser *parser, unsigned int mask,
-                         const char *where)
-{
-  tree clauses = NULL;
-  bool first = true;
-
-  while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
-    {
-      location_t here;
-      pragma_omp_clause c_kind;
-      const char *c_name;
-      tree prev = clauses;
-
-      if (!first && c_parser_next_token_is (parser, CPP_COMMA))
-       c_parser_consume_token (parser);
-
-      first = false;
-      here = c_parser_peek_token (parser)->location;
-      c_kind = c_parser_omp_clause_name (parser);
-
-      switch (c_kind)
-       {
-       case PRAGMA_OMP_CLAUSE_COLLAPSE:
-         clauses = c_parser_omp_clause_collapse (parser, clauses);
-         c_name = "collapse";
-         break;
-       case PRAGMA_OMP_CLAUSE_COPYIN:
-         clauses = c_parser_omp_clause_copyin (parser, clauses);
-         c_name = "copyin";
-         break;
-       case PRAGMA_OMP_CLAUSE_COPYPRIVATE:
-         clauses = c_parser_omp_clause_copyprivate (parser, clauses);
-         c_name = "copyprivate";
-         break;
-       case PRAGMA_OMP_CLAUSE_DEFAULT:
-         clauses = c_parser_omp_clause_default (parser, clauses);
-         c_name = "default";
-         break;
-       case PRAGMA_OMP_CLAUSE_FIRSTPRIVATE:
-         clauses = c_parser_omp_clause_firstprivate (parser, clauses);
-         c_name = "firstprivate";
-         break;
-       case PRAGMA_OMP_CLAUSE_FINAL:
-         clauses = c_parser_omp_clause_final (parser, clauses);
-         c_name = "final";
-         break;
-       case PRAGMA_OMP_CLAUSE_IF:
-         clauses = c_parser_omp_clause_if (parser, clauses);
-         c_name = "if";
-         break;
-       case PRAGMA_OMP_CLAUSE_LASTPRIVATE:
-         clauses = c_parser_omp_clause_lastprivate (parser, clauses);
-         c_name = "lastprivate";
-         break;
-       case PRAGMA_OMP_CLAUSE_MERGEABLE:
-         clauses = c_parser_omp_clause_mergeable (parser, clauses);
-         c_name = "mergeable";
-         break;
-       case PRAGMA_OMP_CLAUSE_NOWAIT:
-         clauses = c_parser_omp_clause_nowait (parser, clauses);
-         c_name = "nowait";
-         break;
-       case PRAGMA_OMP_CLAUSE_NUM_THREADS:
-         clauses = c_parser_omp_clause_num_threads (parser, clauses);
-         c_name = "num_threads";
-         break;
-       case PRAGMA_OMP_CLAUSE_ORDERED:
-         clauses = c_parser_omp_clause_ordered (parser, clauses);
-         c_name = "ordered";
-         break;
-       case PRAGMA_OMP_CLAUSE_PRIVATE:
-         clauses = c_parser_omp_clause_private (parser, clauses);
-         c_name = "private";
-         break;
-       case PRAGMA_OMP_CLAUSE_REDUCTION:
-         clauses = c_parser_omp_clause_reduction (parser, clauses);
-         c_name = "reduction";
-         break;
-       case PRAGMA_OMP_CLAUSE_SCHEDULE:
-         clauses = c_parser_omp_clause_schedule (parser, clauses);
-         c_name = "schedule";
-         break;
-       case PRAGMA_OMP_CLAUSE_SHARED:
-         clauses = c_parser_omp_clause_shared (parser, clauses);
-         c_name = "shared";
-         break;
-       case PRAGMA_OMP_CLAUSE_UNTIED:
-         clauses = c_parser_omp_clause_untied (parser, clauses);
-         c_name = "untied";
-         break;
-       default:
-         c_parser_error (parser, "expected %<#pragma omp%> clause");
-         goto saw_error;
-       }
-
-      if (((mask >> c_kind) & 1) == 0 && !parser->error)
-       {
-         /* Remove the invalid clause(s) from the list to avoid
-            confusing the rest of the compiler.  */
-         clauses = prev;
-         error_at (here, "%qs is not valid for %qs", c_name, where);
-       }
-    }
-
- saw_error:
-  c_parser_skip_to_pragma_eol (parser);
-
-  return c_finish_omp_clauses (clauses);
-}
-
-/* OpenMP 2.5:
-   structured-block:
-     statement
-
-   In practice, we're also interested in adding the statement to an
-   outer node.  So it is convenient if we work around the fact that
-   c_parser_statement calls add_stmt.  */
-
-static tree
-c_parser_omp_structured_block (c_parser *parser)
-{
-  tree stmt = push_stmt_list ();
-  c_parser_statement (parser);
-  return pop_stmt_list (stmt);
-}
-
-/* OpenMP 2.5:
-   # pragma omp atomic new-line
-     expression-stmt
-
-   expression-stmt:
-     x binop= expr | x++ | ++x | x-- | --x
-   binop:
-     +, *, -, /, &, ^, |, <<, >>
-
-  where x is an lvalue expression with scalar type.
-
-   OpenMP 3.1:
-   # pragma omp atomic new-line
-     update-stmt
-
-   # pragma omp atomic read new-line
-     read-stmt
-
-   # pragma omp atomic write new-line
-     write-stmt
-
-   # pragma omp atomic update new-line
-     update-stmt
-
-   # pragma omp atomic capture new-line
-     capture-stmt
-
-   # pragma omp atomic capture new-line
-     capture-block
-
-   read-stmt:
-     v = x
-   write-stmt:
-     x = expr
-   update-stmt:
-     expression-stmt | x = x binop expr
-   capture-stmt:
-     v = x binop= expr | v = x++ | v = ++x | v = x-- | v = --x
-   capture-block:
-     { v = x; update-stmt; } | { update-stmt; v = x; }
-
-  where x and v are lvalue expressions with scalar type.
-
-  LOC is the location of the #pragma token.  */
-
-static void
-c_parser_omp_atomic (location_t loc, c_parser *parser)
-{
-  tree lhs = NULL_TREE, rhs = NULL_TREE, v = NULL_TREE;
-  tree lhs1 = NULL_TREE, rhs1 = NULL_TREE;
-  tree stmt, orig_lhs;
-  enum tree_code code = OMP_ATOMIC, opcode = NOP_EXPR;
-  struct c_expr rhs_expr;
-  bool structured_block = false;
-
-  if (c_parser_next_token_is (parser, CPP_NAME))
-    {
-      const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
-
-      if (!strcmp (p, "read"))
-       code = OMP_ATOMIC_READ;
-      else if (!strcmp (p, "write"))
-       code = NOP_EXPR;
-      else if (!strcmp (p, "update"))
-       code = OMP_ATOMIC;
-      else if (!strcmp (p, "capture"))
-       code = OMP_ATOMIC_CAPTURE_NEW;
-      else
-       p = NULL;
-      if (p)
-       c_parser_consume_token (parser);
-    }
-  c_parser_skip_to_pragma_eol (parser);
-
-  switch (code)
-    {
-    case OMP_ATOMIC_READ:
-    case NOP_EXPR: /* atomic write */
-      v = c_parser_unary_expression (parser).value;
-      v = c_fully_fold (v, false, NULL);
-      if (v == error_mark_node)
-       goto saw_error;
-      loc = c_parser_peek_token (parser)->location;
-      if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
-       goto saw_error;
-      if (code == NOP_EXPR)
-       lhs = c_parser_expression (parser).value;
-      else
-       lhs = c_parser_unary_expression (parser).value;
-      lhs = c_fully_fold (lhs, false, NULL);
-      if (lhs == error_mark_node)
-       goto saw_error;
-      if (code == NOP_EXPR)
-       {
-         /* atomic write is represented by OMP_ATOMIC with NOP_EXPR
-            opcode.  */
-         code = OMP_ATOMIC;
-         rhs = lhs;
-         lhs = v;
-         v = NULL_TREE;
-       }
-      goto done;
-    case OMP_ATOMIC_CAPTURE_NEW:
-      if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
-       {
-         c_parser_consume_token (parser);
-         structured_block = true;
-       }
-      else
-       {
-         v = c_parser_unary_expression (parser).value;
-         v = c_fully_fold (v, false, NULL);
-         if (v == error_mark_node)
-           goto saw_error;
-         if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
-           goto saw_error;
-       }
-      break;
-    default:
-      break;
-    }
-
-  /* For structured_block case we don't know yet whether
-     old or new x should be captured.  */
-restart:
-  lhs = c_parser_unary_expression (parser).value;
-  lhs = c_fully_fold (lhs, false, NULL);
-  orig_lhs = lhs;
-  switch (TREE_CODE (lhs))
-    {
-    case ERROR_MARK:
-    saw_error:
-      c_parser_skip_to_end_of_block_or_statement (parser);
-      if (structured_block)
-       {
-         if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
-           c_parser_consume_token (parser);
-         else if (code == OMP_ATOMIC_CAPTURE_NEW)
-           {
-             c_parser_skip_to_end_of_block_or_statement (parser);
-             if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
-               c_parser_consume_token (parser);
-           }
-       }
-      return;
-
-    case POSTINCREMENT_EXPR:
-      if (code == OMP_ATOMIC_CAPTURE_NEW && !structured_block)
-       code = OMP_ATOMIC_CAPTURE_OLD;
-      /* FALLTHROUGH */
-    case PREINCREMENT_EXPR:
-      lhs = TREE_OPERAND (lhs, 0);
-      opcode = PLUS_EXPR;
-      rhs = integer_one_node;
-      break;
-
-    case POSTDECREMENT_EXPR:
-      if (code == OMP_ATOMIC_CAPTURE_NEW && !structured_block)
-       code = OMP_ATOMIC_CAPTURE_OLD;
-      /* FALLTHROUGH */
-    case PREDECREMENT_EXPR:
-      lhs = TREE_OPERAND (lhs, 0);
-      opcode = MINUS_EXPR;
-      rhs = integer_one_node;
-      break;
-
-    case COMPOUND_EXPR:
-      if (TREE_CODE (TREE_OPERAND (lhs, 0)) == SAVE_EXPR
-         && TREE_CODE (TREE_OPERAND (lhs, 1)) == COMPOUND_EXPR
-         && TREE_CODE (TREE_OPERAND (TREE_OPERAND (lhs, 1), 0)) == MODIFY_EXPR
-         && TREE_OPERAND (TREE_OPERAND (lhs, 1), 1) == TREE_OPERAND (lhs, 0)
-         && TREE_CODE (TREE_TYPE (TREE_OPERAND (TREE_OPERAND
-                                             (TREE_OPERAND (lhs, 1), 0), 0)))
-            == BOOLEAN_TYPE)
-       /* Undo effects of boolean_increment for post {in,de}crement.  */
-       lhs = TREE_OPERAND (TREE_OPERAND (lhs, 1), 0);
-      /* FALLTHRU */
-    case MODIFY_EXPR:
-      if (TREE_CODE (lhs) == MODIFY_EXPR
-         && TREE_CODE (TREE_TYPE (TREE_OPERAND (lhs, 0))) == BOOLEAN_TYPE)
-       {
-         /* Undo effects of boolean_increment.  */
-         if (integer_onep (TREE_OPERAND (lhs, 1)))
-           {
-             /* This is pre or post increment.  */
-             rhs = TREE_OPERAND (lhs, 1);
-             lhs = TREE_OPERAND (lhs, 0);
-             opcode = NOP_EXPR;
-             if (code == OMP_ATOMIC_CAPTURE_NEW
-                 && !structured_block
-                 && TREE_CODE (orig_lhs) == COMPOUND_EXPR)
-               code = OMP_ATOMIC_CAPTURE_OLD;
-             break;
-           }
-         if (TREE_CODE (TREE_OPERAND (lhs, 1)) == TRUTH_NOT_EXPR
-             && TREE_OPERAND (lhs, 0)
-                == TREE_OPERAND (TREE_OPERAND (lhs, 1), 0))
-           {
-             /* This is pre or post decrement.  */
-             rhs = TREE_OPERAND (lhs, 1);
-             lhs = TREE_OPERAND (lhs, 0);
-             opcode = NOP_EXPR;
-             if (code == OMP_ATOMIC_CAPTURE_NEW
-                 && !structured_block
-                 && TREE_CODE (orig_lhs) == COMPOUND_EXPR)
-               code = OMP_ATOMIC_CAPTURE_OLD;
-             break;
-           }
-       }
-      /* FALLTHRU */
-    default:
-      switch (c_parser_peek_token (parser)->type)
-       {
-       case CPP_MULT_EQ:
-         opcode = MULT_EXPR;
-         break;
-       case CPP_DIV_EQ:
-         opcode = TRUNC_DIV_EXPR;
-         break;
-       case CPP_PLUS_EQ:
-         opcode = PLUS_EXPR;
-         break;
-       case CPP_MINUS_EQ:
-         opcode = MINUS_EXPR;
-         break;
-       case CPP_LSHIFT_EQ:
-         opcode = LSHIFT_EXPR;
-         break;
-       case CPP_RSHIFT_EQ:
-         opcode = RSHIFT_EXPR;
-         break;
-       case CPP_AND_EQ:
-         opcode = BIT_AND_EXPR;
-         break;
-       case CPP_OR_EQ:
-         opcode = BIT_IOR_EXPR;
-         break;
-       case CPP_XOR_EQ:
-         opcode = BIT_XOR_EXPR;
-         break;
-       case CPP_EQ:
-         if (structured_block || code == OMP_ATOMIC)
-           {
-             location_t aloc = c_parser_peek_token (parser)->location;
-             location_t rhs_loc;
-             enum c_parser_prec oprec = PREC_NONE;
-
-             c_parser_consume_token (parser);
-             rhs1 = c_parser_unary_expression (parser).value;
-             rhs1 = c_fully_fold (rhs1, false, NULL);
-             if (rhs1 == error_mark_node)
-               goto saw_error;
-             switch (c_parser_peek_token (parser)->type)
-               {
-               case CPP_SEMICOLON:
-                 if (code == OMP_ATOMIC_CAPTURE_NEW)
-                   {
-                     code = OMP_ATOMIC_CAPTURE_OLD;
-                     v = lhs;
-                     lhs = NULL_TREE;
-                     lhs1 = rhs1;
-                     rhs1 = NULL_TREE;
-                     c_parser_consume_token (parser);
-                     goto restart;
-                   }
-                 c_parser_error (parser,
-                                 "invalid form of %<#pragma omp atomic%>");
-                 goto saw_error;
-               case CPP_MULT:
-                 opcode = MULT_EXPR;
-                 oprec = PREC_MULT;
-                 break;
-               case CPP_DIV:
-                 opcode = TRUNC_DIV_EXPR;
-                 oprec = PREC_MULT;
-                 break;
-               case CPP_PLUS:
-                 opcode = PLUS_EXPR;
-                 oprec = PREC_ADD;
-                 break;
-               case CPP_MINUS:
-                 opcode = MINUS_EXPR;
-                 oprec = PREC_ADD;
-                 break;
-               case CPP_LSHIFT:
-                 opcode = LSHIFT_EXPR;
-                 oprec = PREC_SHIFT;
-                 break;
-               case CPP_RSHIFT:
-                 opcode = RSHIFT_EXPR;
-                 oprec = PREC_SHIFT;
-                 break;
-               case CPP_AND:
-                 opcode = BIT_AND_EXPR;
-                 oprec = PREC_BITAND;
-                 break;
-               case CPP_OR:
-                 opcode = BIT_IOR_EXPR;
-                 oprec = PREC_BITOR;
-                 break;
-               case CPP_XOR:
-                 opcode = BIT_XOR_EXPR;
-                 oprec = PREC_BITXOR;
-                 break;
-               default:
-                 c_parser_error (parser,
-                                 "invalid operator for %<#pragma omp atomic%>");
-                 goto saw_error;
-               }
-             loc = aloc;
-             c_parser_consume_token (parser);
-             rhs_loc = c_parser_peek_token (parser)->location;
-             if (commutative_tree_code (opcode))
-               oprec = (enum c_parser_prec) (oprec - 1);
-             rhs_expr = c_parser_binary_expression (parser, NULL, oprec);
-             rhs_expr = default_function_array_read_conversion (rhs_loc,
-                                                                rhs_expr);
-             rhs = rhs_expr.value;
-             rhs = c_fully_fold (rhs, false, NULL);
-             goto stmt_done; 
-           }
-         /* FALLTHROUGH */
-       default:
-         c_parser_error (parser,
-                         "invalid operator for %<#pragma omp atomic%>");
-         goto saw_error;
-       }
-
-      /* Arrange to pass the location of the assignment operator to
-        c_finish_omp_atomic.  */
-      loc = c_parser_peek_token (parser)->location;
-      c_parser_consume_token (parser);
-      {
-       location_t rhs_loc = c_parser_peek_token (parser)->location;
-       rhs_expr = c_parser_expression (parser);
-       rhs_expr = default_function_array_read_conversion (rhs_loc, rhs_expr);
-      }
-      rhs = rhs_expr.value;
-      rhs = c_fully_fold (rhs, false, NULL);
-      break;
-    }
-stmt_done:
-  if (structured_block && code == OMP_ATOMIC_CAPTURE_NEW)
-    {
-      if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
-       goto saw_error;
-      v = c_parser_unary_expression (parser).value;
-      v = c_fully_fold (v, false, NULL);
-      if (v == error_mark_node)
-       goto saw_error;
-      if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
-       goto saw_error;
-      lhs1 = c_parser_unary_expression (parser).value;
-      lhs1 = c_fully_fold (lhs1, false, NULL);
-      if (lhs1 == error_mark_node)
-       goto saw_error;
-    }
-  if (structured_block)
-    {
-      c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
-      c_parser_require (parser, CPP_CLOSE_BRACE, "expected %<}%>");
-    }
-done:
-  stmt = c_finish_omp_atomic (loc, code, opcode, lhs, rhs, v, lhs1, rhs1);
-  if (stmt != error_mark_node)
-    add_stmt (stmt);
-
-  if (!structured_block)
-    c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
-}
-
-
-/* OpenMP 2.5:
-   # pragma omp barrier new-line
-*/
-
-static void
-c_parser_omp_barrier (c_parser *parser)
-{
-  location_t loc = c_parser_peek_token (parser)->location;
-  c_parser_consume_pragma (parser);
-  c_parser_skip_to_pragma_eol (parser);
-
-  c_finish_omp_barrier (loc);
-}
-
-/* OpenMP 2.5:
-   # pragma omp critical [(name)] new-line
-     structured-block
-
-  LOC is the location of the #pragma itself.  */
-
-static tree
-c_parser_omp_critical (location_t loc, c_parser *parser)
-{
-  tree stmt, name = NULL;
-
-  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
-    {
-      c_parser_consume_token (parser);
-      if (c_parser_next_token_is (parser, CPP_NAME))
-       {
-         name = c_parser_peek_token (parser)->value;
-         c_parser_consume_token (parser);
-         c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>");
-       }
-      else
-       c_parser_error (parser, "expected identifier");
-    }
-  else if (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
-    c_parser_error (parser, "expected %<(%> or end of line");
-  c_parser_skip_to_pragma_eol (parser);
-
-  stmt = c_parser_omp_structured_block (parser);
-  return c_finish_omp_critical (loc, stmt, name);
-}
-
-/* OpenMP 2.5:
-   # pragma omp flush flush-vars[opt] new-line
-
-   flush-vars:
-     ( variable-list ) */
-
-static void
-c_parser_omp_flush (c_parser *parser)
-{
-  location_t loc = c_parser_peek_token (parser)->location;
-  c_parser_consume_pragma (parser);
-  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
-    c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ERROR, NULL);
-  else if (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
-    c_parser_error (parser, "expected %<(%> or end of line");
-  c_parser_skip_to_pragma_eol (parser);
-
-  c_finish_omp_flush (loc);
-}
-
-/* Parse the restricted form of the for statement allowed by OpenMP.
-   The real trick here is to determine the loop control variable early
-   so that we can push a new decl if necessary to make it private.
-   LOC is the location of the OMP in "#pragma omp".  */
-
-static tree
-c_parser_omp_for_loop (location_t loc,
-                      c_parser *parser, tree clauses, tree *par_clauses)
-{
-  tree decl, cond, incr, save_break, save_cont, body, init, stmt, cl;
-  tree declv, condv, incrv, initv, ret = NULL;
-  bool fail = false, open_brace_parsed = false;
-  int i, collapse = 1, nbraces = 0;
-  location_t for_loc;
-  VEC(tree,gc) *for_block = make_tree_vector ();
-
-  for (cl = clauses; cl; cl = OMP_CLAUSE_CHAIN (cl))
-    if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_COLLAPSE)
-      collapse = tree_low_cst (OMP_CLAUSE_COLLAPSE_EXPR (cl), 0);
-
-  gcc_assert (collapse >= 1);
-
-  declv = make_tree_vec (collapse);
-  initv = make_tree_vec (collapse);
-  condv = make_tree_vec (collapse);
-  incrv = make_tree_vec (collapse);
-
-  if (!c_parser_next_token_is_keyword (parser, RID_FOR))
-    {
-      c_parser_error (parser, "for statement expected");
-      return NULL;
-    }
-  for_loc = c_parser_peek_token (parser)->location;
-  c_parser_consume_token (parser);
-
-  for (i = 0; i < collapse; i++)
-    {
-      int bracecount = 0;
-
-      if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
-       goto pop_scopes;
-
-      /* Parse the initialization declaration or expression.  */
-      if (c_parser_next_tokens_start_declaration (parser))
-       {
-         if (i > 0)
-           VEC_safe_push (tree, gc, for_block, c_begin_compound_stmt (true));
-         c_parser_declaration_or_fndef (parser, true, true, true, true, true, NULL);
-         decl = check_for_loop_decls (for_loc, flag_isoc99);
-         if (decl == NULL)
-           goto error_init;
-         if (DECL_INITIAL (decl) == error_mark_node)
-           decl = error_mark_node;
-         init = decl;
-       }
-      else if (c_parser_next_token_is (parser, CPP_NAME)
-              && c_parser_peek_2nd_token (parser)->type == CPP_EQ)
-       {
-         struct c_expr decl_exp;
-         struct c_expr init_exp;
-         location_t init_loc;
-
-         decl_exp = c_parser_postfix_expression (parser);
-         decl = decl_exp.value;
-
-         c_parser_require (parser, CPP_EQ, "expected %<=%>");
-
-         init_loc = c_parser_peek_token (parser)->location;
-         init_exp = c_parser_expr_no_commas (parser, NULL);
-         init_exp = default_function_array_read_conversion (init_loc,
-                                                            init_exp);
-         init = build_modify_expr (init_loc, decl, decl_exp.original_type,
-                                   NOP_EXPR, init_loc, init_exp.value,
-                                   init_exp.original_type);
-         init = c_process_expr_stmt (init_loc, init);
-
-         c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
-       }
-      else
-       {
-       error_init:
-         c_parser_error (parser,
-                         "expected iteration declaration or initialization");
-         c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
-                                    "expected %<)%>");
-         fail = true;
-         goto parse_next;
-       }
-
-      /* Parse the loop condition.  */
-      cond = NULL_TREE;
-      if (c_parser_next_token_is_not (parser, CPP_SEMICOLON))
-       {
-         location_t cond_loc = c_parser_peek_token (parser)->location;
-         struct c_expr cond_expr = c_parser_binary_expression (parser, NULL,
-                                                               PREC_NONE);
-
-         cond = cond_expr.value;
-         cond = c_objc_common_truthvalue_conversion (cond_loc, cond);
-         cond = c_fully_fold (cond, false, NULL);
-         switch (cond_expr.original_code)
-           {
-           case GT_EXPR:
-           case GE_EXPR:
-           case LT_EXPR:
-           case LE_EXPR:
-             break;
-           default:
-             /* Can't be cond = error_mark_node, because we want to preserve
-                the location until c_finish_omp_for.  */
-             cond = build1 (NOP_EXPR, boolean_type_node, error_mark_node);
-             break;
-           }
-         protected_set_expr_location (cond, cond_loc);
-       }
-      c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
-
-      /* Parse the increment expression.  */
-      incr = NULL_TREE;
-      if (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN))
-       {
-         location_t incr_loc = c_parser_peek_token (parser)->location;
-
-         incr = c_process_expr_stmt (incr_loc,
-                                     c_parser_expression (parser).value);
-       }
-      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
-
-      if (decl == NULL || decl == error_mark_node || init == error_mark_node)
-       fail = true;
-      else
-       {
-         TREE_VEC_ELT (declv, i) = decl;
-         TREE_VEC_ELT (initv, i) = init;
-         TREE_VEC_ELT (condv, i) = cond;
-         TREE_VEC_ELT (incrv, i) = incr;
-       }
-
-    parse_next:
-      if (i == collapse - 1)
-       break;
-
-      /* FIXME: OpenMP 3.0 draft isn't very clear on what exactly is allowed
-        in between the collapsed for loops to be still considered perfectly
-        nested.  Hopefully the final version clarifies this.
-        For now handle (multiple) {'s and empty statements.  */
-      do
-       {
-         if (c_parser_next_token_is_keyword (parser, RID_FOR))
-           {
-             c_parser_consume_token (parser);
-             break;
-           }
-         else if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
-           {
-             c_parser_consume_token (parser);
-             bracecount++;
-           }
-         else if (bracecount
-                  && c_parser_next_token_is (parser, CPP_SEMICOLON))
-           c_parser_consume_token (parser);
-         else
-           {
-             c_parser_error (parser, "not enough perfectly nested loops");
-             if (bracecount)
-               {
-                 open_brace_parsed = true;
-                 bracecount--;
-               }
-             fail = true;
-             collapse = 0;
-             break;
-           }
-       }
-      while (1);
-
-      nbraces += bracecount;
-    }
-
-  save_break = c_break_label;
-  c_break_label = size_one_node;
-  save_cont = c_cont_label;
-  c_cont_label = NULL_TREE;
-  body = push_stmt_list ();
-
-  if (open_brace_parsed)
-    {
-      location_t here = c_parser_peek_token (parser)->location;
-      stmt = c_begin_compound_stmt (true);
-      c_parser_compound_statement_nostart (parser);
-      add_stmt (c_end_compound_stmt (here, stmt, true));
-    }
-  else
-    add_stmt (c_parser_c99_block_statement (parser));
-  if (c_cont_label)
-    {
-      tree t = build1 (LABEL_EXPR, void_type_node, c_cont_label);
-      SET_EXPR_LOCATION (t, loc);
-      add_stmt (t);
-    }
-
-  body = pop_stmt_list (body);
-  c_break_label = save_break;
-  c_cont_label = save_cont;
-
-  while (nbraces)
-    {
-      if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
-       {
-         c_parser_consume_token (parser);
-         nbraces--;
-       }
-      else if (c_parser_next_token_is (parser, CPP_SEMICOLON))
-       c_parser_consume_token (parser);
-      else
-       {
-         c_parser_error (parser, "collapsed loops not perfectly nested");
-         while (nbraces)
-           {
-             location_t here = c_parser_peek_token (parser)->location;
-             stmt = c_begin_compound_stmt (true);
-             add_stmt (body);
-             c_parser_compound_statement_nostart (parser);
-             body = c_end_compound_stmt (here, stmt, true);
-             nbraces--;
-           }
-         goto pop_scopes;
-       }
-    }
-
-  /* Only bother calling c_finish_omp_for if we haven't already generated
-     an error from the initialization parsing.  */
-  if (!fail)
-    {
-      stmt = c_finish_omp_for (loc, declv, initv, condv, incrv, body, NULL);
-      if (stmt)
-       {
-         if (par_clauses != NULL)
-           {
-             tree *c;
-             for (c = par_clauses; *c ; )
-               if (OMP_CLAUSE_CODE (*c) != OMP_CLAUSE_FIRSTPRIVATE
-                   && OMP_CLAUSE_CODE (*c) != OMP_CLAUSE_LASTPRIVATE)
-                 c = &OMP_CLAUSE_CHAIN (*c);
-               else
-                 {
-                   for (i = 0; i < collapse; i++)
-                     if (TREE_VEC_ELT (declv, i) == OMP_CLAUSE_DECL (*c))
-                       break;
-                   if (i == collapse)
-                     c = &OMP_CLAUSE_CHAIN (*c);
-                   else if (OMP_CLAUSE_CODE (*c) == OMP_CLAUSE_FIRSTPRIVATE)
-                     {
-                       error_at (loc,
-                                 "iteration variable %qD should not be firstprivate",
-                                 OMP_CLAUSE_DECL (*c));
-                       *c = OMP_CLAUSE_CHAIN (*c);
-                     }
-                   else
-                     {
-                       /* Copy lastprivate (decl) clause to OMP_FOR_CLAUSES,
-                          change it to shared (decl) in
-                          OMP_PARALLEL_CLAUSES.  */
-                       tree l = build_omp_clause (OMP_CLAUSE_LOCATION (*c),
-                                                  OMP_CLAUSE_LASTPRIVATE);
-                       OMP_CLAUSE_DECL (l) = OMP_CLAUSE_DECL (*c);
-                       OMP_CLAUSE_CHAIN (l) = clauses;
-                       clauses = l;
-                       OMP_CLAUSE_SET_CODE (*c, OMP_CLAUSE_SHARED);
-                     }
-                 }
-           }
-         OMP_FOR_CLAUSES (stmt) = clauses;
-       }
-      ret = stmt;
-    }
-pop_scopes:
-  while (!VEC_empty (tree, for_block))
-    {
-      /* FIXME diagnostics: LOC below should be the actual location of
-        this particular for block.  We need to build a list of
-        locations to go along with FOR_BLOCK.  */
-      stmt = c_end_compound_stmt (loc, VEC_pop (tree, for_block), true);
-      add_stmt (stmt);
-    }
-  release_tree_vector (for_block);
-  return ret;
-}
-
-/* OpenMP 2.5:
-   #pragma omp for for-clause[optseq] new-line
-     for-loop
-
-   LOC is the location of the #pragma token.
-*/
-
-#define OMP_FOR_CLAUSE_MASK                            \
-       ( (1u << PRAGMA_OMP_CLAUSE_PRIVATE)             \
-       | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE)        \
-       | (1u << PRAGMA_OMP_CLAUSE_LASTPRIVATE)         \
-       | (1u << PRAGMA_OMP_CLAUSE_REDUCTION)           \
-       | (1u << PRAGMA_OMP_CLAUSE_ORDERED)             \
-       | (1u << PRAGMA_OMP_CLAUSE_SCHEDULE)            \
-       | (1u << PRAGMA_OMP_CLAUSE_COLLAPSE)            \
-       | (1u << PRAGMA_OMP_CLAUSE_NOWAIT))
-
-static tree
-c_parser_omp_for (location_t loc, c_parser *parser)
-{
-  tree block, clauses, ret;
-
-  clauses = c_parser_omp_all_clauses (parser, OMP_FOR_CLAUSE_MASK,
-                                     "#pragma omp for");
-
-  block = c_begin_compound_stmt (true);
-  ret = c_parser_omp_for_loop (loc, parser, clauses, NULL);
-  block = c_end_compound_stmt (loc, block, true);
-  add_stmt (block);
-
-  return ret;
-}
-
-/* OpenMP 2.5:
-   # pragma omp master new-line
-     structured-block
-
-   LOC is the location of the #pragma token.
-*/
-
-static tree
-c_parser_omp_master (location_t loc, c_parser *parser)
-{
-  c_parser_skip_to_pragma_eol (parser);
-  return c_finish_omp_master (loc, c_parser_omp_structured_block (parser));
-}
-
-/* OpenMP 2.5:
-   # pragma omp ordered new-line
-     structured-block
-
-   LOC is the location of the #pragma itself.
-*/
-
-static tree
-c_parser_omp_ordered (location_t loc, c_parser *parser)
-{
-  c_parser_skip_to_pragma_eol (parser);
-  return c_finish_omp_ordered (loc, c_parser_omp_structured_block (parser));
-}
-
-/* OpenMP 2.5:
-
-   section-scope:
-     { section-sequence }
-
-   section-sequence:
-     section-directive[opt] structured-block
-     section-sequence section-directive structured-block
-
-    SECTIONS_LOC is the location of the #pragma omp sections.  */
-
-static tree
-c_parser_omp_sections_scope (location_t sections_loc, c_parser *parser)
-{
-  tree stmt, substmt;
-  bool error_suppress = false;
-  location_t loc;
-
-  loc = c_parser_peek_token (parser)->location;
-  if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
-    {
-      /* Avoid skipping until the end of the block.  */
-      parser->error = false;
-      return NULL_TREE;
-    }
-
-  stmt = push_stmt_list ();
-
-  if (c_parser_peek_token (parser)->pragma_kind != PRAGMA_OMP_SECTION)
-    {
-      substmt = push_stmt_list ();
-
-      while (1)
-       {
-          c_parser_statement (parser);
-
-         if (c_parser_peek_token (parser)->pragma_kind == PRAGMA_OMP_SECTION)
-           break;
-         if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
-           break;
-         if (c_parser_next_token_is (parser, CPP_EOF))
-           break;
-       }
-
-      substmt = pop_stmt_list (substmt);
-      substmt = build1 (OMP_SECTION, void_type_node, substmt);
-      SET_EXPR_LOCATION (substmt, loc);
-      add_stmt (substmt);
-    }
-
-  while (1)
-    {
-      if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
-       break;
-      if (c_parser_next_token_is (parser, CPP_EOF))
-       break;
-
-      loc = c_parser_peek_token (parser)->location;
-      if (c_parser_peek_token (parser)->pragma_kind == PRAGMA_OMP_SECTION)
-       {
-         c_parser_consume_pragma (parser);
-         c_parser_skip_to_pragma_eol (parser);
-         error_suppress = false;
-       }
-      else if (!error_suppress)
-       {
-         error_at (loc, "expected %<#pragma omp section%> or %<}%>");
-         error_suppress = true;
-       }
-
-      substmt = c_parser_omp_structured_block (parser);
-      substmt = build1 (OMP_SECTION, void_type_node, substmt);
-      SET_EXPR_LOCATION (substmt, loc);
-      add_stmt (substmt);
-    }
-  c_parser_skip_until_found (parser, CPP_CLOSE_BRACE,
-                            "expected %<#pragma omp section%> or %<}%>");
-
-  substmt = pop_stmt_list (stmt);
-
-  stmt = make_node (OMP_SECTIONS);
-  SET_EXPR_LOCATION (stmt, sections_loc);
-  TREE_TYPE (stmt) = void_type_node;
-  OMP_SECTIONS_BODY (stmt) = substmt;
-
-  return add_stmt (stmt);
-}
-
-/* OpenMP 2.5:
-   # pragma omp sections sections-clause[optseq] newline
-     sections-scope
-
-   LOC is the location of the #pragma token.
-*/
-
-#define OMP_SECTIONS_CLAUSE_MASK                       \
-       ( (1u << PRAGMA_OMP_CLAUSE_PRIVATE)             \
-       | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE)        \
-       | (1u << PRAGMA_OMP_CLAUSE_LASTPRIVATE)         \
-       | (1u << PRAGMA_OMP_CLAUSE_REDUCTION)           \
-       | (1u << PRAGMA_OMP_CLAUSE_NOWAIT))
-
-static tree
-c_parser_omp_sections (location_t loc, c_parser *parser)
-{
-  tree block, clauses, ret;
-
-  clauses = c_parser_omp_all_clauses (parser, OMP_SECTIONS_CLAUSE_MASK,
-                                     "#pragma omp sections");
-
-  block = c_begin_compound_stmt (true);
-  ret = c_parser_omp_sections_scope (loc, parser);
-  if (ret)
-    OMP_SECTIONS_CLAUSES (ret) = clauses;
-  block = c_end_compound_stmt (loc, block, true);
-  add_stmt (block);
-
-  return ret;
-}
-
-/* OpenMP 2.5:
-   # pragma parallel parallel-clause new-line
-   # pragma parallel for parallel-for-clause new-line
-   # pragma parallel sections parallel-sections-clause new-line
-
-   LOC is the location of the #pragma token.
-*/
-
-#define OMP_PARALLEL_CLAUSE_MASK                       \
-       ( (1u << PRAGMA_OMP_CLAUSE_IF)                  \
-       | (1u << PRAGMA_OMP_CLAUSE_PRIVATE)             \
-       | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE)        \
-       | (1u << PRAGMA_OMP_CLAUSE_DEFAULT)             \
-       | (1u << PRAGMA_OMP_CLAUSE_SHARED)              \
-       | (1u << PRAGMA_OMP_CLAUSE_COPYIN)              \
-       | (1u << PRAGMA_OMP_CLAUSE_REDUCTION)           \
-       | (1u << PRAGMA_OMP_CLAUSE_NUM_THREADS))
-
-static tree
-c_parser_omp_parallel (location_t loc, c_parser *parser)
-{
-  enum pragma_kind p_kind = PRAGMA_OMP_PARALLEL;
-  const char *p_name = "#pragma omp parallel";
-  tree stmt, clauses, par_clause, ws_clause, block;
-  unsigned int mask = OMP_PARALLEL_CLAUSE_MASK;
-
-  if (c_parser_next_token_is_keyword (parser, RID_FOR))
-    {
-      c_parser_consume_token (parser);
-      p_kind = PRAGMA_OMP_PARALLEL_FOR;
-      p_name = "#pragma omp parallel for";
-      mask |= OMP_FOR_CLAUSE_MASK;
-      mask &= ~(1u << PRAGMA_OMP_CLAUSE_NOWAIT);
-    }
-  else if (c_parser_next_token_is (parser, CPP_NAME))
-    {
-      const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
-      if (strcmp (p, "sections") == 0)
-       {
-         c_parser_consume_token (parser);
-         p_kind = PRAGMA_OMP_PARALLEL_SECTIONS;
-         p_name = "#pragma omp parallel sections";
-         mask |= OMP_SECTIONS_CLAUSE_MASK;
-         mask &= ~(1u << PRAGMA_OMP_CLAUSE_NOWAIT);
-       }
-    }
-
-  clauses = c_parser_omp_all_clauses (parser, mask, p_name);
-
-  switch (p_kind)
-    {
-    case PRAGMA_OMP_PARALLEL:
-      block = c_begin_omp_parallel ();
-      c_parser_statement (parser);
-      stmt = c_finish_omp_parallel (loc, clauses, block);
-      break;
-
-    case PRAGMA_OMP_PARALLEL_FOR:
-      block = c_begin_omp_parallel ();
-      c_split_parallel_clauses (loc, clauses, &par_clause, &ws_clause);
-      c_parser_omp_for_loop (loc, parser, ws_clause, &par_clause);
-      stmt = c_finish_omp_parallel (loc, par_clause, block);
-      OMP_PARALLEL_COMBINED (stmt) = 1;
-      break;
-
-    case PRAGMA_OMP_PARALLEL_SECTIONS:
-      block = c_begin_omp_parallel ();
-      c_split_parallel_clauses (loc, clauses, &par_clause, &ws_clause);
-      stmt = c_parser_omp_sections_scope (loc, parser);
-      if (stmt)
-       OMP_SECTIONS_CLAUSES (stmt) = ws_clause;
-      stmt = c_finish_omp_parallel (loc, par_clause, block);
-      OMP_PARALLEL_COMBINED (stmt) = 1;
-      break;
-
-    default:
-      gcc_unreachable ();
-    }
-
-  return stmt;
-}
-
-/* OpenMP 2.5:
-   # pragma omp single single-clause[optseq] new-line
-     structured-block
-
-   LOC is the location of the #pragma.
-*/
-
-#define OMP_SINGLE_CLAUSE_MASK                         \
-       ( (1u << PRAGMA_OMP_CLAUSE_PRIVATE)             \
-       | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE)        \
-       | (1u << PRAGMA_OMP_CLAUSE_COPYPRIVATE)         \
-       | (1u << PRAGMA_OMP_CLAUSE_NOWAIT))
-
-static tree
-c_parser_omp_single (location_t loc, c_parser *parser)
-{
-  tree stmt = make_node (OMP_SINGLE);
-  SET_EXPR_LOCATION (stmt, loc);
-  TREE_TYPE (stmt) = void_type_node;
-
-  OMP_SINGLE_CLAUSES (stmt)
-    = c_parser_omp_all_clauses (parser, OMP_SINGLE_CLAUSE_MASK,
-                               "#pragma omp single");
-  OMP_SINGLE_BODY (stmt) = c_parser_omp_structured_block (parser);
-
-  return add_stmt (stmt);
-}
-
-/* OpenMP 3.0:
-   # pragma omp task task-clause[optseq] new-line
-
-   LOC is the location of the #pragma.
-*/
-
-#define OMP_TASK_CLAUSE_MASK                           \
-       ( (1u << PRAGMA_OMP_CLAUSE_IF)                  \
-       | (1u << PRAGMA_OMP_CLAUSE_UNTIED)              \
-       | (1u << PRAGMA_OMP_CLAUSE_DEFAULT)             \
-       | (1u << PRAGMA_OMP_CLAUSE_PRIVATE)             \
-       | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE)        \
-       | (1u << PRAGMA_OMP_CLAUSE_SHARED)              \
-       | (1u << PRAGMA_OMP_CLAUSE_FINAL)               \
-       | (1u << PRAGMA_OMP_CLAUSE_MERGEABLE))
-
-static tree
-c_parser_omp_task (location_t loc, c_parser *parser)
-{
-  tree clauses, block;
-
-  clauses = c_parser_omp_all_clauses (parser, OMP_TASK_CLAUSE_MASK,
-                                     "#pragma omp task");
-
-  block = c_begin_omp_task ();
-  c_parser_statement (parser);
-  return c_finish_omp_task (loc, clauses, block);
-}
-
-/* OpenMP 3.0:
-   # pragma omp taskwait new-line
-*/
-
-static void
-c_parser_omp_taskwait (c_parser *parser)
-{
-  location_t loc = c_parser_peek_token (parser)->location;
-  c_parser_consume_pragma (parser);
-  c_parser_skip_to_pragma_eol (parser);
-
-  c_finish_omp_taskwait (loc);
-}
-
-/* OpenMP 3.1:
-   # pragma omp taskyield new-line
-*/
-
-static void
-c_parser_omp_taskyield (c_parser *parser)
-{
-  location_t loc = c_parser_peek_token (parser)->location;
-  c_parser_consume_pragma (parser);
-  c_parser_skip_to_pragma_eol (parser);
-
-  c_finish_omp_taskyield (loc);
-}
-
-/* Main entry point to parsing most OpenMP pragmas.  */
-
-static void
-c_parser_omp_construct (c_parser *parser)
-{
-  enum pragma_kind p_kind;
-  location_t loc;
-  tree stmt;
-
-  loc = c_parser_peek_token (parser)->location;
-  p_kind = c_parser_peek_token (parser)->pragma_kind;
-  c_parser_consume_pragma (parser);
-
-  switch (p_kind)
-    {
-    case PRAGMA_OMP_ATOMIC:
-      c_parser_omp_atomic (loc, parser);
-      return;
-    case PRAGMA_OMP_CRITICAL:
-      stmt = c_parser_omp_critical (loc, parser);
-      break;
-    case PRAGMA_OMP_FOR:
-      stmt = c_parser_omp_for (loc, parser);
-      break;
-    case PRAGMA_OMP_MASTER:
-      stmt = c_parser_omp_master (loc, parser);
-      break;
-    case PRAGMA_OMP_ORDERED:
-      stmt = c_parser_omp_ordered (loc, parser);
-      break;
-    case PRAGMA_OMP_PARALLEL:
-      stmt = c_parser_omp_parallel (loc, parser);
-      break;
-    case PRAGMA_OMP_SECTIONS:
-      stmt = c_parser_omp_sections (loc, parser);
-      break;
-    case PRAGMA_OMP_SINGLE:
-      stmt = c_parser_omp_single (loc, parser);
-      break;
-    case PRAGMA_OMP_TASK:
-      stmt = c_parser_omp_task (loc, parser);
-      break;
-    default:
-      gcc_unreachable ();
-    }
-
-  if (stmt)
-    gcc_assert (EXPR_LOCATION (stmt) != UNKNOWN_LOCATION);
-}
-
-
-/* OpenMP 2.5:
-   # pragma omp threadprivate (variable-list) */
-
-static void
-c_parser_omp_threadprivate (c_parser *parser)
-{
-  tree vars, t;
-  location_t loc;
-
-  c_parser_consume_pragma (parser);
-  loc = c_parser_peek_token (parser)->location;
-  vars = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ERROR, NULL);
-
-  /* Mark every variable in VARS to be assigned thread local storage.  */
-  for (t = vars; t; t = TREE_CHAIN (t))
-    {
-      tree v = TREE_PURPOSE (t);
-
-      /* FIXME diagnostics: Ideally we should keep individual
-        locations for all the variables in the var list to make the
-        following errors more precise.  Perhaps
-        c_parser_omp_var_list_parens() should construct a list of
-        locations to go along with the var list.  */
-
-      /* If V had already been marked threadprivate, it doesn't matter
-        whether it had been used prior to this point.  */
-      if (TREE_CODE (v) != VAR_DECL)
-       error_at (loc, "%qD is not a variable", v);
-      else if (TREE_USED (v) && !C_DECL_THREADPRIVATE_P (v))
-       error_at (loc, "%qE declared %<threadprivate%> after first use", v);
-      else if (! TREE_STATIC (v) && ! DECL_EXTERNAL (v))
-       error_at (loc, "automatic variable %qE cannot be %<threadprivate%>", v);
-      else if (TREE_TYPE (v) == error_mark_node)
-       ;
-      else if (! COMPLETE_TYPE_P (TREE_TYPE (v)))
-       error_at (loc, "%<threadprivate%> %qE has incomplete type", v);
-      else
-       {
-         if (! DECL_THREAD_LOCAL_P (v))
-           {
-             DECL_TLS_MODEL (v) = decl_default_tls_model (v);
-             /* If rtl has been already set for this var, call
-                make_decl_rtl once again, so that encode_section_info
-                has a chance to look at the new decl flags.  */
-             if (DECL_RTL_SET_P (v))
-               make_decl_rtl (v);
-           }
-         C_DECL_THREADPRIVATE_P (v) = 1;
-       }
-    }
-
-  c_parser_skip_to_pragma_eol (parser);
-}
-
-/* Parse a transaction attribute (GCC Extension).
-
-   transaction-attribute:
-     attributes
-     [ [ any-word ] ]
-
-   The transactional memory language description is written for C++,
-   and uses the C++0x attribute syntax.  For compatibility, allow the
-   bracket style for transactions in C as well.  */
-
-static tree
-c_parser_transaction_attributes (c_parser *parser)
-{
-  tree attr_name, attr = NULL;
-
-  if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
-    return c_parser_attributes (parser);
-
-  if (!c_parser_next_token_is (parser, CPP_OPEN_SQUARE))
-    return NULL_TREE;
-  c_parser_consume_token (parser);
-  if (!c_parser_require (parser, CPP_OPEN_SQUARE, "expected %<[%>"))
-    goto error1;
-
-  attr_name = c_parser_attribute_any_word (parser);
-  if (attr_name)
-    {
-      c_parser_consume_token (parser);
-      attr = build_tree_list (attr_name, NULL_TREE);
-    }
-  else
-    c_parser_error (parser, "expected identifier");
-
-  c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, "expected %<]%>");
- error1:
-  c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, "expected %<]%>");
-  return attr;
-}
-
-/* Parse a __transaction_atomic or __transaction_relaxed statement
-   (GCC Extension).
-
-   transaction-statement:
-     __transaction_atomic transaction-attribute[opt] compound-statement
-     __transaction_relaxed compound-statement
-
-   Note that the only valid attribute is: "outer".
-*/
-
-static tree
-c_parser_transaction (c_parser *parser, enum rid keyword)
-{
-  unsigned int old_in = parser->in_transaction;
-  unsigned int this_in = 1, new_in;
-  location_t loc = c_parser_peek_token (parser)->location;
-  tree stmt, attrs;
-
-  gcc_assert ((keyword == RID_TRANSACTION_ATOMIC
-      || keyword == RID_TRANSACTION_RELAXED)
-      && c_parser_next_token_is_keyword (parser, keyword));
-  c_parser_consume_token (parser);
-
-  if (keyword == RID_TRANSACTION_RELAXED)
-    this_in |= TM_STMT_ATTR_RELAXED;
-  else
-    {
-      attrs = c_parser_transaction_attributes (parser);
-      if (attrs)
-       this_in |= parse_tm_stmt_attr (attrs, TM_STMT_ATTR_OUTER);
-    }
-
-  /* Keep track if we're in the lexical scope of an outer transaction.  */
-  new_in = this_in | (old_in & TM_STMT_ATTR_OUTER);
-
-  parser->in_transaction = new_in;
-  stmt = c_parser_compound_statement (parser);
-  parser->in_transaction = old_in;
-
-  if (flag_tm)
-    stmt = c_finish_transaction (loc, stmt, this_in);
-  else
-    error_at (loc, (keyword == RID_TRANSACTION_ATOMIC ?
-       "%<__transaction_atomic%> without transactional memory support enabled"
-       : "%<__transaction_relaxed %> "
-       "without transactional memory support enabled"));
-
-  return stmt;
-}
-
-/* Parse a __transaction_atomic or __transaction_relaxed expression
-   (GCC Extension).
-
-   transaction-expression:
-     __transaction_atomic ( expression )
-     __transaction_relaxed ( expression )
-*/
-
-static struct c_expr
-c_parser_transaction_expression (c_parser *parser, enum rid keyword)
-{
-  struct c_expr ret;
-  unsigned int old_in = parser->in_transaction;
-  unsigned int this_in = 1;
-  location_t loc = c_parser_peek_token (parser)->location;
-  tree attrs;
-
-  gcc_assert ((keyword == RID_TRANSACTION_ATOMIC
-      || keyword == RID_TRANSACTION_RELAXED)
-      && c_parser_next_token_is_keyword (parser, keyword));
-  c_parser_consume_token (parser);
-
-  if (keyword == RID_TRANSACTION_RELAXED)
-    this_in |= TM_STMT_ATTR_RELAXED;
-  else
-    {
-      attrs = c_parser_transaction_attributes (parser);
-      if (attrs)
-       this_in |= parse_tm_stmt_attr (attrs, 0);
-    }
-
-  parser->in_transaction = this_in;
-  if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
-    {
-      tree expr = c_parser_expression (parser).value;
-      ret.original_type = TREE_TYPE (expr);
-      ret.value = build1 (TRANSACTION_EXPR, ret.original_type, expr);
-      if (this_in & TM_STMT_ATTR_RELAXED)
-       TRANSACTION_EXPR_RELAXED (ret.value) = 1;
-      SET_EXPR_LOCATION (ret.value, loc);
-      ret.original_code = TRANSACTION_EXPR;
-      if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
-       {
-         c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
-         goto error;
-       }
-    }
-  else
-    {
-     error:
-      ret.value = error_mark_node;
-      ret.original_code = ERROR_MARK;
-      ret.original_type = NULL;
-    }
-  parser->in_transaction = old_in;
-
-  if (!flag_tm)
-    error_at (loc, (keyword == RID_TRANSACTION_ATOMIC ?
-       "%<__transaction_atomic%> without transactional memory support enabled"
-       : "%<__transaction_relaxed %> "
-       "without transactional memory support enabled"));
-
-  return ret;
-}
-
-/* Parse a __transaction_cancel statement (GCC Extension).
-
-   transaction-cancel-statement:
-     __transaction_cancel transaction-attribute[opt] ;
-
-   Note that the only valid attribute is "outer".
-*/
-
-static tree
-c_parser_transaction_cancel(c_parser *parser)
-{
-  location_t loc = c_parser_peek_token (parser)->location;
-  tree attrs;
-  bool is_outer = false;
-
-  gcc_assert (c_parser_next_token_is_keyword (parser, RID_TRANSACTION_CANCEL));
-  c_parser_consume_token (parser);
-
-  attrs = c_parser_transaction_attributes (parser);
-  if (attrs)
-    is_outer = (parse_tm_stmt_attr (attrs, TM_STMT_ATTR_OUTER) != 0);
-
-  if (!flag_tm)
-    {
-      error_at (loc, "%<__transaction_cancel%> without "
-               "transactional memory support enabled");
-      goto ret_error;
-    }
-  else if (parser->in_transaction & TM_STMT_ATTR_RELAXED)
-    {
-      error_at (loc, "%<__transaction_cancel%> within a "
-               "%<__transaction_relaxed%>");
-      goto ret_error;
-    }
-  else if (is_outer)
-    {
-      if ((parser->in_transaction & TM_STMT_ATTR_OUTER) == 0
-         && !is_tm_may_cancel_outer (current_function_decl))
-       {
-         error_at (loc, "outer %<__transaction_cancel%> not "
-                   "within outer %<__transaction_atomic%>");
-         error_at (loc, "  or a %<transaction_may_cancel_outer%> function");
-         goto ret_error;
-       }
-    }
-  else if (parser->in_transaction == 0)
-    {
-      error_at (loc, "%<__transaction_cancel%> not within "
-               "%<__transaction_atomic%>");
-      goto ret_error;
-    }
-
-  return add_stmt (build_tm_abort_call (loc, is_outer));
-
- ret_error:
-  return build1 (NOP_EXPR, void_type_node, error_mark_node);
-}
-\f
-/* Parse a single source file.  */
-
-void
-c_parse_file (void)
-{
-  /* Use local storage to begin.  If the first token is a pragma, parse it.
-     If it is #pragma GCC pch_preprocess, then this will load a PCH file
-     which will cause garbage collection.  */
-  c_parser tparser;
-
-  memset (&tparser, 0, sizeof tparser);
-  the_parser = &tparser;
-
-  if (c_parser_peek_token (&tparser)->pragma_kind == PRAGMA_GCC_PCH_PREPROCESS)
-    c_parser_pragma_pch_preprocess (&tparser);
-
-  the_parser = ggc_alloc_c_parser ();
-  *the_parser = tparser;
-
-  /* Initialize EH, if we've been told to do so.  */
-  if (flag_exceptions)
-    using_eh_for_cleanups ();
-
-  c_parser_translation_unit (the_parser);
-  the_parser = NULL;
-}
-
-#include "gt-c-parser.h"
diff --git a/gcc/c-tree.h b/gcc/c-tree.h
deleted file mode 100644 (file)
index 145df35..0000000
+++ /dev/null
@@ -1,676 +0,0 @@
-/* Definitions for C parsing and type checking.
-   Copyright (C) 1987, 1993, 1994, 1995, 1997, 1998,
-   1999, 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 GCC_C_TREE_H
-#define GCC_C_TREE_H
-
-#include "c-family/c-common.h"
-#include "diagnostic.h"
-
-/* struct lang_identifier is private to c-decl.c, but langhooks.c needs to
-   know how big it is.  This is sanity-checked in c-decl.c.  */
-#define C_SIZEOF_STRUCT_LANG_IDENTIFIER \
-  (sizeof (struct c_common_identifier) + 3 * sizeof (void *))
-
-/* In a RECORD_TYPE or UNION_TYPE, nonzero if any component is read-only.  */
-#define C_TYPE_FIELDS_READONLY(TYPE) TREE_LANG_FLAG_1 (TYPE)
-
-/* In a RECORD_TYPE or UNION_TYPE, nonzero if any component is volatile.  */
-#define C_TYPE_FIELDS_VOLATILE(TYPE) TREE_LANG_FLAG_2 (TYPE)
-
-/* In a RECORD_TYPE or UNION_TYPE or ENUMERAL_TYPE
-   nonzero if the definition of the type has already started.  */
-#define C_TYPE_BEING_DEFINED(TYPE) TYPE_LANG_FLAG_0 (TYPE)
-
-/* In an incomplete RECORD_TYPE or UNION_TYPE, a list of variable
-   declarations whose type would be completed by completing that type.  */
-#define C_TYPE_INCOMPLETE_VARS(TYPE) TYPE_VFIELD (TYPE)
-
-/* In an IDENTIFIER_NODE, nonzero if this identifier is actually a
-   keyword.  C_RID_CODE (node) is then the RID_* value of the keyword,
-   and C_RID_YYCODE is the token number wanted by Yacc.  */
-#define C_IS_RESERVED_WORD(ID) TREE_LANG_FLAG_0 (ID)
-
-/* Record whether a type or decl was written with nonconstant size.
-   Note that TYPE_SIZE may have simplified to a constant.  */
-#define C_TYPE_VARIABLE_SIZE(TYPE) TYPE_LANG_FLAG_1 (TYPE)
-#define C_DECL_VARIABLE_SIZE(TYPE) DECL_LANG_FLAG_0 (TYPE)
-
-/* Record whether a type is defined inside a struct or union type.
-   This is used for -Wc++-compat. */
-#define C_TYPE_DEFINED_IN_STRUCT(TYPE) TYPE_LANG_FLAG_2 (TYPE)
-
-/* Record whether a typedef for type `int' was actually `signed int'.  */
-#define C_TYPEDEF_EXPLICITLY_SIGNED(EXP) DECL_LANG_FLAG_1 (EXP)
-
-/* For a FUNCTION_DECL, nonzero if it was defined without an explicit
-   return type.  */
-#define C_FUNCTION_IMPLICIT_INT(EXP) DECL_LANG_FLAG_1 (EXP)
-
-/* For a FUNCTION_DECL, nonzero if it was an implicit declaration.  */
-#define C_DECL_IMPLICIT(EXP) DECL_LANG_FLAG_2 (EXP)
-
-/* For FUNCTION_DECLs, evaluates true if the decl is built-in but has
-   been declared.  */
-#define C_DECL_DECLARED_BUILTIN(EXP)           \
-  DECL_LANG_FLAG_3 (FUNCTION_DECL_CHECK (EXP))
-
-/* For FUNCTION_DECLs, evaluates true if the decl is built-in, has a
-   built-in prototype and does not have a non-built-in prototype.  */
-#define C_DECL_BUILTIN_PROTOTYPE(EXP)          \
-  DECL_LANG_FLAG_6 (FUNCTION_DECL_CHECK (EXP))
-
-/* Record whether a decl was declared register.  This is strictly a
-   front-end flag, whereas DECL_REGISTER is used for code generation;
-   they may differ for structures with volatile fields.  */
-#define C_DECL_REGISTER(EXP) DECL_LANG_FLAG_4 (EXP)
-
-/* Record whether a decl was used in an expression anywhere except an
-   unevaluated operand of sizeof / typeof / alignof.  This is only
-   used for functions declared static but not defined, though outside
-   sizeof and typeof it is set for other function decls as well.  */
-#define C_DECL_USED(EXP) DECL_LANG_FLAG_5 (FUNCTION_DECL_CHECK (EXP))
-
-/* Record whether a variable has been declared threadprivate by
-   #pragma omp threadprivate.  */
-#define C_DECL_THREADPRIVATE_P(DECL) DECL_LANG_FLAG_3 (VAR_DECL_CHECK (DECL))
-
-/* Nonzero for a decl which either doesn't exist or isn't a prototype.
-   N.B. Could be simplified if all built-in decls had complete prototypes
-   (but this is presently difficult because some of them need FILE*).  */
-#define C_DECL_ISNT_PROTOTYPE(EXP)                     \
-       (EXP == 0                                       \
-       || (!prototype_p (TREE_TYPE (EXP))      \
-           && !DECL_BUILT_IN (EXP)))
-
-/* For FUNCTION_TYPE, a hidden list of types of arguments.  The same as
-   TYPE_ARG_TYPES for functions with prototypes, but created for functions
-   without prototypes.  */
-#define TYPE_ACTUAL_ARG_TYPES(NODE) TYPE_LANG_SLOT_1 (NODE)
-
-/* For a CONSTRUCTOR, whether some initializer contains a
-   subexpression meaning it is not a constant expression.  */
-#define CONSTRUCTOR_NON_CONST(EXPR) TREE_LANG_FLAG_1 (CONSTRUCTOR_CHECK (EXPR))
-
-/* Record parser information about an expression that is irrelevant
-   for code generation alongside a tree representing its value.  */
-struct c_expr
-{
-  /* The value of the expression.  */
-  tree value;
-  /* Record the original unary/binary operator of an expression, which may
-     have been changed by fold, STRING_CST for unparenthesized string
-     constants, C_MAYBE_CONST_EXPR for __builtin_constant_p calls
-     (even if parenthesized), for subexpressions, and for non-constant
-     initializers, or ERROR_MARK for other expressions (including
-     parenthesized expressions).  */
-  enum tree_code original_code;
-  /* If not NULL, the original type of an expression.  This will
-     differ from the type of the value field for an enum constant.
-     The type of an enum constant is a plain integer type, but this
-     field will be the enum type.  */
-  tree original_type;
-};
-
-/* Type alias for struct c_expr. This allows to use the structure
-   inside the VEC types.  */
-typedef struct c_expr c_expr_t;
-
-/* A varray of c_expr_t.  */
-DEF_VEC_O (c_expr_t);
-DEF_VEC_ALLOC_O (c_expr_t, gc);
-DEF_VEC_ALLOC_O (c_expr_t, heap);
-
-/* Append a new c_expr_t element to V.  */
-#define C_EXPR_APPEND(V, ELEM) \
-  do { \
-    c_expr_t *__elem_p = VEC_safe_push (c_expr_t, gc, V, NULL); \
-    *__elem_p = (ELEM); \
-  } while (0)
-
-/* A kind of type specifier.  Note that this information is currently
-   only used to distinguish tag definitions, tag references and typeof
-   uses.  */
-enum c_typespec_kind {
-  /* No typespec.  This appears only in struct c_declspec.  */
-  ctsk_none,
-  /* A reserved keyword type specifier.  */
-  ctsk_resword,
-  /* A reference to a tag, previously declared, such as "struct foo".
-     This includes where the previous declaration was as a different
-     kind of tag, in which case this is only valid if shadowing that
-     tag in an inner scope.  */
-  ctsk_tagref,
-  /* A reference to a tag, not previously declared in a visible
-     scope.  */
-  ctsk_tagfirstref,
-  /* A definition of a tag such as "struct foo { int a; }".  */
-  ctsk_tagdef,
-  /* A typedef name.  */
-  ctsk_typedef,
-  /* An ObjC-specific kind of type specifier.  */
-  ctsk_objc,
-  /* A typeof specifier.  */
-  ctsk_typeof
-};
-
-/* A type specifier: this structure is created in the parser and
-   passed to declspecs_add_type only.  */
-struct c_typespec {
-  /* What kind of type specifier this is.  */
-  enum c_typespec_kind kind;
-  /* Whether the expression has operands suitable for use in constant
-     expressions.  */
-  bool expr_const_operands;
-  /* The specifier itself.  */
-  tree spec;
-  /* An expression to be evaluated before the type specifier, in the
-     case of typeof specifiers, or NULL otherwise or if no such
-     expression is required for a particular typeof specifier.  In
-     particular, when typeof is applied to an expression of variably
-     modified type, that expression must be evaluated in order to
-     determine array sizes that form part of the type, but the
-     expression itself (as opposed to the array sizes) forms no part
-     of the type and so needs to be recorded separately.  */
-  tree expr;
-};
-
-/* A storage class specifier.  */
-enum c_storage_class {
-  csc_none,
-  csc_auto,
-  csc_extern,
-  csc_register,
-  csc_static,
-  csc_typedef
-};
-
-/* A type specifier keyword "void", "_Bool", "char", "int", "float",
-   "double", "_Decimal32", "_Decimal64", "_Decimal128", "_Fract", "_Accum",
-   or none of these.  */
-enum c_typespec_keyword {
-  cts_none,
-  cts_void,
-  cts_bool,
-  cts_char,
-  cts_int,
-  cts_float,
-  cts_int128,
-  cts_double,
-  cts_dfloat32,
-  cts_dfloat64,
-  cts_dfloat128,
-  cts_fract,
-  cts_accum
-};
-
-/* This enum lists all the possible declarator specifiers, storage
-   class or attribute that a user can write.  There is at least one
-   enumerator per possible declarator specifier in the struct
-   c_declspecs below.
-
-   It is used to index the array of declspec locations in struct
-   c_declspecs.  */
-enum c_declspec_word {
-  cdw_typespec /* A catch-all for a typespec.  */,
-  cdw_storage_class  /* A catch-all for a storage class */,
-  cdw_attributes,
-  cdw_typedef,
-  cdw_explicit_signed,
-  cdw_deprecated,
-  cdw_default_int,
-  cdw_long,
-  cdw_long_long,
-  cdw_short,
-  cdw_signed,
-  cdw_unsigned,
-  cdw_complex,
-  cdw_inline,
-  cdw_noreturn,
-  cdw_thread,
-  cdw_const,
-  cdw_volatile,
-  cdw_restrict,
-  cdw_saturating,
-  cdw_alignas,
-  cdw_address_space,
-  cdw_number_of_elements /* This one must always be the last
-                           enumerator.  */
-};
-
-/* A sequence of declaration specifiers in C.  When a new declaration
-   specifier is added, please update the enum c_declspec_word above
-   accordingly.  */
-struct c_declspecs {
-  source_location locations[cdw_number_of_elements];
-  /* The type specified, if a single type specifier such as a struct,
-     union or enum specifier, typedef name or typeof specifies the
-     whole type, or NULL_TREE if none or a keyword such as "void" or
-     "char" is used.  Does not include qualifiers.  */
-  tree type;
-  /* Any expression to be evaluated before the type, from a typeof
-     specifier.  */
-  tree expr;
-  /* The attributes from a typedef decl.  */
-  tree decl_attr;
-  /* When parsing, the attributes.  Outside the parser, this will be
-     NULL; attributes (possibly from multiple lists) will be passed
-     separately.  */
-  tree attrs;
-  /* The base-2 log of the greatest alignment required by an _Alignas
-     specifier, in bytes, or -1 if no such specifiers with nonzero
-     alignment.  */
-  int align_log;
-  /* The storage class specifier, or csc_none if none.  */
-  enum c_storage_class storage_class;
-  /* Any type specifier keyword used such as "int", not reflecting
-     modifiers such as "short", or cts_none if none.  */
-  ENUM_BITFIELD (c_typespec_keyword) typespec_word : 8;
-  /* The kind of type specifier if one has been seen, ctsk_none
-     otherwise.  */
-  ENUM_BITFIELD (c_typespec_kind) typespec_kind : 3;
-  /* Whether any expressions in typeof specifiers may appear in
-     constant expressions.  */
-  BOOL_BITFIELD expr_const_operands : 1;
-  /* Whether any declaration specifiers have been seen at all.  */
-  BOOL_BITFIELD declspecs_seen_p : 1;
-  /* Whether something other than a storage class specifier or
-     attribute has been seen.  This is used to warn for the
-     obsolescent usage of storage class specifiers other than at the
-     start of the list.  (Doing this properly would require function
-     specifiers to be handled separately from storage class
-     specifiers.)  */
-  BOOL_BITFIELD non_sc_seen_p : 1;
-  /* Whether the type is specified by a typedef or typeof name.  */
-  BOOL_BITFIELD typedef_p : 1;
-  /* Whether the type is explicitly "signed" or specified by a typedef
-     whose type is explicitly "signed".  */
-  BOOL_BITFIELD explicit_signed_p : 1;
-  /* Whether the specifiers include a deprecated typedef.  */
-  BOOL_BITFIELD deprecated_p : 1;
-  /* Whether the type defaulted to "int" because there were no type
-     specifiers.  */
-  BOOL_BITFIELD default_int_p : 1;
-  /* Whether "long" was specified.  */
-  BOOL_BITFIELD long_p : 1;
-  /* Whether "long" was specified more than once.  */
-  BOOL_BITFIELD long_long_p : 1;
-  /* Whether "short" was specified.  */
-  BOOL_BITFIELD short_p : 1;
-  /* Whether "signed" was specified.  */
-  BOOL_BITFIELD signed_p : 1;
-  /* Whether "unsigned" was specified.  */
-  BOOL_BITFIELD unsigned_p : 1;
-  /* Whether "complex" was specified.  */
-  BOOL_BITFIELD complex_p : 1;
-  /* Whether "inline" was specified.  */
-  BOOL_BITFIELD inline_p : 1;
-  /* Whether "_Noreturn" was speciied.  */
-  BOOL_BITFIELD noreturn_p : 1;
-  /* Whether "__thread" was specified.  */
-  BOOL_BITFIELD thread_p : 1;
-  /* Whether "const" was specified.  */
-  BOOL_BITFIELD const_p : 1;
-  /* Whether "volatile" was specified.  */
-  BOOL_BITFIELD volatile_p : 1;
-  /* Whether "restrict" was specified.  */
-  BOOL_BITFIELD restrict_p : 1;
-  /* Whether "_Sat" was specified.  */
-  BOOL_BITFIELD saturating_p : 1;
-  /* Whether any alignment specifier (even with zero alignment) was
-     specified.  */
-  BOOL_BITFIELD alignas_p : 1;
-  /* The address space that the declaration belongs to.  */
-  addr_space_t address_space;
-};
-
-/* The various kinds of declarators in C.  */
-enum c_declarator_kind {
-  /* An identifier.  */
-  cdk_id,
-  /* A function.  */
-  cdk_function,
-  /* An array.  */
-  cdk_array,
-  /* A pointer.  */
-  cdk_pointer,
-  /* Parenthesized declarator with nested attributes.  */
-  cdk_attrs
-};
-
-typedef struct c_arg_tag_d {
-  /* The argument name.  */
-  tree id;
-  /* The type of the argument.  */
-  tree type;
-} c_arg_tag;
-
-DEF_VEC_O(c_arg_tag);
-DEF_VEC_ALLOC_O(c_arg_tag,gc);
-
-/* Information about the parameters in a function declarator.  */
-struct c_arg_info {
-  /* A list of parameter decls.  */
-  tree parms;
-  /* A list of structure, union and enum tags defined.  */
-  VEC(c_arg_tag,gc) *tags;
-  /* A list of argument types to go in the FUNCTION_TYPE.  */
-  tree types;
-  /* A list of non-parameter decls (notably enumeration constants)
-     defined with the parameters.  */
-  tree others;
-  /* A compound expression of VLA sizes from the parameters, or NULL.
-     In a function definition, these are used to ensure that
-     side-effects in sizes of arrays converted to pointers (such as a
-     parameter int i[n++]) take place; otherwise, they are
-     ignored.  */
-  tree pending_sizes;
-  /* True when these arguments had [*].  */
-  BOOL_BITFIELD had_vla_unspec : 1;
-};
-
-/* A declarator.  */
-struct c_declarator {
-  /* The kind of declarator.  */
-  enum c_declarator_kind kind;
-  location_t id_loc; /* Currently only set for cdk_id, cdk_array. */
-  /* Except for cdk_id, the contained declarator.  For cdk_id, NULL.  */
-  struct c_declarator *declarator;
-  union {
-    /* For identifiers, an IDENTIFIER_NODE or NULL_TREE if an abstract
-       declarator.  */
-    tree id;
-    /* For functions.  */
-    struct c_arg_info *arg_info;
-    /* For arrays.  */
-    struct {
-      /* The array dimension, or NULL for [] and [*].  */
-      tree dimen;
-      /* The qualifiers inside [].  */
-      int quals;
-      /* The attributes (currently ignored) inside [].  */
-      tree attrs;
-      /* Whether [static] was used.  */
-      BOOL_BITFIELD static_p : 1;
-      /* Whether [*] was used.  */
-      BOOL_BITFIELD vla_unspec_p : 1;
-    } array;
-    /* For pointers, the qualifiers on the pointer type.  */
-    int pointer_quals;
-    /* For attributes.  */
-    tree attrs;
-  } u;
-};
-
-/* A type name.  */
-struct c_type_name {
-  /* The declaration specifiers.  */
-  struct c_declspecs *specs;
-  /* The declarator.  */
-  struct c_declarator *declarator;
-};
-
-/* A parameter.  */
-struct c_parm {
-  /* The declaration specifiers, minus any prefix attributes.  */
-  struct c_declspecs *specs;
-  /* The attributes.  */
-  tree attrs;
-  /* The declarator.  */
-  struct c_declarator *declarator;
-};
-
-/* Used when parsing an enum.  Initialized by start_enum.  */
-struct c_enum_contents
-{
-  /* While defining an enum type, this is 1 plus the last enumerator
-     constant value.  */
-  tree enum_next_value;
-
-  /* Nonzero means that there was overflow computing enum_next_value.  */
-  int enum_overflow;
-};
-
-/* A type of reference to a static identifier in an inline
-   function.  */
-enum c_inline_static_type {
-  /* Identifier with internal linkage used in function that may be an
-     inline definition (i.e., file-scope static).  */
-  csi_internal,
-  /* Modifiable object with static storage duration defined in
-     function that may be an inline definition (i.e., local
-     static).  */
-  csi_modifiable
-};
-
-\f
-/* in c-parser.c */
-extern void c_parse_init (void);
-
-/* in c-aux-info.c */
-extern void gen_aux_info_record (tree, int, int, int);
-
-/* in c-decl.c */
-struct c_spot_bindings;
-struct c_struct_parse_info;
-extern struct obstack parser_obstack;
-extern tree c_break_label;
-extern tree c_cont_label;
-
-extern bool global_bindings_p (void);
-extern void push_scope (void);
-extern tree pop_scope (void);
-extern void c_bindings_start_stmt_expr (struct c_spot_bindings *);
-extern void c_bindings_end_stmt_expr (struct c_spot_bindings *);
-
-extern void record_inline_static (location_t, tree, tree,
-                                 enum c_inline_static_type);
-extern void c_init_decl_processing (void);
-extern void c_print_identifier (FILE *, tree, int);
-extern int quals_from_declspecs (const struct c_declspecs *);
-extern struct c_declarator *build_array_declarator (location_t, tree,
-                                                   struct c_declspecs *,
-                                                   bool, bool);
-extern tree build_enumerator (location_t, location_t, struct c_enum_contents *,
-                             tree, tree);
-extern tree check_for_loop_decls (location_t, bool);
-extern void mark_forward_parm_decls (void);
-extern void declare_parm_level (void);
-extern void undeclared_variable (location_t, tree);
-extern tree lookup_label_for_goto (location_t, tree);
-extern tree declare_label (tree);
-extern tree define_label (location_t, tree);
-extern struct c_spot_bindings *c_get_switch_bindings (void);
-extern void c_release_switch_bindings (struct c_spot_bindings *);
-extern bool c_check_switch_jump_warnings (struct c_spot_bindings *,
-                                         location_t, location_t);
-extern void finish_decl (tree, location_t, tree, tree, tree);
-extern tree finish_enum (tree, tree, tree);
-extern void finish_function (void);
-extern tree finish_struct (location_t, tree, tree, tree,
-                          struct c_struct_parse_info *);
-extern struct c_arg_info *build_arg_info (void);
-extern struct c_arg_info *get_parm_info (bool, tree);
-extern tree grokfield (location_t, struct c_declarator *,
-                      struct c_declspecs *, tree, tree *);
-extern tree groktypename (struct c_type_name *, tree *, bool *);
-extern tree grokparm (const struct c_parm *, tree *);
-extern tree implicitly_declare (location_t, tree);
-extern void keep_next_level (void);
-extern void pending_xref_error (void);
-extern void c_push_function_context (void);
-extern void c_pop_function_context (void);
-extern void push_parm_decl (const struct c_parm *, tree *);
-extern struct c_declarator *set_array_declarator_inner (struct c_declarator *,
-                                                       struct c_declarator *);
-extern tree c_builtin_function (tree);
-extern tree c_builtin_function_ext_scope (tree);
-extern void shadow_tag (const struct c_declspecs *);
-extern void shadow_tag_warned (const struct c_declspecs *, int);
-extern tree start_enum (location_t, struct c_enum_contents *, tree);
-extern int  start_function (struct c_declspecs *, struct c_declarator *, tree);
-extern tree start_decl (struct c_declarator *, struct c_declspecs *, bool,
-                       tree);
-extern tree start_struct (location_t, enum tree_code, tree,
-                         struct c_struct_parse_info **);
-extern void store_parm_decls (void);
-extern void store_parm_decls_from (struct c_arg_info *);
-extern tree xref_tag (enum tree_code, tree);
-extern struct c_typespec parser_xref_tag (location_t, enum tree_code, tree);
-extern struct c_parm *build_c_parm (struct c_declspecs *, tree,
-                                   struct c_declarator *);
-extern struct c_declarator *build_attrs_declarator (tree,
-                                                   struct c_declarator *);
-extern struct c_declarator *build_function_declarator (struct c_arg_info *,
-                                                      struct c_declarator *);
-extern struct c_declarator *build_id_declarator (tree);
-extern struct c_declarator *make_pointer_declarator (struct c_declspecs *,
-                                                    struct c_declarator *);
-extern struct c_declspecs *build_null_declspecs (void);
-extern struct c_declspecs *declspecs_add_qual (source_location,
-                                              struct c_declspecs *, tree);
-extern struct c_declspecs *declspecs_add_type (location_t,
-                                              struct c_declspecs *,
-                                              struct c_typespec);
-extern struct c_declspecs *declspecs_add_scspec (source_location,
-                                                struct c_declspecs *, tree);
-extern struct c_declspecs *declspecs_add_attrs (source_location,
-                                               struct c_declspecs *, tree);
-extern struct c_declspecs *declspecs_add_addrspace (source_location,
-                                                   struct c_declspecs *,
-                                                   addr_space_t);
-extern struct c_declspecs *declspecs_add_alignas (source_location,
-                                                 struct c_declspecs *, tree);
-extern struct c_declspecs *finish_declspecs (struct c_declspecs *);
-
-/* in c-objc-common.c */
-extern bool c_objc_common_init (void);
-extern bool c_missing_noreturn_ok_p (tree);
-extern bool c_warn_unused_global_decl (const_tree);
-extern void c_initialize_diagnostics (diagnostic_context *);
-extern bool c_vla_unspec_p (tree x, tree fn);
-
-/* in c-typeck.c */
-extern int in_alignof;
-extern int in_sizeof;
-extern int in_typeof;
-
-extern struct c_switch *c_switch_stack;
-
-extern tree c_objc_common_truthvalue_conversion (location_t, tree);
-extern tree require_complete_type (tree);
-extern int same_translation_unit_p (const_tree, const_tree);
-extern int comptypes (tree, tree);
-extern int comptypes_check_different_types (tree, tree, bool *);
-extern bool c_vla_type_p (const_tree);
-extern bool c_mark_addressable (tree);
-extern void c_incomplete_type_error (const_tree, const_tree);
-extern tree c_type_promotes_to (tree);
-extern struct c_expr default_function_array_conversion (location_t,
-                                                       struct c_expr);
-extern struct c_expr default_function_array_read_conversion (location_t,
-                                                            struct c_expr);
-extern void mark_exp_read (tree);
-extern tree composite_type (tree, tree);
-extern tree build_component_ref (location_t, tree, tree);
-extern tree build_array_ref (location_t, tree, tree);
-extern tree build_external_ref (location_t, tree, int, tree *);
-extern void pop_maybe_used (bool);
-extern struct c_expr c_expr_sizeof_expr (location_t, struct c_expr);
-extern struct c_expr c_expr_sizeof_type (location_t, struct c_type_name *);
-extern struct c_expr parser_build_unary_op (location_t, enum tree_code,
-                                           struct c_expr);
-extern struct c_expr parser_build_binary_op (location_t,
-                                            enum tree_code, struct c_expr,
-                                            struct c_expr);
-extern tree build_conditional_expr (location_t, tree, bool, tree, tree,
-                                   tree, tree);
-extern tree build_compound_expr (location_t, tree, tree);
-extern tree c_cast_expr (location_t, struct c_type_name *, tree);
-extern tree build_c_cast (location_t, tree, tree);
-extern void store_init_value (location_t, tree, tree, tree);
-extern void error_init (const char *);
-extern void pedwarn_init (location_t, int opt, const char *);
-extern void maybe_warn_string_init (tree, struct c_expr);
-extern void start_init (tree, tree, int);
-extern void finish_init (void);
-extern void really_start_incremental_init (tree);
-extern void push_init_level (int, struct obstack *);
-extern struct c_expr pop_init_level (int, struct obstack *);
-extern void set_init_index (tree, tree, struct obstack *);
-extern void set_init_label (tree, struct obstack *);
-extern void process_init_element (struct c_expr, bool, struct obstack *);
-extern tree build_compound_literal (location_t, tree, tree, bool);
-extern void check_compound_literal_type (location_t, struct c_type_name *);
-extern tree c_start_case (location_t, location_t, tree);
-extern void c_finish_case (tree);
-extern tree build_asm_expr (location_t, tree, tree, tree, tree, tree, bool);
-extern tree build_asm_stmt (tree, tree);
-extern int c_types_compatible_p (tree, tree);
-extern tree c_begin_compound_stmt (bool);
-extern tree c_end_compound_stmt (location_t, tree, bool);
-extern void c_finish_if_stmt (location_t, tree, tree, tree, bool);
-extern void c_finish_loop (location_t, tree, tree, tree, tree, tree, bool);
-extern tree c_begin_stmt_expr (void);
-extern tree c_finish_stmt_expr (location_t, tree);
-extern tree c_process_expr_stmt (location_t, tree);
-extern tree c_finish_expr_stmt (location_t, tree);
-extern tree c_finish_return (location_t, tree, tree);
-extern tree c_finish_bc_stmt (location_t, tree *, bool);
-extern tree c_finish_goto_label (location_t, tree);
-extern tree c_finish_goto_ptr (location_t, tree);
-extern tree c_expr_to_decl (tree, bool *, bool *);
-extern tree c_begin_omp_parallel (void);
-extern tree c_finish_omp_parallel (location_t, tree, tree);
-extern tree c_begin_omp_task (void);
-extern tree c_finish_omp_task (location_t, tree, tree);
-extern tree c_finish_omp_clauses (tree);
-extern tree c_build_va_arg (location_t, tree, tree);
-extern tree c_finish_transaction (location_t, tree, int);
-
-/* Set to 0 at beginning of a function definition, set to 1 if
-   a return statement that specifies a return value is seen.  */
-
-extern int current_function_returns_value;
-
-/* Set to 0 at beginning of a function definition, set to 1 if
-   a return statement with no argument is seen.  */
-
-extern int current_function_returns_null;
-
-/* Set to 0 at beginning of a function definition, set to 1 if
-   a call to a noreturn function is seen.  */
-
-extern int current_function_returns_abnormally;
-
-/* Mode used to build pointers (VOIDmode means ptr_mode).  */
-
-extern enum machine_mode c_default_pointer_mode;
-
-/* In c-decl.c */
-extern void c_finish_incomplete_decl (tree);
-extern void c_write_global_declarations (void);
-
-/* In c-errors.c */
-extern void pedwarn_c90 (location_t, int opt, const char *, ...) ATTRIBUTE_GCC_DIAG(3,4);
-extern void pedwarn_c99 (location_t, int opt, const char *, ...) ATTRIBUTE_GCC_DIAG(3,4);
-
-#endif /* ! GCC_C_TREE_H */
diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c
deleted file mode 100644 (file)
index c2f713e..0000000
+++ /dev/null
@@ -1,10939 +0,0 @@
-/* Build expressions with type checking for C compiler.
-   Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 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 file is part of the C front end.
-   It contains routines to build C expressions given their operands,
-   including computing the types of the result, C-specific error checks,
-   and some optimization.  */
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "tm.h"
-#include "tree.h"
-#include "langhooks.h"
-#include "c-tree.h"
-#include "c-lang.h"
-#include "flags.h"
-#include "intl.h"
-#include "target.h"
-#include "tree-iterator.h"
-#include "bitmap.h"
-#include "gimple.h"
-#include "c-family/c-objc.h"
-
-/* Possible cases of implicit bad conversions.  Used to select
-   diagnostic messages in convert_for_assignment.  */
-enum impl_conv {
-  ic_argpass,
-  ic_assign,
-  ic_init,
-  ic_return
-};
-
-/* Possibe cases of scalar_to_vector conversion.  */
-enum stv_conv {
-  stv_error,        /* Error occured.  */
-  stv_nothing,      /* Nothing happened.  */
-  stv_firstarg,     /* First argument must be expanded.  */
-  stv_secondarg     /* Second argument must be expanded.  */
-};
-
-/* The level of nesting inside "__alignof__".  */
-int in_alignof;
-
-/* The level of nesting inside "sizeof".  */
-int in_sizeof;
-
-/* The level of nesting inside "typeof".  */
-int in_typeof;
-
-/* Nonzero if we've already printed a "missing braces around initializer"
-   message within this initializer.  */
-static int missing_braces_mentioned;
-
-static int require_constant_value;
-static int require_constant_elements;
-
-static bool null_pointer_constant_p (const_tree);
-static tree qualify_type (tree, tree);
-static int tagged_types_tu_compatible_p (const_tree, const_tree, bool *,
-                                        bool *);
-static int comp_target_types (location_t, tree, tree);
-static int function_types_compatible_p (const_tree, const_tree, bool *,
-                                       bool *);
-static int type_lists_compatible_p (const_tree, const_tree, bool *, bool *);
-static tree lookup_field (tree, tree);
-static int convert_arguments (tree, VEC(tree,gc) *, VEC(tree,gc) *, tree,
-                             tree);
-static tree pointer_diff (location_t, tree, tree);
-static tree convert_for_assignment (location_t, tree, tree, tree,
-                                   enum impl_conv, bool, tree, tree, int);
-static tree valid_compound_expr_initializer (tree, tree);
-static void push_string (const char *);
-static void push_member_name (tree);
-static int spelling_length (void);
-static char *print_spelling (char *);
-static void warning_init (int, const char *);
-static tree digest_init (location_t, tree, tree, tree, bool, bool, int);
-static void output_init_element (tree, tree, bool, tree, tree, int, bool,
-                                struct obstack *);
-static void output_pending_init_elements (int, struct obstack *);
-static int set_designator (int, struct obstack *);
-static void push_range_stack (tree, struct obstack *);
-static void add_pending_init (tree, tree, tree, bool, struct obstack *);
-static void set_nonincremental_init (struct obstack *);
-static void set_nonincremental_init_from_string (tree, struct obstack *);
-static tree find_init_member (tree, struct obstack *);
-static void readonly_warning (tree, enum lvalue_use);
-static int lvalue_or_else (location_t, const_tree, enum lvalue_use);
-static void record_maybe_used_decl (tree);
-static int comptypes_internal (const_tree, const_tree, bool *, bool *);
-\f
-/* Return true if EXP is a null pointer constant, false otherwise.  */
-
-static bool
-null_pointer_constant_p (const_tree expr)
-{
-  /* This should really operate on c_expr structures, but they aren't
-     yet available everywhere required.  */
-  tree type = TREE_TYPE (expr);
-  return (TREE_CODE (expr) == INTEGER_CST
-         && !TREE_OVERFLOW (expr)
-         && integer_zerop (expr)
-         && (INTEGRAL_TYPE_P (type)
-             || (TREE_CODE (type) == POINTER_TYPE
-                 && VOID_TYPE_P (TREE_TYPE (type))
-                 && TYPE_QUALS (TREE_TYPE (type)) == TYPE_UNQUALIFIED)));
-}
-
-/* EXPR may appear in an unevaluated part of an integer constant
-   expression, but not in an evaluated part.  Wrap it in a
-   C_MAYBE_CONST_EXPR, or mark it with TREE_OVERFLOW if it is just an
-   INTEGER_CST and we cannot create a C_MAYBE_CONST_EXPR.  */
-
-static tree
-note_integer_operands (tree expr)
-{
-  tree ret;
-  if (TREE_CODE (expr) == INTEGER_CST && in_late_binary_op)
-    {
-      ret = copy_node (expr);
-      TREE_OVERFLOW (ret) = 1;
-    }
-  else
-    {
-      ret = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (expr), NULL_TREE, expr);
-      C_MAYBE_CONST_EXPR_INT_OPERANDS (ret) = 1;
-    }
-  return ret;
-}
-
-/* Having checked whether EXPR may appear in an unevaluated part of an
-   integer constant expression and found that it may, remove any
-   C_MAYBE_CONST_EXPR noting this fact and return the resulting
-   expression.  */
-
-static inline tree
-remove_c_maybe_const_expr (tree expr)
-{
-  if (TREE_CODE (expr) == C_MAYBE_CONST_EXPR)
-    return C_MAYBE_CONST_EXPR_EXPR (expr);
-  else
-    return expr;
-}
-
-\f/* This is a cache to hold if two types are compatible or not.  */
-
-struct tagged_tu_seen_cache {
-  const struct tagged_tu_seen_cache * next;
-  const_tree t1;
-  const_tree t2;
-  /* The return value of tagged_types_tu_compatible_p if we had seen
-     these two types already.  */
-  int val;
-};
-
-static const struct tagged_tu_seen_cache * tagged_tu_seen_base;
-static void free_all_tagged_tu_seen_up_to (const struct tagged_tu_seen_cache *);
-
-/* Do `exp = require_complete_type (exp);' to make sure exp
-   does not have an incomplete type.  (That includes void types.)  */
-
-tree
-require_complete_type (tree value)
-{
-  tree type = TREE_TYPE (value);
-
-  if (value == error_mark_node || type == error_mark_node)
-    return error_mark_node;
-
-  /* First, detect a valid value with a complete type.  */
-  if (COMPLETE_TYPE_P (type))
-    return value;
-
-  c_incomplete_type_error (value, type);
-  return error_mark_node;
-}
-
-/* Print an error message for invalid use of an incomplete type.
-   VALUE is the expression that was used (or 0 if that isn't known)
-   and TYPE is the type that was invalid.  */
-
-void
-c_incomplete_type_error (const_tree value, const_tree type)
-{
-  const char *type_code_string;
-
-  /* Avoid duplicate error message.  */
-  if (TREE_CODE (type) == ERROR_MARK)
-    return;
-
-  if (value != 0 && (TREE_CODE (value) == VAR_DECL
-                    || TREE_CODE (value) == PARM_DECL))
-    error ("%qD has an incomplete type", value);
-  else
-    {
-    retry:
-      /* We must print an error message.  Be clever about what it says.  */
-
-      switch (TREE_CODE (type))
-       {
-       case RECORD_TYPE:
-         type_code_string = "struct";
-         break;
-
-       case UNION_TYPE:
-         type_code_string = "union";
-         break;
-
-       case ENUMERAL_TYPE:
-         type_code_string = "enum";
-         break;
-
-       case VOID_TYPE:
-         error ("invalid use of void expression");
-         return;
-
-       case ARRAY_TYPE:
-         if (TYPE_DOMAIN (type))
-           {
-             if (TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL)
-               {
-                 error ("invalid use of flexible array member");
-                 return;
-               }
-             type = TREE_TYPE (type);
-             goto retry;
-           }
-         error ("invalid use of array with unspecified bounds");
-         return;
-
-       default:
-         gcc_unreachable ();
-       }
-
-      if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
-       error ("invalid use of undefined type %<%s %E%>",
-              type_code_string, TYPE_NAME (type));
-      else
-       /* If this type has a typedef-name, the TYPE_NAME is a TYPE_DECL.  */
-       error ("invalid use of incomplete typedef %qD", TYPE_NAME (type));
-    }
-}
-
-/* Given a type, apply default promotions wrt unnamed function
-   arguments and return the new type.  */
-
-tree
-c_type_promotes_to (tree type)
-{
-  if (TYPE_MAIN_VARIANT (type) == float_type_node)
-    return double_type_node;
-
-  if (c_promoting_integer_type_p (type))
-    {
-      /* Preserve unsignedness if not really getting any wider.  */
-      if (TYPE_UNSIGNED (type)
-         && (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node)))
-       return unsigned_type_node;
-      return integer_type_node;
-    }
-
-  return type;
-}
-
-/* Return true if between two named address spaces, whether there is a superset
-   named address space that encompasses both address spaces.  If there is a
-   superset, return which address space is the superset.  */
-
-static bool
-addr_space_superset (addr_space_t as1, addr_space_t as2, addr_space_t *common)
-{
-  if (as1 == as2)
-    {
-      *common = as1;
-      return true;
-    }
-  else if (targetm.addr_space.subset_p (as1, as2))
-    {
-      *common = as2;
-      return true;
-    }
-  else if (targetm.addr_space.subset_p (as2, as1))
-    {
-      *common = as1;
-      return true;
-    }
-  else
-    return false;
-}
-
-/* Return a variant of TYPE which has all the type qualifiers of LIKE
-   as well as those of TYPE.  */
-
-static tree
-qualify_type (tree type, tree like)
-{
-  addr_space_t as_type = TYPE_ADDR_SPACE (type);
-  addr_space_t as_like = TYPE_ADDR_SPACE (like);
-  addr_space_t as_common;
-
-  /* If the two named address spaces are different, determine the common
-     superset address space.  If there isn't one, raise an error.  */
-  if (!addr_space_superset (as_type, as_like, &as_common))
-    {
-      as_common = as_type;
-      error ("%qT and %qT are in disjoint named address spaces",
-            type, like);
-    }
-
-  return c_build_qualified_type (type,
-                                TYPE_QUALS_NO_ADDR_SPACE (type)
-                                | TYPE_QUALS_NO_ADDR_SPACE (like)
-                                | ENCODE_QUAL_ADDR_SPACE (as_common));
-}
-
-/* Return true iff the given tree T is a variable length array.  */
-
-bool
-c_vla_type_p (const_tree t)
-{
-  if (TREE_CODE (t) == ARRAY_TYPE
-      && C_TYPE_VARIABLE_SIZE (t))
-    return true;
-  return false;
-}
-\f
-/* Return the composite type of two compatible types.
-
-   We assume that comptypes has already been done and returned
-   nonzero; if that isn't so, this may crash.  In particular, we
-   assume that qualifiers match.  */
-
-tree
-composite_type (tree t1, tree t2)
-{
-  enum tree_code code1;
-  enum tree_code code2;
-  tree attributes;
-
-  /* Save time if the two types are the same.  */
-
-  if (t1 == t2) return t1;
-
-  /* If one type is nonsense, use the other.  */
-  if (t1 == error_mark_node)
-    return t2;
-  if (t2 == error_mark_node)
-    return t1;
-
-  code1 = TREE_CODE (t1);
-  code2 = TREE_CODE (t2);
-
-  /* Merge the attributes.  */
-  attributes = targetm.merge_type_attributes (t1, t2);
-
-  /* If one is an enumerated type and the other is the compatible
-     integer type, the composite type might be either of the two
-     (DR#013 question 3).  For consistency, use the enumerated type as
-     the composite type.  */
-
-  if (code1 == ENUMERAL_TYPE && code2 == INTEGER_TYPE)
-    return t1;
-  if (code2 == ENUMERAL_TYPE && code1 == INTEGER_TYPE)
-    return t2;
-
-  gcc_assert (code1 == code2);
-
-  switch (code1)
-    {
-    case POINTER_TYPE:
-      /* For two pointers, do this recursively on the target type.  */
-      {
-       tree pointed_to_1 = TREE_TYPE (t1);
-       tree pointed_to_2 = TREE_TYPE (t2);
-       tree target = composite_type (pointed_to_1, pointed_to_2);
-        t1 = build_pointer_type_for_mode (target, TYPE_MODE (t1), false);
-       t1 = build_type_attribute_variant (t1, attributes);
-       return qualify_type (t1, t2);
-      }
-
-    case ARRAY_TYPE:
-      {
-       tree elt = composite_type (TREE_TYPE (t1), TREE_TYPE (t2));
-       int quals;
-       tree unqual_elt;
-       tree d1 = TYPE_DOMAIN (t1);
-       tree d2 = TYPE_DOMAIN (t2);
-       bool d1_variable, d2_variable;
-       bool d1_zero, d2_zero;
-       bool t1_complete, t2_complete;
-
-       /* We should not have any type quals on arrays at all.  */
-       gcc_assert (!TYPE_QUALS_NO_ADDR_SPACE (t1)
-                   && !TYPE_QUALS_NO_ADDR_SPACE (t2));
-
-       t1_complete = COMPLETE_TYPE_P (t1);
-       t2_complete = COMPLETE_TYPE_P (t2);
-
-       d1_zero = d1 == 0 || !TYPE_MAX_VALUE (d1);
-       d2_zero = d2 == 0 || !TYPE_MAX_VALUE (d2);
-
-       d1_variable = (!d1_zero
-                      && (TREE_CODE (TYPE_MIN_VALUE (d1)) != INTEGER_CST
-                          || TREE_CODE (TYPE_MAX_VALUE (d1)) != INTEGER_CST));
-       d2_variable = (!d2_zero
-                      && (TREE_CODE (TYPE_MIN_VALUE (d2)) != INTEGER_CST
-                          || TREE_CODE (TYPE_MAX_VALUE (d2)) != INTEGER_CST));
-       d1_variable = d1_variable || (d1_zero && c_vla_type_p (t1));
-       d2_variable = d2_variable || (d2_zero && c_vla_type_p (t2));
-
-       /* Save space: see if the result is identical to one of the args.  */
-       if (elt == TREE_TYPE (t1) && TYPE_DOMAIN (t1)
-           && (d2_variable || d2_zero || !d1_variable))
-         return build_type_attribute_variant (t1, attributes);
-       if (elt == TREE_TYPE (t2) && TYPE_DOMAIN (t2)
-           && (d1_variable || d1_zero || !d2_variable))
-         return build_type_attribute_variant (t2, attributes);
-
-       if (elt == TREE_TYPE (t1) && !TYPE_DOMAIN (t2) && !TYPE_DOMAIN (t1))
-         return build_type_attribute_variant (t1, attributes);
-       if (elt == TREE_TYPE (t2) && !TYPE_DOMAIN (t2) && !TYPE_DOMAIN (t1))
-         return build_type_attribute_variant (t2, attributes);
-
-       /* Merge the element types, and have a size if either arg has
-          one.  We may have qualifiers on the element types.  To set
-          up TYPE_MAIN_VARIANT correctly, we need to form the
-          composite of the unqualified types and add the qualifiers
-          back at the end.  */
-       quals = TYPE_QUALS (strip_array_types (elt));
-       unqual_elt = c_build_qualified_type (elt, TYPE_UNQUALIFIED);
-       t1 = build_array_type (unqual_elt,
-                              TYPE_DOMAIN ((TYPE_DOMAIN (t1)
-                                            && (d2_variable
-                                                || d2_zero
-                                                || !d1_variable))
-                                           ? t1
-                                           : t2));
-       /* Ensure a composite type involving a zero-length array type
-          is a zero-length type not an incomplete type.  */
-       if (d1_zero && d2_zero
-           && (t1_complete || t2_complete)
-           && !COMPLETE_TYPE_P (t1))
-         {
-           TYPE_SIZE (t1) = bitsize_zero_node;
-           TYPE_SIZE_UNIT (t1) = size_zero_node;
-         }
-       t1 = c_build_qualified_type (t1, quals);
-       return build_type_attribute_variant (t1, attributes);
-      }
-
-    case ENUMERAL_TYPE:
-    case RECORD_TYPE:
-    case UNION_TYPE:
-      if (attributes != NULL)
-       {
-         /* Try harder not to create a new aggregate type.  */
-         if (attribute_list_equal (TYPE_ATTRIBUTES (t1), attributes))
-           return t1;
-         if (attribute_list_equal (TYPE_ATTRIBUTES (t2), attributes))
-           return t2;
-       }
-      return build_type_attribute_variant (t1, attributes);
-
-    case FUNCTION_TYPE:
-      /* Function types: prefer the one that specified arg types.
-        If both do, merge the arg types.  Also merge the return types.  */
-      {
-       tree valtype = composite_type (TREE_TYPE (t1), TREE_TYPE (t2));
-       tree p1 = TYPE_ARG_TYPES (t1);
-       tree p2 = TYPE_ARG_TYPES (t2);
-       int len;
-       tree newargs, n;
-       int i;
-
-       /* Save space: see if the result is identical to one of the args.  */
-       if (valtype == TREE_TYPE (t1) && !TYPE_ARG_TYPES (t2))
-         return build_type_attribute_variant (t1, attributes);
-       if (valtype == TREE_TYPE (t2) && !TYPE_ARG_TYPES (t1))
-         return build_type_attribute_variant (t2, attributes);
-
-       /* Simple way if one arg fails to specify argument types.  */
-       if (TYPE_ARG_TYPES (t1) == 0)
-        {
-           t1 = build_function_type (valtype, TYPE_ARG_TYPES (t2));
-           t1 = build_type_attribute_variant (t1, attributes);
-           return qualify_type (t1, t2);
-        }
-       if (TYPE_ARG_TYPES (t2) == 0)
-        {
-          t1 = build_function_type (valtype, TYPE_ARG_TYPES (t1));
-          t1 = build_type_attribute_variant (t1, attributes);
-          return qualify_type (t1, t2);
-        }
-
-       /* If both args specify argument types, we must merge the two
-          lists, argument by argument.  */
-
-       len = list_length (p1);
-       newargs = 0;
-
-       for (i = 0; i < len; i++)
-         newargs = tree_cons (NULL_TREE, NULL_TREE, newargs);
-
-       n = newargs;
-
-       for (; p1;
-            p1 = TREE_CHAIN (p1), p2 = TREE_CHAIN (p2), n = TREE_CHAIN (n))
-         {
-           /* A null type means arg type is not specified.
-              Take whatever the other function type has.  */
-           if (TREE_VALUE (p1) == 0)
-             {
-               TREE_VALUE (n) = TREE_VALUE (p2);
-               goto parm_done;
-             }
-           if (TREE_VALUE (p2) == 0)
-             {
-               TREE_VALUE (n) = TREE_VALUE (p1);
-               goto parm_done;
-             }
-
-           /* Given  wait (union {union wait *u; int *i} *)
-              and  wait (union wait *),
-              prefer  union wait *  as type of parm.  */
-           if (TREE_CODE (TREE_VALUE (p1)) == UNION_TYPE
-               && TREE_VALUE (p1) != TREE_VALUE (p2))
-             {
-               tree memb;
-               tree mv2 = TREE_VALUE (p2);
-               if (mv2 && mv2 != error_mark_node
-                   && TREE_CODE (mv2) != ARRAY_TYPE)
-                 mv2 = TYPE_MAIN_VARIANT (mv2);
-               for (memb = TYPE_FIELDS (TREE_VALUE (p1));
-                    memb; memb = DECL_CHAIN (memb))
-                 {
-                   tree mv3 = TREE_TYPE (memb);
-                   if (mv3 && mv3 != error_mark_node
-                       && TREE_CODE (mv3) != ARRAY_TYPE)
-                     mv3 = TYPE_MAIN_VARIANT (mv3);
-                   if (comptypes (mv3, mv2))
-                     {
-                       TREE_VALUE (n) = composite_type (TREE_TYPE (memb),
-                                                        TREE_VALUE (p2));
-                       pedwarn (input_location, OPT_Wpedantic,
-                                "function types not truly compatible in ISO C");
-                       goto parm_done;
-                     }
-                 }
-             }
-           if (TREE_CODE (TREE_VALUE (p2)) == UNION_TYPE
-               && TREE_VALUE (p2) != TREE_VALUE (p1))
-             {
-               tree memb;
-               tree mv1 = TREE_VALUE (p1);
-               if (mv1 && mv1 != error_mark_node
-                   && TREE_CODE (mv1) != ARRAY_TYPE)
-                 mv1 = TYPE_MAIN_VARIANT (mv1);
-               for (memb = TYPE_FIELDS (TREE_VALUE (p2));
-                    memb; memb = DECL_CHAIN (memb))
-                 {
-                   tree mv3 = TREE_TYPE (memb);
-                   if (mv3 && mv3 != error_mark_node
-                       && TREE_CODE (mv3) != ARRAY_TYPE)
-                     mv3 = TYPE_MAIN_VARIANT (mv3);
-                   if (comptypes (mv3, mv1))
-                     {
-                       TREE_VALUE (n) = composite_type (TREE_TYPE (memb),
-                                                        TREE_VALUE (p1));
-                       pedwarn (input_location, OPT_Wpedantic,
-                                "function types not truly compatible in ISO C");
-                       goto parm_done;
-                     }
-                 }
-             }
-           TREE_VALUE (n) = composite_type (TREE_VALUE (p1), TREE_VALUE (p2));
-         parm_done: ;
-         }
-
-       t1 = build_function_type (valtype, newargs);
-       t1 = qualify_type (t1, t2);
-       /* ... falls through ...  */
-      }
-
-    default:
-      return build_type_attribute_variant (t1, attributes);
-    }
-
-}
-
-/* Return the type of a conditional expression between pointers to
-   possibly differently qualified versions of compatible types.
-
-   We assume that comp_target_types has already been done and returned
-   nonzero; if that isn't so, this may crash.  */
-
-static tree
-common_pointer_type (tree t1, tree t2)
-{
-  tree attributes;
-  tree pointed_to_1, mv1;
-  tree pointed_to_2, mv2;
-  tree target;
-  unsigned target_quals;
-  addr_space_t as1, as2, as_common;
-  int quals1, quals2;
-
-  /* Save time if the two types are the same.  */
-
-  if (t1 == t2) return t1;
-
-  /* If one type is nonsense, use the other.  */
-  if (t1 == error_mark_node)
-    return t2;
-  if (t2 == error_mark_node)
-    return t1;
-
-  gcc_assert (TREE_CODE (t1) == POINTER_TYPE
-             && TREE_CODE (t2) == POINTER_TYPE);
-
-  /* Merge the attributes.  */
-  attributes = targetm.merge_type_attributes (t1, t2);
-
-  /* Find the composite type of the target types, and combine the
-     qualifiers of the two types' targets.  Do not lose qualifiers on
-     array element types by taking the TYPE_MAIN_VARIANT.  */
-  mv1 = pointed_to_1 = TREE_TYPE (t1);
-  mv2 = pointed_to_2 = TREE_TYPE (t2);
-  if (TREE_CODE (mv1) != ARRAY_TYPE)
-    mv1 = TYPE_MAIN_VARIANT (pointed_to_1);
-  if (TREE_CODE (mv2) != ARRAY_TYPE)
-    mv2 = TYPE_MAIN_VARIANT (pointed_to_2);
-  target = composite_type (mv1, mv2);
-
-  /* For function types do not merge const qualifiers, but drop them
-     if used inconsistently.  The middle-end uses these to mark const
-     and noreturn functions.  */
-  quals1 = TYPE_QUALS_NO_ADDR_SPACE (pointed_to_1);
-  quals2 = TYPE_QUALS_NO_ADDR_SPACE (pointed_to_2);
-
-  if (TREE_CODE (pointed_to_1) == FUNCTION_TYPE)
-    target_quals = (quals1 & quals2);
-  else
-    target_quals = (quals1 | quals2);
-
-  /* If the two named address spaces are different, determine the common
-     superset address space.  This is guaranteed to exist due to the
-     assumption that comp_target_type returned non-zero.  */
-  as1 = TYPE_ADDR_SPACE (pointed_to_1);
-  as2 = TYPE_ADDR_SPACE (pointed_to_2);
-  if (!addr_space_superset (as1, as2, &as_common))
-    gcc_unreachable ();
-
-  target_quals |= ENCODE_QUAL_ADDR_SPACE (as_common);
-
-  t1 = build_pointer_type (c_build_qualified_type (target, target_quals));
-  return build_type_attribute_variant (t1, attributes);
-}
-
-/* Return the common type for two arithmetic types under the usual
-   arithmetic conversions.  The default conversions have already been
-   applied, and enumerated types converted to their compatible integer
-   types.  The resulting type is unqualified and has no attributes.
-
-   This is the type for the result of most arithmetic operations
-   if the operands have the given two types.  */
-
-static tree
-c_common_type (tree t1, tree t2)
-{
-  enum tree_code code1;
-  enum tree_code code2;
-
-  /* If one type is nonsense, use the other.  */
-  if (t1 == error_mark_node)
-    return t2;
-  if (t2 == error_mark_node)
-    return t1;
-
-  if (TYPE_QUALS (t1) != TYPE_UNQUALIFIED)
-    t1 = TYPE_MAIN_VARIANT (t1);
-
-  if (TYPE_QUALS (t2) != TYPE_UNQUALIFIED)
-    t2 = TYPE_MAIN_VARIANT (t2);
-
-  if (TYPE_ATTRIBUTES (t1) != NULL_TREE)
-    t1 = build_type_attribute_variant (t1, NULL_TREE);
-
-  if (TYPE_ATTRIBUTES (t2) != NULL_TREE)
-    t2 = build_type_attribute_variant (t2, NULL_TREE);
-
-  /* Save time if the two types are the same.  */
-
-  if (t1 == t2) return t1;
-
-  code1 = TREE_CODE (t1);
-  code2 = TREE_CODE (t2);
-
-  gcc_assert (code1 == VECTOR_TYPE || code1 == COMPLEX_TYPE
-             || code1 == FIXED_POINT_TYPE || code1 == REAL_TYPE
-             || code1 == INTEGER_TYPE);
-  gcc_assert (code2 == VECTOR_TYPE || code2 == COMPLEX_TYPE
-             || code2 == FIXED_POINT_TYPE || code2 == REAL_TYPE
-             || code2 == INTEGER_TYPE);
-
-  /* When one operand is a decimal float type, the other operand cannot be
-     a generic float type or a complex type.  We also disallow vector types
-     here.  */
-  if ((DECIMAL_FLOAT_TYPE_P (t1) || DECIMAL_FLOAT_TYPE_P (t2))
-      && !(DECIMAL_FLOAT_TYPE_P (t1) && DECIMAL_FLOAT_TYPE_P (t2)))
-    {
-      if (code1 == VECTOR_TYPE || code2 == VECTOR_TYPE)
-       {
-         error ("can%'t mix operands of decimal float and vector types");
-         return error_mark_node;
-       }
-      if (code1 == COMPLEX_TYPE || code2 == COMPLEX_TYPE)
-       {
-         error ("can%'t mix operands of decimal float and complex types");
-         return error_mark_node;
-       }
-      if (code1 == REAL_TYPE && code2 == REAL_TYPE)
-       {
-         error ("can%'t mix operands of decimal float and other float types");
-         return error_mark_node;
-       }
-    }
-
-  /* If one type is a vector type, return that type.  (How the usual
-     arithmetic conversions apply to the vector types extension is not
-     precisely specified.)  */
-  if (code1 == VECTOR_TYPE)
-    return t1;
-
-  if (code2 == VECTOR_TYPE)
-    return t2;
-
-  /* If one type is complex, form the common type of the non-complex
-     components, then make that complex.  Use T1 or T2 if it is the
-     required type.  */
-  if (code1 == COMPLEX_TYPE || code2 == COMPLEX_TYPE)
-    {
-      tree subtype1 = code1 == COMPLEX_TYPE ? TREE_TYPE (t1) : t1;
-      tree subtype2 = code2 == COMPLEX_TYPE ? TREE_TYPE (t2) : t2;
-      tree subtype = c_common_type (subtype1, subtype2);
-
-      if (code1 == COMPLEX_TYPE && TREE_TYPE (t1) == subtype)
-       return t1;
-      else if (code2 == COMPLEX_TYPE && TREE_TYPE (t2) == subtype)
-       return t2;
-      else
-       return build_complex_type (subtype);
-    }
-
-  /* If only one is real, use it as the result.  */
-
-  if (code1 == REAL_TYPE && code2 != REAL_TYPE)
-    return t1;
-
-  if (code2 == REAL_TYPE && code1 != REAL_TYPE)
-    return t2;
-
-  /* If both are real and either are decimal floating point types, use
-     the decimal floating point type with the greater precision. */
-
-  if (code1 == REAL_TYPE && code2 == REAL_TYPE)
-    {
-      if (TYPE_MAIN_VARIANT (t1) == dfloat128_type_node
-         || TYPE_MAIN_VARIANT (t2) == dfloat128_type_node)
-       return dfloat128_type_node;
-      else if (TYPE_MAIN_VARIANT (t1) == dfloat64_type_node
-              || TYPE_MAIN_VARIANT (t2) == dfloat64_type_node)
-       return dfloat64_type_node;
-      else if (TYPE_MAIN_VARIANT (t1) == dfloat32_type_node
-              || TYPE_MAIN_VARIANT (t2) == dfloat32_type_node)
-       return dfloat32_type_node;
-    }
-
-  /* Deal with fixed-point types.  */
-  if (code1 == FIXED_POINT_TYPE || code2 == FIXED_POINT_TYPE)
-    {
-      unsigned int unsignedp = 0, satp = 0;
-      enum machine_mode m1, m2;
-      unsigned int fbit1, ibit1, fbit2, ibit2, max_fbit, max_ibit;
-
-      m1 = TYPE_MODE (t1);
-      m2 = TYPE_MODE (t2);
-
-      /* If one input type is saturating, the result type is saturating.  */
-      if (TYPE_SATURATING (t1) || TYPE_SATURATING (t2))
-       satp = 1;
-
-      /* If both fixed-point types are unsigned, the result type is unsigned.
-        When mixing fixed-point and integer types, follow the sign of the
-        fixed-point type.
-        Otherwise, the result type is signed.  */
-      if ((TYPE_UNSIGNED (t1) && TYPE_UNSIGNED (t2)
-          && code1 == FIXED_POINT_TYPE && code2 == FIXED_POINT_TYPE)
-         || (code1 == FIXED_POINT_TYPE && code2 != FIXED_POINT_TYPE
-             && TYPE_UNSIGNED (t1))
-         || (code1 != FIXED_POINT_TYPE && code2 == FIXED_POINT_TYPE
-             && TYPE_UNSIGNED (t2)))
-       unsignedp = 1;
-
-      /* The result type is signed.  */
-      if (unsignedp == 0)
-       {
-         /* If the input type is unsigned, we need to convert to the
-            signed type.  */
-         if (code1 == FIXED_POINT_TYPE && TYPE_UNSIGNED (t1))
-           {
-             enum mode_class mclass = (enum mode_class) 0;
-             if (GET_MODE_CLASS (m1) == MODE_UFRACT)
-               mclass = MODE_FRACT;
-             else if (GET_MODE_CLASS (m1) == MODE_UACCUM)
-               mclass = MODE_ACCUM;
-             else
-               gcc_unreachable ();
-             m1 = mode_for_size (GET_MODE_PRECISION (m1), mclass, 0);
-           }
-         if (code2 == FIXED_POINT_TYPE && TYPE_UNSIGNED (t2))
-           {
-             enum mode_class mclass = (enum mode_class) 0;
-             if (GET_MODE_CLASS (m2) == MODE_UFRACT)
-               mclass = MODE_FRACT;
-             else if (GET_MODE_CLASS (m2) == MODE_UACCUM)
-               mclass = MODE_ACCUM;
-             else
-               gcc_unreachable ();
-             m2 = mode_for_size (GET_MODE_PRECISION (m2), mclass, 0);
-           }
-       }
-
-      if (code1 == FIXED_POINT_TYPE)
-       {
-         fbit1 = GET_MODE_FBIT (m1);
-         ibit1 = GET_MODE_IBIT (m1);
-       }
-      else
-       {
-         fbit1 = 0;
-         /* Signed integers need to subtract one sign bit.  */
-         ibit1 = TYPE_PRECISION (t1) - (!TYPE_UNSIGNED (t1));
-       }
-
-      if (code2 == FIXED_POINT_TYPE)
-       {
-         fbit2 = GET_MODE_FBIT (m2);
-         ibit2 = GET_MODE_IBIT (m2);
-       }
-      else
-       {
-         fbit2 = 0;
-         /* Signed integers need to subtract one sign bit.  */
-         ibit2 = TYPE_PRECISION (t2) - (!TYPE_UNSIGNED (t2));
-       }
-
-      max_ibit = ibit1 >= ibit2 ?  ibit1 : ibit2;
-      max_fbit = fbit1 >= fbit2 ?  fbit1 : fbit2;
-      return c_common_fixed_point_type_for_size (max_ibit, max_fbit, unsignedp,
-                                                satp);
-    }
-
-  /* Both real or both integers; use the one with greater precision.  */
-
-  if (TYPE_PRECISION (t1) > TYPE_PRECISION (t2))
-    return t1;
-  else if (TYPE_PRECISION (t2) > TYPE_PRECISION (t1))
-    return t2;
-
-  /* Same precision.  Prefer long longs to longs to ints when the
-     same precision, following the C99 rules on integer type rank
-     (which are equivalent to the C90 rules for C90 types).  */
-
-  if (TYPE_MAIN_VARIANT (t1) == long_long_unsigned_type_node
-      || TYPE_MAIN_VARIANT (t2) == long_long_unsigned_type_node)
-    return long_long_unsigned_type_node;
-
-  if (TYPE_MAIN_VARIANT (t1) == long_long_integer_type_node
-      || TYPE_MAIN_VARIANT (t2) == long_long_integer_type_node)
-    {
-      if (TYPE_UNSIGNED (t1) || TYPE_UNSIGNED (t2))
-       return long_long_unsigned_type_node;
-      else
-       return long_long_integer_type_node;
-    }
-
-  if (TYPE_MAIN_VARIANT (t1) == long_unsigned_type_node
-      || TYPE_MAIN_VARIANT (t2) == long_unsigned_type_node)
-    return long_unsigned_type_node;
-
-  if (TYPE_MAIN_VARIANT (t1) == long_integer_type_node
-      || TYPE_MAIN_VARIANT (t2) == long_integer_type_node)
-    {
-      /* But preserve unsignedness from the other type,
-        since long cannot hold all the values of an unsigned int.  */
-      if (TYPE_UNSIGNED (t1) || TYPE_UNSIGNED (t2))
-       return long_unsigned_type_node;
-      else
-       return long_integer_type_node;
-    }
-
-  /* Likewise, prefer long double to double even if same size.  */
-  if (TYPE_MAIN_VARIANT (t1) == long_double_type_node
-      || TYPE_MAIN_VARIANT (t2) == long_double_type_node)
-    return long_double_type_node;
-
-  /* Otherwise prefer the unsigned one.  */
-
-  if (TYPE_UNSIGNED (t1))
-    return t1;
-  else
-    return t2;
-}
-\f
-/* Wrapper around c_common_type that is used by c-common.c and other
-   front end optimizations that remove promotions.  ENUMERAL_TYPEs
-   are allowed here and are converted to their compatible integer types.
-   BOOLEAN_TYPEs are allowed here and return either boolean_type_node or
-   preferably a non-Boolean type as the common type.  */
-tree
-common_type (tree t1, tree t2)
-{
-  if (TREE_CODE (t1) == ENUMERAL_TYPE)
-    t1 = c_common_type_for_size (TYPE_PRECISION (t1), 1);
-  if (TREE_CODE (t2) == ENUMERAL_TYPE)
-    t2 = c_common_type_for_size (TYPE_PRECISION (t2), 1);
-
-  /* If both types are BOOLEAN_TYPE, then return boolean_type_node.  */
-  if (TREE_CODE (t1) == BOOLEAN_TYPE
-      && TREE_CODE (t2) == BOOLEAN_TYPE)
-    return boolean_type_node;
-
-  /* If either type is BOOLEAN_TYPE, then return the other.  */
-  if (TREE_CODE (t1) == BOOLEAN_TYPE)
-    return t2;
-  if (TREE_CODE (t2) == BOOLEAN_TYPE)
-    return t1;
-
-  return c_common_type (t1, t2);
-}
-
-/* Return 1 if TYPE1 and TYPE2 are compatible types for assignment
-   or various other operations.  Return 2 if they are compatible
-   but a warning may be needed if you use them together.  */
-
-int
-comptypes (tree type1, tree type2)
-{
-  const struct tagged_tu_seen_cache * tagged_tu_seen_base1 = tagged_tu_seen_base;
-  int val;
-
-  val = comptypes_internal (type1, type2, NULL, NULL);
-  free_all_tagged_tu_seen_up_to (tagged_tu_seen_base1);
-
-  return val;
-}
-
-/* Like comptypes, but if it returns non-zero because enum and int are
-   compatible, it sets *ENUM_AND_INT_P to true.  */
-
-static int
-comptypes_check_enum_int (tree type1, tree type2, bool *enum_and_int_p)
-{
-  const struct tagged_tu_seen_cache * tagged_tu_seen_base1 = tagged_tu_seen_base;
-  int val;
-
-  val = comptypes_internal (type1, type2, enum_and_int_p, NULL);
-  free_all_tagged_tu_seen_up_to (tagged_tu_seen_base1);
-
-  return val;
-}
-
-/* Like comptypes, but if it returns nonzero for different types, it
-   sets *DIFFERENT_TYPES_P to true.  */
-
-int
-comptypes_check_different_types (tree type1, tree type2,
-                                bool *different_types_p)
-{
-  const struct tagged_tu_seen_cache * tagged_tu_seen_base1 = tagged_tu_seen_base;
-  int val;
-
-  val = comptypes_internal (type1, type2, NULL, different_types_p);
-  free_all_tagged_tu_seen_up_to (tagged_tu_seen_base1);
-
-  return val;
-}
-\f
-/* Return 1 if TYPE1 and TYPE2 are compatible types for assignment
-   or various other operations.  Return 2 if they are compatible
-   but a warning may be needed if you use them together.  If
-   ENUM_AND_INT_P is not NULL, and one type is an enum and the other a
-   compatible integer type, then this sets *ENUM_AND_INT_P to true;
-   *ENUM_AND_INT_P is never set to false.  If DIFFERENT_TYPES_P is not
-   NULL, and the types are compatible but different enough not to be
-   permitted in C11 typedef redeclarations, then this sets
-   *DIFFERENT_TYPES_P to true; *DIFFERENT_TYPES_P is never set to
-   false, but may or may not be set if the types are incompatible.
-   This differs from comptypes, in that we don't free the seen
-   types.  */
-
-static int
-comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p,
-                   bool *different_types_p)
-{
-  const_tree t1 = type1;
-  const_tree t2 = type2;
-  int attrval, val;
-
-  /* Suppress errors caused by previously reported errors.  */
-
-  if (t1 == t2 || !t1 || !t2
-      || TREE_CODE (t1) == ERROR_MARK || TREE_CODE (t2) == ERROR_MARK)
-    return 1;
-
-  /* Enumerated types are compatible with integer types, but this is
-     not transitive: two enumerated types in the same translation unit
-     are compatible with each other only if they are the same type.  */
-
-  if (TREE_CODE (t1) == ENUMERAL_TYPE && TREE_CODE (t2) != ENUMERAL_TYPE)
-    {
-      t1 = c_common_type_for_size (TYPE_PRECISION (t1), TYPE_UNSIGNED (t1));
-      if (TREE_CODE (t2) != VOID_TYPE)
-       {
-         if (enum_and_int_p != NULL)
-           *enum_and_int_p = true;
-         if (different_types_p != NULL)
-           *different_types_p = true;
-       }
-    }
-  else if (TREE_CODE (t2) == ENUMERAL_TYPE && TREE_CODE (t1) != ENUMERAL_TYPE)
-    {
-      t2 = c_common_type_for_size (TYPE_PRECISION (t2), TYPE_UNSIGNED (t2));
-      if (TREE_CODE (t1) != VOID_TYPE)
-       {
-         if (enum_and_int_p != NULL)
-           *enum_and_int_p = true;
-         if (different_types_p != NULL)
-           *different_types_p = true;
-       }
-    }
-
-  if (t1 == t2)
-    return 1;
-
-  /* Different classes of types can't be compatible.  */
-
-  if (TREE_CODE (t1) != TREE_CODE (t2))
-    return 0;
-
-  /* Qualifiers must match. C99 6.7.3p9 */
-
-  if (TYPE_QUALS (t1) != TYPE_QUALS (t2))
-    return 0;
-
-  /* Allow for two different type nodes which have essentially the same
-     definition.  Note that we already checked for equality of the type
-     qualifiers (just above).  */
-
-  if (TREE_CODE (t1) != ARRAY_TYPE
-      && TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
-    return 1;
-
-  /* 1 if no need for warning yet, 2 if warning cause has been seen.  */
-  if (!(attrval = comp_type_attributes (t1, t2)))
-     return 0;
-
-  /* 1 if no need for warning yet, 2 if warning cause has been seen.  */
-  val = 0;
-
-  switch (TREE_CODE (t1))
-    {
-    case POINTER_TYPE:
-      /* Do not remove mode or aliasing information.  */
-      if (TYPE_MODE (t1) != TYPE_MODE (t2)
-         || TYPE_REF_CAN_ALIAS_ALL (t1) != TYPE_REF_CAN_ALIAS_ALL (t2))
-       break;
-      val = (TREE_TYPE (t1) == TREE_TYPE (t2)
-            ? 1 : comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2),
-                                      enum_and_int_p, different_types_p));
-      break;
-
-    case FUNCTION_TYPE:
-      val = function_types_compatible_p (t1, t2, enum_and_int_p,
-                                        different_types_p);
-      break;
-
-    case ARRAY_TYPE:
-      {
-       tree d1 = TYPE_DOMAIN (t1);
-       tree d2 = TYPE_DOMAIN (t2);
-       bool d1_variable, d2_variable;
-       bool d1_zero, d2_zero;
-       val = 1;
-
-       /* Target types must match incl. qualifiers.  */
-       if (TREE_TYPE (t1) != TREE_TYPE (t2)
-           && 0 == (val = comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2),
-                                              enum_and_int_p,
-                                              different_types_p)))
-         return 0;
-
-       if (different_types_p != NULL
-           && (d1 == 0) != (d2 == 0))
-         *different_types_p = true;
-       /* Sizes must match unless one is missing or variable.  */
-       if (d1 == 0 || d2 == 0 || d1 == d2)
-         break;
-
-       d1_zero = !TYPE_MAX_VALUE (d1);
-       d2_zero = !TYPE_MAX_VALUE (d2);
-
-       d1_variable = (!d1_zero
-                      && (TREE_CODE (TYPE_MIN_VALUE (d1)) != INTEGER_CST
-                          || TREE_CODE (TYPE_MAX_VALUE (d1)) != INTEGER_CST));
-       d2_variable = (!d2_zero
-                      && (TREE_CODE (TYPE_MIN_VALUE (d2)) != INTEGER_CST
-                          || TREE_CODE (TYPE_MAX_VALUE (d2)) != INTEGER_CST));
-       d1_variable = d1_variable || (d1_zero && c_vla_type_p (t1));
-       d2_variable = d2_variable || (d2_zero && c_vla_type_p (t2));
-
-       if (different_types_p != NULL
-           && d1_variable != d2_variable)
-         *different_types_p = true;
-       if (d1_variable || d2_variable)
-         break;
-       if (d1_zero && d2_zero)
-         break;
-       if (d1_zero || d2_zero
-           || !tree_int_cst_equal (TYPE_MIN_VALUE (d1), TYPE_MIN_VALUE (d2))
-           || !tree_int_cst_equal (TYPE_MAX_VALUE (d1), TYPE_MAX_VALUE (d2)))
-         val = 0;
-
-       break;
-      }
-
-    case ENUMERAL_TYPE:
-    case RECORD_TYPE:
-    case UNION_TYPE:
-      if (val != 1 && !same_translation_unit_p (t1, t2))
-       {
-         tree a1 = TYPE_ATTRIBUTES (t1);
-         tree a2 = TYPE_ATTRIBUTES (t2);
-
-         if (! attribute_list_contained (a1, a2)
-             && ! attribute_list_contained (a2, a1))
-           break;
-
-         if (attrval != 2)
-           return tagged_types_tu_compatible_p (t1, t2, enum_and_int_p,
-                                                different_types_p);
-         val = tagged_types_tu_compatible_p (t1, t2, enum_and_int_p,
-                                             different_types_p);
-       }
-      break;
-
-    case VECTOR_TYPE:
-      val = (TYPE_VECTOR_SUBPARTS (t1) == TYPE_VECTOR_SUBPARTS (t2)
-            && comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2),
-                                   enum_and_int_p, different_types_p));
-      break;
-
-    default:
-      break;
-    }
-  return attrval == 2 && val == 1 ? 2 : val;
-}
-
-/* Return 1 if TTL and TTR are pointers to types that are equivalent, ignoring
-   their qualifiers, except for named address spaces.  If the pointers point to
-   different named addresses, then we must determine if one address space is a
-   subset of the other.  */
-
-static int
-comp_target_types (location_t location, tree ttl, tree ttr)
-{
-  int val;
-  tree mvl = TREE_TYPE (ttl);
-  tree mvr = TREE_TYPE (ttr);
-  addr_space_t asl = TYPE_ADDR_SPACE (mvl);
-  addr_space_t asr = TYPE_ADDR_SPACE (mvr);
-  addr_space_t as_common;
-  bool enum_and_int_p;
-
-  /* Fail if pointers point to incompatible address spaces.  */
-  if (!addr_space_superset (asl, asr, &as_common))
-    return 0;
-
-  /* Do not lose qualifiers on element types of array types that are
-     pointer targets by taking their TYPE_MAIN_VARIANT.  */
-  if (TREE_CODE (mvl) != ARRAY_TYPE)
-    mvl = TYPE_MAIN_VARIANT (mvl);
-  if (TREE_CODE (mvr) != ARRAY_TYPE)
-    mvr = TYPE_MAIN_VARIANT (mvr);
-  enum_and_int_p = false;
-  val = comptypes_check_enum_int (mvl, mvr, &enum_and_int_p);
-
-  if (val == 2)
-    pedwarn (location, OPT_Wpedantic, "types are not quite compatible");
-
-  if (val == 1 && enum_and_int_p && warn_cxx_compat)
-    warning_at (location, OPT_Wc___compat,
-               "pointer target types incompatible in C++");
-
-  return val;
-}
-\f
-/* Subroutines of `comptypes'.  */
-
-/* Determine whether two trees derive from the same translation unit.
-   If the CONTEXT chain ends in a null, that tree's context is still
-   being parsed, so if two trees have context chains ending in null,
-   they're in the same translation unit.  */
-int
-same_translation_unit_p (const_tree t1, const_tree t2)
-{
-  while (t1 && TREE_CODE (t1) != TRANSLATION_UNIT_DECL)
-    switch (TREE_CODE_CLASS (TREE_CODE (t1)))
-      {
-      case tcc_declaration:
-       t1 = DECL_CONTEXT (t1); break;
-      case tcc_type:
-       t1 = TYPE_CONTEXT (t1); break;
-      case tcc_exceptional:
-       t1 = BLOCK_SUPERCONTEXT (t1); break;  /* assume block */
-      default: gcc_unreachable ();
-      }
-
-  while (t2 && TREE_CODE (t2) != TRANSLATION_UNIT_DECL)
-    switch (TREE_CODE_CLASS (TREE_CODE (t2)))
-      {
-      case tcc_declaration:
-       t2 = DECL_CONTEXT (t2); break;
-      case tcc_type:
-       t2 = TYPE_CONTEXT (t2); break;
-      case tcc_exceptional:
-       t2 = BLOCK_SUPERCONTEXT (t2); break;  /* assume block */
-      default: gcc_unreachable ();
-      }
-
-  return t1 == t2;
-}
-
-/* Allocate the seen two types, assuming that they are compatible. */
-
-static struct tagged_tu_seen_cache *
-alloc_tagged_tu_seen_cache (const_tree t1, const_tree t2)
-{
-  struct tagged_tu_seen_cache *tu = XNEW (struct tagged_tu_seen_cache);
-  tu->next = tagged_tu_seen_base;
-  tu->t1 = t1;
-  tu->t2 = t2;
-
-  tagged_tu_seen_base = tu;
-
-  /* The C standard says that two structures in different translation
-     units are compatible with each other only if the types of their
-     fields are compatible (among other things).  We assume that they
-     are compatible until proven otherwise when building the cache.
-     An example where this can occur is:
-     struct a
-     {
-       struct a *next;
-     };
-     If we are comparing this against a similar struct in another TU,
-     and did not assume they were compatible, we end up with an infinite
-     loop.  */
-  tu->val = 1;
-  return tu;
-}
-
-/* Free the seen types until we get to TU_TIL. */
-
-static void
-free_all_tagged_tu_seen_up_to (const struct tagged_tu_seen_cache *tu_til)
-{
-  const struct tagged_tu_seen_cache *tu = tagged_tu_seen_base;
-  while (tu != tu_til)
-    {
-      const struct tagged_tu_seen_cache *const tu1
-       = (const struct tagged_tu_seen_cache *) tu;
-      tu = tu1->next;
-      free (CONST_CAST (struct tagged_tu_seen_cache *, tu1));
-    }
-  tagged_tu_seen_base = tu_til;
-}
-
-/* Return 1 if two 'struct', 'union', or 'enum' types T1 and T2 are
-   compatible.  If the two types are not the same (which has been
-   checked earlier), this can only happen when multiple translation
-   units are being compiled.  See C99 6.2.7 paragraph 1 for the exact
-   rules.  ENUM_AND_INT_P and DIFFERENT_TYPES_P are as in
-   comptypes_internal.  */
-
-static int
-tagged_types_tu_compatible_p (const_tree t1, const_tree t2,
-                             bool *enum_and_int_p, bool *different_types_p)
-{
-  tree s1, s2;
-  bool needs_warning = false;
-
-  /* We have to verify that the tags of the types are the same.  This
-     is harder than it looks because this may be a typedef, so we have
-     to go look at the original type.  It may even be a typedef of a
-     typedef...
-     In the case of compiler-created builtin structs the TYPE_DECL
-     may be a dummy, with no DECL_ORIGINAL_TYPE.  Don't fault.  */
-  while (TYPE_NAME (t1)
-        && TREE_CODE (TYPE_NAME (t1)) == TYPE_DECL
-        && DECL_ORIGINAL_TYPE (TYPE_NAME (t1)))
-    t1 = DECL_ORIGINAL_TYPE (TYPE_NAME (t1));
-
-  while (TYPE_NAME (t2)
-        && TREE_CODE (TYPE_NAME (t2)) == TYPE_DECL
-        && DECL_ORIGINAL_TYPE (TYPE_NAME (t2)))
-    t2 = DECL_ORIGINAL_TYPE (TYPE_NAME (t2));
-
-  /* C90 didn't have the requirement that the two tags be the same.  */
-  if (flag_isoc99 && TYPE_NAME (t1) != TYPE_NAME (t2))
-    return 0;
-
-  /* C90 didn't say what happened if one or both of the types were
-     incomplete; we choose to follow C99 rules here, which is that they
-     are compatible.  */
-  if (TYPE_SIZE (t1) == NULL
-      || TYPE_SIZE (t2) == NULL)
-    return 1;
-
-  {
-    const struct tagged_tu_seen_cache * tts_i;
-    for (tts_i = tagged_tu_seen_base; tts_i != NULL; tts_i = tts_i->next)
-      if (tts_i->t1 == t1 && tts_i->t2 == t2)
-       return tts_i->val;
-  }
-
-  switch (TREE_CODE (t1))
-    {
-    case ENUMERAL_TYPE:
-      {
-       struct tagged_tu_seen_cache *tu = alloc_tagged_tu_seen_cache (t1, t2);
-       /* Speed up the case where the type values are in the same order.  */
-       tree tv1 = TYPE_VALUES (t1);
-       tree tv2 = TYPE_VALUES (t2);
-
-       if (tv1 == tv2)
-         {
-           return 1;
-         }
-
-       for (;tv1 && tv2; tv1 = TREE_CHAIN (tv1), tv2 = TREE_CHAIN (tv2))
-         {
-           if (TREE_PURPOSE (tv1) != TREE_PURPOSE (tv2))
-             break;
-           if (simple_cst_equal (TREE_VALUE (tv1), TREE_VALUE (tv2)) != 1)
-             {
-               tu->val = 0;
-               return 0;
-             }
-         }
-
-       if (tv1 == NULL_TREE && tv2 == NULL_TREE)
-         {
-           return 1;
-         }
-       if (tv1 == NULL_TREE || tv2 == NULL_TREE)
-         {
-           tu->val = 0;
-           return 0;
-         }
-
-       if (list_length (TYPE_VALUES (t1)) != list_length (TYPE_VALUES (t2)))
-         {
-           tu->val = 0;
-           return 0;
-         }
-
-       for (s1 = TYPE_VALUES (t1); s1; s1 = TREE_CHAIN (s1))
-         {
-           s2 = purpose_member (TREE_PURPOSE (s1), TYPE_VALUES (t2));
-           if (s2 == NULL
-               || simple_cst_equal (TREE_VALUE (s1), TREE_VALUE (s2)) != 1)
-             {
-               tu->val = 0;
-               return 0;
-             }
-         }
-       return 1;
-      }
-
-    case UNION_TYPE:
-      {
-       struct tagged_tu_seen_cache *tu = alloc_tagged_tu_seen_cache (t1, t2);
-       if (list_length (TYPE_FIELDS (t1)) != list_length (TYPE_FIELDS (t2)))
-         {
-           tu->val = 0;
-           return 0;
-         }
-
-       /*  Speed up the common case where the fields are in the same order. */
-       for (s1 = TYPE_FIELDS (t1), s2 = TYPE_FIELDS (t2); s1 && s2;
-            s1 = DECL_CHAIN (s1), s2 = DECL_CHAIN (s2))
-         {
-           int result;
-
-           if (DECL_NAME (s1) != DECL_NAME (s2))
-             break;
-           result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2),
-                                        enum_and_int_p, different_types_p);
-
-           if (result != 1 && !DECL_NAME (s1))
-             break;
-           if (result == 0)
-             {
-               tu->val = 0;
-               return 0;
-             }
-           if (result == 2)
-             needs_warning = true;
-
-           if (TREE_CODE (s1) == FIELD_DECL
-               && simple_cst_equal (DECL_FIELD_BIT_OFFSET (s1),
-                                    DECL_FIELD_BIT_OFFSET (s2)) != 1)
-             {
-               tu->val = 0;
-               return 0;
-             }
-         }
-       if (!s1 && !s2)
-         {
-           tu->val = needs_warning ? 2 : 1;
-           return tu->val;
-         }
-
-       for (s1 = TYPE_FIELDS (t1); s1; s1 = DECL_CHAIN (s1))
-         {
-           bool ok = false;
-
-           for (s2 = TYPE_FIELDS (t2); s2; s2 = DECL_CHAIN (s2))
-             if (DECL_NAME (s1) == DECL_NAME (s2))
-               {
-                 int result;
-
-                 result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2),
-                                              enum_and_int_p,
-                                              different_types_p);
-
-                 if (result != 1 && !DECL_NAME (s1))
-                   continue;
-                 if (result == 0)
-                   {
-                     tu->val = 0;
-                     return 0;
-                   }
-                 if (result == 2)
-                   needs_warning = true;
-
-                 if (TREE_CODE (s1) == FIELD_DECL
-                     && simple_cst_equal (DECL_FIELD_BIT_OFFSET (s1),
-                                          DECL_FIELD_BIT_OFFSET (s2)) != 1)
-                   break;
-
-                 ok = true;
-                 break;
-               }
-           if (!ok)
-             {
-               tu->val = 0;
-               return 0;
-             }
-         }
-       tu->val = needs_warning ? 2 : 10;
-       return tu->val;
-      }
-
-    case RECORD_TYPE:
-      {
-       struct tagged_tu_seen_cache *tu = alloc_tagged_tu_seen_cache (t1, t2);
-
-       for (s1 = TYPE_FIELDS (t1), s2 = TYPE_FIELDS (t2);
-            s1 && s2;
-            s1 = DECL_CHAIN (s1), s2 = DECL_CHAIN (s2))
-         {
-           int result;
-           if (TREE_CODE (s1) != TREE_CODE (s2)
-               || DECL_NAME (s1) != DECL_NAME (s2))
-             break;
-           result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2),
-                                        enum_and_int_p, different_types_p);
-           if (result == 0)
-             break;
-           if (result == 2)
-             needs_warning = true;
-
-           if (TREE_CODE (s1) == FIELD_DECL
-               && simple_cst_equal (DECL_FIELD_BIT_OFFSET (s1),
-                                    DECL_FIELD_BIT_OFFSET (s2)) != 1)
-             break;
-         }
-       if (s1 && s2)
-         tu->val = 0;
-       else
-         tu->val = needs_warning ? 2 : 1;
-       return tu->val;
-      }
-
-    default:
-      gcc_unreachable ();
-    }
-}
-
-/* Return 1 if two function types F1 and F2 are compatible.
-   If either type specifies no argument types,
-   the other must specify a fixed number of self-promoting arg types.
-   Otherwise, if one type specifies only the number of arguments,
-   the other must specify that number of self-promoting arg types.
-   Otherwise, the argument types must match.
-   ENUM_AND_INT_P and DIFFERENT_TYPES_P are as in comptypes_internal.  */
-
-static int
-function_types_compatible_p (const_tree f1, const_tree f2,
-                            bool *enum_and_int_p, bool *different_types_p)
-{
-  tree args1, args2;
-  /* 1 if no need for warning yet, 2 if warning cause has been seen.  */
-  int val = 1;
-  int val1;
-  tree ret1, ret2;
-
-  ret1 = TREE_TYPE (f1);
-  ret2 = TREE_TYPE (f2);
-
-  /* 'volatile' qualifiers on a function's return type used to mean
-     the function is noreturn.  */
-  if (TYPE_VOLATILE (ret1) != TYPE_VOLATILE (ret2))
-    pedwarn (input_location, 0, "function return types not compatible due to %<volatile%>");
-  if (TYPE_VOLATILE (ret1))
-    ret1 = build_qualified_type (TYPE_MAIN_VARIANT (ret1),
-                                TYPE_QUALS (ret1) & ~TYPE_QUAL_VOLATILE);
-  if (TYPE_VOLATILE (ret2))
-    ret2 = build_qualified_type (TYPE_MAIN_VARIANT (ret2),
-                                TYPE_QUALS (ret2) & ~TYPE_QUAL_VOLATILE);
-  val = comptypes_internal (ret1, ret2, enum_and_int_p, different_types_p);
-  if (val == 0)
-    return 0;
-
-  args1 = TYPE_ARG_TYPES (f1);
-  args2 = TYPE_ARG_TYPES (f2);
-
-  if (different_types_p != NULL
-      && (args1 == 0) != (args2 == 0))
-    *different_types_p = true;
-
-  /* An unspecified parmlist matches any specified parmlist
-     whose argument types don't need default promotions.  */
-
-  if (args1 == 0)
-    {
-      if (!self_promoting_args_p (args2))
-       return 0;
-      /* If one of these types comes from a non-prototype fn definition,
-        compare that with the other type's arglist.
-        If they don't match, ask for a warning (but no error).  */
-      if (TYPE_ACTUAL_ARG_TYPES (f1)
-         && 1 != type_lists_compatible_p (args2, TYPE_ACTUAL_ARG_TYPES (f1),
-                                          enum_and_int_p, different_types_p))
-       val = 2;
-      return val;
-    }
-  if (args2 == 0)
-    {
-      if (!self_promoting_args_p (args1))
-       return 0;
-      if (TYPE_ACTUAL_ARG_TYPES (f2)
-         && 1 != type_lists_compatible_p (args1, TYPE_ACTUAL_ARG_TYPES (f2),
-                                          enum_and_int_p, different_types_p))
-       val = 2;
-      return val;
-    }
-
-  /* Both types have argument lists: compare them and propagate results.  */
-  val1 = type_lists_compatible_p (args1, args2, enum_and_int_p,
-                                 different_types_p);
-  return val1 != 1 ? val1 : val;
-}
-
-/* Check two lists of types for compatibility, returning 0 for
-   incompatible, 1 for compatible, or 2 for compatible with
-   warning.  ENUM_AND_INT_P and DIFFERENT_TYPES_P are as in
-   comptypes_internal.  */
-
-static int
-type_lists_compatible_p (const_tree args1, const_tree args2,
-                        bool *enum_and_int_p, bool *different_types_p)
-{
-  /* 1 if no need for warning yet, 2 if warning cause has been seen.  */
-  int val = 1;
-  int newval = 0;
-
-  while (1)
-    {
-      tree a1, mv1, a2, mv2;
-      if (args1 == 0 && args2 == 0)
-       return val;
-      /* If one list is shorter than the other,
-        they fail to match.  */
-      if (args1 == 0 || args2 == 0)
-       return 0;
-      mv1 = a1 = TREE_VALUE (args1);
-      mv2 = a2 = TREE_VALUE (args2);
-      if (mv1 && mv1 != error_mark_node && TREE_CODE (mv1) != ARRAY_TYPE)
-       mv1 = TYPE_MAIN_VARIANT (mv1);
-      if (mv2 && mv2 != error_mark_node && TREE_CODE (mv2) != ARRAY_TYPE)
-       mv2 = TYPE_MAIN_VARIANT (mv2);
-      /* A null pointer instead of a type
-        means there is supposed to be an argument
-        but nothing is specified about what type it has.
-        So match anything that self-promotes.  */
-      if (different_types_p != NULL
-         && (a1 == 0) != (a2 == 0))
-       *different_types_p = true;
-      if (a1 == 0)
-       {
-         if (c_type_promotes_to (a2) != a2)
-           return 0;
-       }
-      else if (a2 == 0)
-       {
-         if (c_type_promotes_to (a1) != a1)
-           return 0;
-       }
-      /* If one of the lists has an error marker, ignore this arg.  */
-      else if (TREE_CODE (a1) == ERROR_MARK
-              || TREE_CODE (a2) == ERROR_MARK)
-       ;
-      else if (!(newval = comptypes_internal (mv1, mv2, enum_and_int_p,
-                                             different_types_p)))
-       {
-         if (different_types_p != NULL)
-           *different_types_p = true;
-         /* Allow  wait (union {union wait *u; int *i} *)
-            and  wait (union wait *)  to be compatible.  */
-         if (TREE_CODE (a1) == UNION_TYPE
-             && (TYPE_NAME (a1) == 0
-                 || TYPE_TRANSPARENT_AGGR (a1))
-             && TREE_CODE (TYPE_SIZE (a1)) == INTEGER_CST
-             && tree_int_cst_equal (TYPE_SIZE (a1),
-                                    TYPE_SIZE (a2)))
-           {
-             tree memb;
-             for (memb = TYPE_FIELDS (a1);
-                  memb; memb = DECL_CHAIN (memb))
-               {
-                 tree mv3 = TREE_TYPE (memb);
-                 if (mv3 && mv3 != error_mark_node
-                     && TREE_CODE (mv3) != ARRAY_TYPE)
-                   mv3 = TYPE_MAIN_VARIANT (mv3);
-                 if (comptypes_internal (mv3, mv2, enum_and_int_p,
-                                         different_types_p))
-                   break;
-               }
-             if (memb == 0)
-               return 0;
-           }
-         else if (TREE_CODE (a2) == UNION_TYPE
-                  && (TYPE_NAME (a2) == 0
-                      || TYPE_TRANSPARENT_AGGR (a2))
-                  && TREE_CODE (TYPE_SIZE (a2)) == INTEGER_CST
-                  && tree_int_cst_equal (TYPE_SIZE (a2),
-                                         TYPE_SIZE (a1)))
-           {
-             tree memb;
-             for (memb = TYPE_FIELDS (a2);
-                  memb; memb = DECL_CHAIN (memb))
-               {
-                 tree mv3 = TREE_TYPE (memb);
-                 if (mv3 && mv3 != error_mark_node
-                     && TREE_CODE (mv3) != ARRAY_TYPE)
-                   mv3 = TYPE_MAIN_VARIANT (mv3);
-                 if (comptypes_internal (mv3, mv1, enum_and_int_p,
-                                         different_types_p))
-                   break;
-               }
-             if (memb == 0)
-               return 0;
-           }
-         else
-           return 0;
-       }
-
-      /* comptypes said ok, but record if it said to warn.  */
-      if (newval > val)
-       val = newval;
-
-      args1 = TREE_CHAIN (args1);
-      args2 = TREE_CHAIN (args2);
-    }
-}
-\f
-/* Compute the size to increment a pointer by.  */
-
-static tree
-c_size_in_bytes (const_tree type)
-{
-  enum tree_code code = TREE_CODE (type);
-
-  if (code == FUNCTION_TYPE || code == VOID_TYPE || code == ERROR_MARK)
-    return size_one_node;
-
-  if (!COMPLETE_OR_VOID_TYPE_P (type))
-    {
-      error ("arithmetic on pointer to an incomplete type");
-      return size_one_node;
-    }
-
-  /* Convert in case a char is more than one unit.  */
-  return size_binop_loc (input_location, CEIL_DIV_EXPR, TYPE_SIZE_UNIT (type),
-                        size_int (TYPE_PRECISION (char_type_node)
-                                  / BITS_PER_UNIT));
-}
-\f
-/* Return either DECL or its known constant value (if it has one).  */
-
-tree
-decl_constant_value (tree decl)
-{
-  if (/* Don't change a variable array bound or initial value to a constant
-        in a place where a variable is invalid.  Note that DECL_INITIAL
-        isn't valid for a PARM_DECL.  */
-      current_function_decl != 0
-      && TREE_CODE (decl) != PARM_DECL
-      && !TREE_THIS_VOLATILE (decl)
-      && TREE_READONLY (decl)
-      && DECL_INITIAL (decl) != 0
-      && TREE_CODE (DECL_INITIAL (decl)) != ERROR_MARK
-      /* This is invalid if initial value is not constant.
-        If it has either a function call, a memory reference,
-        or a variable, then re-evaluating it could give different results.  */
-      && TREE_CONSTANT (DECL_INITIAL (decl))
-      /* Check for cases where this is sub-optimal, even though valid.  */
-      && TREE_CODE (DECL_INITIAL (decl)) != CONSTRUCTOR)
-    return DECL_INITIAL (decl);
-  return decl;
-}
-
-/* Convert the array expression EXP to a pointer.  */
-static tree
-array_to_pointer_conversion (location_t loc, tree exp)
-{
-  tree orig_exp = exp;
-  tree type = TREE_TYPE (exp);
-  tree adr;
-  tree restype = TREE_TYPE (type);
-  tree ptrtype;
-
-  gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
-
-  STRIP_TYPE_NOPS (exp);
-
-  if (TREE_NO_WARNING (orig_exp))
-    TREE_NO_WARNING (exp) = 1;
-
-  ptrtype = build_pointer_type (restype);
-
-  if (TREE_CODE (exp) == INDIRECT_REF)
-    return convert (ptrtype, TREE_OPERAND (exp, 0));
-
-  /* In C++ array compound literals are temporary objects unless they are
-     const or appear in namespace scope, so they are destroyed too soon
-     to use them for much of anything  (c++/53220).  */
-  if (warn_cxx_compat && TREE_CODE (exp) == COMPOUND_LITERAL_EXPR)
-    {
-      tree decl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
-      if (!TREE_READONLY (decl) && !TREE_STATIC (decl))
-       warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wc___compat,
-                   "converting an array compound literal to a pointer "
-                   "is ill-formed in C++");
-    }
-
-  adr = build_unary_op (loc, ADDR_EXPR, exp, 1);
-  return convert (ptrtype, adr);
-}
-
-/* Convert the function expression EXP to a pointer.  */
-static tree
-function_to_pointer_conversion (location_t loc, tree exp)
-{
-  tree orig_exp = exp;
-
-  gcc_assert (TREE_CODE (TREE_TYPE (exp)) == FUNCTION_TYPE);
-
-  STRIP_TYPE_NOPS (exp);
-
-  if (TREE_NO_WARNING (orig_exp))
-    TREE_NO_WARNING (exp) = 1;
-
-  return build_unary_op (loc, ADDR_EXPR, exp, 0);
-}
-
-/* Mark EXP as read, not just set, for set but not used -Wunused
-   warning purposes.  */
-
-void
-mark_exp_read (tree exp)
-{
-  switch (TREE_CODE (exp))
-    {
-    case VAR_DECL:
-    case PARM_DECL:
-      DECL_READ_P (exp) = 1;
-      break;
-    case ARRAY_REF:
-    case COMPONENT_REF:
-    case MODIFY_EXPR:
-    case REALPART_EXPR:
-    case IMAGPART_EXPR:
-    CASE_CONVERT:
-    case ADDR_EXPR:
-      mark_exp_read (TREE_OPERAND (exp, 0));
-      break;
-    case COMPOUND_EXPR:
-    case C_MAYBE_CONST_EXPR:
-      mark_exp_read (TREE_OPERAND (exp, 1));
-      break;
-    default:
-      break;
-    }
-}
-
-/* Perform the default conversion of arrays and functions to pointers.
-   Return the result of converting EXP.  For any other expression, just
-   return EXP.
-
-   LOC is the location of the expression.  */
-
-struct c_expr
-default_function_array_conversion (location_t loc, struct c_expr exp)
-{
-  tree orig_exp = exp.value;
-  tree type = TREE_TYPE (exp.value);
-  enum tree_code code = TREE_CODE (type);
-
-  switch (code)
-    {
-    case ARRAY_TYPE:
-      {
-       bool not_lvalue = false;
-       bool lvalue_array_p;
-
-       while ((TREE_CODE (exp.value) == NON_LVALUE_EXPR
-               || CONVERT_EXPR_P (exp.value))
-              && TREE_TYPE (TREE_OPERAND (exp.value, 0)) == type)
-         {
-           if (TREE_CODE (exp.value) == NON_LVALUE_EXPR)
-             not_lvalue = true;
-           exp.value = TREE_OPERAND (exp.value, 0);
-         }
-
-       if (TREE_NO_WARNING (orig_exp))
-         TREE_NO_WARNING (exp.value) = 1;
-
-       lvalue_array_p = !not_lvalue && lvalue_p (exp.value);
-       if (!flag_isoc99 && !lvalue_array_p)
-         {
-           /* Before C99, non-lvalue arrays do not decay to pointers.
-              Normally, using such an array would be invalid; but it can
-              be used correctly inside sizeof or as a statement expression.
-              Thus, do not give an error here; an error will result later.  */
-           return exp;
-         }
-
-       exp.value = array_to_pointer_conversion (loc, exp.value);
-      }
-      break;
-    case FUNCTION_TYPE:
-      exp.value = function_to_pointer_conversion (loc, exp.value);
-      break;
-    default:
-      break;
-    }
-
-  return exp;
-}
-
-struct c_expr
-default_function_array_read_conversion (location_t loc, struct c_expr exp)
-{
-  mark_exp_read (exp.value);
-  return default_function_array_conversion (loc, exp);
-}
-
-/* EXP is an expression of integer type.  Apply the integer promotions
-   to it and return the promoted value.  */
-
-tree
-perform_integral_promotions (tree exp)
-{
-  tree type = TREE_TYPE (exp);
-  enum tree_code code = TREE_CODE (type);
-
-  gcc_assert (INTEGRAL_TYPE_P (type));
-
-  /* Normally convert enums to int,
-     but convert wide enums to something wider.  */
-  if (code == ENUMERAL_TYPE)
-    {
-      type = c_common_type_for_size (MAX (TYPE_PRECISION (type),
-                                         TYPE_PRECISION (integer_type_node)),
-                                    ((TYPE_PRECISION (type)
-                                      >= TYPE_PRECISION (integer_type_node))
-                                     && TYPE_UNSIGNED (type)));
-
-      return convert (type, exp);
-    }
-
-  /* ??? This should no longer be needed now bit-fields have their
-     proper types.  */
-  if (TREE_CODE (exp) == COMPONENT_REF
-      && DECL_C_BIT_FIELD (TREE_OPERAND (exp, 1))
-      /* If it's thinner than an int, promote it like a
-        c_promoting_integer_type_p, otherwise leave it alone.  */
-      && 0 > compare_tree_int (DECL_SIZE (TREE_OPERAND (exp, 1)),
-                              TYPE_PRECISION (integer_type_node)))
-    return convert (integer_type_node, exp);
-
-  if (c_promoting_integer_type_p (type))
-    {
-      /* Preserve unsignedness if not really getting any wider.  */
-      if (TYPE_UNSIGNED (type)
-         && TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node))
-       return convert (unsigned_type_node, exp);
-
-      return convert (integer_type_node, exp);
-    }
-
-  return exp;
-}
-
-
-/* Perform default promotions for C data used in expressions.
-   Enumeral types or short or char are converted to int.
-   In addition, manifest constants symbols are replaced by their values.  */
-
-tree
-default_conversion (tree exp)
-{
-  tree orig_exp;
-  tree type = TREE_TYPE (exp);
-  enum tree_code code = TREE_CODE (type);
-  tree promoted_type;
-
-  mark_exp_read (exp);
-
-  /* Functions and arrays have been converted during parsing.  */
-  gcc_assert (code != FUNCTION_TYPE);
-  if (code == ARRAY_TYPE)
-    return exp;
-
-  /* Constants can be used directly unless they're not loadable.  */
-  if (TREE_CODE (exp) == CONST_DECL)
-    exp = DECL_INITIAL (exp);
-
-  /* Strip no-op conversions.  */
-  orig_exp = exp;
-  STRIP_TYPE_NOPS (exp);
-
-  if (TREE_NO_WARNING (orig_exp))
-    TREE_NO_WARNING (exp) = 1;
-
-  if (code == VOID_TYPE)
-    {
-      error ("void value not ignored as it ought to be");
-      return error_mark_node;
-    }
-
-  exp = require_complete_type (exp);
-  if (exp == error_mark_node)
-    return error_mark_node;
-
-  promoted_type = targetm.promoted_type (type);
-  if (promoted_type)
-    return convert (promoted_type, exp);
-
-  if (INTEGRAL_TYPE_P (type))
-    return perform_integral_promotions (exp);
-
-  return exp;
-}
-\f
-/* Look up COMPONENT in a structure or union TYPE.
-
-   If the component name is not found, returns NULL_TREE.  Otherwise,
-   the return value is a TREE_LIST, with each TREE_VALUE a FIELD_DECL
-   stepping down the chain to the component, which is in the last
-   TREE_VALUE of the list.  Normally the list is of length one, but if
-   the component is embedded within (nested) anonymous structures or
-   unions, the list steps down the chain to the component.  */
-
-static tree
-lookup_field (tree type, tree component)
-{
-  tree field;
-
-  /* If TYPE_LANG_SPECIFIC is set, then it is a sorted array of pointers
-     to the field elements.  Use a binary search on this array to quickly
-     find the element.  Otherwise, do a linear search.  TYPE_LANG_SPECIFIC
-     will always be set for structures which have many elements.  */
-
-  if (TYPE_LANG_SPECIFIC (type) && TYPE_LANG_SPECIFIC (type)->s)
-    {
-      int bot, top, half;
-      tree *field_array = &TYPE_LANG_SPECIFIC (type)->s->elts[0];
-
-      field = TYPE_FIELDS (type);
-      bot = 0;
-      top = TYPE_LANG_SPECIFIC (type)->s->len;
-      while (top - bot > 1)
-       {
-         half = (top - bot + 1) >> 1;
-         field = field_array[bot+half];
-
-         if (DECL_NAME (field) == NULL_TREE)
-           {
-             /* Step through all anon unions in linear fashion.  */
-             while (DECL_NAME (field_array[bot]) == NULL_TREE)
-               {
-                 field = field_array[bot++];
-                 if (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
-                     || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
-                   {
-                     tree anon = lookup_field (TREE_TYPE (field), component);
-
-                     if (anon)
-                       return tree_cons (NULL_TREE, field, anon);
-
-                     /* The Plan 9 compiler permits referring
-                        directly to an anonymous struct/union field
-                        using a typedef name.  */
-                     if (flag_plan9_extensions
-                         && TYPE_NAME (TREE_TYPE (field)) != NULL_TREE
-                         && (TREE_CODE (TYPE_NAME (TREE_TYPE (field)))
-                             == TYPE_DECL)
-                         && (DECL_NAME (TYPE_NAME (TREE_TYPE (field)))
-                             == component))
-                       break;
-                   }
-               }
-
-             /* Entire record is only anon unions.  */
-             if (bot > top)
-               return NULL_TREE;
-
-             /* Restart the binary search, with new lower bound.  */
-             continue;
-           }
-
-         if (DECL_NAME (field) == component)
-           break;
-         if (DECL_NAME (field) < component)
-           bot += half;
-         else
-           top = bot + half;
-       }
-
-      if (DECL_NAME (field_array[bot]) == component)
-       field = field_array[bot];
-      else if (DECL_NAME (field) != component)
-       return NULL_TREE;
-    }
-  else
-    {
-      for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
-       {
-         if (DECL_NAME (field) == NULL_TREE
-             && (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
-                 || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE))
-           {
-             tree anon = lookup_field (TREE_TYPE (field), component);
-
-             if (anon)
-               return tree_cons (NULL_TREE, field, anon);
-
-             /* The Plan 9 compiler permits referring directly to an
-                anonymous struct/union field using a typedef
-                name.  */
-             if (flag_plan9_extensions
-                 && TYPE_NAME (TREE_TYPE (field)) != NULL_TREE
-                 && TREE_CODE (TYPE_NAME (TREE_TYPE (field))) == TYPE_DECL
-                 && (DECL_NAME (TYPE_NAME (TREE_TYPE (field)))
-                     == component))
-               break;
-           }
-
-         if (DECL_NAME (field) == component)
-           break;
-       }
-
-      if (field == NULL_TREE)
-       return NULL_TREE;
-    }
-
-  return tree_cons (NULL_TREE, field, NULL_TREE);
-}
-
-/* Make an expression to refer to the COMPONENT field of structure or
-   union value DATUM.  COMPONENT is an IDENTIFIER_NODE.  LOC is the
-   location of the COMPONENT_REF.  */
-
-tree
-build_component_ref (location_t loc, tree datum, tree component)
-{
-  tree type = TREE_TYPE (datum);
-  enum tree_code code = TREE_CODE (type);
-  tree field = NULL;
-  tree ref;
-  bool datum_lvalue = lvalue_p (datum);
-
-  if (!objc_is_public (datum, component))
-    return error_mark_node;
-
-  /* Detect Objective-C property syntax object.property.  */
-  if (c_dialect_objc ()
-      && (ref = objc_maybe_build_component_ref (datum, component)))
-    return ref;
-
-  /* See if there is a field or component with name COMPONENT.  */
-
-  if (code == RECORD_TYPE || code == UNION_TYPE)
-    {
-      if (!COMPLETE_TYPE_P (type))
-       {
-         c_incomplete_type_error (NULL_TREE, type);
-         return error_mark_node;
-       }
-
-      field = lookup_field (type, component);
-
-      if (!field)
-       {
-         error_at (loc, "%qT has no member named %qE", type, component);
-         return error_mark_node;
-       }
-
-      /* Chain the COMPONENT_REFs if necessary down to the FIELD.
-        This might be better solved in future the way the C++ front
-        end does it - by giving the anonymous entities each a
-        separate name and type, and then have build_component_ref
-        recursively call itself.  We can't do that here.  */
-      do
-       {
-         tree subdatum = TREE_VALUE (field);
-         int quals;
-         tree subtype;
-         bool use_datum_quals;
-
-         if (TREE_TYPE (subdatum) == error_mark_node)
-           return error_mark_node;
-
-         /* If this is an rvalue, it does not have qualifiers in C
-            standard terms and we must avoid propagating such
-            qualifiers down to a non-lvalue array that is then
-            converted to a pointer.  */
-         use_datum_quals = (datum_lvalue
-                            || TREE_CODE (TREE_TYPE (subdatum)) != ARRAY_TYPE);
-
-         quals = TYPE_QUALS (strip_array_types (TREE_TYPE (subdatum)));
-         if (use_datum_quals)
-           quals |= TYPE_QUALS (TREE_TYPE (datum));
-         subtype = c_build_qualified_type (TREE_TYPE (subdatum), quals);
-
-         ref = build3 (COMPONENT_REF, subtype, datum, subdatum,
-                       NULL_TREE);
-         SET_EXPR_LOCATION (ref, loc);
-         if (TREE_READONLY (subdatum)
-             || (use_datum_quals && TREE_READONLY (datum)))
-           TREE_READONLY (ref) = 1;
-         if (TREE_THIS_VOLATILE (subdatum)
-             || (use_datum_quals && TREE_THIS_VOLATILE (datum)))
-           TREE_THIS_VOLATILE (ref) = 1;
-
-         if (TREE_DEPRECATED (subdatum))
-           warn_deprecated_use (subdatum, NULL_TREE);
-
-         datum = ref;
-
-         field = TREE_CHAIN (field);
-       }
-      while (field);
-
-      return ref;
-    }
-  else if (code != ERROR_MARK)
-    error_at (loc,
-             "request for member %qE in something not a structure or union",
-             component);
-
-  return error_mark_node;
-}
-\f
-/* Given an expression PTR for a pointer, return an expression
-   for the value pointed to.
-   ERRORSTRING is the name of the operator to appear in error messages.
-
-   LOC is the location to use for the generated tree.  */
-
-tree
-build_indirect_ref (location_t loc, tree ptr, ref_operator errstring)
-{
-  tree pointer = default_conversion (ptr);
-  tree type = TREE_TYPE (pointer);
-  tree ref;
-
-  if (TREE_CODE (type) == POINTER_TYPE)
-    {
-      if (CONVERT_EXPR_P (pointer)
-          || TREE_CODE (pointer) == VIEW_CONVERT_EXPR)
-       {
-         /* If a warning is issued, mark it to avoid duplicates from
-            the backend.  This only needs to be done at
-            warn_strict_aliasing > 2.  */
-         if (warn_strict_aliasing > 2)
-           if (strict_aliasing_warning (TREE_TYPE (TREE_OPERAND (pointer, 0)),
-                                        type, TREE_OPERAND (pointer, 0)))
-             TREE_NO_WARNING (pointer) = 1;
-       }
-
-      if (TREE_CODE (pointer) == ADDR_EXPR
-         && (TREE_TYPE (TREE_OPERAND (pointer, 0))
-             == TREE_TYPE (type)))
-       {
-         ref = TREE_OPERAND (pointer, 0);
-         protected_set_expr_location (ref, loc);
-         return ref;
-       }
-      else
-       {
-         tree t = TREE_TYPE (type);
-
-         ref = build1 (INDIRECT_REF, t, pointer);
-
-         if (!COMPLETE_OR_VOID_TYPE_P (t) && TREE_CODE (t) != ARRAY_TYPE)
-           {
-             error_at (loc, "dereferencing pointer to incomplete type");
-             return error_mark_node;
-           }
-         if (VOID_TYPE_P (t) && c_inhibit_evaluation_warnings == 0)
-           warning_at (loc, 0, "dereferencing %<void *%> pointer");
-
-         /* We *must* set TREE_READONLY when dereferencing a pointer to const,
-            so that we get the proper error message if the result is used
-            to assign to.  Also, &* is supposed to be a no-op.
-            And ANSI C seems to specify that the type of the result
-            should be the const type.  */
-         /* A de-reference of a pointer to const is not a const.  It is valid
-            to change it via some other pointer.  */
-         TREE_READONLY (ref) = TYPE_READONLY (t);
-         TREE_SIDE_EFFECTS (ref)
-           = TYPE_VOLATILE (t) || TREE_SIDE_EFFECTS (pointer);
-         TREE_THIS_VOLATILE (ref) = TYPE_VOLATILE (t);
-         protected_set_expr_location (ref, loc);
-         return ref;
-       }
-    }
-  else if (TREE_CODE (pointer) != ERROR_MARK)
-    invalid_indirection_error (loc, type, errstring);
-
-  return error_mark_node;
-}
-
-/* This handles expressions of the form "a[i]", which denotes
-   an array reference.
-
-   This is logically equivalent in C to *(a+i), but we may do it differently.
-   If A is a variable or a member, we generate a primitive ARRAY_REF.
-   This avoids forcing the array out of registers, and can work on
-   arrays that are not lvalues (for example, members of structures returned
-   by functions).
-
-   For vector types, allow vector[i] but not i[vector], and create
-   *(((type*)&vectortype) + i) for the expression.
-
-   LOC is the location to use for the returned expression.  */
-
-tree
-build_array_ref (location_t loc, tree array, tree index)
-{
-  tree ret;
-  bool swapped = false;
-  if (TREE_TYPE (array) == error_mark_node
-      || TREE_TYPE (index) == error_mark_node)
-    return error_mark_node;
-
-  if (TREE_CODE (TREE_TYPE (array)) != ARRAY_TYPE
-      && TREE_CODE (TREE_TYPE (array)) != POINTER_TYPE
-      /* Allow vector[index] but not index[vector].  */
-      && TREE_CODE (TREE_TYPE (array)) != VECTOR_TYPE)
-    {
-      tree temp;
-      if (TREE_CODE (TREE_TYPE (index)) != ARRAY_TYPE
-         && TREE_CODE (TREE_TYPE (index)) != POINTER_TYPE)
-       {
-          error_at (loc,
-            "subscripted value is neither array nor pointer nor vector");
-
-         return error_mark_node;
-       }
-      temp = array;
-      array = index;
-      index = temp;
-      swapped = true;
-    }
-
-  if (!INTEGRAL_TYPE_P (TREE_TYPE (index)))
-    {
-      error_at (loc, "array subscript is not an integer");
-      return error_mark_node;
-    }
-
-  if (TREE_CODE (TREE_TYPE (TREE_TYPE (array))) == FUNCTION_TYPE)
-    {
-      error_at (loc, "subscripted value is pointer to function");
-      return error_mark_node;
-    }
-
-  /* ??? Existing practice has been to warn only when the char
-     index is syntactically the index, not for char[array].  */
-  if (!swapped)
-     warn_array_subscript_with_type_char (index);
-
-  /* Apply default promotions *after* noticing character types.  */
-  index = default_conversion (index);
-
-  gcc_assert (TREE_CODE (TREE_TYPE (index)) == INTEGER_TYPE);
-
-  convert_vector_to_pointer_for_subscript (loc, &array, index);
-
-  if (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE)
-    {
-      tree rval, type;
-
-      /* An array that is indexed by a non-constant
-        cannot be stored in a register; we must be able to do
-        address arithmetic on its address.
-        Likewise an array of elements of variable size.  */
-      if (TREE_CODE (index) != INTEGER_CST
-         || (COMPLETE_TYPE_P (TREE_TYPE (TREE_TYPE (array)))
-             && TREE_CODE (TYPE_SIZE (TREE_TYPE (TREE_TYPE (array)))) != INTEGER_CST))
-       {
-         if (!c_mark_addressable (array))
-           return error_mark_node;
-       }
-      /* An array that is indexed by a constant value which is not within
-        the array bounds cannot be stored in a register either; because we
-        would get a crash in store_bit_field/extract_bit_field when trying
-        to access a non-existent part of the register.  */
-      if (TREE_CODE (index) == INTEGER_CST
-         && TYPE_DOMAIN (TREE_TYPE (array))
-         && !int_fits_type_p (index, TYPE_DOMAIN (TREE_TYPE (array))))
-       {
-         if (!c_mark_addressable (array))
-           return error_mark_node;
-       }
-
-      if (pedantic)
-       {
-         tree foo = array;
-         while (TREE_CODE (foo) == COMPONENT_REF)
-           foo = TREE_OPERAND (foo, 0);
-         if (TREE_CODE (foo) == VAR_DECL && C_DECL_REGISTER (foo))
-           pedwarn (loc, OPT_Wpedantic,
-                    "ISO C forbids subscripting %<register%> array");
-         else if (!flag_isoc99 && !lvalue_p (foo))
-           pedwarn (loc, OPT_Wpedantic,
-                    "ISO C90 forbids subscripting non-lvalue array");
-       }
-
-      type = TREE_TYPE (TREE_TYPE (array));
-      rval = build4 (ARRAY_REF, type, array, index, NULL_TREE, NULL_TREE);
-      /* Array ref is const/volatile if the array elements are
-        or if the array is.  */
-      TREE_READONLY (rval)
-       |= (TYPE_READONLY (TREE_TYPE (TREE_TYPE (array)))
-           | TREE_READONLY (array));
-      TREE_SIDE_EFFECTS (rval)
-       |= (TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (array)))
-           | TREE_SIDE_EFFECTS (array));
-      TREE_THIS_VOLATILE (rval)
-       |= (TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (array)))
-           /* This was added by rms on 16 Nov 91.
-              It fixes  vol struct foo *a;  a->elts[1]
-              in an inline function.
-              Hope it doesn't break something else.  */
-           | TREE_THIS_VOLATILE (array));
-      ret = require_complete_type (rval);
-      protected_set_expr_location (ret, loc);
-      return ret;
-    }
-  else
-    {
-      tree ar = default_conversion (array);
-
-      if (ar == error_mark_node)
-       return ar;
-
-      gcc_assert (TREE_CODE (TREE_TYPE (ar)) == POINTER_TYPE);
-      gcc_assert (TREE_CODE (TREE_TYPE (TREE_TYPE (ar))) != FUNCTION_TYPE);
-
-      return build_indirect_ref
-       (loc, build_binary_op (loc, PLUS_EXPR, ar, index, 0),
-        RO_ARRAY_INDEXING);
-    }
-}
-\f
-/* Build an external reference to identifier ID.  FUN indicates
-   whether this will be used for a function call.  LOC is the source
-   location of the identifier.  This sets *TYPE to the type of the
-   identifier, which is not the same as the type of the returned value
-   for CONST_DECLs defined as enum constants.  If the type of the
-   identifier is not available, *TYPE is set to NULL.  */
-tree
-build_external_ref (location_t loc, tree id, int fun, tree *type)
-{
-  tree ref;
-  tree decl = lookup_name (id);
-
-  /* In Objective-C, an instance variable (ivar) may be preferred to
-     whatever lookup_name() found.  */
-  decl = objc_lookup_ivar (decl, id);
-
-  *type = NULL;
-  if (decl && decl != error_mark_node)
-    {
-      ref = decl;
-      *type = TREE_TYPE (ref);
-    }
-  else if (fun)
-    /* Implicit function declaration.  */
-    ref = implicitly_declare (loc, id);
-  else if (decl == error_mark_node)
-    /* Don't complain about something that's already been
-       complained about.  */
-    return error_mark_node;
-  else
-    {
-      undeclared_variable (loc, id);
-      return error_mark_node;
-    }
-
-  if (TREE_TYPE (ref) == error_mark_node)
-    return error_mark_node;
-
-  if (TREE_DEPRECATED (ref))
-    warn_deprecated_use (ref, NULL_TREE);
-
-  /* Recursive call does not count as usage.  */
-  if (ref != current_function_decl)
-    {
-      TREE_USED (ref) = 1;
-    }
-
-  if (TREE_CODE (ref) == FUNCTION_DECL && !in_alignof)
-    {
-      if (!in_sizeof && !in_typeof)
-       C_DECL_USED (ref) = 1;
-      else if (DECL_INITIAL (ref) == 0
-              && DECL_EXTERNAL (ref)
-              && !TREE_PUBLIC (ref))
-       record_maybe_used_decl (ref);
-    }
-
-  if (TREE_CODE (ref) == CONST_DECL)
-    {
-      used_types_insert (TREE_TYPE (ref));
-
-      if (warn_cxx_compat
-         && TREE_CODE (TREE_TYPE (ref)) == ENUMERAL_TYPE
-         && C_TYPE_DEFINED_IN_STRUCT (TREE_TYPE (ref)))
-       {
-         warning_at (loc, OPT_Wc___compat,
-                     ("enum constant defined in struct or union "
-                      "is not visible in C++"));
-         inform (DECL_SOURCE_LOCATION (ref), "enum constant defined here");
-       }
-
-      ref = DECL_INITIAL (ref);
-      TREE_CONSTANT (ref) = 1;
-    }
-  else if (current_function_decl != 0
-          && !DECL_FILE_SCOPE_P (current_function_decl)
-          && (TREE_CODE (ref) == VAR_DECL
-              || TREE_CODE (ref) == PARM_DECL
-              || TREE_CODE (ref) == FUNCTION_DECL))
-    {
-      tree context = decl_function_context (ref);
-
-      if (context != 0 && context != current_function_decl)
-       DECL_NONLOCAL (ref) = 1;
-    }
-  /* C99 6.7.4p3: An inline definition of a function with external
-     linkage ... shall not contain a reference to an identifier with
-     internal linkage.  */
-  else if (current_function_decl != 0
-          && DECL_DECLARED_INLINE_P (current_function_decl)
-          && DECL_EXTERNAL (current_function_decl)
-          && VAR_OR_FUNCTION_DECL_P (ref)
-          && (TREE_CODE (ref) != VAR_DECL || TREE_STATIC (ref))
-          && ! TREE_PUBLIC (ref)
-          && DECL_CONTEXT (ref) != current_function_decl)
-    record_inline_static (loc, current_function_decl, ref,
-                         csi_internal);
-
-  return ref;
-}
-
-/* Record details of decls possibly used inside sizeof or typeof.  */
-struct maybe_used_decl
-{
-  /* The decl.  */
-  tree decl;
-  /* The level seen at (in_sizeof + in_typeof).  */
-  int level;
-  /* The next one at this level or above, or NULL.  */
-  struct maybe_used_decl *next;
-};
-
-static struct maybe_used_decl *maybe_used_decls;
-
-/* Record that DECL, an undefined static function reference seen
-   inside sizeof or typeof, might be used if the operand of sizeof is
-   a VLA type or the operand of typeof is a variably modified
-   type.  */
-
-static void
-record_maybe_used_decl (tree decl)
-{
-  struct maybe_used_decl *t = XOBNEW (&parser_obstack, struct maybe_used_decl);
-  t->decl = decl;
-  t->level = in_sizeof + in_typeof;
-  t->next = maybe_used_decls;
-  maybe_used_decls = t;
-}
-
-/* Pop the stack of decls possibly used inside sizeof or typeof.  If
-   USED is false, just discard them.  If it is true, mark them used
-   (if no longer inside sizeof or typeof) or move them to the next
-   level up (if still inside sizeof or typeof).  */
-
-void
-pop_maybe_used (bool used)
-{
-  struct maybe_used_decl *p = maybe_used_decls;
-  int cur_level = in_sizeof + in_typeof;
-  while (p && p->level > cur_level)
-    {
-      if (used)
-       {
-         if (cur_level == 0)
-           C_DECL_USED (p->decl) = 1;
-         else
-           p->level = cur_level;
-       }
-      p = p->next;
-    }
-  if (!used || cur_level == 0)
-    maybe_used_decls = p;
-}
-
-/* Return the result of sizeof applied to EXPR.  */
-
-struct c_expr
-c_expr_sizeof_expr (location_t loc, struct c_expr expr)
-{
-  struct c_expr ret;
-  if (expr.value == error_mark_node)
-    {
-      ret.value = error_mark_node;
-      ret.original_code = ERROR_MARK;
-      ret.original_type = NULL;
-      pop_maybe_used (false);
-    }
-  else
-    {
-      bool expr_const_operands = true;
-      tree folded_expr = c_fully_fold (expr.value, require_constant_value,
-                                      &expr_const_operands);
-      ret.value = c_sizeof (loc, TREE_TYPE (folded_expr));
-      ret.original_code = ERROR_MARK;
-      ret.original_type = NULL;
-      if (c_vla_type_p (TREE_TYPE (folded_expr)))
-       {
-         /* sizeof is evaluated when given a vla (C99 6.5.3.4p2).  */
-         ret.value = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (ret.value),
-                             folded_expr, ret.value);
-         C_MAYBE_CONST_EXPR_NON_CONST (ret.value) = !expr_const_operands;
-         SET_EXPR_LOCATION (ret.value, loc);
-       }
-      pop_maybe_used (C_TYPE_VARIABLE_SIZE (TREE_TYPE (folded_expr)));
-    }
-  return ret;
-}
-
-/* Return the result of sizeof applied to T, a structure for the type
-   name passed to sizeof (rather than the type itself).  LOC is the
-   location of the original expression.  */
-
-struct c_expr
-c_expr_sizeof_type (location_t loc, struct c_type_name *t)
-{
-  tree type;
-  struct c_expr ret;
-  tree type_expr = NULL_TREE;
-  bool type_expr_const = true;
-  type = groktypename (t, &type_expr, &type_expr_const);
-  ret.value = c_sizeof (loc, type);
-  ret.original_code = ERROR_MARK;
-  ret.original_type = NULL;
-  if ((type_expr || TREE_CODE (ret.value) == INTEGER_CST)
-      && c_vla_type_p (type))
-    {
-      /* If the type is a [*] array, it is a VLA but is represented as
-        having a size of zero.  In such a case we must ensure that
-        the result of sizeof does not get folded to a constant by
-        c_fully_fold, because if the size is evaluated the result is
-        not constant and so constraints on zero or negative size
-        arrays must not be applied when this sizeof call is inside
-        another array declarator.  */
-      if (!type_expr)
-       type_expr = integer_zero_node;
-      ret.value = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (ret.value),
-                         type_expr, ret.value);
-      C_MAYBE_CONST_EXPR_NON_CONST (ret.value) = !type_expr_const;
-    }
-  pop_maybe_used (type != error_mark_node
-                 ? C_TYPE_VARIABLE_SIZE (type) : false);
-  return ret;
-}
-
-/* Build a function call to function FUNCTION with parameters PARAMS.
-   The function call is at LOC.
-   PARAMS is a list--a chain of TREE_LIST nodes--in which the
-   TREE_VALUE of each node is a parameter-expression.
-   FUNCTION's data type may be a function type or a pointer-to-function.  */
-
-tree
-build_function_call (location_t loc, tree function, tree params)
-{
-  VEC(tree,gc) *vec;
-  tree ret;
-
-  vec = VEC_alloc (tree, gc, list_length (params));
-  for (; params; params = TREE_CHAIN (params))
-    VEC_quick_push (tree, vec, TREE_VALUE (params));
-  ret = build_function_call_vec (loc, function, vec, NULL);
-  VEC_free (tree, gc, vec);
-  return ret;
-}
-
-/* Give a note about the location of the declaration of DECL.  */
-
-static void inform_declaration (tree decl)
-{
-  if (decl && (TREE_CODE (decl) != FUNCTION_DECL || !DECL_BUILT_IN (decl)))
-    inform (DECL_SOURCE_LOCATION (decl), "declared here");
-}
-
-/* Build a function call to function FUNCTION with parameters PARAMS.
-   ORIGTYPES, if not NULL, is a vector of types; each element is
-   either NULL or the original type of the corresponding element in
-   PARAMS.  The original type may differ from TREE_TYPE of the
-   parameter for enums.  FUNCTION's data type may be a function type
-   or pointer-to-function.  This function changes the elements of
-   PARAMS.  */
-
-tree
-build_function_call_vec (location_t loc, tree function, VEC(tree,gc) *params,
-                        VEC(tree,gc) *origtypes)
-{
-  tree fntype, fundecl = 0;
-  tree name = NULL_TREE, result;
-  tree tem;
-  int nargs;
-  tree *argarray;
-
-
-  /* Strip NON_LVALUE_EXPRs, etc., since we aren't using as an lvalue.  */
-  STRIP_TYPE_NOPS (function);
-
-  /* Convert anything with function type to a pointer-to-function.  */
-  if (TREE_CODE (function) == FUNCTION_DECL)
-    {
-      /* Implement type-directed function overloading for builtins.
-        resolve_overloaded_builtin and targetm.resolve_overloaded_builtin
-        handle all the type checking.  The result is a complete expression
-        that implements this function call.  */
-      tem = resolve_overloaded_builtin (loc, function, params);
-      if (tem)
-       return tem;
-
-      name = DECL_NAME (function);
-
-      if (flag_tm)
-       tm_malloc_replacement (function);
-      fundecl = function;
-      /* Atomic functions have type checking/casting already done.  They are 
-        often rewritten and don't match the original parameter list.  */
-      if (name && !strncmp (IDENTIFIER_POINTER (name), "__atomic_", 9))
-        origtypes = NULL;
-    }
-  if (TREE_CODE (TREE_TYPE (function)) == FUNCTION_TYPE)
-    function = function_to_pointer_conversion (loc, function);
-
-  /* For Objective-C, convert any calls via a cast to OBJC_TYPE_REF
-     expressions, like those used for ObjC messenger dispatches.  */
-  if (!VEC_empty (tree, params))
-    function = objc_rewrite_function_call (function,
-                                          VEC_index (tree, params, 0));
-
-  function = c_fully_fold (function, false, NULL);
-
-  fntype = TREE_TYPE (function);
-
-  if (TREE_CODE (fntype) == ERROR_MARK)
-    return error_mark_node;
-
-  if (!(TREE_CODE (fntype) == POINTER_TYPE
-       && TREE_CODE (TREE_TYPE (fntype)) == FUNCTION_TYPE))
-    {
-      if (!flag_diagnostics_show_caret)
-       error_at (loc,
-                 "called object %qE is not a function or function pointer",
-                 function);
-      else if (DECL_P (function))
-       {
-         error_at (loc,
-                   "called object %qD is not a function or function pointer",
-                   function);
-         inform_declaration (function);
-       }
-      else
-       error_at (loc,
-                 "called object is not a function or function pointer");
-      return error_mark_node;
-    }
-
-  if (fundecl && TREE_THIS_VOLATILE (fundecl))
-    current_function_returns_abnormally = 1;
-
-  /* fntype now gets the type of function pointed to.  */
-  fntype = TREE_TYPE (fntype);
-
-  /* Convert the parameters to the types declared in the
-     function prototype, or apply default promotions.  */
-
-  nargs = convert_arguments (TYPE_ARG_TYPES (fntype), params, origtypes,
-                            function, fundecl);
-  if (nargs < 0)
-    return error_mark_node;
-
-  /* Check that the function is called through a compatible prototype.
-     If it is not, replace the call by a trap, wrapped up in a compound
-     expression if necessary.  This has the nice side-effect to prevent
-     the tree-inliner from generating invalid assignment trees which may
-     blow up in the RTL expander later.  */
-  if (CONVERT_EXPR_P (function)
-      && TREE_CODE (tem = TREE_OPERAND (function, 0)) == ADDR_EXPR
-      && TREE_CODE (tem = TREE_OPERAND (tem, 0)) == FUNCTION_DECL
-      && !comptypes (fntype, TREE_TYPE (tem)))
-    {
-      tree return_type = TREE_TYPE (fntype);
-      tree trap = build_function_call (loc,
-                                      builtin_decl_explicit (BUILT_IN_TRAP),
-                                      NULL_TREE);
-      int i;
-
-      /* This situation leads to run-time undefined behavior.  We can't,
-        therefore, simply error unless we can prove that all possible
-        executions of the program must execute the code.  */
-      if (warning_at (loc, 0, "function called through a non-compatible type"))
-       /* We can, however, treat "undefined" any way we please.
-          Call abort to encourage the user to fix the program.  */
-       inform (loc, "if this code is reached, the program will abort");
-      /* Before the abort, allow the function arguments to exit or
-        call longjmp.  */
-      for (i = 0; i < nargs; i++)
-       trap = build2 (COMPOUND_EXPR, void_type_node,
-                      VEC_index (tree, params, i), trap);
-
-      if (VOID_TYPE_P (return_type))
-       {
-         if (TYPE_QUALS (return_type) != TYPE_UNQUALIFIED)
-           pedwarn (loc, 0,
-                    "function with qualified void return type called");
-         return trap;
-       }
-      else
-       {
-         tree rhs;
-
-         if (AGGREGATE_TYPE_P (return_type))
-           rhs = build_compound_literal (loc, return_type,
-                                         build_constructor (return_type, 0),
-                                         false);
-         else
-           rhs = build_zero_cst (return_type);
-
-         return require_complete_type (build2 (COMPOUND_EXPR, return_type,
-                                               trap, rhs));
-       }
-    }
-
-  argarray = VEC_address (tree, params);
-
-  /* Check that arguments to builtin functions match the expectations.  */
-  if (fundecl
-      && DECL_BUILT_IN (fundecl)
-      && DECL_BUILT_IN_CLASS (fundecl) == BUILT_IN_NORMAL
-      && !check_builtin_function_arguments (fundecl, nargs, argarray))
-    return error_mark_node;
-
-  /* Check that the arguments to the function are valid.  */
-  check_function_arguments (fntype, nargs, argarray);
-
-  if (name != NULL_TREE
-      && !strncmp (IDENTIFIER_POINTER (name), "__builtin_", 10))
-    {
-      if (require_constant_value)
-       result =
-         fold_build_call_array_initializer_loc (loc, TREE_TYPE (fntype),
-                                                function, nargs, argarray);
-      else
-       result = fold_build_call_array_loc (loc, TREE_TYPE (fntype),
-                                           function, nargs, argarray);
-      if (TREE_CODE (result) == NOP_EXPR
-         && TREE_CODE (TREE_OPERAND (result, 0)) == INTEGER_CST)
-       STRIP_TYPE_NOPS (result);
-    }
-  else
-    result = build_call_array_loc (loc, TREE_TYPE (fntype),
-                                  function, nargs, argarray);
-
-  if (VOID_TYPE_P (TREE_TYPE (result)))
-    {
-      if (TYPE_QUALS (TREE_TYPE (result)) != TYPE_UNQUALIFIED)
-       pedwarn (loc, 0,
-                "function with qualified void return type called");
-      return result;
-    }
-  return require_complete_type (result);
-}
-\f
-/* Convert the argument expressions in the vector VALUES
-   to the types in the list TYPELIST.
-
-   If TYPELIST is exhausted, or when an element has NULL as its type,
-   perform the default conversions.
-
-   ORIGTYPES is the original types of the expressions in VALUES.  This
-   holds the type of enum values which have been converted to integral
-   types.  It may be NULL.
-
-   FUNCTION is a tree for the called function.  It is used only for
-   error messages, where it is formatted with %qE.
-
-   This is also where warnings about wrong number of args are generated.
-
-   Returns the actual number of arguments processed (which may be less
-   than the length of VALUES in some error situations), or -1 on
-   failure.  */
-
-static int
-convert_arguments (tree typelist, VEC(tree,gc) *values,
-                  VEC(tree,gc) *origtypes, tree function, tree fundecl)
-{
-  tree typetail, val;
-  unsigned int parmnum;
-  bool error_args = false;
-  const bool type_generic = fundecl
-    && lookup_attribute ("type generic", TYPE_ATTRIBUTES(TREE_TYPE (fundecl)));
-  bool type_generic_remove_excess_precision = false;
-  tree selector;
-
-  /* Change pointer to function to the function itself for
-     diagnostics.  */
-  if (TREE_CODE (function) == ADDR_EXPR
-      && TREE_CODE (TREE_OPERAND (function, 0)) == FUNCTION_DECL)
-    function = TREE_OPERAND (function, 0);
-
-  /* Handle an ObjC selector specially for diagnostics.  */
-  selector = objc_message_selector ();
-
-  /* For type-generic built-in functions, determine whether excess
-     precision should be removed (classification) or not
-     (comparison).  */
-  if (type_generic
-      && DECL_BUILT_IN (fundecl)
-      && DECL_BUILT_IN_CLASS (fundecl) == BUILT_IN_NORMAL)
-    {
-      switch (DECL_FUNCTION_CODE (fundecl))
-       {
-       case BUILT_IN_ISFINITE:
-       case BUILT_IN_ISINF:
-       case BUILT_IN_ISINF_SIGN:
-       case BUILT_IN_ISNAN:
-       case BUILT_IN_ISNORMAL:
-       case BUILT_IN_FPCLASSIFY:
-         type_generic_remove_excess_precision = true;
-         break;
-
-       default:
-         type_generic_remove_excess_precision = false;
-         break;
-       }
-    }
-
-  /* Scan the given expressions and types, producing individual
-     converted arguments.  */
-
-  for (typetail = typelist, parmnum = 0;
-       VEC_iterate (tree, values, parmnum, val);
-       ++parmnum)
-    {
-      tree type = typetail ? TREE_VALUE (typetail) : 0;
-      tree valtype = TREE_TYPE (val);
-      tree rname = function;
-      int argnum = parmnum + 1;
-      const char *invalid_func_diag;
-      bool excess_precision = false;
-      bool npc;
-      tree parmval;
-
-      if (type == void_type_node)
-       {
-         if (selector)
-           error_at (input_location,
-                     "too many arguments to method %qE", selector);
-         else
-           error_at (input_location,
-                     "too many arguments to function %qE", function);
-         inform_declaration (fundecl);
-         return parmnum;
-       }
-
-      if (selector && argnum > 2)
-       {
-         rname = selector;
-         argnum -= 2;
-       }
-
-      npc = null_pointer_constant_p (val);
-
-      /* If there is excess precision and a prototype, convert once to
-        the required type rather than converting via the semantic
-        type.  Likewise without a prototype a float value represented
-        as long double should be converted once to double.  But for
-        type-generic classification functions excess precision must
-        be removed here.  */
-      if (TREE_CODE (val) == EXCESS_PRECISION_EXPR
-         && (type || !type_generic || !type_generic_remove_excess_precision))
-       {
-         val = TREE_OPERAND (val, 0);
-         excess_precision = true;
-       }
-      val = c_fully_fold (val, false, NULL);
-      STRIP_TYPE_NOPS (val);
-
-      val = require_complete_type (val);
-
-      if (type != 0)
-       {
-         /* Formal parm type is specified by a function prototype.  */
-
-         if (type == error_mark_node || !COMPLETE_TYPE_P (type))
-           {
-             error ("type of formal parameter %d is incomplete", parmnum + 1);
-             parmval = val;
-           }
-         else
-           {
-             tree origtype;
-
-             /* Optionally warn about conversions that
-                differ from the default conversions.  */
-             if (warn_traditional_conversion || warn_traditional)
-               {
-                 unsigned int formal_prec = TYPE_PRECISION (type);
-
-                 if (INTEGRAL_TYPE_P (type)
-                     && TREE_CODE (valtype) == REAL_TYPE)
-                   warning (0, "passing argument %d of %qE as integer "
-                            "rather than floating due to prototype",
-                            argnum, rname);
-                 if (INTEGRAL_TYPE_P (type)
-                     && TREE_CODE (valtype) == COMPLEX_TYPE)
-                   warning (0, "passing argument %d of %qE as integer "
-                            "rather than complex due to prototype",
-                            argnum, rname);
-                 else if (TREE_CODE (type) == COMPLEX_TYPE
-                          && TREE_CODE (valtype) == REAL_TYPE)
-                   warning (0, "passing argument %d of %qE as complex "
-                            "rather than floating due to prototype",
-                            argnum, rname);
-                 else if (TREE_CODE (type) == REAL_TYPE
-                          && INTEGRAL_TYPE_P (valtype))
-                   warning (0, "passing argument %d of %qE as floating "
-                            "rather than integer due to prototype",
-                            argnum, rname);
-                 else if (TREE_CODE (type) == COMPLEX_TYPE
-                          && INTEGRAL_TYPE_P (valtype))
-                   warning (0, "passing argument %d of %qE as complex "
-                            "rather than integer due to prototype",
-                            argnum, rname);
-                 else if (TREE_CODE (type) == REAL_TYPE
-                          && TREE_CODE (valtype) == COMPLEX_TYPE)
-                   warning (0, "passing argument %d of %qE as floating "
-                            "rather than complex due to prototype",
-                            argnum, rname);
-                 /* ??? At some point, messages should be written about
-                    conversions between complex types, but that's too messy
-                    to do now.  */
-                 else if (TREE_CODE (type) == REAL_TYPE
-                          && TREE_CODE (valtype) == REAL_TYPE)
-                   {
-                     /* Warn if any argument is passed as `float',
-                        since without a prototype it would be `double'.  */
-                     if (formal_prec == TYPE_PRECISION (float_type_node)
-                         && type != dfloat32_type_node)
-                       warning (0, "passing argument %d of %qE as %<float%> "
-                                "rather than %<double%> due to prototype",
-                                argnum, rname);
-
-                     /* Warn if mismatch between argument and prototype
-                        for decimal float types.  Warn of conversions with
-                        binary float types and of precision narrowing due to
-                        prototype. */
-                     else if (type != valtype
-                              && (type == dfloat32_type_node
-                                  || type == dfloat64_type_node
-                                  || type == dfloat128_type_node
-                                  || valtype == dfloat32_type_node
-                                  || valtype == dfloat64_type_node
-                                  || valtype == dfloat128_type_node)
-                              && (formal_prec
-                                  <= TYPE_PRECISION (valtype)
-                                  || (type == dfloat128_type_node
-                                      && (valtype
-                                          != dfloat64_type_node
-                                          && (valtype
-                                              != dfloat32_type_node)))
-                                  || (type == dfloat64_type_node
-                                      && (valtype
-                                          != dfloat32_type_node))))
-                       warning (0, "passing argument %d of %qE as %qT "
-                                "rather than %qT due to prototype",
-                                argnum, rname, type, valtype);
-
-                   }
-                 /* Detect integer changing in width or signedness.
-                    These warnings are only activated with
-                    -Wtraditional-conversion, not with -Wtraditional.  */
-                 else if (warn_traditional_conversion && INTEGRAL_TYPE_P (type)
-                          && INTEGRAL_TYPE_P (valtype))
-                   {
-                     tree would_have_been = default_conversion (val);
-                     tree type1 = TREE_TYPE (would_have_been);
-
-                     if (TREE_CODE (type) == ENUMERAL_TYPE
-                         && (TYPE_MAIN_VARIANT (type)
-                             == TYPE_MAIN_VARIANT (valtype)))
-                       /* No warning if function asks for enum
-                          and the actual arg is that enum type.  */
-                       ;
-                     else if (formal_prec != TYPE_PRECISION (type1))
-                       warning (OPT_Wtraditional_conversion,
-                                "passing argument %d of %qE "
-                                "with different width due to prototype",
-                                argnum, rname);
-                     else if (TYPE_UNSIGNED (type) == TYPE_UNSIGNED (type1))
-                       ;
-                     /* Don't complain if the formal parameter type
-                        is an enum, because we can't tell now whether
-                        the value was an enum--even the same enum.  */
-                     else if (TREE_CODE (type) == ENUMERAL_TYPE)
-                       ;
-                     else if (TREE_CODE (val) == INTEGER_CST
-                              && int_fits_type_p (val, type))
-                       /* Change in signedness doesn't matter
-                          if a constant value is unaffected.  */
-                       ;
-                     /* If the value is extended from a narrower
-                        unsigned type, it doesn't matter whether we
-                        pass it as signed or unsigned; the value
-                        certainly is the same either way.  */
-                     else if (TYPE_PRECISION (valtype) < TYPE_PRECISION (type)
-                              && TYPE_UNSIGNED (valtype))
-                       ;
-                     else if (TYPE_UNSIGNED (type))
-                       warning (OPT_Wtraditional_conversion,
-                                "passing argument %d of %qE "
-                                "as unsigned due to prototype",
-                                argnum, rname);
-                     else
-                       warning (OPT_Wtraditional_conversion,
-                                "passing argument %d of %qE "
-                                "as signed due to prototype", argnum, rname);
-                   }
-               }
-
-             /* Possibly restore an EXCESS_PRECISION_EXPR for the
-                sake of better warnings from convert_and_check.  */
-             if (excess_precision)
-               val = build1 (EXCESS_PRECISION_EXPR, valtype, val);
-             origtype = (origtypes == NULL
-                         ? NULL_TREE
-                         : VEC_index (tree, origtypes, parmnum));
-             parmval = convert_for_assignment (input_location, type, val,
-                                               origtype, ic_argpass, npc,
-                                               fundecl, function,
-                                               parmnum + 1);
-
-             if (targetm.calls.promote_prototypes (fundecl ? TREE_TYPE (fundecl) : 0)
-                 && INTEGRAL_TYPE_P (type)
-                 && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
-               parmval = default_conversion (parmval);
-           }
-       }
-      else if (TREE_CODE (valtype) == REAL_TYPE
-              && (TYPE_PRECISION (valtype)
-                  < TYPE_PRECISION (double_type_node))
-              && !DECIMAL_FLOAT_MODE_P (TYPE_MODE (valtype)))
-        {
-         if (type_generic)
-           parmval = val;
-         else
-           {
-             /* Convert `float' to `double'.  */
-             if (warn_double_promotion && !c_inhibit_evaluation_warnings)
-               warning (OPT_Wdouble_promotion,
-                        "implicit conversion from %qT to %qT when passing "
-                        "argument to function",
-                        valtype, double_type_node);
-             parmval = convert (double_type_node, val);
-           }
-       }
-      else if (excess_precision && !type_generic)
-       /* A "double" argument with excess precision being passed
-          without a prototype or in variable arguments.  */
-       parmval = convert (valtype, val);
-      else if ((invalid_func_diag =
-               targetm.calls.invalid_arg_for_unprototyped_fn (typelist, fundecl, val)))
-       {
-         error (invalid_func_diag);
-         return -1;
-       }
-      else
-       /* Convert `short' and `char' to full-size `int'.  */
-       parmval = default_conversion (val);
-
-      VEC_replace (tree, values, parmnum, parmval);
-      if (parmval == error_mark_node)
-       error_args = true;
-
-      if (typetail)
-       typetail = TREE_CHAIN (typetail);
-    }
-
-  gcc_assert (parmnum == VEC_length (tree, values));
-
-  if (typetail != 0 && TREE_VALUE (typetail) != void_type_node)
-    {
-      error_at (input_location,
-               "too few arguments to function %qE", function);
-      inform_declaration (fundecl);
-      return -1;
-    }
-
-  return error_args ? -1 : (int) parmnum;
-}
-\f
-/* This is the entry point used by the parser to build unary operators
-   in the input.  CODE, a tree_code, specifies the unary operator, and
-   ARG is the operand.  For unary plus, the C parser currently uses
-   CONVERT_EXPR for code.
-
-   LOC is the location to use for the tree generated.
-*/
-
-struct c_expr
-parser_build_unary_op (location_t loc, enum tree_code code, struct c_expr arg)
-{
-  struct c_expr result;
-
-  result.value = build_unary_op (loc, code, arg.value, 0);
-  result.original_code = code;
-  result.original_type = NULL;
-
-  if (TREE_OVERFLOW_P (result.value) && !TREE_OVERFLOW_P (arg.value))
-    overflow_warning (loc, result.value);
-
-  return result;
-}
-
-/* This is the entry point used by the parser to build binary operators
-   in the input.  CODE, a tree_code, specifies the binary operator, and
-   ARG1 and ARG2 are the operands.  In addition to constructing the
-   expression, we check for operands that were written with other binary
-   operators in a way that is likely to confuse the user.
-
-   LOCATION is the location of the binary operator.  */
-
-struct c_expr
-parser_build_binary_op (location_t location, enum tree_code code,
-                       struct c_expr arg1, struct c_expr arg2)
-{
-  struct c_expr result;
-
-  enum tree_code code1 = arg1.original_code;
-  enum tree_code code2 = arg2.original_code;
-  tree type1 = (arg1.original_type
-                ? arg1.original_type
-                : TREE_TYPE (arg1.value));
-  tree type2 = (arg2.original_type
-                ? arg2.original_type
-                : TREE_TYPE (arg2.value));
-
-  result.value = build_binary_op (location, code,
-                                 arg1.value, arg2.value, 1);
-  result.original_code = code;
-  result.original_type = NULL;
-
-  if (TREE_CODE (result.value) == ERROR_MARK)
-    return result;
-
-  if (location != UNKNOWN_LOCATION)
-    protected_set_expr_location (result.value, location);
-
-  /* Check for cases such as x+y<<z which users are likely
-     to misinterpret.  */
-  if (warn_parentheses)
-    warn_about_parentheses (code, code1, arg1.value, code2, arg2.value);
-
-  if (warn_logical_op)
-    warn_logical_operator (input_location, code, TREE_TYPE (result.value),
-                          code1, arg1.value, code2, arg2.value);
-
-  /* Warn about comparisons against string literals, with the exception
-     of testing for equality or inequality of a string literal with NULL.  */
-  if (code == EQ_EXPR || code == NE_EXPR)
-    {
-      if ((code1 == STRING_CST && !integer_zerop (arg2.value))
-         || (code2 == STRING_CST && !integer_zerop (arg1.value)))
-       warning_at (location, OPT_Waddress,
-                   "comparison with string literal results in unspecified behavior");
-    }
-  else if (TREE_CODE_CLASS (code) == tcc_comparison
-          && (code1 == STRING_CST || code2 == STRING_CST))
-    warning_at (location, OPT_Waddress,
-               "comparison with string literal results in unspecified behavior");
-
-  if (TREE_OVERFLOW_P (result.value)
-      && !TREE_OVERFLOW_P (arg1.value)
-      && !TREE_OVERFLOW_P (arg2.value))
-    overflow_warning (location, result.value);
-
-  /* Warn about comparisons of different enum types.  */
-  if (warn_enum_compare
-      && TREE_CODE_CLASS (code) == tcc_comparison
-      && TREE_CODE (type1) == ENUMERAL_TYPE
-      && TREE_CODE (type2) == ENUMERAL_TYPE
-      && TYPE_MAIN_VARIANT (type1) != TYPE_MAIN_VARIANT (type2))
-    warning_at (location, OPT_Wenum_compare,
-               "comparison between %qT and %qT",
-               type1, type2);
-
-  return result;
-}
-\f
-/* Return a tree for the difference of pointers OP0 and OP1.
-   The resulting tree has type int.  */
-
-static tree
-pointer_diff (location_t loc, tree op0, tree op1)
-{
-  tree restype = ptrdiff_type_node;
-  tree result, inttype;
-
-  addr_space_t as0 = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (op0)));
-  addr_space_t as1 = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (op1)));
-  tree target_type = TREE_TYPE (TREE_TYPE (op0));
-  tree con0, con1, lit0, lit1;
-  tree orig_op1 = op1;
-
-  /* If the operands point into different address spaces, we need to
-     explicitly convert them to pointers into the common address space
-     before we can subtract the numerical address values.  */
-  if (as0 != as1)
-    {
-      addr_space_t as_common;
-      tree common_type;
-
-      /* Determine the common superset address space.  This is guaranteed
-        to exist because the caller verified that comp_target_types
-        returned non-zero.  */
-      if (!addr_space_superset (as0, as1, &as_common))
-       gcc_unreachable ();
-
-      common_type = common_pointer_type (TREE_TYPE (op0), TREE_TYPE (op1));
-      op0 = convert (common_type, op0);
-      op1 = convert (common_type, op1);
-    }
-
-  /* Determine integer type to perform computations in.  This will usually
-     be the same as the result type (ptrdiff_t), but may need to be a wider
-     type if pointers for the address space are wider than ptrdiff_t.  */
-  if (TYPE_PRECISION (restype) < TYPE_PRECISION (TREE_TYPE (op0)))
-    inttype = c_common_type_for_size (TYPE_PRECISION (TREE_TYPE (op0)), 0);
-  else
-    inttype = restype;
-
-
-  if (TREE_CODE (target_type) == VOID_TYPE)
-    pedwarn (loc, pedantic ? OPT_Wpedantic : OPT_Wpointer_arith,
-            "pointer of type %<void *%> used in subtraction");
-  if (TREE_CODE (target_type) == FUNCTION_TYPE)
-    pedwarn (loc, pedantic ? OPT_Wpedantic : OPT_Wpointer_arith,
-            "pointer to a function used in subtraction");
-
-  /* If the conversion to ptrdiff_type does anything like widening or
-     converting a partial to an integral mode, we get a convert_expression
-     that is in the way to do any simplifications.
-     (fold-const.c doesn't know that the extra bits won't be needed.
-     split_tree uses STRIP_SIGN_NOPS, which leaves conversions to a
-     different mode in place.)
-     So first try to find a common term here 'by hand'; we want to cover
-     at least the cases that occur in legal static initializers.  */
-  if (CONVERT_EXPR_P (op0)
-      && (TYPE_PRECISION (TREE_TYPE (op0))
-         == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (op0, 0)))))
-    con0 = TREE_OPERAND (op0, 0);
-  else
-    con0 = op0;
-  if (CONVERT_EXPR_P (op1)
-      && (TYPE_PRECISION (TREE_TYPE (op1))
-         == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (op1, 0)))))
-    con1 = TREE_OPERAND (op1, 0);
-  else
-    con1 = op1;
-
-  if (TREE_CODE (con0) == POINTER_PLUS_EXPR)
-    {
-      lit0 = TREE_OPERAND (con0, 1);
-      con0 = TREE_OPERAND (con0, 0);
-    }
-  else
-    lit0 = integer_zero_node;
-
-  if (TREE_CODE (con1) == POINTER_PLUS_EXPR)
-    {
-      lit1 = TREE_OPERAND (con1, 1);
-      con1 = TREE_OPERAND (con1, 0);
-    }
-  else
-    lit1 = integer_zero_node;
-
-  if (operand_equal_p (con0, con1, 0))
-    {
-      op0 = lit0;
-      op1 = lit1;
-    }
-
-
-  /* First do the subtraction as integers;
-     then drop through to build the divide operator.
-     Do not do default conversions on the minus operator
-     in case restype is a short type.  */
-
-  op0 = build_binary_op (loc,
-                        MINUS_EXPR, convert (inttype, op0),
-                        convert (inttype, op1), 0);
-  /* This generates an error if op1 is pointer to incomplete type.  */
-  if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (TREE_TYPE (orig_op1))))
-    error_at (loc, "arithmetic on pointer to an incomplete type");
-
-  /* This generates an error if op0 is pointer to incomplete type.  */
-  op1 = c_size_in_bytes (target_type);
-
-  /* Divide by the size, in easiest possible way.  */
-  result = fold_build2_loc (loc, EXACT_DIV_EXPR, inttype,
-                           op0, convert (inttype, op1));
-
-  /* Convert to final result type if necessary.  */
-  return convert (restype, result);
-}
-\f
-/* Construct and perhaps optimize a tree representation
-   for a unary operation.  CODE, a tree_code, specifies the operation
-   and XARG is the operand.
-   For any CODE other than ADDR_EXPR, FLAG nonzero suppresses
-   the default promotions (such as from short to int).
-   For ADDR_EXPR, the default promotions are not applied; FLAG nonzero
-   allows non-lvalues; this is only used to handle conversion of non-lvalue
-   arrays to pointers in C99.
-
-   LOCATION is the location of the operator.  */
-
-tree
-build_unary_op (location_t location,
-               enum tree_code code, tree xarg, int flag)
-{
-  /* No default_conversion here.  It causes trouble for ADDR_EXPR.  */
-  tree arg = xarg;
-  tree argtype = 0;
-  enum tree_code typecode;
-  tree val;
-  tree ret = error_mark_node;
-  tree eptype = NULL_TREE;
-  int noconvert = flag;
-  const char *invalid_op_diag;
-  bool int_operands;
-
-  int_operands = EXPR_INT_CONST_OPERANDS (xarg);
-  if (int_operands)
-    arg = remove_c_maybe_const_expr (arg);
-
-  if (code != ADDR_EXPR)
-    arg = require_complete_type (arg);
-
-  typecode = TREE_CODE (TREE_TYPE (arg));
-  if (typecode == ERROR_MARK)
-    return error_mark_node;
-  if (typecode == ENUMERAL_TYPE || typecode == BOOLEAN_TYPE)
-    typecode = INTEGER_TYPE;
-
-  if ((invalid_op_diag
-       = targetm.invalid_unary_op (code, TREE_TYPE (xarg))))
-    {
-      error_at (location, invalid_op_diag);
-      return error_mark_node;
-    }
-
-  if (TREE_CODE (arg) == EXCESS_PRECISION_EXPR)
-    {
-      eptype = TREE_TYPE (arg);
-      arg = TREE_OPERAND (arg, 0);
-    }
-
-  switch (code)
-    {
-    case CONVERT_EXPR:
-      /* This is used for unary plus, because a CONVERT_EXPR
-        is enough to prevent anybody from looking inside for
-        associativity, but won't generate any code.  */
-      if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE
-           || typecode == FIXED_POINT_TYPE || typecode == COMPLEX_TYPE
-           || typecode == VECTOR_TYPE))
-       {
-         error_at (location, "wrong type argument to unary plus");
-         return error_mark_node;
-       }
-      else if (!noconvert)
-       arg = default_conversion (arg);
-      arg = non_lvalue_loc (location, arg);
-      break;
-
-    case NEGATE_EXPR:
-      if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE
-           || typecode == FIXED_POINT_TYPE || typecode == COMPLEX_TYPE
-           || typecode == VECTOR_TYPE))
-       {
-         error_at (location, "wrong type argument to unary minus");
-         return error_mark_node;
-       }
-      else if (!noconvert)
-       arg = default_conversion (arg);
-      break;
-
-    case BIT_NOT_EXPR:
-      /* ~ works on integer types and non float vectors. */
-      if (typecode == INTEGER_TYPE
-         || (typecode == VECTOR_TYPE
-             && !VECTOR_FLOAT_TYPE_P (TREE_TYPE (arg))))
-       {
-         if (!noconvert)
-           arg = default_conversion (arg);
-       }
-      else if (typecode == COMPLEX_TYPE)
-       {
-         code = CONJ_EXPR;
-         pedwarn (location, OPT_Wpedantic,
-                  "ISO C does not support %<~%> for complex conjugation");
-         if (!noconvert)
-           arg = default_conversion (arg);
-       }
-      else
-       {
-         error_at (location, "wrong type argument to bit-complement");
-         return error_mark_node;
-       }
-      break;
-
-    case ABS_EXPR:
-      if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE))
-       {
-         error_at (location, "wrong type argument to abs");
-         return error_mark_node;
-       }
-      else if (!noconvert)
-       arg = default_conversion (arg);
-      break;
-
-    case CONJ_EXPR:
-      /* Conjugating a real value is a no-op, but allow it anyway.  */
-      if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE
-           || typecode == COMPLEX_TYPE))
-       {
-         error_at (location, "wrong type argument to conjugation");
-         return error_mark_node;
-       }
-      else if (!noconvert)
-       arg = default_conversion (arg);
-      break;
-
-    case TRUTH_NOT_EXPR:
-      if (typecode != INTEGER_TYPE && typecode != FIXED_POINT_TYPE
-         && typecode != REAL_TYPE && typecode != POINTER_TYPE
-         && typecode != COMPLEX_TYPE)
-       {
-         error_at (location,
-                   "wrong type argument to unary exclamation mark");
-         return error_mark_node;
-       }
-      arg = c_objc_common_truthvalue_conversion (location, arg);
-      ret = invert_truthvalue_loc (location, arg);
-      /* If the TRUTH_NOT_EXPR has been folded, reset the location.  */
-      if (EXPR_P (ret) && EXPR_HAS_LOCATION (ret))
-       location = EXPR_LOCATION (ret);
-      goto return_build_unary_op;
-
-    case REALPART_EXPR:
-    case IMAGPART_EXPR:
-      ret = build_real_imag_expr (location, code, arg);
-      if (ret == error_mark_node)
-       return error_mark_node;
-      if (eptype && TREE_CODE (eptype) == COMPLEX_TYPE)
-       eptype = TREE_TYPE (eptype);
-      goto return_build_unary_op;
-
-    case PREINCREMENT_EXPR:
-    case POSTINCREMENT_EXPR:
-    case PREDECREMENT_EXPR:
-    case POSTDECREMENT_EXPR:
-
-      if (TREE_CODE (arg) == C_MAYBE_CONST_EXPR)
-       {
-         tree inner = build_unary_op (location, code,
-                                      C_MAYBE_CONST_EXPR_EXPR (arg), flag);
-         if (inner == error_mark_node)
-           return error_mark_node;
-         ret = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (inner),
-                       C_MAYBE_CONST_EXPR_PRE (arg), inner);
-         gcc_assert (!C_MAYBE_CONST_EXPR_INT_OPERANDS (arg));
-         C_MAYBE_CONST_EXPR_NON_CONST (ret) = 1;
-         goto return_build_unary_op;
-       }
-
-      /* Complain about anything that is not a true lvalue.  In
-        Objective-C, skip this check for property_refs.  */
-      if (!objc_is_property_ref (arg)
-         && !lvalue_or_else (location,
-                             arg, ((code == PREINCREMENT_EXPR
-                                    || code == POSTINCREMENT_EXPR)
-                                   ? lv_increment
-                                   : lv_decrement)))
-       return error_mark_node;
-
-      if (warn_cxx_compat && TREE_CODE (TREE_TYPE (arg)) == ENUMERAL_TYPE)
-       {
-         if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR)
-           warning_at (location, OPT_Wc___compat,
-                       "increment of enumeration value is invalid in C++");
-         else
-           warning_at (location, OPT_Wc___compat,
-                       "decrement of enumeration value is invalid in C++");
-       }
-
-      /* Ensure the argument is fully folded inside any SAVE_EXPR.  */
-      arg = c_fully_fold (arg, false, NULL);
-
-      /* Increment or decrement the real part of the value,
-        and don't change the imaginary part.  */
-      if (typecode == COMPLEX_TYPE)
-       {
-         tree real, imag;
-
-         pedwarn (location, OPT_Wpedantic,
-                  "ISO C does not support %<++%> and %<--%> on complex types");
-
-         arg = stabilize_reference (arg);
-         real = build_unary_op (EXPR_LOCATION (arg), REALPART_EXPR, arg, 1);
-         imag = build_unary_op (EXPR_LOCATION (arg), IMAGPART_EXPR, arg, 1);
-         real = build_unary_op (EXPR_LOCATION (arg), code, real, 1);
-         if (real == error_mark_node || imag == error_mark_node)
-           return error_mark_node;
-         ret = build2 (COMPLEX_EXPR, TREE_TYPE (arg),
-                       real, imag);
-         goto return_build_unary_op;
-       }
-
-      /* Report invalid types.  */
-
-      if (typecode != POINTER_TYPE && typecode != FIXED_POINT_TYPE
-         && typecode != INTEGER_TYPE && typecode != REAL_TYPE)
-       {
-         if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR)
-           error_at (location, "wrong type argument to increment");
-         else
-           error_at (location, "wrong type argument to decrement");
-
-         return error_mark_node;
-       }
-
-      {
-       tree inc;
-
-       argtype = TREE_TYPE (arg);
-
-       /* Compute the increment.  */
-
-       if (typecode == POINTER_TYPE)
-         {
-           /* If pointer target is an undefined struct,
-              we just cannot know how to do the arithmetic.  */
-           if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (argtype)))
-             {
-               if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR)
-                 error_at (location,
-                           "increment of pointer to unknown structure");
-               else
-                 error_at (location,
-                           "decrement of pointer to unknown structure");
-             }
-           else if (TREE_CODE (TREE_TYPE (argtype)) == FUNCTION_TYPE
-                    || TREE_CODE (TREE_TYPE (argtype)) == VOID_TYPE)
-             {
-               if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR)
-                 pedwarn (location, pedantic ? OPT_Wpedantic : OPT_Wpointer_arith,
-                          "wrong type argument to increment");
-               else
-                 pedwarn (location, pedantic ? OPT_Wpedantic : OPT_Wpointer_arith,
-                          "wrong type argument to decrement");
-             }
-
-           inc = c_size_in_bytes (TREE_TYPE (argtype));
-           inc = convert_to_ptrofftype_loc (location, inc);
-         }
-       else if (FRACT_MODE_P (TYPE_MODE (argtype)))
-         {
-           /* For signed fract types, we invert ++ to -- or
-              -- to ++, and change inc from 1 to -1, because
-              it is not possible to represent 1 in signed fract constants.
-              For unsigned fract types, the result always overflows and
-              we get an undefined (original) or the maximum value.  */
-           if (code == PREINCREMENT_EXPR)
-             code = PREDECREMENT_EXPR;
-           else if (code == PREDECREMENT_EXPR)
-             code = PREINCREMENT_EXPR;
-           else if (code == POSTINCREMENT_EXPR)
-             code = POSTDECREMENT_EXPR;
-           else /* code == POSTDECREMENT_EXPR  */
-             code = POSTINCREMENT_EXPR;
-
-           inc = integer_minus_one_node;
-           inc = convert (argtype, inc);
-         }
-       else
-         {
-           inc = integer_one_node;
-           inc = convert (argtype, inc);
-         }
-
-       /* If 'arg' is an Objective-C PROPERTY_REF expression, then we
-          need to ask Objective-C to build the increment or decrement
-          expression for it.  */
-       if (objc_is_property_ref (arg))
-         return objc_build_incr_expr_for_property_ref (location, code,
-                                                       arg, inc);
-
-       /* Report a read-only lvalue.  */
-       if (TYPE_READONLY (argtype))
-         {
-           readonly_error (arg,
-                           ((code == PREINCREMENT_EXPR
-                             || code == POSTINCREMENT_EXPR)
-                            ? lv_increment : lv_decrement));
-           return error_mark_node;
-         }
-       else if (TREE_READONLY (arg))
-         readonly_warning (arg,
-                           ((code == PREINCREMENT_EXPR
-                             || code == POSTINCREMENT_EXPR)
-                            ? lv_increment : lv_decrement));
-
-       if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE)
-         val = boolean_increment (code, arg);
-       else
-         val = build2 (code, TREE_TYPE (arg), arg, inc);
-       TREE_SIDE_EFFECTS (val) = 1;
-       if (TREE_CODE (val) != code)
-         TREE_NO_WARNING (val) = 1;
-       ret = val;
-       goto return_build_unary_op;
-      }
-
-    case ADDR_EXPR:
-      /* Note that this operation never does default_conversion.  */
-
-      /* The operand of unary '&' must be an lvalue (which excludes
-        expressions of type void), or, in C99, the result of a [] or
-        unary '*' operator.  */
-      if (VOID_TYPE_P (TREE_TYPE (arg))
-         && TYPE_QUALS (TREE_TYPE (arg)) == TYPE_UNQUALIFIED
-         && (TREE_CODE (arg) != INDIRECT_REF
-             || !flag_isoc99))
-       pedwarn (location, 0, "taking address of expression of type %<void%>");
-
-      /* Let &* cancel out to simplify resulting code.  */
-      if (TREE_CODE (arg) == INDIRECT_REF)
-       {
-         /* Don't let this be an lvalue.  */
-         if (lvalue_p (TREE_OPERAND (arg, 0)))
-           return non_lvalue_loc (location, TREE_OPERAND (arg, 0));
-         ret = TREE_OPERAND (arg, 0);
-         goto return_build_unary_op;
-       }
-
-      /* For &x[y], return x+y */
-      if (TREE_CODE (arg) == ARRAY_REF)
-       {
-         tree op0 = TREE_OPERAND (arg, 0);
-         if (!c_mark_addressable (op0))
-           return error_mark_node;
-       }
-
-      /* Anything not already handled and not a true memory reference
-        or a non-lvalue array is an error.  */
-      else if (typecode != FUNCTION_TYPE && !flag
-              && !lvalue_or_else (location, arg, lv_addressof))
-       return error_mark_node;
-
-      /* Move address operations inside C_MAYBE_CONST_EXPR to simplify
-        folding later.  */
-      if (TREE_CODE (arg) == C_MAYBE_CONST_EXPR)
-       {
-         tree inner = build_unary_op (location, code,
-                                      C_MAYBE_CONST_EXPR_EXPR (arg), flag);
-         ret = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (inner),
-                       C_MAYBE_CONST_EXPR_PRE (arg), inner);
-         gcc_assert (!C_MAYBE_CONST_EXPR_INT_OPERANDS (arg));
-         C_MAYBE_CONST_EXPR_NON_CONST (ret)
-           = C_MAYBE_CONST_EXPR_NON_CONST (arg);
-         goto return_build_unary_op;
-       }
-
-      /* Ordinary case; arg is a COMPONENT_REF or a decl.  */
-      argtype = TREE_TYPE (arg);
-
-      /* If the lvalue is const or volatile, merge that into the type
-        to which the address will point.  This is only needed
-        for function types.  */
-      if ((DECL_P (arg) || REFERENCE_CLASS_P (arg))
-         && (TREE_READONLY (arg) || TREE_THIS_VOLATILE (arg))
-         && TREE_CODE (argtype) == FUNCTION_TYPE)
-       {
-         int orig_quals = TYPE_QUALS (strip_array_types (argtype));
-         int quals = orig_quals;
-
-         if (TREE_READONLY (arg))
-           quals |= TYPE_QUAL_CONST;
-         if (TREE_THIS_VOLATILE (arg))
-           quals |= TYPE_QUAL_VOLATILE;
-
-         argtype = c_build_qualified_type (argtype, quals);
-       }
-
-      if (!c_mark_addressable (arg))
-       return error_mark_node;
-
-      gcc_assert (TREE_CODE (arg) != COMPONENT_REF
-                 || !DECL_C_BIT_FIELD (TREE_OPERAND (arg, 1)));
-
-      argtype = build_pointer_type (argtype);
-
-      /* ??? Cope with user tricks that amount to offsetof.  Delete this
-        when we have proper support for integer constant expressions.  */
-      val = get_base_address (arg);
-      if (val && TREE_CODE (val) == INDIRECT_REF
-          && TREE_CONSTANT (TREE_OPERAND (val, 0)))
-       {
-         ret = fold_convert_loc (location, argtype, fold_offsetof_1 (arg));
-         goto return_build_unary_op;
-       }
-
-      val = build1 (ADDR_EXPR, argtype, arg);
-
-      ret = val;
-      goto return_build_unary_op;
-
-    default:
-      gcc_unreachable ();
-    }
-
-  if (argtype == 0)
-    argtype = TREE_TYPE (arg);
-  if (TREE_CODE (arg) == INTEGER_CST)
-    ret = (require_constant_value
-          ? fold_build1_initializer_loc (location, code, argtype, arg)
-          : fold_build1_loc (location, code, argtype, arg));
-  else
-    ret = build1 (code, argtype, arg);
- return_build_unary_op:
-  gcc_assert (ret != error_mark_node);
-  if (TREE_CODE (ret) == INTEGER_CST && !TREE_OVERFLOW (ret)
-      && !(TREE_CODE (xarg) == INTEGER_CST && !TREE_OVERFLOW (xarg)))
-    ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret);
-  else if (TREE_CODE (ret) != INTEGER_CST && int_operands)
-    ret = note_integer_operands (ret);
-  if (eptype)
-    ret = build1 (EXCESS_PRECISION_EXPR, eptype, ret);
-  protected_set_expr_location (ret, location);
-  return ret;
-}
-
-/* Return nonzero if REF is an lvalue valid for this language.
-   Lvalues can be assigned, unless their type has TYPE_READONLY.
-   Lvalues can have their address taken, unless they have C_DECL_REGISTER.  */
-
-bool
-lvalue_p (const_tree ref)
-{
-  const enum tree_code code = TREE_CODE (ref);
-
-  switch (code)
-    {
-    case REALPART_EXPR:
-    case IMAGPART_EXPR:
-    case COMPONENT_REF:
-      return lvalue_p (TREE_OPERAND (ref, 0));
-
-    case C_MAYBE_CONST_EXPR:
-      return lvalue_p (TREE_OPERAND (ref, 1));
-
-    case COMPOUND_LITERAL_EXPR:
-    case STRING_CST:
-      return 1;
-
-    case INDIRECT_REF:
-    case ARRAY_REF:
-    case VAR_DECL:
-    case PARM_DECL:
-    case RESULT_DECL:
-    case ERROR_MARK:
-      return (TREE_CODE (TREE_TYPE (ref)) != FUNCTION_TYPE
-             && TREE_CODE (TREE_TYPE (ref)) != METHOD_TYPE);
-
-    case BIND_EXPR:
-      return TREE_CODE (TREE_TYPE (ref)) == ARRAY_TYPE;
-
-    default:
-      return 0;
-    }
-}
-\f
-/* Give a warning for storing in something that is read-only in GCC
-   terms but not const in ISO C terms.  */
-
-static void
-readonly_warning (tree arg, enum lvalue_use use)
-{
-  switch (use)
-    {
-    case lv_assign:
-      warning (0, "assignment of read-only location %qE", arg);
-      break;
-    case lv_increment:
-      warning (0, "increment of read-only location %qE", arg);
-      break;
-    case lv_decrement:
-      warning (0, "decrement of read-only location %qE", arg);
-      break;
-    default:
-      gcc_unreachable ();
-    }
-  return;
-}
-
-
-/* Return nonzero if REF is an lvalue valid for this language;
-   otherwise, print an error message and return zero.  USE says
-   how the lvalue is being used and so selects the error message.
-   LOCATION is the location at which any error should be reported.  */
-
-static int
-lvalue_or_else (location_t loc, const_tree ref, enum lvalue_use use)
-{
-  int win = lvalue_p (ref);
-
-  if (!win)
-    lvalue_error (loc, use);
-
-  return win;
-}
-\f
-/* Mark EXP saying that we need to be able to take the
-   address of it; it should not be allocated in a register.
-   Returns true if successful.  */
-
-bool
-c_mark_addressable (tree exp)
-{
-  tree x = exp;
-
-  while (1)
-    switch (TREE_CODE (x))
-      {
-      case COMPONENT_REF:
-       if (DECL_C_BIT_FIELD (TREE_OPERAND (x, 1)))
-         {
-           error
-             ("cannot take address of bit-field %qD", TREE_OPERAND (x, 1));
-           return false;
-         }
-
-       /* ... fall through ...  */
-
-      case ADDR_EXPR:
-      case ARRAY_REF:
-      case REALPART_EXPR:
-      case IMAGPART_EXPR:
-       x = TREE_OPERAND (x, 0);
-       break;
-
-      case COMPOUND_LITERAL_EXPR:
-      case CONSTRUCTOR:
-       TREE_ADDRESSABLE (x) = 1;
-       return true;
-
-      case VAR_DECL:
-      case CONST_DECL:
-      case PARM_DECL:
-      case RESULT_DECL:
-       if (C_DECL_REGISTER (x)
-           && DECL_NONLOCAL (x))
-         {
-           if (TREE_PUBLIC (x) || TREE_STATIC (x) || DECL_EXTERNAL (x))
-             {
-               error
-                 ("global register variable %qD used in nested function", x);
-               return false;
-             }
-           pedwarn (input_location, 0, "register variable %qD used in nested function", x);
-         }
-       else if (C_DECL_REGISTER (x))
-         {
-           if (TREE_PUBLIC (x) || TREE_STATIC (x) || DECL_EXTERNAL (x))
-             error ("address of global register variable %qD requested", x);
-           else
-             error ("address of register variable %qD requested", x);
-           return false;
-         }
-
-       /* drops in */
-      case FUNCTION_DECL:
-       TREE_ADDRESSABLE (x) = 1;
-       /* drops out */
-      default:
-       return true;
-    }
-}
-\f
-/* Convert EXPR to TYPE, warning about conversion problems with
-   constants.  SEMANTIC_TYPE is the type this conversion would use
-   without excess precision. If SEMANTIC_TYPE is NULL, this function
-   is equivalent to convert_and_check. This function is a wrapper that
-   handles conversions that may be different than
-   the usual ones because of excess precision.  */
-
-static tree
-ep_convert_and_check (tree type, tree expr, tree semantic_type)
-{
-  if (TREE_TYPE (expr) == type)
-    return expr;
-
-  if (!semantic_type)
-    return convert_and_check (type, expr);
-
-  if (TREE_CODE (TREE_TYPE (expr)) == INTEGER_TYPE
-      && TREE_TYPE (expr) != semantic_type)
-    {
-      /* For integers, we need to check the real conversion, not
-        the conversion to the excess precision type.  */
-      expr = convert_and_check (semantic_type, expr);
-    }
-  /* Result type is the excess precision type, which should be
-     large enough, so do not check.  */
-  return convert (type, expr);
-}
-
-/* Build and return a conditional expression IFEXP ? OP1 : OP2.  If
-   IFEXP_BCP then the condition is a call to __builtin_constant_p, and
-   if folded to an integer constant then the unselected half may
-   contain arbitrary operations not normally permitted in constant
-   expressions.  Set the location of the expression to LOC.  */
-
-tree
-build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
-                       tree op1, tree op1_original_type, tree op2,
-                       tree op2_original_type)
-{
-  tree type1;
-  tree type2;
-  enum tree_code code1;
-  enum tree_code code2;
-  tree result_type = NULL;
-  tree semantic_result_type = NULL;
-  tree orig_op1 = op1, orig_op2 = op2;
-  bool int_const, op1_int_operands, op2_int_operands, int_operands;
-  bool ifexp_int_operands;
-  tree ret;
-
-  op1_int_operands = EXPR_INT_CONST_OPERANDS (orig_op1);
-  if (op1_int_operands)
-    op1 = remove_c_maybe_const_expr (op1);
-  op2_int_operands = EXPR_INT_CONST_OPERANDS (orig_op2);
-  if (op2_int_operands)
-    op2 = remove_c_maybe_const_expr (op2);
-  ifexp_int_operands = EXPR_INT_CONST_OPERANDS (ifexp);
-  if (ifexp_int_operands)
-    ifexp = remove_c_maybe_const_expr (ifexp);
-
-  /* Promote both alternatives.  */
-
-  if (TREE_CODE (TREE_TYPE (op1)) != VOID_TYPE)
-    op1 = default_conversion (op1);
-  if (TREE_CODE (TREE_TYPE (op2)) != VOID_TYPE)
-    op2 = default_conversion (op2);
-
-  if (TREE_CODE (ifexp) == ERROR_MARK
-      || TREE_CODE (TREE_TYPE (op1)) == ERROR_MARK
-      || TREE_CODE (TREE_TYPE (op2)) == ERROR_MARK)
-    return error_mark_node;
-
-  type1 = TREE_TYPE (op1);
-  code1 = TREE_CODE (type1);
-  type2 = TREE_TYPE (op2);
-  code2 = TREE_CODE (type2);
-
-  /* C90 does not permit non-lvalue arrays in conditional expressions.
-     In C99 they will be pointers by now.  */
-  if (code1 == ARRAY_TYPE || code2 == ARRAY_TYPE)
-    {
-      error_at (colon_loc, "non-lvalue array in conditional expression");
-      return error_mark_node;
-    }
-
-  if ((TREE_CODE (op1) == EXCESS_PRECISION_EXPR
-       || TREE_CODE (op2) == EXCESS_PRECISION_EXPR)
-      && (code1 == INTEGER_TYPE || code1 == REAL_TYPE
-         || code1 == COMPLEX_TYPE)
-      && (code2 == INTEGER_TYPE || code2 == REAL_TYPE
-         || code2 == COMPLEX_TYPE))
-    {
-      semantic_result_type = c_common_type (type1, type2);
-      if (TREE_CODE (op1) == EXCESS_PRECISION_EXPR)
-       {
-         op1 = TREE_OPERAND (op1, 0);
-         type1 = TREE_TYPE (op1);
-         gcc_assert (TREE_CODE (type1) == code1);
-       }
-      if (TREE_CODE (op2) == EXCESS_PRECISION_EXPR)
-       {
-         op2 = TREE_OPERAND (op2, 0);
-         type2 = TREE_TYPE (op2);
-         gcc_assert (TREE_CODE (type2) == code2);
-       }
-    }
-
-  if (warn_cxx_compat)
-    {
-      tree t1 = op1_original_type ? op1_original_type : TREE_TYPE (orig_op1);
-      tree t2 = op2_original_type ? op2_original_type : TREE_TYPE (orig_op2);
-
-      if (TREE_CODE (t1) == ENUMERAL_TYPE
-         && TREE_CODE (t2) == ENUMERAL_TYPE
-         && TYPE_MAIN_VARIANT (t1) != TYPE_MAIN_VARIANT (t2))
-       warning_at (colon_loc, OPT_Wc___compat,
-                   ("different enum types in conditional is "
-                    "invalid in C++: %qT vs %qT"),
-                   t1, t2);
-    }
-
-  /* Quickly detect the usual case where op1 and op2 have the same type
-     after promotion.  */
-  if (TYPE_MAIN_VARIANT (type1) == TYPE_MAIN_VARIANT (type2))
-    {
-      if (type1 == type2)
-       result_type = type1;
-      else
-       result_type = TYPE_MAIN_VARIANT (type1);
-    }
-  else if ((code1 == INTEGER_TYPE || code1 == REAL_TYPE
-           || code1 == COMPLEX_TYPE)
-          && (code2 == INTEGER_TYPE || code2 == REAL_TYPE
-              || code2 == COMPLEX_TYPE))
-    {
-      result_type = c_common_type (type1, type2);
-      do_warn_double_promotion (result_type, type1, type2,
-                               "implicit conversion from %qT to %qT to "
-                               "match other result of conditional",
-                               colon_loc);
-
-      /* If -Wsign-compare, warn here if type1 and type2 have
-        different signedness.  We'll promote the signed to unsigned
-        and later code won't know it used to be different.
-        Do this check on the original types, so that explicit casts
-        will be considered, but default promotions won't.  */
-      if (c_inhibit_evaluation_warnings == 0)
-       {
-         int unsigned_op1 = TYPE_UNSIGNED (TREE_TYPE (orig_op1));
-         int unsigned_op2 = TYPE_UNSIGNED (TREE_TYPE (orig_op2));
-
-         if (unsigned_op1 ^ unsigned_op2)
-           {
-             bool ovf;
-
-             /* Do not warn if the result type is signed, since the
-                signed type will only be chosen if it can represent
-                all the values of the unsigned type.  */
-             if (!TYPE_UNSIGNED (result_type))
-               /* OK */;
-             else
-               {
-                 bool op1_maybe_const = true;
-                 bool op2_maybe_const = true;
-
-                 /* Do not warn if the signed quantity is an
-                    unsuffixed integer literal (or some static
-                    constant expression involving such literals) and
-                    it is non-negative.  This warning requires the
-                    operands to be folded for best results, so do
-                    that folding in this case even without
-                    warn_sign_compare to avoid warning options
-                    possibly affecting code generation.  */
-                 c_inhibit_evaluation_warnings
-                   += (ifexp == truthvalue_false_node);
-                 op1 = c_fully_fold (op1, require_constant_value,
-                                     &op1_maybe_const);
-                 c_inhibit_evaluation_warnings
-                   -= (ifexp == truthvalue_false_node);
-
-                 c_inhibit_evaluation_warnings
-                   += (ifexp == truthvalue_true_node);
-                 op2 = c_fully_fold (op2, require_constant_value,
-                                     &op2_maybe_const);
-                 c_inhibit_evaluation_warnings
-                   -= (ifexp == truthvalue_true_node);
-
-                 if (warn_sign_compare)
-                   {
-                     if ((unsigned_op2
-                          && tree_expr_nonnegative_warnv_p (op1, &ovf))
-                         || (unsigned_op1
-                             && tree_expr_nonnegative_warnv_p (op2, &ovf)))
-                       /* OK */;
-                     else
-                       warning_at (colon_loc, OPT_Wsign_compare,
-                                   ("signed and unsigned type in "
-                                    "conditional expression"));
-                   }
-                 if (!op1_maybe_const || TREE_CODE (op1) != INTEGER_CST)
-                   op1 = c_wrap_maybe_const (op1, !op1_maybe_const);
-                 if (!op2_maybe_const || TREE_CODE (op2) != INTEGER_CST)
-                   op2 = c_wrap_maybe_const (op2, !op2_maybe_const);
-               }
-           }
-       }
-    }
-  else if (code1 == VOID_TYPE || code2 == VOID_TYPE)
-    {
-      if (code1 != VOID_TYPE || code2 != VOID_TYPE)
-       pedwarn (colon_loc, OPT_Wpedantic,
-                "ISO C forbids conditional expr with only one void side");
-      result_type = void_type_node;
-    }
-  else if (code1 == POINTER_TYPE && code2 == POINTER_TYPE)
-    {
-      addr_space_t as1 = TYPE_ADDR_SPACE (TREE_TYPE (type1));
-      addr_space_t as2 = TYPE_ADDR_SPACE (TREE_TYPE (type2));
-      addr_space_t as_common;
-
-      if (comp_target_types (colon_loc, type1, type2))
-       result_type = common_pointer_type (type1, type2);
-      else if (null_pointer_constant_p (orig_op1))
-       result_type = type2;
-      else if (null_pointer_constant_p (orig_op2))
-       result_type = type1;
-      else if (!addr_space_superset (as1, as2, &as_common))
-       {
-         error_at (colon_loc, "pointers to disjoint address spaces "
-                   "used in conditional expression");
-         return error_mark_node;
-       }
-      else if (VOID_TYPE_P (TREE_TYPE (type1)))
-       {
-         if (TREE_CODE (TREE_TYPE (type2)) == FUNCTION_TYPE)
-           pedwarn (colon_loc, OPT_Wpedantic,
-                    "ISO C forbids conditional expr between "
-                    "%<void *%> and function pointer");
-         result_type = build_pointer_type (qualify_type (TREE_TYPE (type1),
-                                                         TREE_TYPE (type2)));
-       }
-      else if (VOID_TYPE_P (TREE_TYPE (type2)))
-       {
-         if (TREE_CODE (TREE_TYPE (type1)) == FUNCTION_TYPE)
-           pedwarn (colon_loc, OPT_Wpedantic,
-                    "ISO C forbids conditional expr between "
-                    "%<void *%> and function pointer");
-         result_type = build_pointer_type (qualify_type (TREE_TYPE (type2),
-                                                         TREE_TYPE (type1)));
-       }
-      /* Objective-C pointer comparisons are a bit more lenient.  */
-      else if (objc_have_common_type (type1, type2, -3, NULL_TREE))
-       result_type = objc_common_type (type1, type2);
-      else
-       {
-         int qual = ENCODE_QUAL_ADDR_SPACE (as_common);
-
-         pedwarn (colon_loc, 0,
-                  "pointer type mismatch in conditional expression");
-         result_type = build_pointer_type
-                         (build_qualified_type (void_type_node, qual));
-       }
-    }
-  else if (code1 == POINTER_TYPE && code2 == INTEGER_TYPE)
-    {
-      if (!null_pointer_constant_p (orig_op2))
-       pedwarn (colon_loc, 0,
-                "pointer/integer type mismatch in conditional expression");
-      else
-       {
-         op2 = null_pointer_node;
-       }
-      result_type = type1;
-    }
-  else if (code2 == POINTER_TYPE && code1 == INTEGER_TYPE)
-    {
-      if (!null_pointer_constant_p (orig_op1))
-       pedwarn (colon_loc, 0,
-                "pointer/integer type mismatch in conditional expression");
-      else
-       {
-         op1 = null_pointer_node;
-       }
-      result_type = type2;
-    }
-
-  if (!result_type)
-    {
-      if (flag_cond_mismatch)
-       result_type = void_type_node;
-      else
-       {
-         error_at (colon_loc, "type mismatch in conditional expression");
-         return error_mark_node;
-       }
-    }
-
-  /* Merge const and volatile flags of the incoming types.  */
-  result_type
-    = build_type_variant (result_type,
-                         TYPE_READONLY (type1) || TYPE_READONLY (type2),
-                         TYPE_VOLATILE (type1) || TYPE_VOLATILE (type2));
-
-  op1 = ep_convert_and_check (result_type, op1, semantic_result_type);
-  op2 = ep_convert_and_check (result_type, op2, semantic_result_type);
-
-  if (ifexp_bcp && ifexp == truthvalue_true_node)
-    {
-      op2_int_operands = true;
-      op1 = c_fully_fold (op1, require_constant_value, NULL);
-    }
-  if (ifexp_bcp && ifexp == truthvalue_false_node)
-    {
-      op1_int_operands = true;
-      op2 = c_fully_fold (op2, require_constant_value, NULL);
-    }
-  int_const = int_operands = (ifexp_int_operands
-                             && op1_int_operands
-                             && op2_int_operands);
-  if (int_operands)
-    {
-      int_const = ((ifexp == truthvalue_true_node
-                   && TREE_CODE (orig_op1) == INTEGER_CST
-                   && !TREE_OVERFLOW (orig_op1))
-                  || (ifexp == truthvalue_false_node
-                      && TREE_CODE (orig_op2) == INTEGER_CST
-                      && !TREE_OVERFLOW (orig_op2)));
-    }
-  if (int_const || (ifexp_bcp && TREE_CODE (ifexp) == INTEGER_CST))
-    ret = fold_build3_loc (colon_loc, COND_EXPR, result_type, ifexp, op1, op2);
-  else
-    {
-      if (int_operands)
-       {
-         op1 = remove_c_maybe_const_expr (op1);
-         op2 = remove_c_maybe_const_expr (op2);
-       }
-      ret = build3 (COND_EXPR, result_type, ifexp, op1, op2);
-      if (int_operands)
-       ret = note_integer_operands (ret);
-    }
-  if (semantic_result_type)
-    ret = build1 (EXCESS_PRECISION_EXPR, semantic_result_type, ret);
-
-  protected_set_expr_location (ret, colon_loc);
-  return ret;
-}
-\f
-/* Return a compound expression that performs two expressions and
-   returns the value of the second of them.
-
-   LOC is the location of the COMPOUND_EXPR.  */
-
-tree
-build_compound_expr (location_t loc, tree expr1, tree expr2)
-{
-  bool expr1_int_operands, expr2_int_operands;
-  tree eptype = NULL_TREE;
-  tree ret;
-
-  expr1_int_operands = EXPR_INT_CONST_OPERANDS (expr1);
-  if (expr1_int_operands)
-    expr1 = remove_c_maybe_const_expr (expr1);
-  expr2_int_operands = EXPR_INT_CONST_OPERANDS (expr2);
-  if (expr2_int_operands)
-    expr2 = remove_c_maybe_const_expr (expr2);
-
-  if (TREE_CODE (expr1) == EXCESS_PRECISION_EXPR)
-    expr1 = TREE_OPERAND (expr1, 0);
-  if (TREE_CODE (expr2) == EXCESS_PRECISION_EXPR)
-    {
-      eptype = TREE_TYPE (expr2);
-      expr2 = TREE_OPERAND (expr2, 0);
-    }
-
-  if (!TREE_SIDE_EFFECTS (expr1))
-    {
-      /* The left-hand operand of a comma expression is like an expression
-        statement: with -Wunused, we should warn if it doesn't have
-        any side-effects, unless it was explicitly cast to (void).  */
-      if (warn_unused_value)
-       {
-         if (VOID_TYPE_P (TREE_TYPE (expr1))
-             && CONVERT_EXPR_P (expr1))
-           ; /* (void) a, b */
-         else if (VOID_TYPE_P (TREE_TYPE (expr1))
-                  && TREE_CODE (expr1) == COMPOUND_EXPR
-                  && CONVERT_EXPR_P (TREE_OPERAND (expr1, 1)))
-           ; /* (void) a, (void) b, c */
-         else
-           warning_at (loc, OPT_Wunused_value,
-                       "left-hand operand of comma expression has no effect");
-       }
-    }
-
-  /* With -Wunused, we should also warn if the left-hand operand does have
-     side-effects, but computes a value which is not used.  For example, in
-     `foo() + bar(), baz()' the result of the `+' operator is not used,
-     so we should issue a warning.  */
-  else if (warn_unused_value)
-    warn_if_unused_value (expr1, loc);
-
-  if (expr2 == error_mark_node)
-    return error_mark_node;
-
-  ret = build2 (COMPOUND_EXPR, TREE_TYPE (expr2), expr1, expr2);
-
-  if (flag_isoc99
-      && expr1_int_operands
-      && expr2_int_operands)
-    ret = note_integer_operands (ret);
-
-  if (eptype)
-    ret = build1 (EXCESS_PRECISION_EXPR, eptype, ret);
-
-  protected_set_expr_location (ret, loc);
-  return ret;
-}
-
-/* Issue -Wcast-qual warnings when appropriate.  TYPE is the type to
-   which we are casting.  OTYPE is the type of the expression being
-   cast.  Both TYPE and OTYPE are pointer types.  LOC is the location
-   of the cast.  -Wcast-qual appeared on the command line.  Named
-   address space qualifiers are not handled here, because they result
-   in different warnings.  */
-
-static void
-handle_warn_cast_qual (location_t loc, tree type, tree otype)
-{
-  tree in_type = type;
-  tree in_otype = otype;
-  int added = 0;
-  int discarded = 0;
-  bool is_const;
-
-  /* Check that the qualifiers on IN_TYPE are a superset of the
-     qualifiers of IN_OTYPE.  The outermost level of POINTER_TYPE
-     nodes is uninteresting and we stop as soon as we hit a
-     non-POINTER_TYPE node on either type.  */
-  do
-    {
-      in_otype = TREE_TYPE (in_otype);
-      in_type = TREE_TYPE (in_type);
-
-      /* GNU C allows cv-qualified function types.  'const' means the
-        function is very pure, 'volatile' means it can't return.  We
-        need to warn when such qualifiers are added, not when they're
-        taken away.  */
-      if (TREE_CODE (in_otype) == FUNCTION_TYPE
-         && TREE_CODE (in_type) == FUNCTION_TYPE)
-       added |= (TYPE_QUALS_NO_ADDR_SPACE (in_type)
-                 & ~TYPE_QUALS_NO_ADDR_SPACE (in_otype));
-      else
-       discarded |= (TYPE_QUALS_NO_ADDR_SPACE (in_otype)
-                     & ~TYPE_QUALS_NO_ADDR_SPACE (in_type));
-    }
-  while (TREE_CODE (in_type) == POINTER_TYPE
-        && TREE_CODE (in_otype) == POINTER_TYPE);
-
-  if (added)
-    warning_at (loc, OPT_Wcast_qual,
-               "cast adds %q#v qualifier to function type", added);
-
-  if (discarded)
-    /* There are qualifiers present in IN_OTYPE that are not present
-       in IN_TYPE.  */
-    warning_at (loc, OPT_Wcast_qual,
-               "cast discards %q#v qualifier from pointer target type",
-               discarded);
-
-  if (added || discarded)
-    return;
-
-  /* A cast from **T to const **T is unsafe, because it can cause a
-     const value to be changed with no additional warning.  We only
-     issue this warning if T is the same on both sides, and we only
-     issue the warning if there are the same number of pointers on
-     both sides, as otherwise the cast is clearly unsafe anyhow.  A
-     cast is unsafe when a qualifier is added at one level and const
-     is not present at all outer levels.
-
-     To issue this warning, we check at each level whether the cast
-     adds new qualifiers not already seen.  We don't need to special
-     case function types, as they won't have the same
-     TYPE_MAIN_VARIANT.  */
-
-  if (TYPE_MAIN_VARIANT (in_type) != TYPE_MAIN_VARIANT (in_otype))
-    return;
-  if (TREE_CODE (TREE_TYPE (type)) != POINTER_TYPE)
-    return;
-
-  in_type = type;
-  in_otype = otype;
-  is_const = TYPE_READONLY (TREE_TYPE (in_type));
-  do
-    {
-      in_type = TREE_TYPE (in_type);
-      in_otype = TREE_TYPE (in_otype);
-      if ((TYPE_QUALS (in_type) &~ TYPE_QUALS (in_otype)) != 0
-         && !is_const)
-       {
-         warning_at (loc, OPT_Wcast_qual,
-                     "to be safe all intermediate pointers in cast from "
-                      "%qT to %qT must be %<const%> qualified",
-                     otype, type);
-         break;
-       }
-      if (is_const)
-       is_const = TYPE_READONLY (in_type);
-    }
-  while (TREE_CODE (in_type) == POINTER_TYPE);
-}
-
-/* Build an expression representing a cast to type TYPE of expression EXPR.
-   LOC is the location of the cast-- typically the open paren of the cast.  */
-
-tree
-build_c_cast (location_t loc, tree type, tree expr)
-{
-  tree value;
-
-  if (TREE_CODE (expr) == EXCESS_PRECISION_EXPR)
-    expr = TREE_OPERAND (expr, 0);
-
-  value = expr;
-
-  if (type == error_mark_node || expr == error_mark_node)
-    return error_mark_node;
-
-  /* The ObjC front-end uses TYPE_MAIN_VARIANT to tie together types differing
-     only in <protocol> qualifications.  But when constructing cast expressions,
-     the protocols do matter and must be kept around.  */
-  if (objc_is_object_ptr (type) && objc_is_object_ptr (TREE_TYPE (expr)))
-    return build1 (NOP_EXPR, type, expr);
-
-  type = TYPE_MAIN_VARIANT (type);
-
-  if (TREE_CODE (type) == ARRAY_TYPE)
-    {
-      error_at (loc, "cast specifies array type");
-      return error_mark_node;
-    }
-
-  if (TREE_CODE (type) == FUNCTION_TYPE)
-    {
-      error_at (loc, "cast specifies function type");
-      return error_mark_node;
-    }
-
-  if (!VOID_TYPE_P (type))
-    {
-      value = require_complete_type (value);
-      if (value == error_mark_node)
-       return error_mark_node;
-    }
-
-  if (type == TYPE_MAIN_VARIANT (TREE_TYPE (value)))
-    {
-      if (TREE_CODE (type) == RECORD_TYPE
-         || TREE_CODE (type) == UNION_TYPE)
-       pedwarn (loc, OPT_Wpedantic,
-                "ISO C forbids casting nonscalar to the same type");
-    }
-  else if (TREE_CODE (type) == UNION_TYPE)
-    {
-      tree field;
-
-      for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
-       if (TREE_TYPE (field) != error_mark_node
-           && comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (field)),
-                         TYPE_MAIN_VARIANT (TREE_TYPE (value))))
-         break;
-
-      if (field)
-       {
-         tree t;
-         bool maybe_const = true;
-
-         pedwarn (loc, OPT_Wpedantic, "ISO C forbids casts to union type");
-         t = c_fully_fold (value, false, &maybe_const);
-         t = build_constructor_single (type, field, t);
-         if (!maybe_const)
-           t = c_wrap_maybe_const (t, true);
-         t = digest_init (loc, type, t,
-                          NULL_TREE, false, true, 0);
-         TREE_CONSTANT (t) = TREE_CONSTANT (value);
-         return t;
-       }
-      error_at (loc, "cast to union type from type not present in union");
-      return error_mark_node;
-    }
-  else
-    {
-      tree otype, ovalue;
-
-      if (type == void_type_node)
-       {
-         tree t = build1 (CONVERT_EXPR, type, value);
-         SET_EXPR_LOCATION (t, loc);
-         return t;
-       }
-
-      otype = TREE_TYPE (value);
-
-      /* Optionally warn about potentially worrisome casts.  */
-      if (warn_cast_qual
-         && TREE_CODE (type) == POINTER_TYPE
-         && TREE_CODE (otype) == POINTER_TYPE)
-       handle_warn_cast_qual (loc, type, otype);
-
-      /* Warn about conversions between pointers to disjoint
-        address spaces.  */
-      if (TREE_CODE (type) == POINTER_TYPE
-         && TREE_CODE (otype) == POINTER_TYPE
-         && !null_pointer_constant_p (value))
-       {
-         addr_space_t as_to = TYPE_ADDR_SPACE (TREE_TYPE (type));
-         addr_space_t as_from = TYPE_ADDR_SPACE (TREE_TYPE (otype));
-         addr_space_t as_common;
-
-         if (!addr_space_superset (as_to, as_from, &as_common))
-           {
-             if (ADDR_SPACE_GENERIC_P (as_from))
-               warning_at (loc, 0, "cast to %s address space pointer "
-                           "from disjoint generic address space pointer",
-                           c_addr_space_name (as_to));
-
-             else if (ADDR_SPACE_GENERIC_P (as_to))
-               warning_at (loc, 0, "cast to generic address space pointer "
-                           "from disjoint %s address space pointer",
-                           c_addr_space_name (as_from));
-
-             else
-               warning_at (loc, 0, "cast to %s address space pointer "
-                           "from disjoint %s address space pointer",
-                           c_addr_space_name (as_to),
-                           c_addr_space_name (as_from));
-           }
-       }
-
-      /* Warn about possible alignment problems.  */
-      if (STRICT_ALIGNMENT
-         && TREE_CODE (type) == POINTER_TYPE
-         && TREE_CODE (otype) == POINTER_TYPE
-         && TREE_CODE (TREE_TYPE (otype)) != VOID_TYPE
-         && TREE_CODE (TREE_TYPE (otype)) != FUNCTION_TYPE
-         /* Don't warn about opaque types, where the actual alignment
-            restriction is unknown.  */
-         && !((TREE_CODE (TREE_TYPE (otype)) == UNION_TYPE
-               || TREE_CODE (TREE_TYPE (otype)) == RECORD_TYPE)
-              && TYPE_MODE (TREE_TYPE (otype)) == VOIDmode)
-         && TYPE_ALIGN (TREE_TYPE (type)) > TYPE_ALIGN (TREE_TYPE (otype)))
-       warning_at (loc, OPT_Wcast_align,
-                   "cast increases required alignment of target type");
-
-      if (TREE_CODE (type) == INTEGER_TYPE
-         && TREE_CODE (otype) == POINTER_TYPE
-         && TYPE_PRECISION (type) != TYPE_PRECISION (otype))
-      /* Unlike conversion of integers to pointers, where the
-         warning is disabled for converting constants because
-         of cases such as SIG_*, warn about converting constant
-         pointers to integers. In some cases it may cause unwanted
-         sign extension, and a warning is appropriate.  */
-       warning_at (loc, OPT_Wpointer_to_int_cast,
-                   "cast from pointer to integer of different size");
-
-      if (TREE_CODE (value) == CALL_EXPR
-         && TREE_CODE (type) != TREE_CODE (otype))
-       warning_at (loc, OPT_Wbad_function_cast,
-                   "cast from function call of type %qT "
-                   "to non-matching type %qT", otype, type);
-
-      if (TREE_CODE (type) == POINTER_TYPE
-         && TREE_CODE (otype) == INTEGER_TYPE
-         && TYPE_PRECISION (type) != TYPE_PRECISION (otype)
-         /* Don't warn about converting any constant.  */
-         && !TREE_CONSTANT (value))
-       warning_at (loc,
-                   OPT_Wint_to_pointer_cast, "cast to pointer from integer "
-                   "of different size");
-
-      if (warn_strict_aliasing <= 2)
-        strict_aliasing_warning (otype, type, expr);
-
-      /* If pedantic, warn for conversions between function and object
-        pointer types, except for converting a null pointer constant
-        to function pointer type.  */
-      if (pedantic
-         && TREE_CODE (type) == POINTER_TYPE
-         && TREE_CODE (otype) == POINTER_TYPE
-         && TREE_CODE (TREE_TYPE (otype)) == FUNCTION_TYPE
-         && TREE_CODE (TREE_TYPE (type)) != FUNCTION_TYPE)
-       pedwarn (loc, OPT_Wpedantic, "ISO C forbids "
-                "conversion of function pointer to object pointer type");
-
-      if (pedantic
-         && TREE_CODE (type) == POINTER_TYPE
-         && TREE_CODE (otype) == POINTER_TYPE
-         && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE
-         && TREE_CODE (TREE_TYPE (otype)) != FUNCTION_TYPE
-         && !null_pointer_constant_p (value))
-       pedwarn (loc, OPT_Wpedantic, "ISO C forbids "
-                "conversion of object pointer to function pointer type");
-
-      ovalue = value;
-      value = convert (type, value);
-
-      /* Ignore any integer overflow caused by the cast.  */
-      if (TREE_CODE (value) == INTEGER_CST && !FLOAT_TYPE_P (otype))
-       {
-         if (CONSTANT_CLASS_P (ovalue) && TREE_OVERFLOW (ovalue))
-           {
-             if (!TREE_OVERFLOW (value))
-               {
-                 /* Avoid clobbering a shared constant.  */
-                 value = copy_node (value);
-                 TREE_OVERFLOW (value) = TREE_OVERFLOW (ovalue);
-               }
-           }
-         else if (TREE_OVERFLOW (value))
-           /* Reset VALUE's overflow flags, ensuring constant sharing.  */
-           value = build_int_cst_wide (TREE_TYPE (value),
-                                       TREE_INT_CST_LOW (value),
-                                       TREE_INT_CST_HIGH (value));
-       }
-    }
-
-  /* Don't let a cast be an lvalue.  */
-  if (value == expr)
-    value = non_lvalue_loc (loc, value);
-
-  /* Don't allow the results of casting to floating-point or complex
-     types be confused with actual constants, or casts involving
-     integer and pointer types other than direct integer-to-integer
-     and integer-to-pointer be confused with integer constant
-     expressions and null pointer constants.  */
-  if (TREE_CODE (value) == REAL_CST
-      || TREE_CODE (value) == COMPLEX_CST
-      || (TREE_CODE (value) == INTEGER_CST
-         && !((TREE_CODE (expr) == INTEGER_CST
-               && INTEGRAL_TYPE_P (TREE_TYPE (expr)))
-              || TREE_CODE (expr) == REAL_CST
-              || TREE_CODE (expr) == COMPLEX_CST)))
-      value = build1 (NOP_EXPR, type, value);
-
-  if (CAN_HAVE_LOCATION_P (value))
-    SET_EXPR_LOCATION (value, loc);
-  return value;
-}
-
-/* Interpret a cast of expression EXPR to type TYPE.  LOC is the
-   location of the open paren of the cast, or the position of the cast
-   expr.  */
-tree
-c_cast_expr (location_t loc, struct c_type_name *type_name, tree expr)
-{
-  tree type;
-  tree type_expr = NULL_TREE;
-  bool type_expr_const = true;
-  tree ret;
-  int saved_wsp = warn_strict_prototypes;
-
-  /* This avoids warnings about unprototyped casts on
-     integers.  E.g. "#define SIG_DFL (void(*)())0".  */
-  if (TREE_CODE (expr) == INTEGER_CST)
-    warn_strict_prototypes = 0;
-  type = groktypename (type_name, &type_expr, &type_expr_const);
-  warn_strict_prototypes = saved_wsp;
-
-  ret = build_c_cast (loc, type, expr);
-  if (type_expr)
-    {
-      ret = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (ret), type_expr, ret);
-      C_MAYBE_CONST_EXPR_NON_CONST (ret) = !type_expr_const;
-      SET_EXPR_LOCATION (ret, loc);
-    }
-
-  if (CAN_HAVE_LOCATION_P (ret) && !EXPR_HAS_LOCATION (ret))
-    SET_EXPR_LOCATION (ret, loc);
-
-  /* C++ does not permits types to be defined in a cast, but it
-     allows references to incomplete types.  */
-  if (warn_cxx_compat && type_name->specs->typespec_kind == ctsk_tagdef)
-    warning_at (loc, OPT_Wc___compat,
-               "defining a type in a cast is invalid in C++");
-
-  return ret;
-}
-\f
-/* Build an assignment expression of lvalue LHS from value RHS.
-   If LHS_ORIGTYPE is not NULL, it is the original type of LHS, which
-   may differ from TREE_TYPE (LHS) for an enum bitfield.
-   MODIFYCODE is the code for a binary operator that we use
-   to combine the old value of LHS with RHS to get the new value.
-   Or else MODIFYCODE is NOP_EXPR meaning do a simple assignment.
-   If RHS_ORIGTYPE is not NULL_TREE, it is the original type of RHS,
-   which may differ from TREE_TYPE (RHS) for an enum value.
-
-   LOCATION is the location of the MODIFYCODE operator.
-   RHS_LOC is the location of the RHS.  */
-
-tree
-build_modify_expr (location_t location, tree lhs, tree lhs_origtype,
-                  enum tree_code modifycode,
-                  location_t rhs_loc, tree rhs, tree rhs_origtype)
-{
-  tree result;
-  tree newrhs;
-  tree rhs_semantic_type = NULL_TREE;
-  tree lhstype = TREE_TYPE (lhs);
-  tree olhstype = lhstype;
-  bool npc;
-
-  /* Types that aren't fully specified cannot be used in assignments.  */
-  lhs = require_complete_type (lhs);
-
-  /* Avoid duplicate error messages from operands that had errors.  */
-  if (TREE_CODE (lhs) == ERROR_MARK || TREE_CODE (rhs) == ERROR_MARK)
-    return error_mark_node;
-
-  /* For ObjC properties, defer this check.  */
-  if (!objc_is_property_ref (lhs) && !lvalue_or_else (location, lhs, lv_assign))
-    return error_mark_node;
-
-  if (TREE_CODE (rhs) == EXCESS_PRECISION_EXPR)
-    {
-      rhs_semantic_type = TREE_TYPE (rhs);
-      rhs = TREE_OPERAND (rhs, 0);
-    }
-
-  newrhs = rhs;
-
-  if (TREE_CODE (lhs) == C_MAYBE_CONST_EXPR)
-    {
-      tree inner = build_modify_expr (location, C_MAYBE_CONST_EXPR_EXPR (lhs),
-                                     lhs_origtype, modifycode, rhs_loc, rhs,
-                                     rhs_origtype);
-      if (inner == error_mark_node)
-       return error_mark_node;
-      result = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (inner),
-                      C_MAYBE_CONST_EXPR_PRE (lhs), inner);
-      gcc_assert (!C_MAYBE_CONST_EXPR_INT_OPERANDS (lhs));
-      C_MAYBE_CONST_EXPR_NON_CONST (result) = 1;
-      protected_set_expr_location (result, location);
-      return result;
-    }
-
-  /* If a binary op has been requested, combine the old LHS value with the RHS
-     producing the value we should actually store into the LHS.  */
-
-  if (modifycode != NOP_EXPR)
-    {
-      lhs = c_fully_fold (lhs, false, NULL);
-      lhs = stabilize_reference (lhs);
-      newrhs = build_binary_op (location,
-                               modifycode, lhs, rhs, 1);
-
-      /* The original type of the right hand side is no longer
-        meaningful.  */
-      rhs_origtype = NULL_TREE;
-    }
-
-  if (c_dialect_objc ())
-    {
-      /* Check if we are modifying an Objective-C property reference;
-        if so, we need to generate setter calls.  */
-      result = objc_maybe_build_modify_expr (lhs, newrhs);
-      if (result)
-       return result;
-
-      /* Else, do the check that we postponed for Objective-C.  */
-      if (!lvalue_or_else (location, lhs, lv_assign))
-       return error_mark_node;
-    }
-
-  /* Give an error for storing in something that is 'const'.  */
-
-  if (TYPE_READONLY (lhstype)
-      || ((TREE_CODE (lhstype) == RECORD_TYPE
-          || TREE_CODE (lhstype) == UNION_TYPE)
-         && C_TYPE_FIELDS_READONLY (lhstype)))
-    {
-      readonly_error (lhs, lv_assign);
-      return error_mark_node;
-    }
-  else if (TREE_READONLY (lhs))
-    readonly_warning (lhs, lv_assign);
-
-  /* If storing into a structure or union member,
-     it has probably been given type `int'.
-     Compute the type that would go with
-     the actual amount of storage the member occupies.  */
-
-  if (TREE_CODE (lhs) == COMPONENT_REF
-      && (TREE_CODE (lhstype) == INTEGER_TYPE
-         || TREE_CODE (lhstype) == BOOLEAN_TYPE
-         || TREE_CODE (lhstype) == REAL_TYPE
-         || TREE_CODE (lhstype) == ENUMERAL_TYPE))
-    lhstype = TREE_TYPE (get_unwidened (lhs, 0));
-
-  /* If storing in a field that is in actuality a short or narrower than one,
-     we must store in the field in its actual type.  */
-
-  if (lhstype != TREE_TYPE (lhs))
-    {
-      lhs = copy_node (lhs);
-      TREE_TYPE (lhs) = lhstype;
-    }
-
-  /* Issue -Wc++-compat warnings about an assignment to an enum type
-     when LHS does not have its original type.  This happens for,
-     e.g., an enum bitfield in a struct.  */
-  if (warn_cxx_compat
-      && lhs_origtype != NULL_TREE
-      && lhs_origtype != lhstype
-      && TREE_CODE (lhs_origtype) == ENUMERAL_TYPE)
-    {
-      tree checktype = (rhs_origtype != NULL_TREE
-                       ? rhs_origtype
-                       : TREE_TYPE (rhs));
-      if (checktype != error_mark_node
-         && TYPE_MAIN_VARIANT (checktype) != TYPE_MAIN_VARIANT (lhs_origtype))
-       warning_at (location, OPT_Wc___compat,
-                   "enum conversion in assignment is invalid in C++");
-    }
-
-  /* Convert new value to destination type.  Fold it first, then
-     restore any excess precision information, for the sake of
-     conversion warnings.  */
-
-  npc = null_pointer_constant_p (newrhs);
-  newrhs = c_fully_fold (newrhs, false, NULL);
-  if (rhs_semantic_type)
-    newrhs = build1 (EXCESS_PRECISION_EXPR, rhs_semantic_type, newrhs);
-  newrhs = convert_for_assignment (location, lhstype, newrhs, rhs_origtype,
-                                  ic_assign, npc, NULL_TREE, NULL_TREE, 0);
-  if (TREE_CODE (newrhs) == ERROR_MARK)
-    return error_mark_node;
-
-  /* Emit ObjC write barrier, if necessary.  */
-  if (c_dialect_objc () && flag_objc_gc)
-    {
-      result = objc_generate_write_barrier (lhs, modifycode, newrhs);
-      if (result)
-       {
-         protected_set_expr_location (result, location);
-         return result;
-       }
-    }
-
-  /* Scan operands.  */
-
-  result = build2 (MODIFY_EXPR, lhstype, lhs, newrhs);
-  TREE_SIDE_EFFECTS (result) = 1;
-  protected_set_expr_location (result, location);
-
-  /* If we got the LHS in a different type for storing in,
-     convert the result back to the nominal type of LHS
-     so that the value we return always has the same type
-     as the LHS argument.  */
-
-  if (olhstype == TREE_TYPE (result))
-    return result;
-
-  result = convert_for_assignment (location, olhstype, result, rhs_origtype,
-                                  ic_assign, false, NULL_TREE, NULL_TREE, 0);
-  protected_set_expr_location (result, location);
-  return result;
-}
-\f
-/* Return whether STRUCT_TYPE has an anonymous field with type TYPE.
-   This is used to implement -fplan9-extensions.  */
-
-static bool
-find_anonymous_field_with_type (tree struct_type, tree type)
-{
-  tree field;
-  bool found;
-
-  gcc_assert (TREE_CODE (struct_type) == RECORD_TYPE
-             || TREE_CODE (struct_type) == UNION_TYPE);
-  found = false;
-  for (field = TYPE_FIELDS (struct_type);
-       field != NULL_TREE;
-       field = TREE_CHAIN (field))
-    {
-      if (DECL_NAME (field) == NULL
-         && comptypes (type, TYPE_MAIN_VARIANT (TREE_TYPE (field))))
-       {
-         if (found)
-           return false;
-         found = true;
-       }
-      else if (DECL_NAME (field) == NULL
-              && (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
-                  || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
-              && find_anonymous_field_with_type (TREE_TYPE (field), type))
-       {
-         if (found)
-           return false;
-         found = true;
-       }
-    }
-  return found;
-}
-
-/* RHS is an expression whose type is pointer to struct.  If there is
-   an anonymous field in RHS with type TYPE, then return a pointer to
-   that field in RHS.  This is used with -fplan9-extensions.  This
-   returns NULL if no conversion could be found.  */
-
-static tree
-convert_to_anonymous_field (location_t location, tree type, tree rhs)
-{
-  tree rhs_struct_type, lhs_main_type;
-  tree field, found_field;
-  bool found_sub_field;
-  tree ret;
-
-  gcc_assert (POINTER_TYPE_P (TREE_TYPE (rhs)));
-  rhs_struct_type = TREE_TYPE (TREE_TYPE (rhs));
-  gcc_assert (TREE_CODE (rhs_struct_type) == RECORD_TYPE
-             || TREE_CODE (rhs_struct_type) == UNION_TYPE);
-
-  gcc_assert (POINTER_TYPE_P (type));
-  lhs_main_type = TYPE_MAIN_VARIANT (TREE_TYPE (type));
-
-  found_field = NULL_TREE;
-  found_sub_field = false;
-  for (field = TYPE_FIELDS (rhs_struct_type);
-       field != NULL_TREE;
-       field = TREE_CHAIN (field))
-    {
-      if (DECL_NAME (field) != NULL_TREE
-         || (TREE_CODE (TREE_TYPE (field)) != RECORD_TYPE
-             && TREE_CODE (TREE_TYPE (field)) != UNION_TYPE))
-       continue;
-      if (comptypes (lhs_main_type, TYPE_MAIN_VARIANT (TREE_TYPE (field))))
-       {
-         if (found_field != NULL_TREE)
-           return NULL_TREE;
-         found_field = field;
-       }
-      else if (find_anonymous_field_with_type (TREE_TYPE (field),
-                                              lhs_main_type))
-       {
-         if (found_field != NULL_TREE)
-           return NULL_TREE;
-         found_field = field;
-         found_sub_field = true;
-       }
-    }
-
-  if (found_field == NULL_TREE)
-    return NULL_TREE;
-
-  ret = fold_build3_loc (location, COMPONENT_REF, TREE_TYPE (found_field),
-                        build_fold_indirect_ref (rhs), found_field,
-                        NULL_TREE);
-  ret = build_fold_addr_expr_loc (location, ret);
-
-  if (found_sub_field)
-    {
-      ret = convert_to_anonymous_field (location, type, ret);
-      gcc_assert (ret != NULL_TREE);
-    }
-
-  return ret;
-}
-
-/* Convert value RHS to type TYPE as preparation for an assignment to
-   an lvalue of type TYPE.  If ORIGTYPE is not NULL_TREE, it is the
-   original type of RHS; this differs from TREE_TYPE (RHS) for enum
-   types.  NULL_POINTER_CONSTANT says whether RHS was a null pointer
-   constant before any folding.
-   The real work of conversion is done by `convert'.
-   The purpose of this function is to generate error messages
-   for assignments that are not allowed in C.
-   ERRTYPE says whether it is argument passing, assignment,
-   initialization or return.
-
-   LOCATION is the location of the RHS.
-   FUNCTION is a tree for the function being called.
-   PARMNUM is the number of the argument, for printing in error messages.  */
-
-static tree
-convert_for_assignment (location_t location, tree type, tree rhs,
-                       tree origtype, enum impl_conv errtype,
-                       bool null_pointer_constant, tree fundecl,
-                       tree function, int parmnum)
-{
-  enum tree_code codel = TREE_CODE (type);
-  tree orig_rhs = rhs;
-  tree rhstype;
-  enum tree_code coder;
-  tree rname = NULL_TREE;
-  bool objc_ok = false;
-
-  if (errtype == ic_argpass)
-    {
-      tree selector;
-      /* Change pointer to function to the function itself for
-        diagnostics.  */
-      if (TREE_CODE (function) == ADDR_EXPR
-         && TREE_CODE (TREE_OPERAND (function, 0)) == FUNCTION_DECL)
-       function = TREE_OPERAND (function, 0);
-
-      /* Handle an ObjC selector specially for diagnostics.  */
-      selector = objc_message_selector ();
-      rname = function;
-      if (selector && parmnum > 2)
-       {
-         rname = selector;
-         parmnum -= 2;
-       }
-    }
-
-  /* This macro is used to emit diagnostics to ensure that all format
-     strings are complete sentences, visible to gettext and checked at
-     compile time.  */
-#define WARN_FOR_ASSIGNMENT(LOCATION, OPT, AR, AS, IN, RE)                      \
-  do {                                                                   \
-    switch (errtype)                                                     \
-      {                                                                  \
-      case ic_argpass:                                                   \
-        if (pedwarn (LOCATION, OPT, AR, parmnum, rname))                 \
-          inform ((fundecl && !DECL_IS_BUILTIN (fundecl))               \
-                 ? DECL_SOURCE_LOCATION (fundecl) : LOCATION,           \
-                  "expected %qT but argument is of type %qT",            \
-                  type, rhstype);                                        \
-        break;                                                           \
-      case ic_assign:                                                    \
-        pedwarn (LOCATION, OPT, AS);                                     \
-        break;                                                           \
-      case ic_init:                                                      \
-        pedwarn_init (LOCATION, OPT, IN);                                \
-        break;                                                           \
-      case ic_return:                                                    \
-        pedwarn (LOCATION, OPT, RE);                                    \
-        break;                                                           \
-      default:                                                           \
-        gcc_unreachable ();                                              \
-      }                                                                  \
-  } while (0)
-
-  /* This macro is used to emit diagnostics to ensure that all format
-     strings are complete sentences, visible to gettext and checked at
-     compile time.  It is the same as WARN_FOR_ASSIGNMENT but with an
-     extra parameter to enumerate qualifiers.  */
-
-#define WARN_FOR_QUALIFIERS(LOCATION, OPT, AR, AS, IN, RE, QUALS)        \
-  do {                                                                   \
-    switch (errtype)                                                     \
-      {                                                                  \
-      case ic_argpass:                                                   \
-        if (pedwarn (LOCATION, OPT, AR, parmnum, rname, QUALS))          \
-          inform ((fundecl && !DECL_IS_BUILTIN (fundecl))               \
-                 ? DECL_SOURCE_LOCATION (fundecl) : LOCATION,           \
-                  "expected %qT but argument is of type %qT",            \
-                  type, rhstype);                                        \
-        break;                                                           \
-      case ic_assign:                                                    \
-        pedwarn (LOCATION, OPT, AS, QUALS);                          \
-        break;                                                           \
-      case ic_init:                                                      \
-        pedwarn (LOCATION, OPT, IN, QUALS);                          \
-        break;                                                           \
-      case ic_return:                                                    \
-        pedwarn (LOCATION, OPT, RE, QUALS);                             \
-        break;                                                           \
-      default:                                                           \
-        gcc_unreachable ();                                              \
-      }                                                                  \
-  } while (0)
-
-  if (TREE_CODE (rhs) == EXCESS_PRECISION_EXPR)
-    rhs = TREE_OPERAND (rhs, 0);
-
-  rhstype = TREE_TYPE (rhs);
-  coder = TREE_CODE (rhstype);
-
-  if (coder == ERROR_MARK)
-    return error_mark_node;
-
-  if (c_dialect_objc ())
-    {
-      int parmno;
-
-      switch (errtype)
-       {
-       case ic_return:
-         parmno = 0;
-         break;
-
-       case ic_assign:
-         parmno = -1;
-         break;
-
-       case ic_init:
-         parmno = -2;
-         break;
-
-       default:
-         parmno = parmnum;
-         break;
-       }
-
-      objc_ok = objc_compare_types (type, rhstype, parmno, rname);
-    }
-
-  if (warn_cxx_compat)
-    {
-      tree checktype = origtype != NULL_TREE ? origtype : rhstype;
-      if (checktype != error_mark_node
-         && TREE_CODE (type) == ENUMERAL_TYPE
-         && TYPE_MAIN_VARIANT (checktype) != TYPE_MAIN_VARIANT (type))
-       {
-         WARN_FOR_ASSIGNMENT (input_location, OPT_Wc___compat,
-                              G_("enum conversion when passing argument "
-                                 "%d of %qE is invalid in C++"),
-                              G_("enum conversion in assignment is "
-                                 "invalid in C++"),
-                              G_("enum conversion in initialization is "
-                                 "invalid in C++"),
-                              G_("enum conversion in return is "
-                                 "invalid in C++"));
-       }
-    }
-
-  if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (rhstype))
-    return rhs;
-
-  if (coder == VOID_TYPE)
-    {
-      /* Except for passing an argument to an unprototyped function,
-        this is a constraint violation.  When passing an argument to
-        an unprototyped function, it is compile-time undefined;
-        making it a constraint in that case was rejected in
-        DR#252.  */
-      error_at (location, "void value not ignored as it ought to be");
-      return error_mark_node;
-    }
-  rhs = require_complete_type (rhs);
-  if (rhs == error_mark_node)
-    return error_mark_node;
-  /* A type converts to a reference to it.
-     This code doesn't fully support references, it's just for the
-     special case of va_start and va_copy.  */
-  if (codel == REFERENCE_TYPE
-      && comptypes (TREE_TYPE (type), TREE_TYPE (rhs)) == 1)
-    {
-      if (!lvalue_p (rhs))
-       {
-         error_at (location, "cannot pass rvalue to reference parameter");
-         return error_mark_node;
-       }
-      if (!c_mark_addressable (rhs))
-       return error_mark_node;
-      rhs = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (rhs)), rhs);
-      SET_EXPR_LOCATION (rhs, location);
-
-      /* We already know that these two types are compatible, but they
-        may not be exactly identical.  In fact, `TREE_TYPE (type)' is
-        likely to be __builtin_va_list and `TREE_TYPE (rhs)' is
-        likely to be va_list, a typedef to __builtin_va_list, which
-        is different enough that it will cause problems later.  */
-      if (TREE_TYPE (TREE_TYPE (rhs)) != TREE_TYPE (type))
-       {
-         rhs = build1 (NOP_EXPR, build_pointer_type (TREE_TYPE (type)), rhs);
-         SET_EXPR_LOCATION (rhs, location);
-       }
-
-      rhs = build1 (NOP_EXPR, type, rhs);
-      SET_EXPR_LOCATION (rhs, location);
-      return rhs;
-    }
-  /* Some types can interconvert without explicit casts.  */
-  else if (codel == VECTOR_TYPE && coder == VECTOR_TYPE
-          && vector_types_convertible_p (type, TREE_TYPE (rhs), true))
-    return convert (type, rhs);
-  /* Arithmetic types all interconvert, and enum is treated like int.  */
-  else if ((codel == INTEGER_TYPE || codel == REAL_TYPE
-           || codel == FIXED_POINT_TYPE
-           || codel == ENUMERAL_TYPE || codel == COMPLEX_TYPE
-           || codel == BOOLEAN_TYPE)
-          && (coder == INTEGER_TYPE || coder == REAL_TYPE
-              || coder == FIXED_POINT_TYPE
-              || coder == ENUMERAL_TYPE || coder == COMPLEX_TYPE
-              || coder == BOOLEAN_TYPE))
-    {
-      tree ret;
-      bool save = in_late_binary_op;
-      if (codel == BOOLEAN_TYPE || codel == COMPLEX_TYPE)
-       in_late_binary_op = true;
-      ret = convert_and_check (type, orig_rhs);
-      if (codel == BOOLEAN_TYPE || codel == COMPLEX_TYPE)
-       in_late_binary_op = save;
-      return ret;
-    }
-
-  /* Aggregates in different TUs might need conversion.  */
-  if ((codel == RECORD_TYPE || codel == UNION_TYPE)
-      && codel == coder
-      && comptypes (type, rhstype))
-    return convert_and_check (type, rhs);
-
-  /* Conversion to a transparent union or record from its member types.
-     This applies only to function arguments.  */
-  if (((codel == UNION_TYPE || codel == RECORD_TYPE)
-      && TYPE_TRANSPARENT_AGGR (type))
-      && errtype == ic_argpass)
-    {
-      tree memb, marginal_memb = NULL_TREE;
-
-      for (memb = TYPE_FIELDS (type); memb ; memb = DECL_CHAIN (memb))
-       {
-         tree memb_type = TREE_TYPE (memb);
-
-         if (comptypes (TYPE_MAIN_VARIANT (memb_type),
-                        TYPE_MAIN_VARIANT (rhstype)))
-           break;
-
-         if (TREE_CODE (memb_type) != POINTER_TYPE)
-           continue;
-
-         if (coder == POINTER_TYPE)
-           {
-             tree ttl = TREE_TYPE (memb_type);
-             tree ttr = TREE_TYPE (rhstype);
-
-             /* Any non-function converts to a [const][volatile] void *
-                and vice versa; otherwise, targets must be the same.
-                Meanwhile, the lhs target must have all the qualifiers of
-                the rhs.  */
-             if (VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr)
-                 || comp_target_types (location, memb_type, rhstype))
-               {
-                 /* If this type won't generate any warnings, use it.  */
-                 if (TYPE_QUALS (ttl) == TYPE_QUALS (ttr)
-                     || ((TREE_CODE (ttr) == FUNCTION_TYPE
-                          && TREE_CODE (ttl) == FUNCTION_TYPE)
-                         ? ((TYPE_QUALS (ttl) | TYPE_QUALS (ttr))
-                            == TYPE_QUALS (ttr))
-                         : ((TYPE_QUALS (ttl) | TYPE_QUALS (ttr))
-                            == TYPE_QUALS (ttl))))
-                   break;
-
-                 /* Keep looking for a better type, but remember this one.  */
-                 if (!marginal_memb)
-                   marginal_memb = memb;
-               }
-           }
-
-         /* Can convert integer zero to any pointer type.  */
-         if (null_pointer_constant)
-           {
-             rhs = null_pointer_node;
-             break;
-           }
-       }
-
-      if (memb || marginal_memb)
-       {
-         if (!memb)
-           {
-             /* We have only a marginally acceptable member type;
-                it needs a warning.  */
-             tree ttl = TREE_TYPE (TREE_TYPE (marginal_memb));
-             tree ttr = TREE_TYPE (rhstype);
-
-             /* Const and volatile mean something different for function
-                types, so the usual warnings are not appropriate.  */
-             if (TREE_CODE (ttr) == FUNCTION_TYPE
-                 && TREE_CODE (ttl) == FUNCTION_TYPE)
-               {
-                 /* Because const and volatile on functions are
-                    restrictions that say the function will not do
-                    certain things, it is okay to use a const or volatile
-                    function where an ordinary one is wanted, but not
-                    vice-versa.  */
-                 if (TYPE_QUALS_NO_ADDR_SPACE (ttl)
-                     & ~TYPE_QUALS_NO_ADDR_SPACE (ttr))
-                   WARN_FOR_QUALIFIERS (location, 0,
-                                        G_("passing argument %d of %qE "
-                                           "makes %q#v qualified function "
-                                           "pointer from unqualified"),
-                                        G_("assignment makes %q#v qualified "
-                                           "function pointer from "
-                                           "unqualified"),
-                                        G_("initialization makes %q#v qualified "
-                                           "function pointer from "
-                                           "unqualified"),
-                                        G_("return makes %q#v qualified function "
-                                           "pointer from unqualified"),
-                                        TYPE_QUALS (ttl) & ~TYPE_QUALS (ttr));
-               }
-             else if (TYPE_QUALS_NO_ADDR_SPACE (ttr)
-                      & ~TYPE_QUALS_NO_ADDR_SPACE (ttl))
-               WARN_FOR_QUALIFIERS (location, 0,
-                                    G_("passing argument %d of %qE discards "
-                                       "%qv qualifier from pointer target type"),
-                                    G_("assignment discards %qv qualifier "
-                                       "from pointer target type"),
-                                    G_("initialization discards %qv qualifier "
-                                       "from pointer target type"),
-                                    G_("return discards %qv qualifier from "
-                                       "pointer target type"),
-                                    TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl));
-
-             memb = marginal_memb;
-           }
-
-         if (!fundecl || !DECL_IN_SYSTEM_HEADER (fundecl))
-           pedwarn (location, OPT_Wpedantic,
-                    "ISO C prohibits argument conversion to union type");
-
-         rhs = fold_convert_loc (location, TREE_TYPE (memb), rhs);
-         return build_constructor_single (type, memb, rhs);
-       }
-    }
-
-  /* Conversions among pointers */
-  else if ((codel == POINTER_TYPE || codel == REFERENCE_TYPE)
-          && (coder == codel))
-    {
-      tree ttl = TREE_TYPE (type);
-      tree ttr = TREE_TYPE (rhstype);
-      tree mvl = ttl;
-      tree mvr = ttr;
-      bool is_opaque_pointer;
-      int target_cmp = 0;   /* Cache comp_target_types () result.  */
-      addr_space_t asl;
-      addr_space_t asr;
-
-      if (TREE_CODE (mvl) != ARRAY_TYPE)
-       mvl = TYPE_MAIN_VARIANT (mvl);
-      if (TREE_CODE (mvr) != ARRAY_TYPE)
-       mvr = TYPE_MAIN_VARIANT (mvr);
-      /* Opaque pointers are treated like void pointers.  */
-      is_opaque_pointer = vector_targets_convertible_p (ttl, ttr);
-
-      /* The Plan 9 compiler permits a pointer to a struct to be
-        automatically converted into a pointer to an anonymous field
-        within the struct.  */
-      if (flag_plan9_extensions
-         && (TREE_CODE (mvl) == RECORD_TYPE || TREE_CODE(mvl) == UNION_TYPE)
-         && (TREE_CODE (mvr) == RECORD_TYPE || TREE_CODE(mvr) == UNION_TYPE)
-         && mvl != mvr)
-       {
-         tree new_rhs = convert_to_anonymous_field (location, type, rhs);
-         if (new_rhs != NULL_TREE)
-           {
-             rhs = new_rhs;
-             rhstype = TREE_TYPE (rhs);
-             coder = TREE_CODE (rhstype);
-             ttr = TREE_TYPE (rhstype);
-             mvr = TYPE_MAIN_VARIANT (ttr);
-           }
-       }
-
-      /* C++ does not allow the implicit conversion void* -> T*.  However,
-        for the purpose of reducing the number of false positives, we
-        tolerate the special case of
-
-               int *p = NULL;
-
-        where NULL is typically defined in C to be '(void *) 0'.  */
-      if (VOID_TYPE_P (ttr) && rhs != null_pointer_node && !VOID_TYPE_P (ttl))
-       warning_at (location, OPT_Wc___compat,
-                   "request for implicit conversion "
-                   "from %qT to %qT not permitted in C++", rhstype, type);
-
-      /* See if the pointers point to incompatible address spaces.  */
-      asl = TYPE_ADDR_SPACE (ttl);
-      asr = TYPE_ADDR_SPACE (ttr);
-      if (!null_pointer_constant_p (rhs)
-         && asr != asl && !targetm.addr_space.subset_p (asr, asl))
-       {
-         switch (errtype)
-           {
-           case ic_argpass:
-             error_at (location, "passing argument %d of %qE from pointer to "
-                       "non-enclosed address space", parmnum, rname);
-             break;
-           case ic_assign:
-             error_at (location, "assignment from pointer to "
-                       "non-enclosed address space");
-             break;
-           case ic_init:
-             error_at (location, "initialization from pointer to "
-                       "non-enclosed address space");
-             break;
-           case ic_return:
-             error_at (location, "return from pointer to "
-                       "non-enclosed address space");
-             break;
-           default:
-             gcc_unreachable ();
-           }
-         return error_mark_node;
-       }
-
-      /* Check if the right-hand side has a format attribute but the
-        left-hand side doesn't.  */
-      if (warn_suggest_attribute_format
-         && check_missing_format_attribute (type, rhstype))
-       {
-         switch (errtype)
-         {
-         case ic_argpass:
-           warning_at (location, OPT_Wsuggest_attribute_format,
-                       "argument %d of %qE might be "
-                       "a candidate for a format attribute",
-                       parmnum, rname);
-           break;
-         case ic_assign:
-           warning_at (location, OPT_Wsuggest_attribute_format,
-                       "assignment left-hand side might be "
-                       "a candidate for a format attribute");
-           break;
-         case ic_init:
-           warning_at (location, OPT_Wsuggest_attribute_format,
-                       "initialization left-hand side might be "
-                       "a candidate for a format attribute");
-           break;
-         case ic_return:
-           warning_at (location, OPT_Wsuggest_attribute_format,
-                       "return type might be "
-                       "a candidate for a format attribute");
-           break;
-         default:
-           gcc_unreachable ();
-         }
-       }
-
-      /* Any non-function converts to a [const][volatile] void *
-        and vice versa; otherwise, targets must be the same.
-        Meanwhile, the lhs target must have all the qualifiers of the rhs.  */
-      if (VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr)
-         || (target_cmp = comp_target_types (location, type, rhstype))
-         || is_opaque_pointer
-         || (c_common_unsigned_type (mvl)
-             == c_common_unsigned_type (mvr)))
-       {
-         if (pedantic
-             && ((VOID_TYPE_P (ttl) && TREE_CODE (ttr) == FUNCTION_TYPE)
-                 ||
-                 (VOID_TYPE_P (ttr)
-                  && !null_pointer_constant
-                  && TREE_CODE (ttl) == FUNCTION_TYPE)))
-           WARN_FOR_ASSIGNMENT (location, OPT_Wpedantic,
-                                G_("ISO C forbids passing argument %d of "
-                                   "%qE between function pointer "
-                                   "and %<void *%>"),
-                                G_("ISO C forbids assignment between "
-                                   "function pointer and %<void *%>"),
-                                G_("ISO C forbids initialization between "
-                                   "function pointer and %<void *%>"),
-                                G_("ISO C forbids return between function "
-                                   "pointer and %<void *%>"));
-         /* Const and volatile mean something different for function types,
-            so the usual warnings are not appropriate.  */
-         else if (TREE_CODE (ttr) != FUNCTION_TYPE
-                  && TREE_CODE (ttl) != FUNCTION_TYPE)
-           {
-             if (TYPE_QUALS_NO_ADDR_SPACE (ttr)
-                 & ~TYPE_QUALS_NO_ADDR_SPACE (ttl))
-               {
-                 WARN_FOR_QUALIFIERS (location, 0,
-                                      G_("passing argument %d of %qE discards "
-                                         "%qv qualifier from pointer target type"),
-                                      G_("assignment discards %qv qualifier "
-                                         "from pointer target type"),
-                                      G_("initialization discards %qv qualifier "
-                                         "from pointer target type"),
-                                      G_("return discards %qv qualifier from "
-                                         "pointer target type"),
-                                      TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl));
-               }
-             /* If this is not a case of ignoring a mismatch in signedness,
-                no warning.  */
-             else if (VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr)
-                      || target_cmp)
-               ;
-             /* If there is a mismatch, do warn.  */
-             else if (warn_pointer_sign)
-               WARN_FOR_ASSIGNMENT (location, OPT_Wpointer_sign,
-                                    G_("pointer targets in passing argument "
-                                       "%d of %qE differ in signedness"),
-                                    G_("pointer targets in assignment "
-                                       "differ in signedness"),
-                                    G_("pointer targets in initialization "
-                                       "differ in signedness"),
-                                    G_("pointer targets in return differ "
-                                       "in signedness"));
-           }
-         else if (TREE_CODE (ttl) == FUNCTION_TYPE
-                  && TREE_CODE (ttr) == FUNCTION_TYPE)
-           {
-             /* Because const and volatile on functions are restrictions
-                that say the function will not do certain things,
-                it is okay to use a const or volatile function
-                where an ordinary one is wanted, but not vice-versa.  */
-             if (TYPE_QUALS_NO_ADDR_SPACE (ttl)
-                 & ~TYPE_QUALS_NO_ADDR_SPACE (ttr))
-               WARN_FOR_QUALIFIERS (location, 0,
-                                    G_("passing argument %d of %qE makes "
-                                       "%q#v qualified function pointer "
-                                       "from unqualified"),
-                                    G_("assignment makes %q#v qualified function "
-                                       "pointer from unqualified"),
-                                    G_("initialization makes %q#v qualified "
-                                       "function pointer from unqualified"),
-                                    G_("return makes %q#v qualified function "
-                                       "pointer from unqualified"),
-                                    TYPE_QUALS (ttl) & ~TYPE_QUALS (ttr));
-           }
-       }
-      else
-       /* Avoid warning about the volatile ObjC EH puts on decls.  */
-       if (!objc_ok)
-         WARN_FOR_ASSIGNMENT (location, 0,
-                              G_("passing argument %d of %qE from "
-                                 "incompatible pointer type"),
-                              G_("assignment from incompatible pointer type"),
-                              G_("initialization from incompatible "
-                                 "pointer type"),
-                              G_("return from incompatible pointer type"));
-
-      return convert (type, rhs);
-    }
-  else if (codel == POINTER_TYPE && coder == ARRAY_TYPE)
-    {
-      /* ??? This should not be an error when inlining calls to
-        unprototyped functions.  */
-      error_at (location, "invalid use of non-lvalue array");
-      return error_mark_node;
-    }
-  else if (codel == POINTER_TYPE && coder == INTEGER_TYPE)
-    {
-      /* An explicit constant 0 can convert to a pointer,
-        or one that results from arithmetic, even including
-        a cast to integer type.  */
-      if (!null_pointer_constant)
-       WARN_FOR_ASSIGNMENT (location, 0,
-                            G_("passing argument %d of %qE makes "
-                               "pointer from integer without a cast"),
-                            G_("assignment makes pointer from integer "
-                               "without a cast"),
-                            G_("initialization makes pointer from "
-                               "integer without a cast"),
-                            G_("return makes pointer from integer "
-                               "without a cast"));
-
-      return convert (type, rhs);
-    }
-  else if (codel == INTEGER_TYPE && coder == POINTER_TYPE)
-    {
-      WARN_FOR_ASSIGNMENT (location, 0,
-                          G_("passing argument %d of %qE makes integer "
-                             "from pointer without a cast"),
-                          G_("assignment makes integer from pointer "
-                             "without a cast"),
-                          G_("initialization makes integer from pointer "
-                             "without a cast"),
-                          G_("return makes integer from pointer "
-                             "without a cast"));
-      return convert (type, rhs);
-    }
-  else if (codel == BOOLEAN_TYPE && coder == POINTER_TYPE)
-    {
-      tree ret;
-      bool save = in_late_binary_op;
-      in_late_binary_op = true;
-      ret = convert (type, rhs);
-      in_late_binary_op = save;
-      return ret;
-    }
-
-  switch (errtype)
-    {
-    case ic_argpass:
-      error_at (location, "incompatible type for argument %d of %qE", parmnum, rname);
-      inform ((fundecl && !DECL_IS_BUILTIN (fundecl))
-             ? DECL_SOURCE_LOCATION (fundecl) : input_location,
-             "expected %qT but argument is of type %qT", type, rhstype);
-      break;
-    case ic_assign:
-      error_at (location, "incompatible types when assigning to type %qT from "
-               "type %qT", type, rhstype);
-      break;
-    case ic_init:
-      error_at (location,
-               "incompatible types when initializing type %qT using type %qT",
-               type, rhstype);
-      break;
-    case ic_return:
-      error_at (location,
-               "incompatible types when returning type %qT but %qT was "
-               "expected", rhstype, type);
-      break;
-    default:
-      gcc_unreachable ();
-    }
-
-  return error_mark_node;
-}
-\f
-/* If VALUE is a compound expr all of whose expressions are constant, then
-   return its value.  Otherwise, return error_mark_node.
-
-   This is for handling COMPOUND_EXPRs as initializer elements
-   which is allowed with a warning when -pedantic is specified.  */
-
-static tree
-valid_compound_expr_initializer (tree value, tree endtype)
-{
-  if (TREE_CODE (value) == COMPOUND_EXPR)
-    {
-      if (valid_compound_expr_initializer (TREE_OPERAND (value, 0), endtype)
-         == error_mark_node)
-       return error_mark_node;
-      return valid_compound_expr_initializer (TREE_OPERAND (value, 1),
-                                             endtype);
-    }
-  else if (!initializer_constant_valid_p (value, endtype))
-    return error_mark_node;
-  else
-    return value;
-}
-\f
-/* Perform appropriate conversions on the initial value of a variable,
-   store it in the declaration DECL,
-   and print any error messages that are appropriate.
-   If ORIGTYPE is not NULL_TREE, it is the original type of INIT.
-   If the init is invalid, store an ERROR_MARK.
-
-   INIT_LOC is the location of the initial value.  */
-
-void
-store_init_value (location_t init_loc, tree decl, tree init, tree origtype)
-{
-  tree value, type;
-  bool npc = false;
-
-  /* If variable's type was invalidly declared, just ignore it.  */
-
-  type = TREE_TYPE (decl);
-  if (TREE_CODE (type) == ERROR_MARK)
-    return;
-
-  /* Digest the specified initializer into an expression.  */
-
-  if (init)
-    npc = null_pointer_constant_p (init);
-  value = digest_init (init_loc, type, init, origtype, npc,
-                      true, TREE_STATIC (decl));
-
-  /* Store the expression if valid; else report error.  */
-
-  if (!in_system_header
-      && AGGREGATE_TYPE_P (TREE_TYPE (decl)) && !TREE_STATIC (decl))
-    warning (OPT_Wtraditional, "traditional C rejects automatic "
-            "aggregate initialization");
-
-  DECL_INITIAL (decl) = value;
-
-  /* ANSI wants warnings about out-of-range constant initializers.  */
-  STRIP_TYPE_NOPS (value);
-  if (TREE_STATIC (decl))
-    constant_expression_warning (value);
-
-  /* Check if we need to set array size from compound literal size.  */
-  if (TREE_CODE (type) == ARRAY_TYPE
-      && TYPE_DOMAIN (type) == 0
-      && value != error_mark_node)
-    {
-      tree inside_init = init;
-
-      STRIP_TYPE_NOPS (inside_init);
-      inside_init = fold (inside_init);
-
-      if (TREE_CODE (inside_init) == COMPOUND_LITERAL_EXPR)
-       {
-         tree cldecl = COMPOUND_LITERAL_EXPR_DECL (inside_init);
-
-         if (TYPE_DOMAIN (TREE_TYPE (cldecl)))
-           {
-             /* For int foo[] = (int [3]){1}; we need to set array size
-                now since later on array initializer will be just the
-                brace enclosed list of the compound literal.  */
-             tree etype = strip_array_types (TREE_TYPE (decl));
-             type = build_distinct_type_copy (TYPE_MAIN_VARIANT (type));
-             TYPE_DOMAIN (type) = TYPE_DOMAIN (TREE_TYPE (cldecl));
-             layout_type (type);
-             layout_decl (cldecl, 0);
-             TREE_TYPE (decl)
-               = c_build_qualified_type (type, TYPE_QUALS (etype));
-           }
-       }
-    }
-}
-\f
-/* Methods for storing and printing names for error messages.  */
-
-/* Implement a spelling stack that allows components of a name to be pushed
-   and popped.  Each element on the stack is this structure.  */
-
-struct spelling
-{
-  int kind;
-  union
-    {
-      unsigned HOST_WIDE_INT i;
-      const char *s;
-    } u;
-};
-
-#define SPELLING_STRING 1
-#define SPELLING_MEMBER 2
-#define SPELLING_BOUNDS 3
-
-static struct spelling *spelling;      /* Next stack element (unused).  */
-static struct spelling *spelling_base; /* Spelling stack base.  */
-static int spelling_size;              /* Size of the spelling stack.  */
-
-/* Macros to save and restore the spelling stack around push_... functions.
-   Alternative to SAVE_SPELLING_STACK.  */
-
-#define SPELLING_DEPTH() (spelling - spelling_base)
-#define RESTORE_SPELLING_DEPTH(DEPTH) (spelling = spelling_base + (DEPTH))
-
-/* Push an element on the spelling stack with type KIND and assign VALUE
-   to MEMBER.  */
-
-#define PUSH_SPELLING(KIND, VALUE, MEMBER)                             \
-{                                                                      \
-  int depth = SPELLING_DEPTH ();                                       \
-                                                                       \
-  if (depth >= spelling_size)                                          \
-    {                                                                  \
-      spelling_size += 10;                                             \
-      spelling_base = XRESIZEVEC (struct spelling, spelling_base,      \
-                                 spelling_size);                       \
-      RESTORE_SPELLING_DEPTH (depth);                                  \
-    }                                                                  \
-                                                                       \
-  spelling->kind = (KIND);                                             \
-  spelling->MEMBER = (VALUE);                                          \
-  spelling++;                                                          \
-}
-
-/* Push STRING on the stack.  Printed literally.  */
-
-static void
-push_string (const char *string)
-{
-  PUSH_SPELLING (SPELLING_STRING, string, u.s);
-}
-
-/* Push a member name on the stack.  Printed as '.' STRING.  */
-
-static void
-push_member_name (tree decl)
-{
-  const char *const string
-    = (DECL_NAME (decl)
-       ? identifier_to_locale (IDENTIFIER_POINTER (DECL_NAME (decl)))
-       : _("<anonymous>"));
-  PUSH_SPELLING (SPELLING_MEMBER, string, u.s);
-}
-
-/* Push an array bounds on the stack.  Printed as [BOUNDS].  */
-
-static void
-push_array_bounds (unsigned HOST_WIDE_INT bounds)
-{
-  PUSH_SPELLING (SPELLING_BOUNDS, bounds, u.i);
-}
-
-/* Compute the maximum size in bytes of the printed spelling.  */
-
-static int
-spelling_length (void)
-{
-  int size = 0;
-  struct spelling *p;
-
-  for (p = spelling_base; p < spelling; p++)
-    {
-      if (p->kind == SPELLING_BOUNDS)
-       size += 25;
-      else
-       size += strlen (p->u.s) + 1;
-    }
-
-  return size;
-}
-
-/* Print the spelling to BUFFER and return it.  */
-
-static char *
-print_spelling (char *buffer)
-{
-  char *d = buffer;
-  struct spelling *p;
-
-  for (p = spelling_base; p < spelling; p++)
-    if (p->kind == SPELLING_BOUNDS)
-      {
-       sprintf (d, "[" HOST_WIDE_INT_PRINT_UNSIGNED "]", p->u.i);
-       d += strlen (d);
-      }
-    else
-      {
-       const char *s;
-       if (p->kind == SPELLING_MEMBER)
-         *d++ = '.';
-       for (s = p->u.s; (*d = *s++); d++)
-         ;
-      }
-  *d++ = '\0';
-  return buffer;
-}
-
-/* Issue an error message for a bad initializer component.
-   GMSGID identifies the message.
-   The component name is taken from the spelling stack.  */
-
-void
-error_init (const char *gmsgid)
-{
-  char *ofwhat;
-
-  /* The gmsgid may be a format string with %< and %>. */
-  error (gmsgid);
-  ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
-  if (*ofwhat)
-    error ("(near initialization for %qs)", ofwhat);
-}
-
-/* Issue a pedantic warning for a bad initializer component.  OPT is
-   the option OPT_* (from options.h) controlling this warning or 0 if
-   it is unconditionally given.  GMSGID identifies the message.  The
-   component name is taken from the spelling stack.  */
-
-void
-pedwarn_init (location_t location, int opt, const char *gmsgid)
-{
-  char *ofwhat;
-
-  /* The gmsgid may be a format string with %< and %>. */
-  pedwarn (location, opt, gmsgid);
-  ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
-  if (*ofwhat)
-    pedwarn (location, opt, "(near initialization for %qs)", ofwhat);
-}
-
-/* Issue a warning for a bad initializer component.
-
-   OPT is the OPT_W* value corresponding to the warning option that
-   controls this warning.  GMSGID identifies the message.  The
-   component name is taken from the spelling stack.  */
-
-static void
-warning_init (int opt, const char *gmsgid)
-{
-  char *ofwhat;
-
-  /* The gmsgid may be a format string with %< and %>. */
-  warning (opt, gmsgid);
-  ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
-  if (*ofwhat)
-    warning (opt, "(near initialization for %qs)", ofwhat);
-}
-\f
-/* If TYPE is an array type and EXPR is a parenthesized string
-   constant, warn if pedantic that EXPR is being used to initialize an
-   object of type TYPE.  */
-
-void
-maybe_warn_string_init (tree type, struct c_expr expr)
-{
-  if (pedantic
-      && TREE_CODE (type) == ARRAY_TYPE
-      && TREE_CODE (expr.value) == STRING_CST
-      && expr.original_code != STRING_CST)
-    pedwarn_init (input_location, OPT_Wpedantic,
-                 "array initialized from parenthesized string constant");
-}
-
-/* Digest the parser output INIT as an initializer for type TYPE.
-   Return a C expression of type TYPE to represent the initial value.
-
-   If ORIGTYPE is not NULL_TREE, it is the original type of INIT.
-
-   NULL_POINTER_CONSTANT is true if INIT is a null pointer constant.
-
-   If INIT is a string constant, STRICT_STRING is true if it is
-   unparenthesized or we should not warn here for it being parenthesized.
-   For other types of INIT, STRICT_STRING is not used.
-
-   INIT_LOC is the location of the INIT.
-
-   REQUIRE_CONSTANT requests an error if non-constant initializers or
-   elements are seen.  */
-
-static tree
-digest_init (location_t init_loc, tree type, tree init, tree origtype,
-            bool null_pointer_constant, bool strict_string,
-            int require_constant)
-{
-  enum tree_code code = TREE_CODE (type);
-  tree inside_init = init;
-  tree semantic_type = NULL_TREE;
-  bool maybe_const = true;
-
-  if (type == error_mark_node
-      || !init
-      || init == error_mark_node
-      || TREE_TYPE (init) == error_mark_node)
-    return error_mark_node;
-
-  STRIP_TYPE_NOPS (inside_init);
-
-  if (TREE_CODE (inside_init) == EXCESS_PRECISION_EXPR)
-    {
-      semantic_type = TREE_TYPE (inside_init);
-      inside_init = TREE_OPERAND (inside_init, 0);
-    }
-  inside_init = c_fully_fold (inside_init, require_constant, &maybe_const);
-  inside_init = decl_constant_value_for_optimization (inside_init);
-
-  /* Initialization of an array of chars from a string constant
-     optionally enclosed in braces.  */
-
-  if (code == ARRAY_TYPE && inside_init
-      && TREE_CODE (inside_init) == STRING_CST)
-    {
-      tree typ1 = TYPE_MAIN_VARIANT (TREE_TYPE (type));
-      /* Note that an array could be both an array of character type
-        and an array of wchar_t if wchar_t is signed char or unsigned
-        char.  */
-      bool char_array = (typ1 == char_type_node
-                        || typ1 == signed_char_type_node
-                        || typ1 == unsigned_char_type_node);
-      bool wchar_array = !!comptypes (typ1, wchar_type_node);
-      bool char16_array = !!comptypes (typ1, char16_type_node);
-      bool char32_array = !!comptypes (typ1, char32_type_node);
-
-      if (char_array || wchar_array || char16_array || char32_array)
-       {
-         struct c_expr expr;
-         tree typ2 = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (inside_init)));
-         expr.value = inside_init;
-         expr.original_code = (strict_string ? STRING_CST : ERROR_MARK);
-         expr.original_type = NULL;
-         maybe_warn_string_init (type, expr);
-
-         if (TYPE_DOMAIN (type) && !TYPE_MAX_VALUE (TYPE_DOMAIN (type)))
-           pedwarn_init (init_loc, OPT_Wpedantic,
-                         "initialization of a flexible array member");
-
-         if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (inside_init)),
-                        TYPE_MAIN_VARIANT (type)))
-           return inside_init;
-
-         if (char_array)
-           {
-             if (typ2 != char_type_node)
-               {
-                 error_init ("char-array initialized from wide string");
-                 return error_mark_node;
-               }
-           }
-         else
-           {
-             if (typ2 == char_type_node)
-               {
-                 error_init ("wide character array initialized from non-wide "
-                             "string");
-                 return error_mark_node;
-               }
-             else if (!comptypes(typ1, typ2))
-               {
-                 error_init ("wide character array initialized from "
-                             "incompatible wide string");
-                 return error_mark_node;
-               }
-           }
-
-         TREE_TYPE (inside_init) = type;
-         if (TYPE_DOMAIN (type) != 0
-             && TYPE_SIZE (type) != 0
-             && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST)
-           {
-             unsigned HOST_WIDE_INT len = TREE_STRING_LENGTH (inside_init);
-
-             /* Subtract the size of a single (possibly wide) character
-                because it's ok to ignore the terminating null char
-                that is counted in the length of the constant.  */
-             if (0 > compare_tree_int (TYPE_SIZE_UNIT (type),
-                                       (len
-                                        - (TYPE_PRECISION (typ1)
-                                           / BITS_PER_UNIT))))
-               pedwarn_init (init_loc, 0,
-                             ("initializer-string for array of chars "
-                              "is too long"));
-             else if (warn_cxx_compat
-                      && 0 > compare_tree_int (TYPE_SIZE_UNIT (type), len))
-               warning_at (init_loc, OPT_Wc___compat,
-                           ("initializer-string for array chars "
-                            "is too long for C++"));
-           }
-
-         return inside_init;
-       }
-      else if (INTEGRAL_TYPE_P (typ1))
-       {
-         error_init ("array of inappropriate type initialized "
-                     "from string constant");
-         return error_mark_node;
-       }
-    }
-
-  /* Build a VECTOR_CST from a *constant* vector constructor.  If the
-     vector constructor is not constant (e.g. {1,2,3,foo()}) then punt
-     below and handle as a constructor.  */
-  if (code == VECTOR_TYPE
-      && TREE_CODE (TREE_TYPE (inside_init)) == VECTOR_TYPE
-      && vector_types_convertible_p (TREE_TYPE (inside_init), type, true)
-      && TREE_CONSTANT (inside_init))
-    {
-      if (TREE_CODE (inside_init) == VECTOR_CST
-         && comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (inside_init)),
-                       TYPE_MAIN_VARIANT (type)))
-       return inside_init;
-
-      if (TREE_CODE (inside_init) == CONSTRUCTOR)
-       {
-         unsigned HOST_WIDE_INT ix;
-         tree value;
-         bool constant_p = true;
-
-         /* Iterate through elements and check if all constructor
-            elements are *_CSTs.  */
-         FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (inside_init), ix, value)
-           if (!CONSTANT_CLASS_P (value))
-             {
-               constant_p = false;
-               break;
-             }
-
-         if (constant_p)
-           return build_vector_from_ctor (type,
-                                          CONSTRUCTOR_ELTS (inside_init));
-       }
-    }
-
-  if (warn_sequence_point)
-    verify_sequence_points (inside_init);
-
-  /* Any type can be initialized
-     from an expression of the same type, optionally with braces.  */
-
-  if (inside_init && TREE_TYPE (inside_init) != 0
-      && (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (inside_init)),
-                    TYPE_MAIN_VARIANT (type))
-         || (code == ARRAY_TYPE
-             && comptypes (TREE_TYPE (inside_init), type))
-         || (code == VECTOR_TYPE
-             && comptypes (TREE_TYPE (inside_init), type))
-         || (code == POINTER_TYPE
-             && TREE_CODE (TREE_TYPE (inside_init)) == ARRAY_TYPE
-             && comptypes (TREE_TYPE (TREE_TYPE (inside_init)),
-                           TREE_TYPE (type)))))
-    {
-      if (code == POINTER_TYPE)
-       {
-         if (TREE_CODE (TREE_TYPE (inside_init)) == ARRAY_TYPE)
-           {
-             if (TREE_CODE (inside_init) == STRING_CST
-                 || TREE_CODE (inside_init) == COMPOUND_LITERAL_EXPR)
-               inside_init = array_to_pointer_conversion
-                 (init_loc, inside_init);
-             else
-               {
-                 error_init ("invalid use of non-lvalue array");
-                 return error_mark_node;
-               }
-           }
-       }
-
-      if (code == VECTOR_TYPE)
-       /* Although the types are compatible, we may require a
-          conversion.  */
-       inside_init = convert (type, inside_init);
-
-      if (require_constant
-         && (code == VECTOR_TYPE || !flag_isoc99)
-         && TREE_CODE (inside_init) == COMPOUND_LITERAL_EXPR)
-       {
-         /* As an extension, allow initializing objects with static storage
-            duration with compound literals (which are then treated just as
-            the brace enclosed list they contain).  Also allow this for
-            vectors, as we can only assign them with compound literals.  */
-         tree decl = COMPOUND_LITERAL_EXPR_DECL (inside_init);
-         inside_init = DECL_INITIAL (decl);
-       }
-
-      if (code == ARRAY_TYPE && TREE_CODE (inside_init) != STRING_CST
-         && TREE_CODE (inside_init) != CONSTRUCTOR)
-       {
-         error_init ("array initialized from non-constant array expression");
-         return error_mark_node;
-       }
-
-      /* Compound expressions can only occur here if -Wpedantic or
-        -pedantic-errors is specified.  In the later case, we always want
-        an error.  In the former case, we simply want a warning.  */
-      if (require_constant && pedantic
-         && TREE_CODE (inside_init) == COMPOUND_EXPR)
-       {
-         inside_init
-           = valid_compound_expr_initializer (inside_init,
-                                              TREE_TYPE (inside_init));
-         if (inside_init == error_mark_node)
-           error_init ("initializer element is not constant");
-         else
-           pedwarn_init (init_loc, OPT_Wpedantic,
-                         "initializer element is not constant");
-         if (flag_pedantic_errors)
-           inside_init = error_mark_node;
-       }
-      else if (require_constant
-              && !initializer_constant_valid_p (inside_init,
-                                                TREE_TYPE (inside_init)))
-       {
-         error_init ("initializer element is not constant");
-         inside_init = error_mark_node;
-       }
-      else if (require_constant && !maybe_const)
-       pedwarn_init (init_loc, 0,
-                     "initializer element is not a constant expression");
-
-      /* Added to enable additional -Wsuggest-attribute=format warnings.  */
-      if (TREE_CODE (TREE_TYPE (inside_init)) == POINTER_TYPE)
-       inside_init = convert_for_assignment (init_loc, type, inside_init,
-                                             origtype,
-                                             ic_init, null_pointer_constant,
-                                             NULL_TREE, NULL_TREE, 0);
-      return inside_init;
-    }
-
-  /* Handle scalar types, including conversions.  */
-
-  if (code == INTEGER_TYPE || code == REAL_TYPE || code == FIXED_POINT_TYPE
-      || code == POINTER_TYPE || code == ENUMERAL_TYPE || code == BOOLEAN_TYPE
-      || code == COMPLEX_TYPE || code == VECTOR_TYPE)
-    {
-      if (TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE
-         && (TREE_CODE (init) == STRING_CST
-             || TREE_CODE (init) == COMPOUND_LITERAL_EXPR))
-       inside_init = init = array_to_pointer_conversion (init_loc, init);
-      if (semantic_type)
-       inside_init = build1 (EXCESS_PRECISION_EXPR, semantic_type,
-                             inside_init);
-      inside_init
-       = convert_for_assignment (init_loc, type, inside_init, origtype,
-                                 ic_init, null_pointer_constant,
-                                 NULL_TREE, NULL_TREE, 0);
-
-      /* Check to see if we have already given an error message.  */
-      if (inside_init == error_mark_node)
-       ;
-      else if (require_constant && !TREE_CONSTANT (inside_init))
-       {
-         error_init ("initializer element is not constant");
-         inside_init = error_mark_node;
-       }
-      else if (require_constant
-              && !initializer_constant_valid_p (inside_init,
-                                                TREE_TYPE (inside_init)))
-       {
-         error_init ("initializer element is not computable at load time");
-         inside_init = error_mark_node;
-       }
-      else if (require_constant && !maybe_const)
-       pedwarn_init (init_loc, 0,
-                     "initializer element is not a constant expression");
-
-      return inside_init;
-    }
-
-  /* Come here only for records and arrays.  */
-
-  if (COMPLETE_TYPE_P (type) && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
-    {
-      error_init ("variable-sized object may not be initialized");
-      return error_mark_node;
-    }
-
-  error_init ("invalid initializer");
-  return error_mark_node;
-}
-\f
-/* Handle initializers that use braces.  */
-
-/* Type of object we are accumulating a constructor for.
-   This type is always a RECORD_TYPE, UNION_TYPE or ARRAY_TYPE.  */
-static tree constructor_type;
-
-/* For a RECORD_TYPE or UNION_TYPE, this is the chain of fields
-   left to fill.  */
-static tree constructor_fields;
-
-/* For an ARRAY_TYPE, this is the specified index
-   at which to store the next element we get.  */
-static tree constructor_index;
-
-/* For an ARRAY_TYPE, this is the maximum index.  */
-static tree constructor_max_index;
-
-/* For a RECORD_TYPE, this is the first field not yet written out.  */
-static tree constructor_unfilled_fields;
-
-/* For an ARRAY_TYPE, this is the index of the first element
-   not yet written out.  */
-static tree constructor_unfilled_index;
-
-/* In a RECORD_TYPE, the byte index of the next consecutive field.
-   This is so we can generate gaps between fields, when appropriate.  */
-static tree constructor_bit_index;
-
-/* If we are saving up the elements rather than allocating them,
-   this is the list of elements so far (in reverse order,
-   most recent first).  */
-static VEC(constructor_elt,gc) *constructor_elements;
-
-/* 1 if constructor should be incrementally stored into a constructor chain,
-   0 if all the elements should be kept in AVL tree.  */
-static int constructor_incremental;
-
-/* 1 if so far this constructor's elements are all compile-time constants.  */
-static int constructor_constant;
-
-/* 1 if so far this constructor's elements are all valid address constants.  */
-static int constructor_simple;
-
-/* 1 if this constructor has an element that cannot be part of a
-   constant expression.  */
-static int constructor_nonconst;
-
-/* 1 if this constructor is erroneous so far.  */
-static int constructor_erroneous;
-
-/* Structure for managing pending initializer elements, organized as an
-   AVL tree.  */
-
-struct init_node
-{
-  struct init_node *left, *right;
-  struct init_node *parent;
-  int balance;
-  tree purpose;
-  tree value;
-  tree origtype;
-};
-
-/* Tree of pending elements at this constructor level.
-   These are elements encountered out of order
-   which belong at places we haven't reached yet in actually
-   writing the output.
-   Will never hold tree nodes across GC runs.  */
-static struct init_node *constructor_pending_elts;
-
-/* The SPELLING_DEPTH of this constructor.  */
-static int constructor_depth;
-
-/* DECL node for which an initializer is being read.
-   0 means we are reading a constructor expression
-   such as (struct foo) {...}.  */
-static tree constructor_decl;
-
-/* Nonzero if this is an initializer for a top-level decl.  */
-static int constructor_top_level;
-
-/* Nonzero if there were any member designators in this initializer.  */
-static int constructor_designated;
-
-/* Nesting depth of designator list.  */
-static int designator_depth;
-
-/* Nonzero if there were diagnosed errors in this designator list.  */
-static int designator_erroneous;
-
-\f
-/* This stack has a level for each implicit or explicit level of
-   structuring in the initializer, including the outermost one.  It
-   saves the values of most of the variables above.  */
-
-struct constructor_range_stack;
-
-struct constructor_stack
-{
-  struct constructor_stack *next;
-  tree type;
-  tree fields;
-  tree index;
-  tree max_index;
-  tree unfilled_index;
-  tree unfilled_fields;
-  tree bit_index;
-  VEC(constructor_elt,gc) *elements;
-  struct init_node *pending_elts;
-  int offset;
-  int depth;
-  /* If value nonzero, this value should replace the entire
-     constructor at this level.  */
-  struct c_expr replacement_value;
-  struct constructor_range_stack *range_stack;
-  char constant;
-  char simple;
-  char nonconst;
-  char implicit;
-  char erroneous;
-  char outer;
-  char incremental;
-  char designated;
-};
-
-static struct constructor_stack *constructor_stack;
-
-/* This stack represents designators from some range designator up to
-   the last designator in the list.  */
-
-struct constructor_range_stack
-{
-  struct constructor_range_stack *next, *prev;
-  struct constructor_stack *stack;
-  tree range_start;
-  tree index;
-  tree range_end;
-  tree fields;
-};
-
-static struct constructor_range_stack *constructor_range_stack;
-
-/* This stack records separate initializers that are nested.
-   Nested initializers can't happen in ANSI C, but GNU C allows them
-   in cases like { ... (struct foo) { ... } ... }.  */
-
-struct initializer_stack
-{
-  struct initializer_stack *next;
-  tree decl;
-  struct constructor_stack *constructor_stack;
-  struct constructor_range_stack *constructor_range_stack;
-  VEC(constructor_elt,gc) *elements;
-  struct spelling *spelling;
-  struct spelling *spelling_base;
-  int spelling_size;
-  char top_level;
-  char require_constant_value;
-  char require_constant_elements;
-};
-
-static struct initializer_stack *initializer_stack;
-\f
-/* Prepare to parse and output the initializer for variable DECL.  */
-
-void
-start_init (tree decl, tree asmspec_tree ATTRIBUTE_UNUSED, int top_level)
-{
-  const char *locus;
-  struct initializer_stack *p = XNEW (struct initializer_stack);
-
-  p->decl = constructor_decl;
-  p->require_constant_value = require_constant_value;
-  p->require_constant_elements = require_constant_elements;
-  p->constructor_stack = constructor_stack;
-  p->constructor_range_stack = constructor_range_stack;
-  p->elements = constructor_elements;
-  p->spelling = spelling;
-  p->spelling_base = spelling_base;
-  p->spelling_size = spelling_size;
-  p->top_level = constructor_top_level;
-  p->next = initializer_stack;
-  initializer_stack = p;
-
-  constructor_decl = decl;
-  constructor_designated = 0;
-  constructor_top_level = top_level;
-
-  if (decl != 0 && decl != error_mark_node)
-    {
-      require_constant_value = TREE_STATIC (decl);
-      require_constant_elements
-       = ((TREE_STATIC (decl) || (pedantic && !flag_isoc99))
-          /* For a scalar, you can always use any value to initialize,
-             even within braces.  */
-          && (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
-              || TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE
-              || TREE_CODE (TREE_TYPE (decl)) == UNION_TYPE
-              || TREE_CODE (TREE_TYPE (decl)) == QUAL_UNION_TYPE));
-      locus = identifier_to_locale (IDENTIFIER_POINTER (DECL_NAME (decl)));
-    }
-  else
-    {
-      require_constant_value = 0;
-      require_constant_elements = 0;
-      locus = _("(anonymous)");
-    }
-
-  constructor_stack = 0;
-  constructor_range_stack = 0;
-
-  missing_braces_mentioned = 0;
-
-  spelling_base = 0;
-  spelling_size = 0;
-  RESTORE_SPELLING_DEPTH (0);
-
-  if (locus)
-    push_string (locus);
-}
-
-void
-finish_init (void)
-{
-  struct initializer_stack *p = initializer_stack;
-
-  /* Free the whole constructor stack of this initializer.  */
-  while (constructor_stack)
-    {
-      struct constructor_stack *q = constructor_stack;
-      constructor_stack = q->next;
-      free (q);
-    }
-
-  gcc_assert (!constructor_range_stack);
-
-  /* Pop back to the data of the outer initializer (if any).  */
-  free (spelling_base);
-
-  constructor_decl = p->decl;
-  require_constant_value = p->require_constant_value;
-  require_constant_elements = p->require_constant_elements;
-  constructor_stack = p->constructor_stack;
-  constructor_range_stack = p->constructor_range_stack;
-  constructor_elements = p->elements;
-  spelling = p->spelling;
-  spelling_base = p->spelling_base;
-  spelling_size = p->spelling_size;
-  constructor_top_level = p->top_level;
-  initializer_stack = p->next;
-  free (p);
-}
-\f
-/* Call here when we see the initializer is surrounded by braces.
-   This is instead of a call to push_init_level;
-   it is matched by a call to pop_init_level.
-
-   TYPE is the type to initialize, for a constructor expression.
-   For an initializer for a decl, TYPE is zero.  */
-
-void
-really_start_incremental_init (tree type)
-{
-  struct constructor_stack *p = XNEW (struct constructor_stack);
-
-  if (type == 0)
-    type = TREE_TYPE (constructor_decl);
-
-  if (TREE_CODE (type) == VECTOR_TYPE
-      && TYPE_VECTOR_OPAQUE (type))
-    error ("opaque vector types cannot be initialized");
-
-  p->type = constructor_type;
-  p->fields = constructor_fields;
-  p->index = constructor_index;
-  p->max_index = constructor_max_index;
-  p->unfilled_index = constructor_unfilled_index;
-  p->unfilled_fields = constructor_unfilled_fields;
-  p->bit_index = constructor_bit_index;
-  p->elements = constructor_elements;
-  p->constant = constructor_constant;
-  p->simple = constructor_simple;
-  p->nonconst = constructor_nonconst;
-  p->erroneous = constructor_erroneous;
-  p->pending_elts = constructor_pending_elts;
-  p->depth = constructor_depth;
-  p->replacement_value.value = 0;
-  p->replacement_value.original_code = ERROR_MARK;
-  p->replacement_value.original_type = NULL;
-  p->implicit = 0;
-  p->range_stack = 0;
-  p->outer = 0;
-  p->incremental = constructor_incremental;
-  p->designated = constructor_designated;
-  p->next = 0;
-  constructor_stack = p;
-
-  constructor_constant = 1;
-  constructor_simple = 1;
-  constructor_nonconst = 0;
-  constructor_depth = SPELLING_DEPTH ();
-  constructor_elements = 0;
-  constructor_pending_elts = 0;
-  constructor_type = type;
-  constructor_incremental = 1;
-  constructor_designated = 0;
-  designator_depth = 0;
-  designator_erroneous = 0;
-
-  if (TREE_CODE (constructor_type) == RECORD_TYPE
-      || TREE_CODE (constructor_type) == UNION_TYPE)
-    {
-      constructor_fields = TYPE_FIELDS (constructor_type);
-      /* Skip any nameless bit fields at the beginning.  */
-      while (constructor_fields != 0 && DECL_C_BIT_FIELD (constructor_fields)
-            && DECL_NAME (constructor_fields) == 0)
-       constructor_fields = DECL_CHAIN (constructor_fields);
-
-      constructor_unfilled_fields = constructor_fields;
-      constructor_bit_index = bitsize_zero_node;
-    }
-  else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
-    {
-      if (TYPE_DOMAIN (constructor_type))
-       {
-         constructor_max_index
-           = TYPE_MAX_VALUE (TYPE_DOMAIN (constructor_type));
-
-         /* Detect non-empty initializations of zero-length arrays.  */
-         if (constructor_max_index == NULL_TREE
-             && TYPE_SIZE (constructor_type))
-           constructor_max_index = integer_minus_one_node;
-
-         /* constructor_max_index needs to be an INTEGER_CST.  Attempts
-            to initialize VLAs will cause a proper error; avoid tree
-            checking errors as well by setting a safe value.  */
-         if (constructor_max_index
-             && TREE_CODE (constructor_max_index) != INTEGER_CST)
-           constructor_max_index = integer_minus_one_node;
-
-         constructor_index
-           = convert (bitsizetype,
-                      TYPE_MIN_VALUE (TYPE_DOMAIN (constructor_type)));
-       }
-      else
-       {
-         constructor_index = bitsize_zero_node;
-         constructor_max_index = NULL_TREE;
-       }
-
-      constructor_unfilled_index = constructor_index;
-    }
-  else if (TREE_CODE (constructor_type) == VECTOR_TYPE)
-    {
-      /* Vectors are like simple fixed-size arrays.  */
-      constructor_max_index =
-       bitsize_int (TYPE_VECTOR_SUBPARTS (constructor_type) - 1);
-      constructor_index = bitsize_zero_node;
-      constructor_unfilled_index = constructor_index;
-    }
-  else
-    {
-      /* Handle the case of int x = {5}; */
-      constructor_fields = constructor_type;
-      constructor_unfilled_fields = constructor_type;
-    }
-}
-\f
-/* Push down into a subobject, for initialization.
-   If this is for an explicit set of braces, IMPLICIT is 0.
-   If it is because the next element belongs at a lower level,
-   IMPLICIT is 1 (or 2 if the push is because of designator list).  */
-
-void
-push_init_level (int implicit, struct obstack * braced_init_obstack)
-{
-  struct constructor_stack *p;
-  tree value = NULL_TREE;
-
-  /* If we've exhausted any levels that didn't have braces,
-     pop them now.  If implicit == 1, this will have been done in
-     process_init_element; do not repeat it here because in the case
-     of excess initializers for an empty aggregate this leads to an
-     infinite cycle of popping a level and immediately recreating
-     it.  */
-  if (implicit != 1)
-    {
-      while (constructor_stack->implicit)
-       {
-         if ((TREE_CODE (constructor_type) == RECORD_TYPE
-              || TREE_CODE (constructor_type) == UNION_TYPE)
-             && constructor_fields == 0)
-           process_init_element (pop_init_level (1, braced_init_obstack),
-                                 true, braced_init_obstack);
-         else if (TREE_CODE (constructor_type) == ARRAY_TYPE
-                  && constructor_max_index
-                  && tree_int_cst_lt (constructor_max_index,
-                                      constructor_index))
-           process_init_element (pop_init_level (1, braced_init_obstack),
-                                 true, braced_init_obstack);
-         else
-           break;
-       }
-    }
-
-  /* Unless this is an explicit brace, we need to preserve previous
-     content if any.  */
-  if (implicit)
-    {
-      if ((TREE_CODE (constructor_type) == RECORD_TYPE
-          || TREE_CODE (constructor_type) == UNION_TYPE)
-         && constructor_fields)
-       value = find_init_member (constructor_fields, braced_init_obstack);
-      else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
-       value = find_init_member (constructor_index, braced_init_obstack);
-    }
-
-  p = XNEW (struct constructor_stack);
-  p->type = constructor_type;
-  p->fields = constructor_fields;
-  p->index = constructor_index;
-  p->max_index = constructor_max_index;
-  p->unfilled_index = constructor_unfilled_index;
-  p->unfilled_fields = constructor_unfilled_fields;
-  p->bit_index = constructor_bit_index;
-  p->elements = constructor_elements;
-  p->constant = constructor_constant;
-  p->simple = constructor_simple;
-  p->nonconst = constructor_nonconst;
-  p->erroneous = constructor_erroneous;
-  p->pending_elts = constructor_pending_elts;
-  p->depth = constructor_depth;
-  p->replacement_value.value = 0;
-  p->replacement_value.original_code = ERROR_MARK;
-  p->replacement_value.original_type = NULL;
-  p->implicit = implicit;
-  p->outer = 0;
-  p->incremental = constructor_incremental;
-  p->designated = constructor_designated;
-  p->next = constructor_stack;
-  p->range_stack = 0;
-  constructor_stack = p;
-
-  constructor_constant = 1;
-  constructor_simple = 1;
-  constructor_nonconst = 0;
-  constructor_depth = SPELLING_DEPTH ();
-  constructor_elements = 0;
-  constructor_incremental = 1;
-  constructor_designated = 0;
-  constructor_pending_elts = 0;
-  if (!implicit)
-    {
-      p->range_stack = constructor_range_stack;
-      constructor_range_stack = 0;
-      designator_depth = 0;
-      designator_erroneous = 0;
-    }
-
-  /* Don't die if an entire brace-pair level is superfluous
-     in the containing level.  */
-  if (constructor_type == 0)
-    ;
-  else if (TREE_CODE (constructor_type) == RECORD_TYPE
-          || TREE_CODE (constructor_type) == UNION_TYPE)
-    {
-      /* Don't die if there are extra init elts at the end.  */
-      if (constructor_fields == 0)
-       constructor_type = 0;
-      else
-       {
-         constructor_type = TREE_TYPE (constructor_fields);
-         push_member_name (constructor_fields);
-         constructor_depth++;
-       }
-    }
-  else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
-    {
-      constructor_type = TREE_TYPE (constructor_type);
-      push_array_bounds (tree_low_cst (constructor_index, 1));
-      constructor_depth++;
-    }
-
-  if (constructor_type == 0)
-    {
-      error_init ("extra brace group at end of initializer");
-      constructor_fields = 0;
-      constructor_unfilled_fields = 0;
-      return;
-    }
-
-  if (value && TREE_CODE (value) == CONSTRUCTOR)
-    {
-      constructor_constant = TREE_CONSTANT (value);
-      constructor_simple = TREE_STATIC (value);
-      constructor_nonconst = CONSTRUCTOR_NON_CONST (value);
-      constructor_elements = CONSTRUCTOR_ELTS (value);
-      if (!VEC_empty (constructor_elt, constructor_elements)
-         && (TREE_CODE (constructor_type) == RECORD_TYPE
-             || TREE_CODE (constructor_type) == ARRAY_TYPE))
-       set_nonincremental_init (braced_init_obstack);
-    }
-
-  if (implicit == 1 && warn_missing_braces && !missing_braces_mentioned)
-    {
-      missing_braces_mentioned = 1;
-      warning_init (OPT_Wmissing_braces, "missing braces around initializer");
-    }
-
-  if (TREE_CODE (constructor_type) == RECORD_TYPE
-          || TREE_CODE (constructor_type) == UNION_TYPE)
-    {
-      constructor_fields = TYPE_FIELDS (constructor_type);
-      /* Skip any nameless bit fields at the beginning.  */
-      while (constructor_fields != 0 && DECL_C_BIT_FIELD (constructor_fields)
-            && DECL_NAME (constructor_fields) == 0)
-       constructor_fields = DECL_CHAIN (constructor_fields);
-
-      constructor_unfilled_fields = constructor_fields;
-      constructor_bit_index = bitsize_zero_node;
-    }
-  else if (TREE_CODE (constructor_type) == VECTOR_TYPE)
-    {
-      /* Vectors are like simple fixed-size arrays.  */
-      constructor_max_index =
-       bitsize_int (TYPE_VECTOR_SUBPARTS (constructor_type) - 1);
-      constructor_index = bitsize_int (0);
-      constructor_unfilled_index = constructor_index;
-    }
-  else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
-    {
-      if (TYPE_DOMAIN (constructor_type))
-       {
-         constructor_max_index
-           = TYPE_MAX_VALUE (TYPE_DOMAIN (constructor_type));
-
-         /* Detect non-empty initializations of zero-length arrays.  */
-         if (constructor_max_index == NULL_TREE
-             && TYPE_SIZE (constructor_type))
-           constructor_max_index = integer_minus_one_node;
-
-         /* constructor_max_index needs to be an INTEGER_CST.  Attempts
-            to initialize VLAs will cause a proper error; avoid tree
-            checking errors as well by setting a safe value.  */
-         if (constructor_max_index
-             && TREE_CODE (constructor_max_index) != INTEGER_CST)
-           constructor_max_index = integer_minus_one_node;
-
-         constructor_index
-           = convert (bitsizetype,
-                      TYPE_MIN_VALUE (TYPE_DOMAIN (constructor_type)));
-       }
-      else
-       constructor_index = bitsize_zero_node;
-
-      constructor_unfilled_index = constructor_index;
-      if (value && TREE_CODE (value) == STRING_CST)
-       {
-         /* We need to split the char/wchar array into individual
-            characters, so that we don't have to special case it
-            everywhere.  */
-         set_nonincremental_init_from_string (value, braced_init_obstack);
-       }
-    }
-  else
-    {
-      if (constructor_type != error_mark_node)
-       warning_init (0, "braces around scalar initializer");
-      constructor_fields = constructor_type;
-      constructor_unfilled_fields = constructor_type;
-    }
-}
-
-/* At the end of an implicit or explicit brace level,
-   finish up that level of constructor.  If a single expression
-   with redundant braces initialized that level, return the
-   c_expr structure for that expression.  Otherwise, the original_code
-   element is set to ERROR_MARK.
-   If we were outputting the elements as they are read, return 0 as the value
-   from inner levels (process_init_element ignores that),
-   but return error_mark_node as the value from the outermost level
-   (that's what we want to put in DECL_INITIAL).
-   Otherwise, return a CONSTRUCTOR expression as the value.  */
-
-struct c_expr
-pop_init_level (int implicit, struct obstack * braced_init_obstack)
-{
-  struct constructor_stack *p;
-  struct c_expr ret;
-  ret.value = 0;
-  ret.original_code = ERROR_MARK;
-  ret.original_type = NULL;
-
-  if (implicit == 0)
-    {
-      /* When we come to an explicit close brace,
-        pop any inner levels that didn't have explicit braces.  */
-      while (constructor_stack->implicit)
-       {
-         process_init_element (pop_init_level (1, braced_init_obstack),
-                               true, braced_init_obstack);
-       }
-      gcc_assert (!constructor_range_stack);
-    }
-
-  /* Now output all pending elements.  */
-  constructor_incremental = 1;
-  output_pending_init_elements (1, braced_init_obstack);
-
-  p = constructor_stack;
-
-  /* Error for initializing a flexible array member, or a zero-length
-     array member in an inappropriate context.  */
-  if (constructor_type && constructor_fields
-      && TREE_CODE (constructor_type) == ARRAY_TYPE
-      && TYPE_DOMAIN (constructor_type)
-      && !TYPE_MAX_VALUE (TYPE_DOMAIN (constructor_type)))
-    {
-      /* Silently discard empty initializations.  The parser will
-        already have pedwarned for empty brackets.  */
-      if (integer_zerop (constructor_unfilled_index))
-       constructor_type = NULL_TREE;
-      else
-       {
-         gcc_assert (!TYPE_SIZE (constructor_type));
-
-         if (constructor_depth > 2)
-           error_init ("initialization of flexible array member in a nested context");
-         else
-           pedwarn_init (input_location, OPT_Wpedantic,
-                         "initialization of a flexible array member");
-
-         /* We have already issued an error message for the existence
-            of a flexible array member not at the end of the structure.
-            Discard the initializer so that we do not die later.  */
-         if (DECL_CHAIN (constructor_fields) != NULL_TREE)
-           constructor_type = NULL_TREE;
-       }
-    }
-
-  /* Warn when some struct elements are implicitly initialized to zero.  */
-  if (warn_missing_field_initializers
-      && constructor_type
-      && TREE_CODE (constructor_type) == RECORD_TYPE
-      && constructor_unfilled_fields)
-    {
-       bool constructor_zeroinit =
-        (VEC_length (constructor_elt, constructor_elements) == 1
-         && integer_zerop
-             (VEC_index (constructor_elt, constructor_elements, 0)->value));
-
-       /* Do not warn for flexible array members or zero-length arrays.  */
-       while (constructor_unfilled_fields
-              && (!DECL_SIZE (constructor_unfilled_fields)
-                  || integer_zerop (DECL_SIZE (constructor_unfilled_fields))))
-         constructor_unfilled_fields = DECL_CHAIN (constructor_unfilled_fields);
-
-       if (constructor_unfilled_fields
-           /* Do not warn if this level of the initializer uses member
-              designators; it is likely to be deliberate.  */
-           && !constructor_designated
-           /* Do not warn about initializing with ` = {0}'.  */
-           && !constructor_zeroinit)
-         {
-           if (warning_at (input_location, OPT_Wmissing_field_initializers,
-                           "missing initializer for field %qD of %qT",
-                           constructor_unfilled_fields,
-                           constructor_type))
-             inform (DECL_SOURCE_LOCATION (constructor_unfilled_fields),
-                     "%qD declared here", constructor_unfilled_fields);
-         }
-    }
-
-  /* Pad out the end of the structure.  */
-  if (p->replacement_value.value)
-    /* If this closes a superfluous brace pair,
-       just pass out the element between them.  */
-    ret = p->replacement_value;
-  else if (constructor_type == 0)
-    ;
-  else if (TREE_CODE (constructor_type) != RECORD_TYPE
-          && TREE_CODE (constructor_type) != UNION_TYPE
-          && TREE_CODE (constructor_type) != ARRAY_TYPE
-          && TREE_CODE (constructor_type) != VECTOR_TYPE)
-    {
-      /* A nonincremental scalar initializer--just return
-        the element, after verifying there is just one.  */
-      if (VEC_empty (constructor_elt,constructor_elements))
-       {
-         if (!constructor_erroneous)
-           error_init ("empty scalar initializer");
-         ret.value = error_mark_node;
-       }
-      else if (VEC_length (constructor_elt,constructor_elements) != 1)
-       {
-         error_init ("extra elements in scalar initializer");
-         ret.value = VEC_index (constructor_elt,constructor_elements,0)->value;
-       }
-      else
-       ret.value = VEC_index (constructor_elt,constructor_elements,0)->value;
-    }
-  else
-    {
-      if (constructor_erroneous)
-       ret.value = error_mark_node;
-      else
-       {
-         ret.value = build_constructor (constructor_type,
-                                        constructor_elements);
-         if (constructor_constant)
-           TREE_CONSTANT (ret.value) = 1;
-         if (constructor_constant && constructor_simple)
-           TREE_STATIC (ret.value) = 1;
-         if (constructor_nonconst)
-           CONSTRUCTOR_NON_CONST (ret.value) = 1;
-       }
-    }
-
-  if (ret.value && TREE_CODE (ret.value) != CONSTRUCTOR)
-    {
-      if (constructor_nonconst)
-       ret.original_code = C_MAYBE_CONST_EXPR;
-      else if (ret.original_code == C_MAYBE_CONST_EXPR)
-       ret.original_code = ERROR_MARK;
-    }
-
-  constructor_type = p->type;
-  constructor_fields = p->fields;
-  constructor_index = p->index;
-  constructor_max_index = p->max_index;
-  constructor_unfilled_index = p->unfilled_index;
-  constructor_unfilled_fields = p->unfilled_fields;
-  constructor_bit_index = p->bit_index;
-  constructor_elements = p->elements;
-  constructor_constant = p->constant;
-  constructor_simple = p->simple;
-  constructor_nonconst = p->nonconst;
-  constructor_erroneous = p->erroneous;
-  constructor_incremental = p->incremental;
-  constructor_designated = p->designated;
-  constructor_pending_elts = p->pending_elts;
-  constructor_depth = p->depth;
-  if (!p->implicit)
-    constructor_range_stack = p->range_stack;
-  RESTORE_SPELLING_DEPTH (constructor_depth);
-
-  constructor_stack = p->next;
-  free (p);
-
-  if (ret.value == 0 && constructor_stack == 0)
-    ret.value = error_mark_node;
-  return ret;
-}
-
-/* Common handling for both array range and field name designators.
-   ARRAY argument is nonzero for array ranges.  Returns zero for success.  */
-
-static int
-set_designator (int array, struct obstack * braced_init_obstack)
-{
-  tree subtype;
-  enum tree_code subcode;
-
-  /* Don't die if an entire brace-pair level is superfluous
-     in the containing level.  */
-  if (constructor_type == 0)
-    return 1;
-
-  /* If there were errors in this designator list already, bail out
-     silently.  */
-  if (designator_erroneous)
-    return 1;
-
-  if (!designator_depth)
-    {
-      gcc_assert (!constructor_range_stack);
-
-      /* Designator list starts at the level of closest explicit
-        braces.  */
-      while (constructor_stack->implicit)
-       {
-         process_init_element (pop_init_level (1, braced_init_obstack),
-                               true, braced_init_obstack);
-       }
-      constructor_designated = 1;
-      return 0;
-    }
-
-  switch (TREE_CODE (constructor_type))
-    {
-    case  RECORD_TYPE:
-    case  UNION_TYPE:
-      subtype = TREE_TYPE (constructor_fields);
-      if (subtype != error_mark_node)
-       subtype = TYPE_MAIN_VARIANT (subtype);
-      break;
-    case ARRAY_TYPE:
-      subtype = TYPE_MAIN_VARIANT (TREE_TYPE (constructor_type));
-      break;
-    default:
-      gcc_unreachable ();
-    }
-
-  subcode = TREE_CODE (subtype);
-  if (array && subcode != ARRAY_TYPE)
-    {
-      error_init ("array index in non-array initializer");
-      return 1;
-    }
-  else if (!array && subcode != RECORD_TYPE && subcode != UNION_TYPE)
-    {
-      error_init ("field name not in record or union initializer");
-      return 1;
-    }
-
-  constructor_designated = 1;
-  push_init_level (2, braced_init_obstack);
-  return 0;
-}
-
-/* If there are range designators in designator list, push a new designator
-   to constructor_range_stack.  RANGE_END is end of such stack range or
-   NULL_TREE if there is no range designator at this level.  */
-
-static void
-push_range_stack (tree range_end, struct obstack * braced_init_obstack)
-{
-  struct constructor_range_stack *p;
-
-  p = (struct constructor_range_stack *)
-    obstack_alloc (braced_init_obstack,
-                  sizeof (struct constructor_range_stack));
-  p->prev = constructor_range_stack;
-  p->next = 0;
-  p->fields = constructor_fields;
-  p->range_start = constructor_index;
-  p->index = constructor_index;
-  p->stack = constructor_stack;
-  p->range_end = range_end;
-  if (constructor_range_stack)
-    constructor_range_stack->next = p;
-  constructor_range_stack = p;
-}
-
-/* Within an array initializer, specify the next index to be initialized.
-   FIRST is that index.  If LAST is nonzero, then initialize a range
-   of indices, running from FIRST through LAST.  */
-
-void
-set_init_index (tree first, tree last,
-               struct obstack * braced_init_obstack)
-{
-  if (set_designator (1, braced_init_obstack))
-    return;
-
-  designator_erroneous = 1;
-
-  if (!INTEGRAL_TYPE_P (TREE_TYPE (first))
-      || (last && !INTEGRAL_TYPE_P (TREE_TYPE (last))))
-    {
-      error_init ("array index in initializer not of integer type");
-      return;
-    }
-
-  if (TREE_CODE (first) != INTEGER_CST)
-    {
-      first = c_fully_fold (first, false, NULL);
-      if (TREE_CODE (first) == INTEGER_CST)
-       pedwarn_init (input_location, OPT_Wpedantic,
-                     "array index in initializer is not "
-                     "an integer constant expression");
-    }
-
-  if (last && TREE_CODE (last) != INTEGER_CST)
-    {
-      last = c_fully_fold (last, false, NULL);
-      if (TREE_CODE (last) == INTEGER_CST)
-       pedwarn_init (input_location, OPT_Wpedantic,
-                     "array index in initializer is not "
-                     "an integer constant expression");
-    }
-
-  if (TREE_CODE (first) != INTEGER_CST)
-    error_init ("nonconstant array index in initializer");
-  else if (last != 0 && TREE_CODE (last) != INTEGER_CST)
-    error_init ("nonconstant array index in initializer");
-  else if (TREE_CODE (constructor_type) != ARRAY_TYPE)
-    error_init ("array index in non-array initializer");
-  else if (tree_int_cst_sgn (first) == -1)
-    error_init ("array index in initializer exceeds array bounds");
-  else if (constructor_max_index
-          && tree_int_cst_lt (constructor_max_index, first))
-    error_init ("array index in initializer exceeds array bounds");
-  else
-    {
-      constant_expression_warning (first);
-      if (last)
-       constant_expression_warning (last);
-      constructor_index = convert (bitsizetype, first);
-
-      if (last)
-       {
-         if (tree_int_cst_equal (first, last))
-           last = 0;
-         else if (tree_int_cst_lt (last, first))
-           {
-             error_init ("empty index range in initializer");
-             last = 0;
-           }
-         else
-           {
-             last = convert (bitsizetype, last);
-             if (constructor_max_index != 0
-                 && tree_int_cst_lt (constructor_max_index, last))
-               {
-                 error_init ("array index range in initializer exceeds array bounds");
-                 last = 0;
-               }
-           }
-       }
-
-      designator_depth++;
-      designator_erroneous = 0;
-      if (constructor_range_stack || last)
-       push_range_stack (last, braced_init_obstack);
-    }
-}
-
-/* Within a struct initializer, specify the next field to be initialized.  */
-
-void
-set_init_label (tree fieldname, struct obstack * braced_init_obstack)
-{
-  tree field;
-
-  if (set_designator (0, braced_init_obstack))
-    return;
-
-  designator_erroneous = 1;
-
-  if (TREE_CODE (constructor_type) != RECORD_TYPE
-      && TREE_CODE (constructor_type) != UNION_TYPE)
-    {
-      error_init ("field name not in record or union initializer");
-      return;
-    }
-
-  field = lookup_field (constructor_type, fieldname);
-
-  if (field == 0)
-    error ("unknown field %qE specified in initializer", fieldname);
-  else
-    do
-      {
-       constructor_fields = TREE_VALUE (field);
-       designator_depth++;
-       designator_erroneous = 0;
-       if (constructor_range_stack)
-         push_range_stack (NULL_TREE, braced_init_obstack);
-       field = TREE_CHAIN (field);
-       if (field)
-         {
-           if (set_designator (0, braced_init_obstack))
-             return;
-         }
-      }
-    while (field != NULL_TREE);
-}
-\f
-/* Add a new initializer to the tree of pending initializers.  PURPOSE
-   identifies the initializer, either array index or field in a structure.
-   VALUE is the value of that index or field.  If ORIGTYPE is not
-   NULL_TREE, it is the original type of VALUE.
-
-   IMPLICIT is true if value comes from pop_init_level (1),
-   the new initializer has been merged with the existing one
-   and thus no warnings should be emitted about overriding an
-   existing initializer.  */
-
-static void
-add_pending_init (tree purpose, tree value, tree origtype, bool implicit,
-                 struct obstack * braced_init_obstack)
-{
-  struct init_node *p, **q, *r;
-
-  q = &constructor_pending_elts;
-  p = 0;
-
-  if (TREE_CODE (constructor_type) == ARRAY_TYPE)
-    {
-      while (*q != 0)
-       {
-         p = *q;
-         if (tree_int_cst_lt (purpose, p->purpose))
-           q = &p->left;
-         else if (tree_int_cst_lt (p->purpose, purpose))
-           q = &p->right;
-         else
-           {
-             if (!implicit)
-               {
-                 if (TREE_SIDE_EFFECTS (p->value))
-                   warning_init (0, "initialized field with side-effects overwritten");
-                 else if (warn_override_init)
-                   warning_init (OPT_Woverride_init, "initialized field overwritten");
-               }
-             p->value = value;
-             p->origtype = origtype;
-             return;
-           }
-       }
-    }
-  else
-    {
-      tree bitpos;
-
-      bitpos = bit_position (purpose);
-      while (*q != NULL)
-       {
-         p = *q;
-         if (tree_int_cst_lt (bitpos, bit_position (p->purpose)))
-           q = &p->left;
-         else if (p->purpose != purpose)
-           q = &p->right;
-         else
-           {
-             if (!implicit)
-               {
-                 if (TREE_SIDE_EFFECTS (p->value))
-                   warning_init (0, "initialized field with side-effects overwritten");
-                 else if (warn_override_init)
-                   warning_init (OPT_Woverride_init, "initialized field overwritten");
-               }
-             p->value = value;
-             p->origtype = origtype;
-             return;
-           }
-       }
-    }
-
-  r = (struct init_node *) obstack_alloc (braced_init_obstack,
-                                         sizeof (struct init_node));
-  r->purpose = purpose;
-  r->value = value;
-  r->origtype = origtype;
-
-  *q = r;
-  r->parent = p;
-  r->left = 0;
-  r->right = 0;
-  r->balance = 0;
-
-  while (p)
-    {
-      struct init_node *s;
-
-      if (r == p->left)
-       {
-         if (p->balance == 0)
-           p->balance = -1;
-         else if (p->balance < 0)
-           {
-             if (r->balance < 0)
-               {
-                 /* L rotation.  */
-                 p->left = r->right;
-                 if (p->left)
-                   p->left->parent = p;
-                 r->right = p;
-
-                 p->balance = 0;
-                 r->balance = 0;
-
-                 s = p->parent;
-                 p->parent = r;
-                 r->parent = s;
-                 if (s)
-                   {
-                     if (s->left == p)
-                       s->left = r;
-                     else
-                       s->right = r;
-                   }
-                 else
-                   constructor_pending_elts = r;
-               }
-             else
-               {
-                 /* LR rotation.  */
-                 struct init_node *t = r->right;
-
-                 r->right = t->left;
-                 if (r->right)
-                   r->right->parent = r;
-                 t->left = r;
-
-                 p->left = t->right;
-                 if (p->left)
-                   p->left->parent = p;
-                 t->right = p;
-
-                 p->balance = t->balance < 0;
-                 r->balance = -(t->balance > 0);
-                 t->balance = 0;
-
-                 s = p->parent;
-                 p->parent = t;
-                 r->parent = t;
-                 t->parent = s;
-                 if (s)
-                   {
-                     if (s->left == p)
-                       s->left = t;
-                     else
-                       s->right = t;
-                   }
-                 else
-                   constructor_pending_elts = t;
-               }
-             break;
-           }
-         else
-           {
-             /* p->balance == +1; growth of left side balances the node.  */
-             p->balance = 0;
-             break;
-           }
-       }
-      else /* r == p->right */
-       {
-         if (p->balance == 0)
-           /* Growth propagation from right side.  */
-           p->balance++;
-         else if (p->balance > 0)
-           {
-             if (r->balance > 0)
-               {
-                 /* R rotation.  */
-                 p->right = r->left;
-                 if (p->right)
-                   p->right->parent = p;
-                 r->left = p;
-
-                 p->balance = 0;
-                 r->balance = 0;
-
-                 s = p->parent;
-                 p->parent = r;
-                 r->parent = s;
-                 if (s)
-                   {
-                     if (s->left == p)
-                       s->left = r;
-                     else
-                       s->right = r;
-                   }
-                 else
-                   constructor_pending_elts = r;
-               }
-             else /* r->balance == -1 */
-               {
-                 /* RL rotation */
-                 struct init_node *t = r->left;
-
-                 r->left = t->right;
-                 if (r->left)
-                   r->left->parent = r;
-                 t->right = r;
-
-                 p->right = t->left;
-                 if (p->right)
-                   p->right->parent = p;
-                 t->left = p;
-
-                 r->balance = (t->balance < 0);
-                 p->balance = -(t->balance > 0);
-                 t->balance = 0;
-
-                 s = p->parent;
-                 p->parent = t;
-                 r->parent = t;
-                 t->parent = s;
-                 if (s)
-                   {
-                     if (s->left == p)
-                       s->left = t;
-                     else
-                       s->right = t;
-                   }
-                 else
-                   constructor_pending_elts = t;
-               }
-             break;
-           }
-         else
-           {
-             /* p->balance == -1; growth of right side balances the node.  */
-             p->balance = 0;
-             break;
-           }
-       }
-
-      r = p;
-      p = p->parent;
-    }
-}
-
-/* Build AVL tree from a sorted chain.  */
-
-static void
-set_nonincremental_init (struct obstack * braced_init_obstack)
-{
-  unsigned HOST_WIDE_INT ix;
-  tree index, value;
-
-  if (TREE_CODE (constructor_type) != RECORD_TYPE
-      && TREE_CODE (constructor_type) != ARRAY_TYPE)
-    return;
-
-  FOR_EACH_CONSTRUCTOR_ELT (constructor_elements, ix, index, value)
-    {
-      add_pending_init (index, value, NULL_TREE, true,
-                       braced_init_obstack);
-    }
-  constructor_elements = 0;
-  if (TREE_CODE (constructor_type) == RECORD_TYPE)
-    {
-      constructor_unfilled_fields = TYPE_FIELDS (constructor_type);
-      /* Skip any nameless bit fields at the beginning.  */
-      while (constructor_unfilled_fields != 0
-            && DECL_C_BIT_FIELD (constructor_unfilled_fields)
-            && DECL_NAME (constructor_unfilled_fields) == 0)
-       constructor_unfilled_fields = TREE_CHAIN (constructor_unfilled_fields);
-
-    }
-  else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
-    {
-      if (TYPE_DOMAIN (constructor_type))
-       constructor_unfilled_index
-           = convert (bitsizetype,
-                      TYPE_MIN_VALUE (TYPE_DOMAIN (constructor_type)));
-      else
-       constructor_unfilled_index = bitsize_zero_node;
-    }
-  constructor_incremental = 0;
-}
-
-/* Build AVL tree from a string constant.  */
-
-static void
-set_nonincremental_init_from_string (tree str,
-                                    struct obstack * braced_init_obstack)
-{
-  tree value, purpose, type;
-  HOST_WIDE_INT val[2];
-  const char *p, *end;
-  int byte, wchar_bytes, charwidth, bitpos;
-
-  gcc_assert (TREE_CODE (constructor_type) == ARRAY_TYPE);
-
-  wchar_bytes = TYPE_PRECISION (TREE_TYPE (TREE_TYPE (str))) / BITS_PER_UNIT;
-  charwidth = TYPE_PRECISION (char_type_node);
-  type = TREE_TYPE (constructor_type);
-  p = TREE_STRING_POINTER (str);
-  end = p + TREE_STRING_LENGTH (str);
-
-  for (purpose = bitsize_zero_node;
-       p < end && !tree_int_cst_lt (constructor_max_index, purpose);
-       purpose = size_binop (PLUS_EXPR, purpose, bitsize_one_node))
-    {
-      if (wchar_bytes == 1)
-       {
-         val[1] = (unsigned char) *p++;
-         val[0] = 0;
-       }
-      else
-       {
-         val[0] = 0;
-         val[1] = 0;
-         for (byte = 0; byte < wchar_bytes; byte++)
-           {
-             if (BYTES_BIG_ENDIAN)
-               bitpos = (wchar_bytes - byte - 1) * charwidth;
-             else
-               bitpos = byte * charwidth;
-             val[bitpos < HOST_BITS_PER_WIDE_INT]
-               |= ((unsigned HOST_WIDE_INT) ((unsigned char) *p++))
-                  << (bitpos % HOST_BITS_PER_WIDE_INT);
-           }
-       }
-
-      if (!TYPE_UNSIGNED (type))
-       {
-         bitpos = ((wchar_bytes - 1) * charwidth) + HOST_BITS_PER_CHAR;
-         if (bitpos < HOST_BITS_PER_WIDE_INT)
-           {
-             if (val[1] & (((HOST_WIDE_INT) 1) << (bitpos - 1)))
-               {
-                 val[1] |= ((HOST_WIDE_INT) -1) << bitpos;
-                 val[0] = -1;
-               }
-           }
-         else if (bitpos == HOST_BITS_PER_WIDE_INT)
-           {
-             if (val[1] < 0)
-               val[0] = -1;
-           }
-         else if (val[0] & (((HOST_WIDE_INT) 1)
-                            << (bitpos - 1 - HOST_BITS_PER_WIDE_INT)))
-           val[0] |= ((HOST_WIDE_INT) -1)
-                     << (bitpos - HOST_BITS_PER_WIDE_INT);
-       }
-
-      value = build_int_cst_wide (type, val[1], val[0]);
-      add_pending_init (purpose, value, NULL_TREE, true,
-                        braced_init_obstack);
-    }
-
-  constructor_incremental = 0;
-}
-
-/* Return value of FIELD in pending initializer or zero if the field was
-   not initialized yet.  */
-
-static tree
-find_init_member (tree field, struct obstack * braced_init_obstack)
-{
-  struct init_node *p;
-
-  if (TREE_CODE (constructor_type) == ARRAY_TYPE)
-    {
-      if (constructor_incremental
-         && tree_int_cst_lt (field, constructor_unfilled_index))
-       set_nonincremental_init (braced_init_obstack);
-
-      p = constructor_pending_elts;
-      while (p)
-       {
-         if (tree_int_cst_lt (field, p->purpose))
-           p = p->left;
-         else if (tree_int_cst_lt (p->purpose, field))
-           p = p->right;
-         else
-           return p->value;
-       }
-    }
-  else if (TREE_CODE (constructor_type) == RECORD_TYPE)
-    {
-      tree bitpos = bit_position (field);
-
-      if (constructor_incremental
-         && (!constructor_unfilled_fields
-             || tree_int_cst_lt (bitpos,
-                                 bit_position (constructor_unfilled_fields))))
-       set_nonincremental_init (braced_init_obstack);
-
-      p = constructor_pending_elts;
-      while (p)
-       {
-         if (field == p->purpose)
-           return p->value;
-         else if (tree_int_cst_lt (bitpos, bit_position (p->purpose)))
-           p = p->left;
-         else
-           p = p->right;
-       }
-    }
-  else if (TREE_CODE (constructor_type) == UNION_TYPE)
-    {
-      if (!VEC_empty (constructor_elt, constructor_elements)
-         && (VEC_last (constructor_elt, constructor_elements)->index
-             == field))
-       return VEC_last (constructor_elt, constructor_elements)->value;
-    }
-  return 0;
-}
-
-/* "Output" the next constructor element.
-   At top level, really output it to assembler code now.
-   Otherwise, collect it in a list from which we will make a CONSTRUCTOR.
-   If ORIGTYPE is not NULL_TREE, it is the original type of VALUE.
-   TYPE is the data type that the containing data type wants here.
-   FIELD is the field (a FIELD_DECL) or the index that this element fills.
-   If VALUE is a string constant, STRICT_STRING is true if it is
-   unparenthesized or we should not warn here for it being parenthesized.
-   For other types of VALUE, STRICT_STRING is not used.
-
-   PENDING if non-nil means output pending elements that belong
-   right after this element.  (PENDING is normally 1;
-   it is 0 while outputting pending elements, to avoid recursion.)
-
-   IMPLICIT is true if value comes from pop_init_level (1),
-   the new initializer has been merged with the existing one
-   and thus no warnings should be emitted about overriding an
-   existing initializer.  */
-
-static void
-output_init_element (tree value, tree origtype, bool strict_string, tree type,
-                    tree field, int pending, bool implicit,
-                    struct obstack * braced_init_obstack)
-{
-  tree semantic_type = NULL_TREE;
-  constructor_elt *celt;
-  bool maybe_const = true;
-  bool npc;
-
-  if (type == error_mark_node || value == error_mark_node)
-    {
-      constructor_erroneous = 1;
-      return;
-    }
-  if (TREE_CODE (TREE_TYPE (value)) == ARRAY_TYPE
-      && (TREE_CODE (value) == STRING_CST
-         || TREE_CODE (value) == COMPOUND_LITERAL_EXPR)
-      && !(TREE_CODE (value) == STRING_CST
-          && TREE_CODE (type) == ARRAY_TYPE
-          && INTEGRAL_TYPE_P (TREE_TYPE (type)))
-      && !comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (value)),
-                    TYPE_MAIN_VARIANT (type)))
-    value = array_to_pointer_conversion (input_location, value);
-
-  if (TREE_CODE (value) == COMPOUND_LITERAL_EXPR
-      && require_constant_value && !flag_isoc99 && pending)
-    {
-      /* As an extension, allow initializing objects with static storage
-        duration with compound literals (which are then treated just as
-        the brace enclosed list they contain).  */
-      tree decl = COMPOUND_LITERAL_EXPR_DECL (value);
-      value = DECL_INITIAL (decl);
-    }
-
-  npc = null_pointer_constant_p (value);
-  if (TREE_CODE (value) == EXCESS_PRECISION_EXPR)
-    {
-      semantic_type = TREE_TYPE (value);
-      value = TREE_OPERAND (value, 0);
-    }
-  value = c_fully_fold (value, require_constant_value, &maybe_const);
-
-  if (value == error_mark_node)
-    constructor_erroneous = 1;
-  else if (!TREE_CONSTANT (value))
-    constructor_constant = 0;
-  else if (!initializer_constant_valid_p (value, TREE_TYPE (value))
-          || ((TREE_CODE (constructor_type) == RECORD_TYPE
-               || TREE_CODE (constructor_type) == UNION_TYPE)
-              && DECL_C_BIT_FIELD (field)
-              && TREE_CODE (value) != INTEGER_CST))
-    constructor_simple = 0;
-  if (!maybe_const)
-    constructor_nonconst = 1;
-
-  if (!initializer_constant_valid_p (value, TREE_TYPE (value)))
-    {
-      if (require_constant_value)
-       {
-         error_init ("initializer element is not constant");
-         value = error_mark_node;
-       }
-      else if (require_constant_elements)
-       pedwarn (input_location, 0,
-                "initializer element is not computable at load time");
-    }
-  else if (!maybe_const
-          && (require_constant_value || require_constant_elements))
-    pedwarn_init (input_location, 0,
-                 "initializer element is not a constant expression");
-
-  /* Issue -Wc++-compat warnings about initializing a bitfield with
-     enum type.  */
-  if (warn_cxx_compat
-      && field != NULL_TREE
-      && TREE_CODE (field) == FIELD_DECL
-      && DECL_BIT_FIELD_TYPE (field) != NULL_TREE
-      && (TYPE_MAIN_VARIANT (DECL_BIT_FIELD_TYPE (field))
-         != TYPE_MAIN_VARIANT (type))
-      && TREE_CODE (DECL_BIT_FIELD_TYPE (field)) == ENUMERAL_TYPE)
-    {
-      tree checktype = origtype != NULL_TREE ? origtype : TREE_TYPE (value);
-      if (checktype != error_mark_node
-         && (TYPE_MAIN_VARIANT (checktype)
-             != TYPE_MAIN_VARIANT (DECL_BIT_FIELD_TYPE (field))))
-       warning_init (OPT_Wc___compat,
-                     "enum conversion in initialization is invalid in C++");
-    }
-
-  /* If this field is empty (and not at the end of structure),
-     don't do anything other than checking the initializer.  */
-  if (field
-      && (TREE_TYPE (field) == error_mark_node
-         || (COMPLETE_TYPE_P (TREE_TYPE (field))
-             && integer_zerop (TYPE_SIZE (TREE_TYPE (field)))
-             && (TREE_CODE (constructor_type) == ARRAY_TYPE
-                 || DECL_CHAIN (field)))))
-    return;
-
-  if (semantic_type)
-    value = build1 (EXCESS_PRECISION_EXPR, semantic_type, value);
-  value = digest_init (input_location, type, value, origtype, npc,
-                      strict_string, require_constant_value);
-  if (value == error_mark_node)
-    {
-      constructor_erroneous = 1;
-      return;
-    }
-  if (require_constant_value || require_constant_elements)
-    constant_expression_warning (value);
-
-  /* If this element doesn't come next in sequence,
-     put it on constructor_pending_elts.  */
-  if (TREE_CODE (constructor_type) == ARRAY_TYPE
-      && (!constructor_incremental
-         || !tree_int_cst_equal (field, constructor_unfilled_index)))
-    {
-      if (constructor_incremental
-         && tree_int_cst_lt (field, constructor_unfilled_index))
-       set_nonincremental_init (braced_init_obstack);
-
-      add_pending_init (field, value, origtype, implicit,
-                       braced_init_obstack);
-      return;
-    }
-  else if (TREE_CODE (constructor_type) == RECORD_TYPE
-          && (!constructor_incremental
-              || field != constructor_unfilled_fields))
-    {
-      /* We do this for records but not for unions.  In a union,
-        no matter which field is specified, it can be initialized
-        right away since it starts at the beginning of the union.  */
-      if (constructor_incremental)
-       {
-         if (!constructor_unfilled_fields)
-           set_nonincremental_init (braced_init_obstack);
-         else
-           {
-             tree bitpos, unfillpos;
-
-             bitpos = bit_position (field);
-             unfillpos = bit_position (constructor_unfilled_fields);
-
-             if (tree_int_cst_lt (bitpos, unfillpos))
-               set_nonincremental_init (braced_init_obstack);
-           }
-       }
-
-      add_pending_init (field, value, origtype, implicit,
-                       braced_init_obstack);
-      return;
-    }
-  else if (TREE_CODE (constructor_type) == UNION_TYPE
-          && !VEC_empty (constructor_elt, constructor_elements))
-    {
-      if (!implicit)
-       {
-         if (TREE_SIDE_EFFECTS (VEC_last (constructor_elt,
-                                          constructor_elements)->value))
-           warning_init (0,
-                         "initialized field with side-effects overwritten");
-         else if (warn_override_init)
-           warning_init (OPT_Woverride_init, "initialized field overwritten");
-       }
-
-      /* We can have just one union field set.  */
-      constructor_elements = 0;
-    }
-
-  /* Otherwise, output this element either to
-     constructor_elements or to the assembler file.  */
-
-  celt = VEC_safe_push (constructor_elt, gc, constructor_elements, NULL);
-  celt->index = field;
-  celt->value = value;
-
-  /* Advance the variable that indicates sequential elements output.  */
-  if (TREE_CODE (constructor_type) == ARRAY_TYPE)
-    constructor_unfilled_index
-      = size_binop_loc (input_location, PLUS_EXPR, constructor_unfilled_index,
-                       bitsize_one_node);
-  else if (TREE_CODE (constructor_type) == RECORD_TYPE)
-    {
-      constructor_unfilled_fields
-       = DECL_CHAIN (constructor_unfilled_fields);
-
-      /* Skip any nameless bit fields.  */
-      while (constructor_unfilled_fields != 0
-            && DECL_C_BIT_FIELD (constructor_unfilled_fields)
-            && DECL_NAME (constructor_unfilled_fields) == 0)
-       constructor_unfilled_fields =
-         DECL_CHAIN (constructor_unfilled_fields);
-    }
-  else if (TREE_CODE (constructor_type) == UNION_TYPE)
-    constructor_unfilled_fields = 0;
-
-  /* Now output any pending elements which have become next.  */
-  if (pending)
-    output_pending_init_elements (0, braced_init_obstack);
-}
-
-/* Output any pending elements which have become next.
-   As we output elements, constructor_unfilled_{fields,index}
-   advances, which may cause other elements to become next;
-   if so, they too are output.
-
-   If ALL is 0, we return when there are
-   no more pending elements to output now.
-
-   If ALL is 1, we output space as necessary so that
-   we can output all the pending elements.  */
-static void
-output_pending_init_elements (int all, struct obstack * braced_init_obstack)
-{
-  struct init_node *elt = constructor_pending_elts;
-  tree next;
-
- retry:
-
-  /* Look through the whole pending tree.
-     If we find an element that should be output now,
-     output it.  Otherwise, set NEXT to the element
-     that comes first among those still pending.  */
-
-  next = 0;
-  while (elt)
-    {
-      if (TREE_CODE (constructor_type) == ARRAY_TYPE)
-       {
-         if (tree_int_cst_equal (elt->purpose,
-                                 constructor_unfilled_index))
-           output_init_element (elt->value, elt->origtype, true,
-                                TREE_TYPE (constructor_type),
-                                constructor_unfilled_index, 0, false,
-                                braced_init_obstack);
-         else if (tree_int_cst_lt (constructor_unfilled_index,
-                                   elt->purpose))
-           {
-             /* Advance to the next smaller node.  */
-             if (elt->left)
-               elt = elt->left;
-             else
-               {
-                 /* We have reached the smallest node bigger than the
-                    current unfilled index.  Fill the space first.  */
-                 next = elt->purpose;
-                 break;
-               }
-           }
-         else
-           {
-             /* Advance to the next bigger node.  */
-             if (elt->right)
-               elt = elt->right;
-             else
-               {
-                 /* We have reached the biggest node in a subtree.  Find
-                    the parent of it, which is the next bigger node.  */
-                 while (elt->parent && elt->parent->right == elt)
-                   elt = elt->parent;
-                 elt = elt->parent;
-                 if (elt && tree_int_cst_lt (constructor_unfilled_index,
-                                             elt->purpose))
-                   {
-                     next = elt->purpose;
-                     break;
-                   }
-               }
-           }
-       }
-      else if (TREE_CODE (constructor_type) == RECORD_TYPE
-              || TREE_CODE (constructor_type) == UNION_TYPE)
-       {
-         tree ctor_unfilled_bitpos, elt_bitpos;
-
-         /* If the current record is complete we are done.  */
-         if (constructor_unfilled_fields == 0)
-           break;
-
-         ctor_unfilled_bitpos = bit_position (constructor_unfilled_fields);
-         elt_bitpos = bit_position (elt->purpose);
-         /* We can't compare fields here because there might be empty
-            fields in between.  */
-         if (tree_int_cst_equal (elt_bitpos, ctor_unfilled_bitpos))
-           {
-             constructor_unfilled_fields = elt->purpose;
-             output_init_element (elt->value, elt->origtype, true,
-                                  TREE_TYPE (elt->purpose),
-                                  elt->purpose, 0, false,
-                                  braced_init_obstack);
-           }
-         else if (tree_int_cst_lt (ctor_unfilled_bitpos, elt_bitpos))
-           {
-             /* Advance to the next smaller node.  */
-             if (elt->left)
-               elt = elt->left;
-             else
-               {
-                 /* We have reached the smallest node bigger than the
-                    current unfilled field.  Fill the space first.  */
-                 next = elt->purpose;
-                 break;
-               }
-           }
-         else
-           {
-             /* Advance to the next bigger node.  */
-             if (elt->right)
-               elt = elt->right;
-             else
-               {
-                 /* We have reached the biggest node in a subtree.  Find
-                    the parent of it, which is the next bigger node.  */
-                 while (elt->parent && elt->parent->right == elt)
-                   elt = elt->parent;
-                 elt = elt->parent;
-                 if (elt
-                     && (tree_int_cst_lt (ctor_unfilled_bitpos,
-                                          bit_position (elt->purpose))))
-                   {
-                     next = elt->purpose;
-                     break;
-                   }
-               }
-           }
-       }
-    }
-
-  /* Ordinarily return, but not if we want to output all
-     and there are elements left.  */
-  if (!(all && next != 0))
-    return;
-
-  /* If it's not incremental, just skip over the gap, so that after
-     jumping to retry we will output the next successive element.  */
-  if (TREE_CODE (constructor_type) == RECORD_TYPE
-      || TREE_CODE (constructor_type) == UNION_TYPE)
-    constructor_unfilled_fields = next;
-  else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
-    constructor_unfilled_index = next;
-
-  /* ELT now points to the node in the pending tree with the next
-     initializer to output.  */
-  goto retry;
-}
-\f
-/* Add one non-braced element to the current constructor level.
-   This adjusts the current position within the constructor's type.
-   This may also start or terminate implicit levels
-   to handle a partly-braced initializer.
-
-   Once this has found the correct level for the new element,
-   it calls output_init_element.
-
-   IMPLICIT is true if value comes from pop_init_level (1),
-   the new initializer has been merged with the existing one
-   and thus no warnings should be emitted about overriding an
-   existing initializer.  */
-
-void
-process_init_element (struct c_expr value, bool implicit,
-                     struct obstack * braced_init_obstack)
-{
-  tree orig_value = value.value;
-  int string_flag = orig_value != 0 && TREE_CODE (orig_value) == STRING_CST;
-  bool strict_string = value.original_code == STRING_CST;
-
-  designator_depth = 0;
-  designator_erroneous = 0;
-
-  /* Handle superfluous braces around string cst as in
-     char x[] = {"foo"}; */
-  if (string_flag
-      && constructor_type
-      && TREE_CODE (constructor_type) == ARRAY_TYPE
-      && INTEGRAL_TYPE_P (TREE_TYPE (constructor_type))
-      && integer_zerop (constructor_unfilled_index))
-    {
-      if (constructor_stack->replacement_value.value)
-       error_init ("excess elements in char array initializer");
-      constructor_stack->replacement_value = value;
-      return;
-    }
-
-  if (constructor_stack->replacement_value.value != 0)
-    {
-      error_init ("excess elements in struct initializer");
-      return;
-    }
-
-  /* Ignore elements of a brace group if it is entirely superfluous
-     and has already been diagnosed.  */
-  if (constructor_type == 0)
-    return;
-
-  /* If we've exhausted any levels that didn't have braces,
-     pop them now.  */
-  while (constructor_stack->implicit)
-    {
-      if ((TREE_CODE (constructor_type) == RECORD_TYPE
-          || TREE_CODE (constructor_type) == UNION_TYPE)
-         && constructor_fields == 0)
-       process_init_element (pop_init_level (1, braced_init_obstack),
-                             true, braced_init_obstack);
-      else if ((TREE_CODE (constructor_type) == ARRAY_TYPE
-               || TREE_CODE (constructor_type) == VECTOR_TYPE)
-              && (constructor_max_index == 0
-                  || tree_int_cst_lt (constructor_max_index,
-                                      constructor_index)))
-       process_init_element (pop_init_level (1, braced_init_obstack),
-                             true, braced_init_obstack);
-      else
-       break;
-    }
-
-  /* In the case of [LO ... HI] = VALUE, only evaluate VALUE once.  */
-  if (constructor_range_stack)
-    {
-      /* If value is a compound literal and we'll be just using its
-        content, don't put it into a SAVE_EXPR.  */
-      if (TREE_CODE (value.value) != COMPOUND_LITERAL_EXPR
-         || !require_constant_value
-         || flag_isoc99)
-       {
-         tree semantic_type = NULL_TREE;
-         if (TREE_CODE (value.value) == EXCESS_PRECISION_EXPR)
-           {
-             semantic_type = TREE_TYPE (value.value);
-             value.value = TREE_OPERAND (value.value, 0);
-           }
-         value.value = c_save_expr (value.value);
-         if (semantic_type)
-           value.value = build1 (EXCESS_PRECISION_EXPR, semantic_type,
-                                 value.value);
-       }
-    }
-
-  while (1)
-    {
-      if (TREE_CODE (constructor_type) == RECORD_TYPE)
-       {
-         tree fieldtype;
-         enum tree_code fieldcode;
-
-         if (constructor_fields == 0)
-           {
-             pedwarn_init (input_location, 0,
-                           "excess elements in struct initializer");
-             break;
-           }
-
-         fieldtype = TREE_TYPE (constructor_fields);
-         if (fieldtype != error_mark_node)
-           fieldtype = TYPE_MAIN_VARIANT (fieldtype);
-         fieldcode = TREE_CODE (fieldtype);
-
-         /* Error for non-static initialization of a flexible array member.  */
-         if (fieldcode == ARRAY_TYPE
-             && !require_constant_value
-             && TYPE_SIZE (fieldtype) == NULL_TREE
-             && DECL_CHAIN (constructor_fields) == NULL_TREE)
-           {
-             error_init ("non-static initialization of a flexible array member");
-             break;
-           }
-
-         /* Accept a string constant to initialize a subarray.  */
-         if (value.value != 0
-             && fieldcode == ARRAY_TYPE
-             && INTEGRAL_TYPE_P (TREE_TYPE (fieldtype))
-             && string_flag)
-           value.value = orig_value;
-         /* Otherwise, if we have come to a subaggregate,
-            and we don't have an element of its type, push into it.  */
-         else if (value.value != 0
-                  && value.value != error_mark_node
-                  && TYPE_MAIN_VARIANT (TREE_TYPE (value.value)) != fieldtype
-                  && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE
-                      || fieldcode == UNION_TYPE || fieldcode == VECTOR_TYPE))
-           {
-             push_init_level (1, braced_init_obstack);
-             continue;
-           }
-
-         if (value.value)
-           {
-             push_member_name (constructor_fields);
-             output_init_element (value.value, value.original_type,
-                                  strict_string, fieldtype,
-                                  constructor_fields, 1, implicit,
-                                  braced_init_obstack);
-             RESTORE_SPELLING_DEPTH (constructor_depth);
-           }
-         else
-           /* Do the bookkeeping for an element that was
-              directly output as a constructor.  */
-           {
-             /* For a record, keep track of end position of last field.  */
-             if (DECL_SIZE (constructor_fields))
-               constructor_bit_index
-                 = size_binop_loc (input_location, PLUS_EXPR,
-                                   bit_position (constructor_fields),
-                                   DECL_SIZE (constructor_fields));
-
-             /* If the current field was the first one not yet written out,
-                it isn't now, so update.  */
-             if (constructor_unfilled_fields == constructor_fields)
-               {
-                 constructor_unfilled_fields = DECL_CHAIN (constructor_fields);
-                 /* Skip any nameless bit fields.  */
-                 while (constructor_unfilled_fields != 0
-                        && DECL_C_BIT_FIELD (constructor_unfilled_fields)
-                        && DECL_NAME (constructor_unfilled_fields) == 0)
-                   constructor_unfilled_fields =
-                     DECL_CHAIN (constructor_unfilled_fields);
-               }
-           }
-
-         constructor_fields = DECL_CHAIN (constructor_fields);
-         /* Skip any nameless bit fields at the beginning.  */
-         while (constructor_fields != 0
-                && DECL_C_BIT_FIELD (constructor_fields)
-                && DECL_NAME (constructor_fields) == 0)
-           constructor_fields = DECL_CHAIN (constructor_fields);
-       }
-      else if (TREE_CODE (constructor_type) == UNION_TYPE)
-       {
-         tree fieldtype;
-         enum tree_code fieldcode;
-
-         if (constructor_fields == 0)
-           {
-             pedwarn_init (input_location, 0,
-                           "excess elements in union initializer");
-             break;
-           }
-
-         fieldtype = TREE_TYPE (constructor_fields);
-         if (fieldtype != error_mark_node)
-           fieldtype = TYPE_MAIN_VARIANT (fieldtype);
-         fieldcode = TREE_CODE (fieldtype);
-
-         /* Warn that traditional C rejects initialization of unions.
-            We skip the warning if the value is zero.  This is done
-            under the assumption that the zero initializer in user
-            code appears conditioned on e.g. __STDC__ to avoid
-            "missing initializer" warnings and relies on default
-            initialization to zero in the traditional C case.
-            We also skip the warning if the initializer is designated,
-            again on the assumption that this must be conditional on
-            __STDC__ anyway (and we've already complained about the
-            member-designator already).  */
-         if (!in_system_header && !constructor_designated
-             && !(value.value && (integer_zerop (value.value)
-                                  || real_zerop (value.value))))
-           warning (OPT_Wtraditional, "traditional C rejects initialization "
-                    "of unions");
-
-         /* Accept a string constant to initialize a subarray.  */
-         if (value.value != 0
-             && fieldcode == ARRAY_TYPE
-             && INTEGRAL_TYPE_P (TREE_TYPE (fieldtype))
-             && string_flag)
-           value.value = orig_value;
-         /* Otherwise, if we have come to a subaggregate,
-            and we don't have an element of its type, push into it.  */
-         else if (value.value != 0
-                  && value.value != error_mark_node
-                  && TYPE_MAIN_VARIANT (TREE_TYPE (value.value)) != fieldtype
-                  && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE
-                      || fieldcode == UNION_TYPE || fieldcode == VECTOR_TYPE))
-           {
-             push_init_level (1, braced_init_obstack);
-             continue;
-           }
-
-         if (value.value)
-           {
-             push_member_name (constructor_fields);
-             output_init_element (value.value, value.original_type,
-                                  strict_string, fieldtype,
-                                  constructor_fields, 1, implicit,
-                                  braced_init_obstack);
-             RESTORE_SPELLING_DEPTH (constructor_depth);
-           }
-         else
-           /* Do the bookkeeping for an element that was
-              directly output as a constructor.  */
-           {
-             constructor_bit_index = DECL_SIZE (constructor_fields);
-             constructor_unfilled_fields = DECL_CHAIN (constructor_fields);
-           }
-
-         constructor_fields = 0;
-       }
-      else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
-       {
-         tree elttype = TYPE_MAIN_VARIANT (TREE_TYPE (constructor_type));
-         enum tree_code eltcode = TREE_CODE (elttype);
-
-         /* Accept a string constant to initialize a subarray.  */
-         if (value.value != 0
-             && eltcode == ARRAY_TYPE
-             && INTEGRAL_TYPE_P (TREE_TYPE (elttype))
-             && string_flag)
-           value.value = orig_value;
-         /* Otherwise, if we have come to a subaggregate,
-            and we don't have an element of its type, push into it.  */
-         else if (value.value != 0
-                  && value.value != error_mark_node
-                  && TYPE_MAIN_VARIANT (TREE_TYPE (value.value)) != elttype
-                  && (eltcode == RECORD_TYPE || eltcode == ARRAY_TYPE
-                      || eltcode == UNION_TYPE || eltcode == VECTOR_TYPE))
-           {
-             push_init_level (1, braced_init_obstack);
-             continue;
-           }
-
-         if (constructor_max_index != 0
-             && (tree_int_cst_lt (constructor_max_index, constructor_index)
-                 || integer_all_onesp (constructor_max_index)))
-           {
-             pedwarn_init (input_location, 0,
-                           "excess elements in array initializer");
-             break;
-           }
-
-         /* Now output the actual element.  */
-         if (value.value)
-           {
-             push_array_bounds (tree_low_cst (constructor_index, 1));
-             output_init_element (value.value, value.original_type,
-                                  strict_string, elttype,
-                                  constructor_index, 1, implicit,
-                                  braced_init_obstack);
-             RESTORE_SPELLING_DEPTH (constructor_depth);
-           }
-
-         constructor_index
-           = size_binop_loc (input_location, PLUS_EXPR,
-                             constructor_index, bitsize_one_node);
-
-         if (!value.value)
-           /* If we are doing the bookkeeping for an element that was
-              directly output as a constructor, we must update
-              constructor_unfilled_index.  */
-           constructor_unfilled_index = constructor_index;
-       }
-      else if (TREE_CODE (constructor_type) == VECTOR_TYPE)
-       {
-         tree elttype = TYPE_MAIN_VARIANT (TREE_TYPE (constructor_type));
-
-        /* Do a basic check of initializer size.  Note that vectors
-           always have a fixed size derived from their type.  */
-         if (tree_int_cst_lt (constructor_max_index, constructor_index))
-           {
-             pedwarn_init (input_location, 0,
-                           "excess elements in vector initializer");
-             break;
-           }
-
-         /* Now output the actual element.  */
-         if (value.value)
-           {
-             if (TREE_CODE (value.value) == VECTOR_CST)
-               elttype = TYPE_MAIN_VARIANT (constructor_type);
-             output_init_element (value.value, value.original_type,
-                                  strict_string, elttype,
-                                  constructor_index, 1, implicit,
-                                  braced_init_obstack);
-           }
-
-         constructor_index
-           = size_binop_loc (input_location,
-                             PLUS_EXPR, constructor_index, bitsize_one_node);
-
-         if (!value.value)
-           /* If we are doing the bookkeeping for an element that was
-              directly output as a constructor, we must update
-              constructor_unfilled_index.  */
-           constructor_unfilled_index = constructor_index;
-       }
-
-      /* Handle the sole element allowed in a braced initializer
-        for a scalar variable.  */
-      else if (constructor_type != error_mark_node
-              && constructor_fields == 0)
-       {
-         pedwarn_init (input_location, 0,
-                       "excess elements in scalar initializer");
-         break;
-       }
-      else
-       {
-         if (value.value)
-           output_init_element (value.value, value.original_type,
-                                strict_string, constructor_type,
-                                NULL_TREE, 1, implicit,
-                                braced_init_obstack);
-         constructor_fields = 0;
-       }
-
-      /* Handle range initializers either at this level or anywhere higher
-        in the designator stack.  */
-      if (constructor_range_stack)
-       {
-         struct constructor_range_stack *p, *range_stack;
-         int finish = 0;
-
-         range_stack = constructor_range_stack;
-         constructor_range_stack = 0;
-         while (constructor_stack != range_stack->stack)
-           {
-             gcc_assert (constructor_stack->implicit);
-             process_init_element (pop_init_level (1,
-                                                   braced_init_obstack),
-                                   true, braced_init_obstack);
-           }
-         for (p = range_stack;
-              !p->range_end || tree_int_cst_equal (p->index, p->range_end);
-              p = p->prev)
-           {
-             gcc_assert (constructor_stack->implicit);
-             process_init_element (pop_init_level (1, braced_init_obstack),
-                                   true, braced_init_obstack);
-           }
-
-         p->index = size_binop_loc (input_location,
-                                    PLUS_EXPR, p->index, bitsize_one_node);
-         if (tree_int_cst_equal (p->index, p->range_end) && !p->prev)
-           finish = 1;
-
-         while (1)
-           {
-             constructor_index = p->index;
-             constructor_fields = p->fields;
-             if (finish && p->range_end && p->index == p->range_start)
-               {
-                 finish = 0;
-                 p->prev = 0;
-               }
-             p = p->next;
-             if (!p)
-               break;
-             push_init_level (2, braced_init_obstack);
-             p->stack = constructor_stack;
-             if (p->range_end && tree_int_cst_equal (p->index, p->range_end))
-               p->index = p->range_start;
-           }
-
-         if (!finish)
-           constructor_range_stack = range_stack;
-         continue;
-       }
-
-      break;
-    }
-
-  constructor_range_stack = 0;
-}
-\f
-/* Build a complete asm-statement, whose components are a CV_QUALIFIER
-   (guaranteed to be 'volatile' or null) and ARGS (represented using
-   an ASM_EXPR node).  */
-tree
-build_asm_stmt (tree cv_qualifier, tree args)
-{
-  if (!ASM_VOLATILE_P (args) && cv_qualifier)
-    ASM_VOLATILE_P (args) = 1;
-  return add_stmt (args);
-}
-
-/* Build an asm-expr, whose components are a STRING, some OUTPUTS,
-   some INPUTS, and some CLOBBERS.  The latter three may be NULL.
-   SIMPLE indicates whether there was anything at all after the
-   string in the asm expression -- asm("blah") and asm("blah" : )
-   are subtly different.  We use a ASM_EXPR node to represent this.  */
-tree
-build_asm_expr (location_t loc, tree string, tree outputs, tree inputs,
-               tree clobbers, tree labels, bool simple)
-{
-  tree tail;
-  tree args;
-  int i;
-  const char *constraint;
-  const char **oconstraints;
-  bool allows_mem, allows_reg, is_inout;
-  int ninputs, noutputs;
-
-  ninputs = list_length (inputs);
-  noutputs = list_length (outputs);
-  oconstraints = (const char **) alloca (noutputs * sizeof (const char *));
-
-  string = resolve_asm_operand_names (string, outputs, inputs, labels);
-
-  /* Remove output conversions that change the type but not the mode.  */
-  for (i = 0, tail = outputs; tail; ++i, tail = TREE_CHAIN (tail))
-    {
-      tree output = TREE_VALUE (tail);
-
-      /* ??? Really, this should not be here.  Users should be using a
-        proper lvalue, dammit.  But there's a long history of using casts
-        in the output operands.  In cases like longlong.h, this becomes a
-        primitive form of typechecking -- if the cast can be removed, then
-        the output operand had a type of the proper width; otherwise we'll
-        get an error.  Gross, but ...  */
-      STRIP_NOPS (output);
-
-      if (!lvalue_or_else (loc, output, lv_asm))
-       output = error_mark_node;
-
-      if (output != error_mark_node
-         && (TREE_READONLY (output)
-             || TYPE_READONLY (TREE_TYPE (output))
-             || ((TREE_CODE (TREE_TYPE (output)) == RECORD_TYPE
-                  || TREE_CODE (TREE_TYPE (output)) == UNION_TYPE)
-                 && C_TYPE_FIELDS_READONLY (TREE_TYPE (output)))))
-       readonly_error (output, lv_asm);
-
-      constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (tail)));
-      oconstraints[i] = constraint;
-
-      if (parse_output_constraint (&constraint, i, ninputs, noutputs,
-                                  &allows_mem, &allows_reg, &is_inout))
-       {
-         /* If the operand is going to end up in memory,
-            mark it addressable.  */
-         if (!allows_reg && !c_mark_addressable (output))
-           output = error_mark_node;
-         if (!(!allows_reg && allows_mem)
-             && output != error_mark_node
-             && VOID_TYPE_P (TREE_TYPE (output)))
-           {
-             error_at (loc, "invalid use of void expression");
-             output = error_mark_node;
-           }
-       }
-      else
-       output = error_mark_node;
-
-      TREE_VALUE (tail) = output;
-    }
-
-  for (i = 0, tail = inputs; tail; ++i, tail = TREE_CHAIN (tail))
-    {
-      tree input;
-
-      constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (tail)));
-      input = TREE_VALUE (tail);
-
-      if (parse_input_constraint (&constraint, i, ninputs, noutputs, 0,
-                                 oconstraints, &allows_mem, &allows_reg))
-       {
-         /* If the operand is going to end up in memory,
-            mark it addressable.  */
-         if (!allows_reg && allows_mem)
-           {
-             /* Strip the nops as we allow this case.  FIXME, this really
-                should be rejected or made deprecated.  */
-             STRIP_NOPS (input);
-             if (!c_mark_addressable (input))
-               input = error_mark_node;
-           }
-         else if (input != error_mark_node && VOID_TYPE_P (TREE_TYPE (input)))
-           {
-             error_at (loc, "invalid use of void expression");
-             input = error_mark_node;
-           }
-       }
-      else
-       input = error_mark_node;
-
-      TREE_VALUE (tail) = input;
-    }
-
-  /* ASMs with labels cannot have outputs.  This should have been
-     enforced by the parser.  */
-  gcc_assert (outputs == NULL || labels == NULL);
-
-  args = build_stmt (loc, ASM_EXPR, string, outputs, inputs, clobbers, labels);
-
-  /* asm statements without outputs, including simple ones, are treated
-     as volatile.  */
-  ASM_INPUT_P (args) = simple;
-  ASM_VOLATILE_P (args) = (noutputs == 0);
-
-  return args;
-}
-\f
-/* Generate a goto statement to LABEL.  LOC is the location of the
-   GOTO.  */
-
-tree
-c_finish_goto_label (location_t loc, tree label)
-{
-  tree decl = lookup_label_for_goto (loc, label);
-  if (!decl)
-    return NULL_TREE;
-  TREE_USED (decl) = 1;
-  {
-    tree t = build1 (GOTO_EXPR, void_type_node, decl);
-    SET_EXPR_LOCATION (t, loc);
-    return add_stmt (t);
-  }
-}
-
-/* Generate a computed goto statement to EXPR.  LOC is the location of
-   the GOTO.  */
-
-tree
-c_finish_goto_ptr (location_t loc, tree expr)
-{
-  tree t;
-  pedwarn (loc, OPT_Wpedantic, "ISO C forbids %<goto *expr;%>");
-  expr = c_fully_fold (expr, false, NULL);
-  expr = convert (ptr_type_node, expr);
-  t = build1 (GOTO_EXPR, void_type_node, expr);
-  SET_EXPR_LOCATION (t, loc);
-  return add_stmt (t);
-}
-
-/* Generate a C `return' statement.  RETVAL is the expression for what
-   to return, or a null pointer for `return;' with no value.  LOC is
-   the location of the return statement.  If ORIGTYPE is not NULL_TREE, it
-   is the original type of RETVAL.  */
-
-tree
-c_finish_return (location_t loc, tree retval, tree origtype)
-{
-  tree valtype = TREE_TYPE (TREE_TYPE (current_function_decl)), ret_stmt;
-  bool no_warning = false;
-  bool npc = false;
-
-  if (TREE_THIS_VOLATILE (current_function_decl))
-    warning_at (loc, 0,
-               "function declared %<noreturn%> has a %<return%> statement");
-
-  if (retval)
-    {
-      tree semantic_type = NULL_TREE;
-      npc = null_pointer_constant_p (retval);
-      if (TREE_CODE (retval) == EXCESS_PRECISION_EXPR)
-       {
-         semantic_type = TREE_TYPE (retval);
-         retval = TREE_OPERAND (retval, 0);
-       }
-      retval = c_fully_fold (retval, false, NULL);
-      if (semantic_type)
-       retval = build1 (EXCESS_PRECISION_EXPR, semantic_type, retval);
-    }
-
-  if (!retval)
-    {
-      current_function_returns_null = 1;
-      if ((warn_return_type || flag_isoc99)
-         && valtype != 0 && TREE_CODE (valtype) != VOID_TYPE)
-       {
-         pedwarn_c99 (loc, flag_isoc99 ? 0 : OPT_Wreturn_type,
-                      "%<return%> with no value, in "
-                      "function returning non-void");
-         no_warning = true;
-       }
-    }
-  else if (valtype == 0 || TREE_CODE (valtype) == VOID_TYPE)
-    {
-      current_function_returns_null = 1;
-      if (TREE_CODE (TREE_TYPE (retval)) != VOID_TYPE)
-       pedwarn (loc, 0,
-                "%<return%> with a value, in function returning void");
-      else
-       pedwarn (loc, OPT_Wpedantic, "ISO C forbids "
-                "%<return%> with expression, in function returning void");
-    }
-  else
-    {
-      tree t = convert_for_assignment (loc, valtype, retval, origtype,
-                                      ic_return,
-                                      npc, NULL_TREE, NULL_TREE, 0);
-      tree res = DECL_RESULT (current_function_decl);
-      tree inner;
-
-      current_function_returns_value = 1;
-      if (t == error_mark_node)
-       return NULL_TREE;
-
-      inner = t = convert (TREE_TYPE (res), t);
-
-      /* Strip any conversions, additions, and subtractions, and see if
-        we are returning the address of a local variable.  Warn if so.  */
-      while (1)
-       {
-         switch (TREE_CODE (inner))
-           {
-           CASE_CONVERT:
-           case NON_LVALUE_EXPR:
-           case PLUS_EXPR:
-           case POINTER_PLUS_EXPR:
-             inner = TREE_OPERAND (inner, 0);
-             continue;
-
-           case MINUS_EXPR:
-             /* If the second operand of the MINUS_EXPR has a pointer
-                type (or is converted from it), this may be valid, so
-                don't give a warning.  */
-             {
-               tree op1 = TREE_OPERAND (inner, 1);
-
-               while (!POINTER_TYPE_P (TREE_TYPE (op1))
-                      && (CONVERT_EXPR_P (op1)
-                          || TREE_CODE (op1) == NON_LVALUE_EXPR))
-                 op1 = TREE_OPERAND (op1, 0);
-
-               if (POINTER_TYPE_P (TREE_TYPE (op1)))
-                 break;
-
-               inner = TREE_OPERAND (inner, 0);
-               continue;
-             }
-
-           case ADDR_EXPR:
-             inner = TREE_OPERAND (inner, 0);
-
-             while (REFERENCE_CLASS_P (inner)
-                    && TREE_CODE (inner) != INDIRECT_REF)
-               inner = TREE_OPERAND (inner, 0);
-
-             if (DECL_P (inner)
-                 && !DECL_EXTERNAL (inner)
-                 && !TREE_STATIC (inner)
-                 && DECL_CONTEXT (inner) == current_function_decl)
-               warning_at (loc,
-                           0, "function returns address of local variable");
-             break;
-
-           default:
-             break;
-           }
-
-         break;
-       }
-
-      retval = build2 (MODIFY_EXPR, TREE_TYPE (res), res, t);
-      SET_EXPR_LOCATION (retval, loc);
-
-      if (warn_sequence_point)
-       verify_sequence_points (retval);
-    }
-
-  ret_stmt = build_stmt (loc, RETURN_EXPR, retval);
-  TREE_NO_WARNING (ret_stmt) |= no_warning;
-  return add_stmt (ret_stmt);
-}
-\f
-struct c_switch {
-  /* The SWITCH_EXPR being built.  */
-  tree switch_expr;
-
-  /* The original type of the testing expression, i.e. before the
-     default conversion is applied.  */
-  tree orig_type;
-
-  /* A splay-tree mapping the low element of a case range to the high
-     element, or NULL_TREE if there is no high element.  Used to
-     determine whether or not a new case label duplicates an old case
-     label.  We need a tree, rather than simply a hash table, because
-     of the GNU case range extension.  */
-  splay_tree cases;
-
-  /* The bindings at the point of the switch.  This is used for
-     warnings crossing decls when branching to a case label.  */
-  struct c_spot_bindings *bindings;
-
-  /* The next node on the stack.  */
-  struct c_switch *next;
-};
-
-/* A stack of the currently active switch statements.  The innermost
-   switch statement is on the top of the stack.  There is no need to
-   mark the stack for garbage collection because it is only active
-   during the processing of the body of a function, and we never
-   collect at that point.  */
-
-struct c_switch *c_switch_stack;
-
-/* Start a C switch statement, testing expression EXP.  Return the new
-   SWITCH_EXPR.  SWITCH_LOC is the location of the `switch'.
-   SWITCH_COND_LOC is the location of the switch's condition.  */
-
-tree
-c_start_case (location_t switch_loc,
-             location_t switch_cond_loc,
-             tree exp)
-{
-  tree orig_type = error_mark_node;
-  struct c_switch *cs;
-
-  if (exp != error_mark_node)
-    {
-      orig_type = TREE_TYPE (exp);
-
-      if (!INTEGRAL_TYPE_P (orig_type))
-       {
-         if (orig_type != error_mark_node)
-           {
-             error_at (switch_cond_loc, "switch quantity not an integer");
-             orig_type = error_mark_node;
-           }
-         exp = integer_zero_node;
-       }
-      else
-       {
-         tree type = TYPE_MAIN_VARIANT (orig_type);
-
-         if (!in_system_header
-             && (type == long_integer_type_node
-                 || type == long_unsigned_type_node))
-           warning_at (switch_cond_loc,
-                       OPT_Wtraditional, "%<long%> switch expression not "
-                       "converted to %<int%> in ISO C");
-
-         exp = c_fully_fold (exp, false, NULL);
-         exp = default_conversion (exp);
-
-         if (warn_sequence_point)
-           verify_sequence_points (exp);
-       }
-    }
-
-  /* Add this new SWITCH_EXPR to the stack.  */
-  cs = XNEW (struct c_switch);
-  cs->switch_expr = build3 (SWITCH_EXPR, orig_type, exp, NULL_TREE, NULL_TREE);
-  SET_EXPR_LOCATION (cs->switch_expr, switch_loc);
-  cs->orig_type = orig_type;
-  cs->cases = splay_tree_new (case_compare, NULL, NULL);
-  cs->bindings = c_get_switch_bindings ();
-  cs->next = c_switch_stack;
-  c_switch_stack = cs;
-
-  return add_stmt (cs->switch_expr);
-}
-
-/* Process a case label at location LOC.  */
-
-tree
-do_case (location_t loc, tree low_value, tree high_value)
-{
-  tree label = NULL_TREE;
-
-  if (low_value && TREE_CODE (low_value) != INTEGER_CST)
-    {
-      low_value = c_fully_fold (low_value, false, NULL);
-      if (TREE_CODE (low_value) == INTEGER_CST)
-       pedwarn (input_location, OPT_Wpedantic,
-                "case label is not an integer constant expression");
-    }
-
-  if (high_value && TREE_CODE (high_value) != INTEGER_CST)
-    {
-      high_value = c_fully_fold (high_value, false, NULL);
-      if (TREE_CODE (high_value) == INTEGER_CST)
-       pedwarn (input_location, OPT_Wpedantic,
-                "case label is not an integer constant expression");
-    }
-
-  if (c_switch_stack == NULL)
-    {
-      if (low_value)
-       error_at (loc, "case label not within a switch statement");
-      else
-       error_at (loc, "%<default%> label not within a switch statement");
-      return NULL_TREE;
-    }
-
-  if (c_check_switch_jump_warnings (c_switch_stack->bindings,
-                                   EXPR_LOCATION (c_switch_stack->switch_expr),
-                                   loc))
-    return NULL_TREE;
-
-  label = c_add_case_label (loc, c_switch_stack->cases,
-                           SWITCH_COND (c_switch_stack->switch_expr),
-                           c_switch_stack->orig_type,
-                           low_value, high_value);
-  if (label == error_mark_node)
-    label = NULL_TREE;
-  return label;
-}
-
-/* Finish the switch statement.  */
-
-void
-c_finish_case (tree body)
-{
-  struct c_switch *cs = c_switch_stack;
-  location_t switch_location;
-
-  SWITCH_BODY (cs->switch_expr) = body;
-
-  /* Emit warnings as needed.  */
-  switch_location = EXPR_LOCATION (cs->switch_expr);
-  c_do_switch_warnings (cs->cases, switch_location,
-                       TREE_TYPE (cs->switch_expr),
-                       SWITCH_COND (cs->switch_expr));
-
-  /* Pop the stack.  */
-  c_switch_stack = cs->next;
-  splay_tree_delete (cs->cases);
-  c_release_switch_bindings (cs->bindings);
-  XDELETE (cs);
-}
-\f
-/* Emit an if statement.  IF_LOCUS is the location of the 'if'.  COND,
-   THEN_BLOCK and ELSE_BLOCK are expressions to be used; ELSE_BLOCK
-   may be null.  NESTED_IF is true if THEN_BLOCK contains another IF
-   statement, and was not surrounded with parenthesis.  */
-
-void
-c_finish_if_stmt (location_t if_locus, tree cond, tree then_block,
-                 tree else_block, bool nested_if)
-{
-  tree stmt;
-
-  /* Diagnose an ambiguous else if if-then-else is nested inside if-then.  */
-  if (warn_parentheses && nested_if && else_block == NULL)
-    {
-      tree inner_if = then_block;
-
-      /* We know from the grammar productions that there is an IF nested
-        within THEN_BLOCK.  Due to labels and c99 conditional declarations,
-        it might not be exactly THEN_BLOCK, but should be the last
-        non-container statement within.  */
-      while (1)
-       switch (TREE_CODE (inner_if))
-         {
-         case COND_EXPR:
-           goto found;
-         case BIND_EXPR:
-           inner_if = BIND_EXPR_BODY (inner_if);
-           break;
-         case STATEMENT_LIST:
-           inner_if = expr_last (then_block);
-           break;
-         case TRY_FINALLY_EXPR:
-         case TRY_CATCH_EXPR:
-           inner_if = TREE_OPERAND (inner_if, 0);
-           break;
-         default:
-           gcc_unreachable ();
-         }
-    found:
-
-      if (COND_EXPR_ELSE (inner_if))
-        warning_at (if_locus, OPT_Wparentheses,
-                    "suggest explicit braces to avoid ambiguous %<else%>");
-    }
-
-  stmt = build3 (COND_EXPR, void_type_node, cond, then_block, else_block);
-  SET_EXPR_LOCATION (stmt, if_locus);
-  add_stmt (stmt);
-}
-
-/* Emit a general-purpose loop construct.  START_LOCUS is the location of
-   the beginning of the loop.  COND is the loop condition.  COND_IS_FIRST
-   is false for DO loops.  INCR is the FOR increment expression.  BODY is
-   the statement controlled by the loop.  BLAB is the break label.  CLAB is
-   the continue label.  Everything is allowed to be NULL.  */
-
-void
-c_finish_loop (location_t start_locus, tree cond, tree incr, tree body,
-              tree blab, tree clab, bool cond_is_first)
-{
-  tree entry = NULL, exit = NULL, t;
-
-  /* If the condition is zero don't generate a loop construct.  */
-  if (cond && integer_zerop (cond))
-    {
-      if (cond_is_first)
-       {
-         t = build_and_jump (&blab);
-         SET_EXPR_LOCATION (t, start_locus);
-         add_stmt (t);
-       }
-    }
-  else
-    {
-      tree top = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
-
-      /* If we have an exit condition, then we build an IF with gotos either
-        out of the loop, or to the top of it.  If there's no exit condition,
-        then we just build a jump back to the top.  */
-      exit = build_and_jump (&LABEL_EXPR_LABEL (top));
-
-      if (cond && !integer_nonzerop (cond))
-       {
-         /* Canonicalize the loop condition to the end.  This means
-            generating a branch to the loop condition.  Reuse the
-            continue label, if possible.  */
-         if (cond_is_first)
-           {
-             if (incr || !clab)
-               {
-                 entry = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
-                 t = build_and_jump (&LABEL_EXPR_LABEL (entry));
-               }
-             else
-               t = build1 (GOTO_EXPR, void_type_node, clab);
-             SET_EXPR_LOCATION (t, start_locus);
-             add_stmt (t);
-           }
-
-         t = build_and_jump (&blab);
-         if (cond_is_first)
-           exit = fold_build3_loc (start_locus,
-                               COND_EXPR, void_type_node, cond, exit, t);
-         else
-           exit = fold_build3_loc (input_location,
-                               COND_EXPR, void_type_node, cond, exit, t);
-       }
-
-      add_stmt (top);
-    }
-
-  if (body)
-    add_stmt (body);
-  if (clab)
-    add_stmt (build1 (LABEL_EXPR, void_type_node, clab));
-  if (incr)
-    add_stmt (incr);
-  if (entry)
-    add_stmt (entry);
-  if (exit)
-    add_stmt (exit);
-  if (blab)
-    add_stmt (build1 (LABEL_EXPR, void_type_node, blab));
-}
-
-tree
-c_finish_bc_stmt (location_t loc, tree *label_p, bool is_break)
-{
-  bool skip;
-  tree label = *label_p;
-
-  /* In switch statements break is sometimes stylistically used after
-     a return statement.  This can lead to spurious warnings about
-     control reaching the end of a non-void function when it is
-     inlined.  Note that we are calling block_may_fallthru with
-     language specific tree nodes; this works because
-     block_may_fallthru returns true when given something it does not
-     understand.  */
-  skip = !block_may_fallthru (cur_stmt_list);
-
-  if (!label)
-    {
-      if (!skip)
-       *label_p = label = create_artificial_label (loc);
-    }
-  else if (TREE_CODE (label) == LABEL_DECL)
-    ;
-  else switch (TREE_INT_CST_LOW (label))
-    {
-    case 0:
-      if (is_break)
-       error_at (loc, "break statement not within loop or switch");
-      else
-       error_at (loc, "continue statement not within a loop");
-      return NULL_TREE;
-
-    case 1:
-      gcc_assert (is_break);
-      error_at (loc, "break statement used with OpenMP for loop");
-      return NULL_TREE;
-
-    default:
-      gcc_unreachable ();
-    }
-
-  if (skip)
-    return NULL_TREE;
-
-  if (!is_break)
-    add_stmt (build_predict_expr (PRED_CONTINUE, NOT_TAKEN));
-
-  return add_stmt (build1 (GOTO_EXPR, void_type_node, label));
-}
-
-/* A helper routine for c_process_expr_stmt and c_finish_stmt_expr.  */
-
-static void
-emit_side_effect_warnings (location_t loc, tree expr)
-{
-  if (expr == error_mark_node)
-    ;
-  else if (!TREE_SIDE_EFFECTS (expr))
-    {
-      if (!VOID_TYPE_P (TREE_TYPE (expr)) && !TREE_NO_WARNING (expr))
-       warning_at (loc, OPT_Wunused_value, "statement with no effect");
-    }
-  else
-    warn_if_unused_value (expr, loc);
-}
-
-/* Process an expression as if it were a complete statement.  Emit
-   diagnostics, but do not call ADD_STMT.  LOC is the location of the
-   statement.  */
-
-tree
-c_process_expr_stmt (location_t loc, tree expr)
-{
-  tree exprv;
-
-  if (!expr)
-    return NULL_TREE;
-
-  expr = c_fully_fold (expr, false, NULL);
-
-  if (warn_sequence_point)
-    verify_sequence_points (expr);
-
-  if (TREE_TYPE (expr) != error_mark_node
-      && !COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (expr))
-      && TREE_CODE (TREE_TYPE (expr)) != ARRAY_TYPE)
-    error_at (loc, "expression statement has incomplete type");
-
-  /* If we're not processing a statement expression, warn about unused values.
-     Warnings for statement expressions will be emitted later, once we figure
-     out which is the result.  */
-  if (!STATEMENT_LIST_STMT_EXPR (cur_stmt_list)
-      && warn_unused_value)
-    emit_side_effect_warnings (loc, expr);
-
-  exprv = expr;
-  while (TREE_CODE (exprv) == COMPOUND_EXPR)
-    exprv = TREE_OPERAND (exprv, 1);
-  while (CONVERT_EXPR_P (exprv))
-    exprv = TREE_OPERAND (exprv, 0);
-  if (DECL_P (exprv)
-      || handled_component_p (exprv)
-      || TREE_CODE (exprv) == ADDR_EXPR)
-    mark_exp_read (exprv);
-
-  /* If the expression is not of a type to which we cannot assign a line
-     number, wrap the thing in a no-op NOP_EXPR.  */
-  if (DECL_P (expr) || CONSTANT_CLASS_P (expr))
-    {
-      expr = build1 (NOP_EXPR, TREE_TYPE (expr), expr);
-      SET_EXPR_LOCATION (expr, loc);
-    }
-
-  return expr;
-}
-
-/* Emit an expression as a statement.  LOC is the location of the
-   expression.  */
-
-tree
-c_finish_expr_stmt (location_t loc, tree expr)
-{
-  if (expr)
-    return add_stmt (c_process_expr_stmt (loc, expr));
-  else
-    return NULL;
-}
-
-/* Do the opposite and emit a statement as an expression.  To begin,
-   create a new binding level and return it.  */
-
-tree
-c_begin_stmt_expr (void)
-{
-  tree ret;
-
-  /* We must force a BLOCK for this level so that, if it is not expanded
-     later, there is a way to turn off the entire subtree of blocks that
-     are contained in it.  */
-  keep_next_level ();
-  ret = c_begin_compound_stmt (true);
-
-  c_bindings_start_stmt_expr (c_switch_stack == NULL
-                             ? NULL
-                             : c_switch_stack->bindings);
-
-  /* Mark the current statement list as belonging to a statement list.  */
-  STATEMENT_LIST_STMT_EXPR (ret) = 1;
-
-  return ret;
-}
-
-/* LOC is the location of the compound statement to which this body
-   belongs.  */
-
-tree
-c_finish_stmt_expr (location_t loc, tree body)
-{
-  tree last, type, tmp, val;
-  tree *last_p;
-
-  body = c_end_compound_stmt (loc, body, true);
-
-  c_bindings_end_stmt_expr (c_switch_stack == NULL
-                           ? NULL
-                           : c_switch_stack->bindings);
-
-  /* Locate the last statement in BODY.  See c_end_compound_stmt
-     about always returning a BIND_EXPR.  */
-  last_p = &BIND_EXPR_BODY (body);
-  last = BIND_EXPR_BODY (body);
-
- continue_searching:
-  if (TREE_CODE (last) == STATEMENT_LIST)
-    {
-      tree_stmt_iterator i;
-
-      /* This can happen with degenerate cases like ({ }).  No value.  */
-      if (!TREE_SIDE_EFFECTS (last))
-       return body;
-
-      /* If we're supposed to generate side effects warnings, process
-        all of the statements except the last.  */
-      if (warn_unused_value)
-       {
-         for (i = tsi_start (last); !tsi_one_before_end_p (i); tsi_next (&i))
-           {
-             location_t tloc;
-             tree t = tsi_stmt (i);
-
-             tloc = EXPR_HAS_LOCATION (t) ? EXPR_LOCATION (t) : loc;
-             emit_side_effect_warnings (tloc, t);
-           }
-       }
-      else
-       i = tsi_last (last);
-      last_p = tsi_stmt_ptr (i);
-      last = *last_p;
-    }
-
-  /* If the end of the list is exception related, then the list was split
-     by a call to push_cleanup.  Continue searching.  */
-  if (TREE_CODE (last) == TRY_FINALLY_EXPR
-      || TREE_CODE (last) == TRY_CATCH_EXPR)
-    {
-      last_p = &TREE_OPERAND (last, 0);
-      last = *last_p;
-      goto continue_searching;
-    }
-
-  if (last == error_mark_node)
-    return last;
-
-  /* In the case that the BIND_EXPR is not necessary, return the
-     expression out from inside it.  */
-  if (last == BIND_EXPR_BODY (body)
-      && BIND_EXPR_VARS (body) == NULL)
-    {
-      /* Even if this looks constant, do not allow it in a constant
-        expression.  */
-      last = c_wrap_maybe_const (last, true);
-      /* Do not warn if the return value of a statement expression is
-        unused.  */
-      TREE_NO_WARNING (last) = 1;
-      return last;
-    }
-
-  /* Extract the type of said expression.  */
-  type = TREE_TYPE (last);
-
-  /* If we're not returning a value at all, then the BIND_EXPR that
-     we already have is a fine expression to return.  */
-  if (!type || VOID_TYPE_P (type))
-    return body;
-
-  /* Now that we've located the expression containing the value, it seems
-     silly to make voidify_wrapper_expr repeat the process.  Create a
-     temporary of the appropriate type and stick it in a TARGET_EXPR.  */
-  tmp = create_tmp_var_raw (type, NULL);
-
-  /* Unwrap a no-op NOP_EXPR as added by c_finish_expr_stmt.  This avoids
-     tree_expr_nonnegative_p giving up immediately.  */
-  val = last;
-  if (TREE_CODE (val) == NOP_EXPR
-      && TREE_TYPE (val) == TREE_TYPE (TREE_OPERAND (val, 0)))
-    val = TREE_OPERAND (val, 0);
-
-  *last_p = build2 (MODIFY_EXPR, void_type_node, tmp, val);
-  SET_EXPR_LOCATION (*last_p, EXPR_LOCATION (last));
-
-  {
-    tree t = build4 (TARGET_EXPR, type, tmp, body, NULL_TREE, NULL_TREE);
-    SET_EXPR_LOCATION (t, loc);
-    return t;
-  }
-}
-\f
-/* Begin and end compound statements.  This is as simple as pushing
-   and popping new statement lists from the tree.  */
-
-tree
-c_begin_compound_stmt (bool do_scope)
-{
-  tree stmt = push_stmt_list ();
-  if (do_scope)
-    push_scope ();
-  return stmt;
-}
-
-/* End a compound statement.  STMT is the statement.  LOC is the
-   location of the compound statement-- this is usually the location
-   of the opening brace.  */
-
-tree
-c_end_compound_stmt (location_t loc, tree stmt, bool do_scope)
-{
-  tree block = NULL;
-
-  if (do_scope)
-    {
-      if (c_dialect_objc ())
-       objc_clear_super_receiver ();
-      block = pop_scope ();
-    }
-
-  stmt = pop_stmt_list (stmt);
-  stmt = c_build_bind_expr (loc, block, stmt);
-
-  /* If this compound statement is nested immediately inside a statement
-     expression, then force a BIND_EXPR to be created.  Otherwise we'll
-     do the wrong thing for ({ { 1; } }) or ({ 1; { } }).  In particular,
-     STATEMENT_LISTs merge, and thus we can lose track of what statement
-     was really last.  */
-  if (building_stmt_list_p ()
-      && STATEMENT_LIST_STMT_EXPR (cur_stmt_list)
-      && TREE_CODE (stmt) != BIND_EXPR)
-    {
-      stmt = build3 (BIND_EXPR, void_type_node, NULL, stmt, NULL);
-      TREE_SIDE_EFFECTS (stmt) = 1;
-      SET_EXPR_LOCATION (stmt, loc);
-    }
-
-  return stmt;
-}
-
-/* Queue a cleanup.  CLEANUP is an expression/statement to be executed
-   when the current scope is exited.  EH_ONLY is true when this is not
-   meant to apply to normal control flow transfer.  */
-
-void
-push_cleanup (tree decl, tree cleanup, bool eh_only)
-{
-  enum tree_code code;
-  tree stmt, list;
-  bool stmt_expr;
-
-  code = eh_only ? TRY_CATCH_EXPR : TRY_FINALLY_EXPR;
-  stmt = build_stmt (DECL_SOURCE_LOCATION (decl), code, NULL, cleanup);
-  add_stmt (stmt);
-  stmt_expr = STATEMENT_LIST_STMT_EXPR (cur_stmt_list);
-  list = push_stmt_list ();
-  TREE_OPERAND (stmt, 0) = list;
-  STATEMENT_LIST_STMT_EXPR (list) = stmt_expr;
-}
-
-/* Convert scalar to vector for the range of operations.  */
-static enum stv_conv
-scalar_to_vector (location_t loc, enum tree_code code, tree op0, tree op1)
-{
-  tree type0 = TREE_TYPE (op0);
-  tree type1 = TREE_TYPE (op1);
-  bool integer_only_op = false;
-  enum stv_conv ret = stv_firstarg;
-
-  gcc_assert (TREE_CODE (type0) == VECTOR_TYPE
-             || TREE_CODE (type1) == VECTOR_TYPE);
-  switch (code)
-    {
-      case RSHIFT_EXPR:
-      case LSHIFT_EXPR:
-       if (TREE_CODE (type0) == INTEGER_TYPE
-           && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE)
-         {
-           if (unsafe_conversion_p (TREE_TYPE (type1), op0, false))
-             {
-               error_at (loc, "conversion of scalar to vector "
-                              "involves truncation");
-               return stv_error;
-             }
-           else
-             return stv_firstarg;
-         }
-       break;
-
-      case BIT_IOR_EXPR:
-      case BIT_XOR_EXPR:
-      case BIT_AND_EXPR:
-       integer_only_op = true;
-       /* ... fall through ...  */
-
-      case PLUS_EXPR:
-      case MINUS_EXPR:
-      case MULT_EXPR:
-      case TRUNC_DIV_EXPR:
-      case TRUNC_MOD_EXPR:
-      case RDIV_EXPR:
-       if (TREE_CODE (type0) == VECTOR_TYPE)
-         {
-           tree tmp;
-           ret = stv_secondarg;
-           /* Swap TYPE0 with TYPE1 and OP0 with OP1  */
-           tmp = type0; type0 = type1; type1 = tmp;
-           tmp = op0; op0 = op1; op1 = tmp;
-         }
-
-       if (TREE_CODE (type0) == INTEGER_TYPE
-           && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE)
-         {
-           if (unsafe_conversion_p (TREE_TYPE (type1), op0, false))
-             {
-               error_at (loc, "conversion of scalar to vector "
-                              "involves truncation");
-               return stv_error;
-             }
-           return ret;
-         }
-       else if (!integer_only_op
-                   /* Allow integer --> real conversion if safe.  */
-                && (TREE_CODE (type0) == REAL_TYPE
-                    || TREE_CODE (type0) == INTEGER_TYPE)
-                && SCALAR_FLOAT_TYPE_P (TREE_TYPE (type1)))
-         {
-           if (unsafe_conversion_p (TREE_TYPE (type1), op0, false))
-             {
-               error_at (loc, "conversion of scalar to vector "
-                              "involves truncation");
-               return stv_error;
-             }
-           return ret;
-         }
-      default:
-       break;
-    }
-
-  return stv_nothing;
-}
-\f
-/* Build a binary-operation expression without default conversions.
-   CODE is the kind of expression to build.
-   LOCATION is the operator's location.
-   This function differs from `build' in several ways:
-   the data type of the result is computed and recorded in it,
-   warnings are generated if arg data types are invalid,
-   special handling for addition and subtraction of pointers is known,
-   and some optimization is done (operations on narrow ints
-   are done in the narrower type when that gives the same result).
-   Constant folding is also done before the result is returned.
-
-   Note that the operands will never have enumeral types, or function
-   or array types, because either they will have the default conversions
-   performed or they have both just been converted to some other type in which
-   the arithmetic is to be done.  */
-
-tree
-build_binary_op (location_t location, enum tree_code code,
-                tree orig_op0, tree orig_op1, int convert_p)
-{
-  tree type0, type1, orig_type0, orig_type1;
-  tree eptype;
-  enum tree_code code0, code1;
-  tree op0, op1;
-  tree ret = error_mark_node;
-  const char *invalid_op_diag;
-  bool op0_int_operands, op1_int_operands;
-  bool int_const, int_const_or_overflow, int_operands;
-
-  /* Expression code to give to the expression when it is built.
-     Normally this is CODE, which is what the caller asked for,
-     but in some special cases we change it.  */
-  enum tree_code resultcode = code;
-
-  /* Data type in which the computation is to be performed.
-     In the simplest cases this is the common type of the arguments.  */
-  tree result_type = NULL;
-
-  /* When the computation is in excess precision, the type of the
-     final EXCESS_PRECISION_EXPR.  */
-  tree semantic_result_type = NULL;
-
-  /* Nonzero means operands have already been type-converted
-     in whatever way is necessary.
-     Zero means they need to be converted to RESULT_TYPE.  */
-  int converted = 0;
-
-  /* Nonzero means create the expression with this type, rather than
-     RESULT_TYPE.  */
-  tree build_type = 0;
-
-  /* Nonzero means after finally constructing the expression
-     convert it to this type.  */
-  tree final_type = 0;
-
-  /* Nonzero if this is an operation like MIN or MAX which can
-     safely be computed in short if both args are promoted shorts.
-     Also implies COMMON.
-     -1 indicates a bitwise operation; this makes a difference
-     in the exact conditions for when it is safe to do the operation
-     in a narrower mode.  */
-  int shorten = 0;
-
-  /* Nonzero if this is a comparison operation;
-     if both args are promoted shorts, compare the original shorts.
-     Also implies COMMON.  */
-  int short_compare = 0;
-
-  /* Nonzero if this is a right-shift operation, which can be computed on the
-     original short and then promoted if the operand is a promoted short.  */
-  int short_shift = 0;
-
-  /* Nonzero means set RESULT_TYPE to the common type of the args.  */
-  int common = 0;
-
-  /* True means types are compatible as far as ObjC is concerned.  */
-  bool objc_ok;
-
-  /* True means this is an arithmetic operation that may need excess
-     precision.  */
-  bool may_need_excess_precision;
-
-  /* True means this is a boolean operation that converts both its
-     operands to truth-values.  */
-  bool boolean_op = false;
-
-  if (location == UNKNOWN_LOCATION)
-    location = input_location;
-
-  op0 = orig_op0;
-  op1 = orig_op1;
-
-  op0_int_operands = EXPR_INT_CONST_OPERANDS (orig_op0);
-  if (op0_int_operands)
-    op0 = remove_c_maybe_const_expr (op0);
-  op1_int_operands = EXPR_INT_CONST_OPERANDS (orig_op1);
-  if (op1_int_operands)
-    op1 = remove_c_maybe_const_expr (op1);
-  int_operands = (op0_int_operands && op1_int_operands);
-  if (int_operands)
-    {
-      int_const_or_overflow = (TREE_CODE (orig_op0) == INTEGER_CST
-                              && TREE_CODE (orig_op1) == INTEGER_CST);
-      int_const = (int_const_or_overflow
-                  && !TREE_OVERFLOW (orig_op0)
-                  && !TREE_OVERFLOW (orig_op1));
-    }
-  else
-    int_const = int_const_or_overflow = false;
-
-  /* Do not apply default conversion in mixed vector/scalar expression.  */
-  if (convert_p
-      && !((TREE_CODE (TREE_TYPE (op0)) == VECTOR_TYPE)
-          != (TREE_CODE (TREE_TYPE (op1)) == VECTOR_TYPE)))
-    {
-      op0 = default_conversion (op0);
-      op1 = default_conversion (op1);
-    }
-
-  orig_type0 = type0 = TREE_TYPE (op0);
-  orig_type1 = type1 = TREE_TYPE (op1);
-
-  /* The expression codes of the data types of the arguments tell us
-     whether the arguments are integers, floating, pointers, etc.  */
-  code0 = TREE_CODE (type0);
-  code1 = TREE_CODE (type1);
-
-  /* Strip NON_LVALUE_EXPRs, etc., since we aren't using as an lvalue.  */
-  STRIP_TYPE_NOPS (op0);
-  STRIP_TYPE_NOPS (op1);
-
-  /* If an error was already reported for one of the arguments,
-     avoid reporting another error.  */
-
-  if (code0 == ERROR_MARK || code1 == ERROR_MARK)
-    return error_mark_node;
-
-  if ((invalid_op_diag
-       = targetm.invalid_binary_op (code, type0, type1)))
-    {
-      error_at (location, invalid_op_diag);
-      return error_mark_node;
-    }
-
-  switch (code)
-    {
-    case PLUS_EXPR:
-    case MINUS_EXPR:
-    case MULT_EXPR:
-    case TRUNC_DIV_EXPR:
-    case CEIL_DIV_EXPR:
-    case FLOOR_DIV_EXPR:
-    case ROUND_DIV_EXPR:
-    case EXACT_DIV_EXPR:
-      may_need_excess_precision = true;
-      break;
-    default:
-      may_need_excess_precision = false;
-      break;
-    }
-  if (TREE_CODE (op0) == EXCESS_PRECISION_EXPR)
-    {
-      op0 = TREE_OPERAND (op0, 0);
-      type0 = TREE_TYPE (op0);
-    }
-  else if (may_need_excess_precision
-          && (eptype = excess_precision_type (type0)) != NULL_TREE)
-    {
-      type0 = eptype;
-      op0 = convert (eptype, op0);
-    }
-  if (TREE_CODE (op1) == EXCESS_PRECISION_EXPR)
-    {
-      op1 = TREE_OPERAND (op1, 0);
-      type1 = TREE_TYPE (op1);
-    }
-  else if (may_need_excess_precision
-          && (eptype = excess_precision_type (type1)) != NULL_TREE)
-    {
-      type1 = eptype;
-      op1 = convert (eptype, op1);
-    }
-
-  objc_ok = objc_compare_types (type0, type1, -3, NULL_TREE);
-
-  /* In case when one of the operands of the binary operation is
-     a vector and another is a scalar -- convert scalar to vector.  */
-  if ((code0 == VECTOR_TYPE) != (code1 == VECTOR_TYPE))
-    {
-      enum stv_conv convert_flag = scalar_to_vector (location, code, op0, op1);
-
-      switch (convert_flag)
-       {
-         case stv_error:
-           return error_mark_node;
-         case stv_firstarg:
-           {
-              bool maybe_const = true;
-              tree sc;
-              sc = c_fully_fold (op0, false, &maybe_const);
-              sc = save_expr (sc);
-              sc = convert (TREE_TYPE (type1), sc);
-              op0 = build_vector_from_val (type1, sc);
-              if (!maybe_const)
-                op0 = c_wrap_maybe_const (op0, true);
-              orig_type0 = type0 = TREE_TYPE (op0);
-              code0 = TREE_CODE (type0);
-              converted = 1;
-              break;
-           }
-         case stv_secondarg:
-           {
-             bool maybe_const = true;
-             tree sc;
-             sc = c_fully_fold (op1, false, &maybe_const);
-             sc = save_expr (sc);
-             sc = convert (TREE_TYPE (type0), sc);
-             op1 = build_vector_from_val (type0, sc);
-             if (!maybe_const)
-               op1 = c_wrap_maybe_const (op1, true);
-             orig_type1 = type1 = TREE_TYPE (op1);
-             code1 = TREE_CODE (type1);
-             converted = 1;
-             break;
-           }
-         default:
-           break;
-       }
-    }
-
-  switch (code)
-    {
-    case PLUS_EXPR:
-      /* Handle the pointer + int case.  */
-      if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
-       {
-         ret = pointer_int_sum (location, PLUS_EXPR, op0, op1);
-         goto return_build_binary_op;
-       }
-      else if (code1 == POINTER_TYPE && code0 == INTEGER_TYPE)
-       {
-         ret = pointer_int_sum (location, PLUS_EXPR, op1, op0);
-         goto return_build_binary_op;
-       }
-      else
-       common = 1;
-      break;
-
-    case MINUS_EXPR:
-      /* Subtraction of two similar pointers.
-        We must subtract them as integers, then divide by object size.  */
-      if (code0 == POINTER_TYPE && code1 == POINTER_TYPE
-         && comp_target_types (location, type0, type1))
-       {
-         ret = pointer_diff (location, op0, op1);
-         goto return_build_binary_op;
-       }
-      /* Handle pointer minus int.  Just like pointer plus int.  */
-      else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
-       {
-         ret = pointer_int_sum (location, MINUS_EXPR, op0, op1);
-         goto return_build_binary_op;
-       }
-      else
-       common = 1;
-      break;
-
-    case MULT_EXPR:
-      common = 1;
-      break;
-
-    case TRUNC_DIV_EXPR:
-    case CEIL_DIV_EXPR:
-    case FLOOR_DIV_EXPR:
-    case ROUND_DIV_EXPR:
-    case EXACT_DIV_EXPR:
-      warn_for_div_by_zero (location, op1);
-
-      if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
-          || code0 == FIXED_POINT_TYPE
-          || code0 == COMPLEX_TYPE || code0 == VECTOR_TYPE)
-         && (code1 == INTEGER_TYPE || code1 == REAL_TYPE
-             || code1 == FIXED_POINT_TYPE
-             || code1 == COMPLEX_TYPE || code1 == VECTOR_TYPE))
-       {
-         enum tree_code tcode0 = code0, tcode1 = code1;
-
-         if (code0 == COMPLEX_TYPE || code0 == VECTOR_TYPE)
-           tcode0 = TREE_CODE (TREE_TYPE (TREE_TYPE (op0)));
-         if (code1 == COMPLEX_TYPE || code1 == VECTOR_TYPE)
-           tcode1 = TREE_CODE (TREE_TYPE (TREE_TYPE (op1)));
-
-         if (!((tcode0 == INTEGER_TYPE && tcode1 == INTEGER_TYPE)
-             || (tcode0 == FIXED_POINT_TYPE && tcode1 == FIXED_POINT_TYPE)))
-           resultcode = RDIV_EXPR;
-         else
-           /* Although it would be tempting to shorten always here, that
-              loses on some targets, since the modulo instruction is
-              undefined if the quotient can't be represented in the
-              computation mode.  We shorten only if unsigned or if
-              dividing by something we know != -1.  */
-           shorten = (TYPE_UNSIGNED (TREE_TYPE (orig_op0))
-                      || (TREE_CODE (op1) == INTEGER_CST
-                          && !integer_all_onesp (op1)));
-         common = 1;
-       }
-      break;
-
-    case BIT_AND_EXPR:
-    case BIT_IOR_EXPR:
-    case BIT_XOR_EXPR:
-      if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
-       shorten = -1;
-      /* Allow vector types which are not floating point types.   */
-      else if (code0 == VECTOR_TYPE
-              && code1 == VECTOR_TYPE
-              && !VECTOR_FLOAT_TYPE_P (type0)
-              && !VECTOR_FLOAT_TYPE_P (type1))
-       common = 1;
-      break;
-
-    case TRUNC_MOD_EXPR:
-    case FLOOR_MOD_EXPR:
-      warn_for_div_by_zero (location, op1);
-
-      if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE
-         && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE
-         && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE)
-       common = 1;
-      else if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
-       {
-         /* Although it would be tempting to shorten always here, that loses
-            on some targets, since the modulo instruction is undefined if the
-            quotient can't be represented in the computation mode.  We shorten
-            only if unsigned or if dividing by something we know != -1.  */
-         shorten = (TYPE_UNSIGNED (TREE_TYPE (orig_op0))
-                    || (TREE_CODE (op1) == INTEGER_CST
-                        && !integer_all_onesp (op1)));
-         common = 1;
-       }
-      break;
-
-    case TRUTH_ANDIF_EXPR:
-    case TRUTH_ORIF_EXPR:
-    case TRUTH_AND_EXPR:
-    case TRUTH_OR_EXPR:
-    case TRUTH_XOR_EXPR:
-      if ((code0 == INTEGER_TYPE || code0 == POINTER_TYPE
-          || code0 == REAL_TYPE || code0 == COMPLEX_TYPE
-          || code0 == FIXED_POINT_TYPE)
-         && (code1 == INTEGER_TYPE || code1 == POINTER_TYPE
-             || code1 == REAL_TYPE || code1 == COMPLEX_TYPE
-             || code1 == FIXED_POINT_TYPE))
-       {
-         /* Result of these operations is always an int,
-            but that does not mean the operands should be
-            converted to ints!  */
-         result_type = integer_type_node;
-         op0 = c_common_truthvalue_conversion (location, op0);
-         op1 = c_common_truthvalue_conversion (location, op1);
-         converted = 1;
-         boolean_op = true;
-       }
-      if (code == TRUTH_ANDIF_EXPR)
-       {
-         int_const_or_overflow = (int_operands
-                                  && TREE_CODE (orig_op0) == INTEGER_CST
-                                  && (op0 == truthvalue_false_node
-                                      || TREE_CODE (orig_op1) == INTEGER_CST));
-         int_const = (int_const_or_overflow
-                      && !TREE_OVERFLOW (orig_op0)
-                      && (op0 == truthvalue_false_node
-                          || !TREE_OVERFLOW (orig_op1)));
-       }
-      else if (code == TRUTH_ORIF_EXPR)
-       {
-         int_const_or_overflow = (int_operands
-                                  && TREE_CODE (orig_op0) == INTEGER_CST
-                                  && (op0 == truthvalue_true_node
-                                      || TREE_CODE (orig_op1) == INTEGER_CST));
-         int_const = (int_const_or_overflow
-                      && !TREE_OVERFLOW (orig_op0)
-                      && (op0 == truthvalue_true_node
-                          || !TREE_OVERFLOW (orig_op1)));
-       }
-      break;
-
-      /* Shift operations: result has same type as first operand;
-        always convert second operand to int.
-        Also set SHORT_SHIFT if shifting rightward.  */
-
-    case RSHIFT_EXPR:
-      if (code0 == VECTOR_TYPE && code1 == INTEGER_TYPE
-          && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE)
-        {
-          result_type = type0;
-          converted = 1;
-        }
-      else if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE
-         && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE
-          && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE
-          && TYPE_VECTOR_SUBPARTS (type0) == TYPE_VECTOR_SUBPARTS (type1))
-       {
-         result_type = type0;
-         converted = 1;
-       }
-      else if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
-         && code1 == INTEGER_TYPE)
-       {
-         if (TREE_CODE (op1) == INTEGER_CST)
-           {
-             if (tree_int_cst_sgn (op1) < 0)
-               {
-                 int_const = false;
-                 if (c_inhibit_evaluation_warnings == 0)
-                   warning (0, "right shift count is negative");
-               }
-             else
-               {
-                 if (!integer_zerop (op1))
-                   short_shift = 1;
-
-                 if (compare_tree_int (op1, TYPE_PRECISION (type0)) >= 0)
-                   {
-                     int_const = false;
-                     if (c_inhibit_evaluation_warnings == 0)
-                       warning (0, "right shift count >= width of type");
-                   }
-               }
-           }
-
-         /* Use the type of the value to be shifted.  */
-         result_type = type0;
-         /* Convert the non vector shift-count to an integer, regardless
-            of size of value being shifted.  */
-         if (TREE_CODE (TREE_TYPE (op1)) != VECTOR_TYPE
-             && TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
-           op1 = convert (integer_type_node, op1);
-         /* Avoid converting op1 to result_type later.  */
-         converted = 1;
-       }
-      break;
-
-    case LSHIFT_EXPR:
-      if (code0 == VECTOR_TYPE && code1 == INTEGER_TYPE
-          && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE)
-        {
-          result_type = type0;
-          converted = 1;
-        }
-      else if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE
-         && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE
-          && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE
-          && TYPE_VECTOR_SUBPARTS (type0) == TYPE_VECTOR_SUBPARTS (type1))
-       {
-         result_type = type0;
-         converted = 1;
-       }
-      else if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
-         && code1 == INTEGER_TYPE)
-       {
-         if (TREE_CODE (op1) == INTEGER_CST)
-           {
-             if (tree_int_cst_sgn (op1) < 0)
-               {
-                 int_const = false;
-                 if (c_inhibit_evaluation_warnings == 0)
-                   warning (0, "left shift count is negative");
-               }
-
-             else if (compare_tree_int (op1, TYPE_PRECISION (type0)) >= 0)
-               {
-                 int_const = false;
-                 if (c_inhibit_evaluation_warnings == 0)
-                   warning (0, "left shift count >= width of type");
-               }
-           }
-
-         /* Use the type of the value to be shifted.  */
-         result_type = type0;
-         /* Convert the non vector shift-count to an integer, regardless
-            of size of value being shifted.  */
-         if (TREE_CODE (TREE_TYPE (op1)) != VECTOR_TYPE
-             && TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
-           op1 = convert (integer_type_node, op1);
-         /* Avoid converting op1 to result_type later.  */
-         converted = 1;
-       }
-      break;
-
-    case EQ_EXPR:
-    case NE_EXPR:
-      if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE)
-        {
-          tree intt;
-          if (TREE_TYPE (type0) != TREE_TYPE (type1))
-            {
-              error_at (location, "comparing vectors with different "
-                                  "element types");
-              return error_mark_node;
-            }
-
-          if (TYPE_VECTOR_SUBPARTS (type0) != TYPE_VECTOR_SUBPARTS (type1))
-            {
-              error_at (location, "comparing vectors with different "
-                                  "number of elements");
-              return error_mark_node;
-            }
-
-          /* Always construct signed integer vector type.  */
-          intt = c_common_type_for_size (GET_MODE_BITSIZE
-                                          (TYPE_MODE (TREE_TYPE (type0))), 0);
-          result_type = build_opaque_vector_type (intt,
-                                                 TYPE_VECTOR_SUBPARTS (type0));
-          converted = 1;
-          break;
-        }
-      if (FLOAT_TYPE_P (type0) || FLOAT_TYPE_P (type1))
-       warning_at (location,
-                   OPT_Wfloat_equal,
-                   "comparing floating point with == or != is unsafe");
-      /* Result of comparison is always int,
-        but don't convert the args to int!  */
-      build_type = integer_type_node;
-      if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
-          || code0 == FIXED_POINT_TYPE || code0 == COMPLEX_TYPE)
-         && (code1 == INTEGER_TYPE || code1 == REAL_TYPE
-             || code1 == FIXED_POINT_TYPE || code1 == COMPLEX_TYPE))
-       short_compare = 1;
-      else if (code0 == POINTER_TYPE && null_pointer_constant_p (orig_op1))
-       {
-         if (TREE_CODE (op0) == ADDR_EXPR
-             && decl_with_nonnull_addr_p (TREE_OPERAND (op0, 0)))
-           {
-             if (code == EQ_EXPR)
-               warning_at (location,
-                           OPT_Waddress,
-                           "the comparison will always evaluate as %<false%> "
-                           "for the address of %qD will never be NULL",
-                           TREE_OPERAND (op0, 0));
-             else
-               warning_at (location,
-                           OPT_Waddress,
-                           "the comparison will always evaluate as %<true%> "
-                           "for the address of %qD will never be NULL",
-                           TREE_OPERAND (op0, 0));
-           }
-         result_type = type0;
-       }
-      else if (code1 == POINTER_TYPE && null_pointer_constant_p (orig_op0))
-       {
-         if (TREE_CODE (op1) == ADDR_EXPR
-             && decl_with_nonnull_addr_p (TREE_OPERAND (op1, 0)))
-           {
-             if (code == EQ_EXPR)
-               warning_at (location,
-                           OPT_Waddress,
-                           "the comparison will always evaluate as %<false%> "
-                           "for the address of %qD will never be NULL",
-                           TREE_OPERAND (op1, 0));
-             else
-               warning_at (location,
-                           OPT_Waddress,
-                           "the comparison will always evaluate as %<true%> "
-                           "for the address of %qD will never be NULL",
-                           TREE_OPERAND (op1, 0));
-           }
-         result_type = type1;
-       }
-      else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
-       {
-         tree tt0 = TREE_TYPE (type0);
-         tree tt1 = TREE_TYPE (type1);
-         addr_space_t as0 = TYPE_ADDR_SPACE (tt0);
-         addr_space_t as1 = TYPE_ADDR_SPACE (tt1);
-         addr_space_t as_common = ADDR_SPACE_GENERIC;
-
-         /* Anything compares with void *.  void * compares with anything.
-            Otherwise, the targets must be compatible
-            and both must be object or both incomplete.  */
-         if (comp_target_types (location, type0, type1))
-           result_type = common_pointer_type (type0, type1);
-         else if (!addr_space_superset (as0, as1, &as_common))
-           {
-             error_at (location, "comparison of pointers to "
-                       "disjoint address spaces");
-             return error_mark_node;
-           }
-         else if (VOID_TYPE_P (tt0))
-           {
-             if (pedantic && TREE_CODE (tt1) == FUNCTION_TYPE)
-               pedwarn (location, OPT_Wpedantic, "ISO C forbids "
-                        "comparison of %<void *%> with function pointer");
-           }
-         else if (VOID_TYPE_P (tt1))
-           {
-             if (pedantic && TREE_CODE (tt0) == FUNCTION_TYPE)
-               pedwarn (location, OPT_Wpedantic, "ISO C forbids "
-                        "comparison of %<void *%> with function pointer");
-           }
-         else
-           /* Avoid warning about the volatile ObjC EH puts on decls.  */
-           if (!objc_ok)
-             pedwarn (location, 0,
-                      "comparison of distinct pointer types lacks a cast");
-
-         if (result_type == NULL_TREE)
-           {
-             int qual = ENCODE_QUAL_ADDR_SPACE (as_common);
-             result_type = build_pointer_type
-                             (build_qualified_type (void_type_node, qual));
-           }
-       }
-      else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
-       {
-         result_type = type0;
-         pedwarn (location, 0, "comparison between pointer and integer");
-       }
-      else if (code0 == INTEGER_TYPE && code1 == POINTER_TYPE)
-       {
-         result_type = type1;
-         pedwarn (location, 0, "comparison between pointer and integer");
-       }
-      break;
-
-    case LE_EXPR:
-    case GE_EXPR:
-    case LT_EXPR:
-    case GT_EXPR:
-      if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE)
-        {
-          tree intt;
-          if (TREE_TYPE (type0) != TREE_TYPE (type1))
-            {
-              error_at (location, "comparing vectors with different "
-                                  "element types");
-              return error_mark_node;
-            }
-
-          if (TYPE_VECTOR_SUBPARTS (type0) != TYPE_VECTOR_SUBPARTS (type1))
-            {
-              error_at (location, "comparing vectors with different "
-                                  "number of elements");
-              return error_mark_node;
-            }
-
-          /* Always construct signed integer vector type.  */
-          intt = c_common_type_for_size (GET_MODE_BITSIZE
-                                          (TYPE_MODE (TREE_TYPE (type0))), 0);
-          result_type = build_opaque_vector_type (intt,
-                                                 TYPE_VECTOR_SUBPARTS (type0));
-          converted = 1;
-          break;
-        }
-      build_type = integer_type_node;
-      if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
-          || code0 == FIXED_POINT_TYPE)
-         && (code1 == INTEGER_TYPE || code1 == REAL_TYPE
-             || code1 == FIXED_POINT_TYPE))
-       short_compare = 1;
-      else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
-       {
-         addr_space_t as0 = TYPE_ADDR_SPACE (TREE_TYPE (type0));
-         addr_space_t as1 = TYPE_ADDR_SPACE (TREE_TYPE (type1));
-         addr_space_t as_common;
-
-         if (comp_target_types (location, type0, type1))
-           {
-             result_type = common_pointer_type (type0, type1);
-             if (!COMPLETE_TYPE_P (TREE_TYPE (type0))
-                 != !COMPLETE_TYPE_P (TREE_TYPE (type1)))
-               pedwarn (location, 0,
-                        "comparison of complete and incomplete pointers");
-             else if (TREE_CODE (TREE_TYPE (type0)) == FUNCTION_TYPE)
-               pedwarn (location, OPT_Wpedantic, "ISO C forbids "
-                        "ordered comparisons of pointers to functions");
-             else if (null_pointer_constant_p (orig_op0)
-                      || null_pointer_constant_p (orig_op1))
-               warning_at (location, OPT_Wextra,
-                           "ordered comparison of pointer with null pointer");
-
-           }
-         else if (!addr_space_superset (as0, as1, &as_common))
-           {
-             error_at (location, "comparison of pointers to "
-                       "disjoint address spaces");
-             return error_mark_node;
-           }
-         else
-           {
-             int qual = ENCODE_QUAL_ADDR_SPACE (as_common);
-             result_type = build_pointer_type
-                             (build_qualified_type (void_type_node, qual));
-             pedwarn (location, 0,
-                      "comparison of distinct pointer types lacks a cast");
-           }
-       }
-      else if (code0 == POINTER_TYPE && null_pointer_constant_p (orig_op1))
-       {
-         result_type = type0;
-         if (pedantic)
-           pedwarn (location, OPT_Wpedantic,
-                    "ordered comparison of pointer with integer zero");
-         else if (extra_warnings)
-           warning_at (location, OPT_Wextra,
-                       "ordered comparison of pointer with integer zero");
-       }
-      else if (code1 == POINTER_TYPE && null_pointer_constant_p (orig_op0))
-       {
-         result_type = type1;
-         if (pedantic)
-           pedwarn (location, OPT_Wpedantic,
-                    "ordered comparison of pointer with integer zero");
-         else if (extra_warnings)
-           warning_at (location, OPT_Wextra,
-                       "ordered comparison of pointer with integer zero");
-       }
-      else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
-       {
-         result_type = type0;
-         pedwarn (location, 0, "comparison between pointer and integer");
-       }
-      else if (code0 == INTEGER_TYPE && code1 == POINTER_TYPE)
-       {
-         result_type = type1;
-         pedwarn (location, 0, "comparison between pointer and integer");
-       }
-      break;
-
-    default:
-      gcc_unreachable ();
-    }
-
-  if (code0 == ERROR_MARK || code1 == ERROR_MARK)
-    return error_mark_node;
-
-  if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE
-      && (!tree_int_cst_equal (TYPE_SIZE (type0), TYPE_SIZE (type1))
-         || !same_scalar_type_ignoring_signedness (TREE_TYPE (type0),
-                                                   TREE_TYPE (type1))))
-    {
-      binary_op_error (location, code, type0, type1);
-      return error_mark_node;
-    }
-
-  if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE || code0 == COMPLEX_TYPE
-       || code0 == FIXED_POINT_TYPE || code0 == VECTOR_TYPE)
-      &&
-      (code1 == INTEGER_TYPE || code1 == REAL_TYPE || code1 == COMPLEX_TYPE
-       || code1 == FIXED_POINT_TYPE || code1 == VECTOR_TYPE))
-    {
-      bool first_complex = (code0 == COMPLEX_TYPE);
-      bool second_complex = (code1 == COMPLEX_TYPE);
-      int none_complex = (!first_complex && !second_complex);
-
-      if (shorten || common || short_compare)
-       {
-         result_type = c_common_type (type0, type1);
-         do_warn_double_promotion (result_type, type0, type1,
-                                   "implicit conversion from %qT to %qT "
-                                   "to match other operand of binary "
-                                   "expression",
-                                   location);
-         if (result_type == error_mark_node)
-           return error_mark_node;
-       }
-
-      if (first_complex != second_complex
-         && (code == PLUS_EXPR
-             || code == MINUS_EXPR
-             || code == MULT_EXPR
-             || (code == TRUNC_DIV_EXPR && first_complex))
-         && TREE_CODE (TREE_TYPE (result_type)) == REAL_TYPE
-         && flag_signed_zeros)
-       {
-         /* An operation on mixed real/complex operands must be
-            handled specially, but the language-independent code can
-            more easily optimize the plain complex arithmetic if
-            -fno-signed-zeros.  */
-         tree real_type = TREE_TYPE (result_type);
-         tree real, imag;
-         if (type0 != orig_type0 || type1 != orig_type1)
-           {
-             gcc_assert (may_need_excess_precision && common);
-             semantic_result_type = c_common_type (orig_type0, orig_type1);
-           }
-         if (first_complex)
-           {
-             if (TREE_TYPE (op0) != result_type)
-               op0 = convert_and_check (result_type, op0);
-             if (TREE_TYPE (op1) != real_type)
-               op1 = convert_and_check (real_type, op1);
-           }
-         else
-           {
-             if (TREE_TYPE (op0) != real_type)
-               op0 = convert_and_check (real_type, op0);
-             if (TREE_TYPE (op1) != result_type)
-               op1 = convert_and_check (result_type, op1);
-           }
-         if (TREE_CODE (op0) == ERROR_MARK || TREE_CODE (op1) == ERROR_MARK)
-           return error_mark_node;
-         if (first_complex)
-           {
-             op0 = c_save_expr (op0);
-             real = build_unary_op (EXPR_LOCATION (orig_op0), REALPART_EXPR,
-                                    op0, 1);
-             imag = build_unary_op (EXPR_LOCATION (orig_op0), IMAGPART_EXPR,
-                                    op0, 1);
-             switch (code)
-               {
-               case MULT_EXPR:
-               case TRUNC_DIV_EXPR:
-                 op1 = c_save_expr (op1);
-                 imag = build2 (resultcode, real_type, imag, op1);
-                 /* Fall through.  */
-               case PLUS_EXPR:
-               case MINUS_EXPR:
-                 real = build2 (resultcode, real_type, real, op1);
-                 break;
-               default:
-                 gcc_unreachable();
-               }
-           }
-         else
-           {
-             op1 = c_save_expr (op1);
-             real = build_unary_op (EXPR_LOCATION (orig_op1), REALPART_EXPR,
-                                    op1, 1);
-             imag = build_unary_op (EXPR_LOCATION (orig_op1), IMAGPART_EXPR,
-                                    op1, 1);
-             switch (code)
-               {
-               case MULT_EXPR:
-                 op0 = c_save_expr (op0);
-                 imag = build2 (resultcode, real_type, op0, imag);
-                 /* Fall through.  */
-               case PLUS_EXPR:
-                 real = build2 (resultcode, real_type, op0, real);
-                 break;
-               case MINUS_EXPR:
-                 real = build2 (resultcode, real_type, op0, real);
-                 imag = build1 (NEGATE_EXPR, real_type, imag);
-                 break;
-               default:
-                 gcc_unreachable();
-               }
-           }
-         ret = build2 (COMPLEX_EXPR, result_type, real, imag);
-         goto return_build_binary_op;
-       }
-
-      /* For certain operations (which identify themselves by shorten != 0)
-        if both args were extended from the same smaller type,
-        do the arithmetic in that type and then extend.
-
-        shorten !=0 and !=1 indicates a bitwise operation.
-        For them, this optimization is safe only if
-        both args are zero-extended or both are sign-extended.
-        Otherwise, we might change the result.
-        Eg, (short)-1 | (unsigned short)-1 is (int)-1
-        but calculated in (unsigned short) it would be (unsigned short)-1.  */
-
-      if (shorten && none_complex)
-       {
-         final_type = result_type;
-         result_type = shorten_binary_op (result_type, op0, op1,
-                                          shorten == -1);
-       }
-
-      /* Shifts can be shortened if shifting right.  */
-
-      if (short_shift)
-       {
-         int unsigned_arg;
-         tree arg0 = get_narrower (op0, &unsigned_arg);
-
-         final_type = result_type;
-
-         if (arg0 == op0 && final_type == TREE_TYPE (op0))
-           unsigned_arg = TYPE_UNSIGNED (TREE_TYPE (op0));
-
-         if (TYPE_PRECISION (TREE_TYPE (arg0)) < TYPE_PRECISION (result_type)
-             && tree_int_cst_sgn (op1) > 0
-             /* We can shorten only if the shift count is less than the
-                number of bits in the smaller type size.  */
-             && compare_tree_int (op1, TYPE_PRECISION (TREE_TYPE (arg0))) < 0
-             /* We cannot drop an unsigned shift after sign-extension.  */
-             && (!TYPE_UNSIGNED (final_type) || unsigned_arg))
-           {
-             /* Do an unsigned shift if the operand was zero-extended.  */
-             result_type
-               = c_common_signed_or_unsigned_type (unsigned_arg,
-                                                   TREE_TYPE (arg0));
-             /* Convert value-to-be-shifted to that type.  */
-             if (TREE_TYPE (op0) != result_type)
-               op0 = convert (result_type, op0);
-             converted = 1;
-           }
-       }
-
-      /* Comparison operations are shortened too but differently.
-        They identify themselves by setting short_compare = 1.  */
-
-      if (short_compare)
-       {
-         /* Don't write &op0, etc., because that would prevent op0
-            from being kept in a register.
-            Instead, make copies of the our local variables and
-            pass the copies by reference, then copy them back afterward.  */
-         tree xop0 = op0, xop1 = op1, xresult_type = result_type;
-         enum tree_code xresultcode = resultcode;
-         tree val
-           = shorten_compare (&xop0, &xop1, &xresult_type, &xresultcode);
-
-         if (val != 0)
-           {
-             ret = val;
-             goto return_build_binary_op;
-           }
-
-         op0 = xop0, op1 = xop1;
-         converted = 1;
-         resultcode = xresultcode;
-
-         if (c_inhibit_evaluation_warnings == 0)
-           {
-             bool op0_maybe_const = true;
-             bool op1_maybe_const = true;
-             tree orig_op0_folded, orig_op1_folded;
-
-             if (in_late_binary_op)
-               {
-                 orig_op0_folded = orig_op0;
-                 orig_op1_folded = orig_op1;
-               }
-             else
-               {
-                 /* Fold for the sake of possible warnings, as in
-                    build_conditional_expr.  This requires the
-                    "original" values to be folded, not just op0 and
-                    op1.  */
-                 c_inhibit_evaluation_warnings++;
-                 op0 = c_fully_fold (op0, require_constant_value,
-                                     &op0_maybe_const);
-                 op1 = c_fully_fold (op1, require_constant_value,
-                                     &op1_maybe_const);
-                 c_inhibit_evaluation_warnings--;
-                 orig_op0_folded = c_fully_fold (orig_op0,
-                                                 require_constant_value,
-                                                 NULL);
-                 orig_op1_folded = c_fully_fold (orig_op1,
-                                                 require_constant_value,
-                                                 NULL);
-               }
-
-             if (warn_sign_compare)
-               warn_for_sign_compare (location, orig_op0_folded,
-                                      orig_op1_folded, op0, op1,
-                                      result_type, resultcode);
-             if (!in_late_binary_op && !int_operands)
-               {
-                 if (!op0_maybe_const || TREE_CODE (op0) != INTEGER_CST)
-                   op0 = c_wrap_maybe_const (op0, !op0_maybe_const);
-                 if (!op1_maybe_const || TREE_CODE (op1) != INTEGER_CST)
-                   op1 = c_wrap_maybe_const (op1, !op1_maybe_const);
-               }
-           }
-       }
-    }
-
-  /* At this point, RESULT_TYPE must be nonzero to avoid an error message.
-     If CONVERTED is zero, both args will be converted to type RESULT_TYPE.
-     Then the expression will be built.
-     It will be given type FINAL_TYPE if that is nonzero;
-     otherwise, it will be given type RESULT_TYPE.  */
-
-  if (!result_type)
-    {
-      binary_op_error (location, code, TREE_TYPE (op0), TREE_TYPE (op1));
-      return error_mark_node;
-    }
-
-  if (build_type == NULL_TREE)
-    {
-      build_type = result_type;
-      if ((type0 != orig_type0 || type1 != orig_type1)
-         && !boolean_op)
-       {
-         gcc_assert (may_need_excess_precision && common);
-         semantic_result_type = c_common_type (orig_type0, orig_type1);
-       }
-    }
-
-  if (!converted)
-    {
-      op0 = ep_convert_and_check (result_type, op0, semantic_result_type);
-      op1 = ep_convert_and_check (result_type, op1, semantic_result_type);
-
-      /* This can happen if one operand has a vector type, and the other
-        has a different type.  */
-      if (TREE_CODE (op0) == ERROR_MARK || TREE_CODE (op1) == ERROR_MARK)
-       return error_mark_node;
-    }
-
-  /* Treat expressions in initializers specially as they can't trap.  */
-  if (int_const_or_overflow)
-    ret = (require_constant_value
-          ? fold_build2_initializer_loc (location, resultcode, build_type,
-                                         op0, op1)
-          : fold_build2_loc (location, resultcode, build_type, op0, op1));
-  else
-    ret = build2 (resultcode, build_type, op0, op1);
-  if (final_type != 0)
-    ret = convert (final_type, ret);
-
- return_build_binary_op:
-  gcc_assert (ret != error_mark_node);
-  if (TREE_CODE (ret) == INTEGER_CST && !TREE_OVERFLOW (ret) && !int_const)
-    ret = (int_operands
-          ? note_integer_operands (ret)
-          : build1 (NOP_EXPR, TREE_TYPE (ret), ret));
-  else if (TREE_CODE (ret) != INTEGER_CST && int_operands
-          && !in_late_binary_op)
-    ret = note_integer_operands (ret);
-  if (semantic_result_type)
-    ret = build1 (EXCESS_PRECISION_EXPR, semantic_result_type, ret);
-  protected_set_expr_location (ret, location);
-  return ret;
-}
-
-
-/* Convert EXPR to be a truth-value, validating its type for this
-   purpose.  LOCATION is the source location for the expression.  */
-
-tree
-c_objc_common_truthvalue_conversion (location_t location, tree expr)
-{
-  bool int_const, int_operands;
-
-  switch (TREE_CODE (TREE_TYPE (expr)))
-    {
-    case ARRAY_TYPE:
-      error_at (location, "used array that cannot be converted to pointer where scalar is required");
-      return error_mark_node;
-
-    case RECORD_TYPE:
-      error_at (location, "used struct type value where scalar is required");
-      return error_mark_node;
-
-    case UNION_TYPE:
-      error_at (location, "used union type value where scalar is required");
-      return error_mark_node;
-
-    case VOID_TYPE:
-      error_at (location, "void value not ignored as it ought to be");
-      return error_mark_node;
-
-    case FUNCTION_TYPE:
-      gcc_unreachable ();
-
-    case VECTOR_TYPE:
-      error_at (location, "used vector type where scalar is required");
-      return error_mark_node;
-
-    default:
-      break;
-    }
-
-  int_const = (TREE_CODE (expr) == INTEGER_CST && !TREE_OVERFLOW (expr));
-  int_operands = EXPR_INT_CONST_OPERANDS (expr);
-  if (int_operands)
-    expr = remove_c_maybe_const_expr (expr);
-
-  /* ??? Should we also give an error for vectors rather than leaving
-     those to give errors later?  */
-  expr = c_common_truthvalue_conversion (location, expr);
-
-  if (TREE_CODE (expr) == INTEGER_CST && int_operands && !int_const)
-    {
-      if (TREE_OVERFLOW (expr))
-       return expr;
-      else
-       return note_integer_operands (expr);
-    }
-  if (TREE_CODE (expr) == INTEGER_CST && !int_const)
-    return build1 (NOP_EXPR, TREE_TYPE (expr), expr);
-  return expr;
-}
-\f
-
-/* Convert EXPR to a contained DECL, updating *TC, *TI and *SE as
-   required.  */
-
-tree
-c_expr_to_decl (tree expr, bool *tc ATTRIBUTE_UNUSED, bool *se)
-{
-  if (TREE_CODE (expr) == COMPOUND_LITERAL_EXPR)
-    {
-      tree decl = COMPOUND_LITERAL_EXPR_DECL (expr);
-      /* Executing a compound literal inside a function reinitializes
-        it.  */
-      if (!TREE_STATIC (decl))
-       *se = true;
-      return decl;
-    }
-  else
-    return expr;
-}
-\f
-/* Like c_begin_compound_stmt, except force the retention of the BLOCK.  */
-
-tree
-c_begin_omp_parallel (void)
-{
-  tree block;
-
-  keep_next_level ();
-  block = c_begin_compound_stmt (true);
-
-  return block;
-}
-
-/* Generate OMP_PARALLEL, with CLAUSES and BLOCK as its compound
-   statement.  LOC is the location of the OMP_PARALLEL.  */
-
-tree
-c_finish_omp_parallel (location_t loc, tree clauses, tree block)
-{
-  tree stmt;
-
-  block = c_end_compound_stmt (loc, block, true);
-
-  stmt = make_node (OMP_PARALLEL);
-  TREE_TYPE (stmt) = void_type_node;
-  OMP_PARALLEL_CLAUSES (stmt) = clauses;
-  OMP_PARALLEL_BODY (stmt) = block;
-  SET_EXPR_LOCATION (stmt, loc);
-
-  return add_stmt (stmt);
-}
-
-/* Like c_begin_compound_stmt, except force the retention of the BLOCK.  */
-
-tree
-c_begin_omp_task (void)
-{
-  tree block;
-
-  keep_next_level ();
-  block = c_begin_compound_stmt (true);
-
-  return block;
-}
-
-/* Generate OMP_TASK, with CLAUSES and BLOCK as its compound
-   statement.  LOC is the location of the #pragma.  */
-
-tree
-c_finish_omp_task (location_t loc, tree clauses, tree block)
-{
-  tree stmt;
-
-  block = c_end_compound_stmt (loc, block, true);
-
-  stmt = make_node (OMP_TASK);
-  TREE_TYPE (stmt) = void_type_node;
-  OMP_TASK_CLAUSES (stmt) = clauses;
-  OMP_TASK_BODY (stmt) = block;
-  SET_EXPR_LOCATION (stmt, loc);
-
-  return add_stmt (stmt);
-}
-
-/* For all elements of CLAUSES, validate them vs OpenMP constraints.
-   Remove any elements from the list that are invalid.  */
-
-tree
-c_finish_omp_clauses (tree clauses)
-{
-  bitmap_head generic_head, firstprivate_head, lastprivate_head;
-  tree c, t, *pc = &clauses;
-  const char *name;
-
-  bitmap_obstack_initialize (NULL);
-  bitmap_initialize (&generic_head, &bitmap_default_obstack);
-  bitmap_initialize (&firstprivate_head, &bitmap_default_obstack);
-  bitmap_initialize (&lastprivate_head, &bitmap_default_obstack);
-
-  for (pc = &clauses, c = clauses; c ; c = *pc)
-    {
-      bool remove = false;
-      bool need_complete = false;
-      bool need_implicitly_determined = false;
-
-      switch (OMP_CLAUSE_CODE (c))
-       {
-       case OMP_CLAUSE_SHARED:
-         name = "shared";
-         need_implicitly_determined = true;
-         goto check_dup_generic;
-
-       case OMP_CLAUSE_PRIVATE:
-         name = "private";
-         need_complete = true;
-         need_implicitly_determined = true;
-         goto check_dup_generic;
-
-       case OMP_CLAUSE_REDUCTION:
-         name = "reduction";
-         need_implicitly_determined = true;
-         t = OMP_CLAUSE_DECL (c);
-         if (AGGREGATE_TYPE_P (TREE_TYPE (t))
-             || POINTER_TYPE_P (TREE_TYPE (t)))
-           {
-             error_at (OMP_CLAUSE_LOCATION (c),
-                       "%qE has invalid type for %<reduction%>", t);
-             remove = true;
-           }
-         else if (FLOAT_TYPE_P (TREE_TYPE (t)))
-           {
-             enum tree_code r_code = OMP_CLAUSE_REDUCTION_CODE (c);
-             const char *r_name = NULL;
-
-             switch (r_code)
-               {
-               case PLUS_EXPR:
-               case MULT_EXPR:
-               case MINUS_EXPR:
-               case MIN_EXPR:
-               case MAX_EXPR:
-                 break;
-               case BIT_AND_EXPR:
-                 r_name = "&";
-                 break;
-               case BIT_XOR_EXPR:
-                 r_name = "^";
-                 break;
-               case BIT_IOR_EXPR:
-                 r_name = "|";
-                 break;
-               case TRUTH_ANDIF_EXPR:
-                 r_name = "&&";
-                 break;
-               case TRUTH_ORIF_EXPR:
-                 r_name = "||";
-                 break;
-               default:
-                 gcc_unreachable ();
-               }
-             if (r_name)
-               {
-                 error_at (OMP_CLAUSE_LOCATION (c),
-                           "%qE has invalid type for %<reduction(%s)%>",
-                           t, r_name);
-                 remove = true;
-               }
-           }
-         goto check_dup_generic;
-
-       case OMP_CLAUSE_COPYPRIVATE:
-         name = "copyprivate";
-         goto check_dup_generic;
-
-       case OMP_CLAUSE_COPYIN:
-         name = "copyin";
-         t = OMP_CLAUSE_DECL (c);
-         if (TREE_CODE (t) != VAR_DECL || !DECL_THREAD_LOCAL_P (t))
-           {
-             error_at (OMP_CLAUSE_LOCATION (c),
-                       "%qE must be %<threadprivate%> for %<copyin%>", t);
-             remove = true;
-           }
-         goto check_dup_generic;
-
-       check_dup_generic:
-         t = OMP_CLAUSE_DECL (c);
-         if (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL)
-           {
-             error_at (OMP_CLAUSE_LOCATION (c),
-                       "%qE is not a variable in clause %qs", t, name);
-             remove = true;
-           }
-         else if (bitmap_bit_p (&generic_head, DECL_UID (t))
-                  || bitmap_bit_p (&firstprivate_head, DECL_UID (t))
-                  || bitmap_bit_p (&lastprivate_head, DECL_UID (t)))
-           {
-             error_at (OMP_CLAUSE_LOCATION (c),
-                       "%qE appears more than once in data clauses", t);
-             remove = true;
-           }
-         else
-           bitmap_set_bit (&generic_head, DECL_UID (t));
-         break;
-
-       case OMP_CLAUSE_FIRSTPRIVATE:
-         name = "firstprivate";
-         t = OMP_CLAUSE_DECL (c);
-         need_complete = true;
-         need_implicitly_determined = true;
-         if (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL)
-           {
-             error_at (OMP_CLAUSE_LOCATION (c),
-                       "%qE is not a variable in clause %<firstprivate%>", t);
-             remove = true;
-           }
-         else if (bitmap_bit_p (&generic_head, DECL_UID (t))
-                  || bitmap_bit_p (&firstprivate_head, DECL_UID (t)))
-           {
-             error_at (OMP_CLAUSE_LOCATION (c),
-                       "%qE appears more than once in data clauses", t);
-             remove = true;
-           }
-         else
-           bitmap_set_bit (&firstprivate_head, DECL_UID (t));
-         break;
-
-       case OMP_CLAUSE_LASTPRIVATE:
-         name = "lastprivate";
-         t = OMP_CLAUSE_DECL (c);
-         need_complete = true;
-         need_implicitly_determined = true;
-         if (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL)
-           {
-             error_at (OMP_CLAUSE_LOCATION (c),
-                       "%qE is not a variable in clause %<lastprivate%>", t);
-             remove = true;
-           }
-         else if (bitmap_bit_p (&generic_head, DECL_UID (t))
-                  || bitmap_bit_p (&lastprivate_head, DECL_UID (t)))
-           {
-             error_at (OMP_CLAUSE_LOCATION (c),
-                    "%qE appears more than once in data clauses", t);
-             remove = true;
-           }
-         else
-           bitmap_set_bit (&lastprivate_head, DECL_UID (t));
-         break;
-
-       case OMP_CLAUSE_IF:
-       case OMP_CLAUSE_NUM_THREADS:
-       case OMP_CLAUSE_SCHEDULE:
-       case OMP_CLAUSE_NOWAIT:
-       case OMP_CLAUSE_ORDERED:
-       case OMP_CLAUSE_DEFAULT:
-       case OMP_CLAUSE_UNTIED:
-       case OMP_CLAUSE_COLLAPSE:
-       case OMP_CLAUSE_FINAL:
-       case OMP_CLAUSE_MERGEABLE:
-         pc = &OMP_CLAUSE_CHAIN (c);
-         continue;
-
-       default:
-         gcc_unreachable ();
-       }
-
-      if (!remove)
-       {
-         t = OMP_CLAUSE_DECL (c);
-
-         if (need_complete)
-           {
-             t = require_complete_type (t);
-             if (t == error_mark_node)
-               remove = true;
-           }
-
-         if (need_implicitly_determined)
-           {
-             const char *share_name = NULL;
-
-             if (TREE_CODE (t) == VAR_DECL && DECL_THREAD_LOCAL_P (t))
-               share_name = "threadprivate";
-             else switch (c_omp_predetermined_sharing (t))
-               {
-               case OMP_CLAUSE_DEFAULT_UNSPECIFIED:
-                 break;
-               case OMP_CLAUSE_DEFAULT_SHARED:
-                 /* const vars may be specified in firstprivate clause.  */
-                 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
-                     && TREE_READONLY (t))
-                   break;
-                 share_name = "shared";
-                 break;
-               case OMP_CLAUSE_DEFAULT_PRIVATE:
-                 share_name = "private";
-                 break;
-               default:
-                 gcc_unreachable ();
-               }
-             if (share_name)
-               {
-                 error_at (OMP_CLAUSE_LOCATION (c),
-                           "%qE is predetermined %qs for %qs",
-                           t, share_name, name);
-                 remove = true;
-               }
-           }
-       }
-
-      if (remove)
-       *pc = OMP_CLAUSE_CHAIN (c);
-      else
-       pc = &OMP_CLAUSE_CHAIN (c);
-    }
-
-  bitmap_obstack_release (NULL);
-  return clauses;
-}
-
-/* Create a transaction node.  */
-
-tree
-c_finish_transaction (location_t loc, tree block, int flags)
-{
-  tree stmt = build_stmt (loc, TRANSACTION_EXPR, block);
-  if (flags & TM_STMT_ATTR_OUTER)
-    TRANSACTION_EXPR_OUTER (stmt) = 1;
-  if (flags & TM_STMT_ATTR_RELAXED)
-    TRANSACTION_EXPR_RELAXED (stmt) = 1;
-  return add_stmt (stmt);
-}
-
-/* Make a variant type in the proper way for C/C++, propagating qualifiers
-   down to the element type of an array.  */
-
-tree
-c_build_qualified_type (tree type, int type_quals)
-{
-  if (type == error_mark_node)
-    return type;
-
-  if (TREE_CODE (type) == ARRAY_TYPE)
-    {
-      tree t;
-      tree element_type = c_build_qualified_type (TREE_TYPE (type),
-                                                 type_quals);
-
-      /* See if we already have an identically qualified type.  */
-      for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
-       {
-         if (TYPE_QUALS (strip_array_types (t)) == type_quals
-             && TYPE_NAME (t) == TYPE_NAME (type)
-             && TYPE_CONTEXT (t) == TYPE_CONTEXT (type)
-             && attribute_list_equal (TYPE_ATTRIBUTES (t),
-                                      TYPE_ATTRIBUTES (type)))
-           break;
-       }
-      if (!t)
-       {
-          tree domain = TYPE_DOMAIN (type);
-
-         t = build_variant_type_copy (type);
-         TREE_TYPE (t) = element_type;
-
-          if (TYPE_STRUCTURAL_EQUALITY_P (element_type)
-              || (domain && TYPE_STRUCTURAL_EQUALITY_P (domain)))
-            SET_TYPE_STRUCTURAL_EQUALITY (t);
-          else if (TYPE_CANONICAL (element_type) != element_type
-                   || (domain && TYPE_CANONICAL (domain) != domain))
-            {
-              tree unqualified_canon
-                = build_array_type (TYPE_CANONICAL (element_type),
-                                    domain? TYPE_CANONICAL (domain)
-                                          : NULL_TREE);
-              TYPE_CANONICAL (t)
-                = c_build_qualified_type (unqualified_canon, type_quals);
-            }
-          else
-            TYPE_CANONICAL (t) = t;
-       }
-      return t;
-    }
-
-  /* A restrict-qualified pointer type must be a pointer to object or
-     incomplete type.  Note that the use of POINTER_TYPE_P also allows
-     REFERENCE_TYPEs, which is appropriate for C++.  */
-  if ((type_quals & TYPE_QUAL_RESTRICT)
-      && (!POINTER_TYPE_P (type)
-         || !C_TYPE_OBJECT_OR_INCOMPLETE_P (TREE_TYPE (type))))
-    {
-      error ("invalid use of %<restrict%>");
-      type_quals &= ~TYPE_QUAL_RESTRICT;
-    }
-
-  return build_qualified_type (type, type_quals);
-}
-
-/* Build a VA_ARG_EXPR for the C parser.  */
-
-tree
-c_build_va_arg (location_t loc, tree expr, tree type)
-{
-  if (warn_cxx_compat && TREE_CODE (type) == ENUMERAL_TYPE)
-    warning_at (loc, OPT_Wc___compat,
-               "C++ requires promoted type, not enum type, in %<va_arg%>");
-  return build_va_arg (loc, expr, type);
-}
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
new file mode 100644 (file)
index 0000000..f8572aa
--- /dev/null
@@ -0,0 +1,25 @@
+2012-06-29  Steven Bosscher  <steven@gcc.gnu.org>
+
+       * Make-lang.in: New file, rules migrated from gcc/Makefile.in
+       and add language Makefile hooks.
+       * config-lang.in: New file.
+       * c-config-lang.in: Moved from gcc/config-lang.in to here, and
+       add the required "normal" config-lang.in rules.
+       * c-lang.h: Moved from gcc/ to here.
+       * c-tree.h: Likewise.
+       * c-objc-common.c: Likewise.
+       * c-objc-common.h: Likewise.
+       * c-typeck.c: Likewise.
+       * c-convert.c: Likewise.
+       * c-lang.c: Likewise.
+       * c-aux-info.c: Likewise.
+       * c-errors.c: Likewise.
+       * gccspec.c: Likewise.
+       * c-decl.c: Likewise.  Include gt-c-c-decl.h, not gt-c-decl.h.
+       * c-parser.c: Likewise.  Include gt-c-c-parser.h, not gt-c-parser.h.
+\f
+Copyright (C) 2012 Free Software Foundation, Inc.
+
+Copying and distribution of this file, with or without modification,
+are permitted in any medium without royalty provided the copyright
+notice and this notice are preserved.
diff --git a/gcc/c/Make-lang.in b/gcc/c/Make-lang.in
new file mode 100644 (file)
index 0000000..08b1ba1
--- /dev/null
@@ -0,0 +1,196 @@
+# Top level -*- makefile -*- fragment for GNU C - C language.
+# Copyright (C) 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+# 2005, 2007, 2008, 2009, 2010, 2011, 2012
+# 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 file provides the language dependent support in the main Makefile.
+# Each language makefile fragment must provide the following targets:
+#
+# foo.all.cross, foo.start.encap, foo.rest.encap,
+# foo.install-common, foo.install-man, foo.install-info, foo.install-pdf,
+# foo.install-html, foo.info, foo.dvi, foo.pdf, foo.html, foo.uninstall,
+# foo.mostlyclean, foo.clean, foo.distclean,
+# foo.maintainer-clean, foo.stage1, foo.stage2, foo.stage3, foo.stage4
+#
+# where `foo' is the name of the language.
+#
+# It should also provide rules for:
+#
+# - making any compiler driver (eg: gcc)
+# - the compiler proper (eg: cc1)
+# - define the names for selecting the language in LANGUAGES.
+
+#\f
+# Define the names for selecting c in LANGUAGES.
+c: cc1$(exeext)
+
+# Tell GNU make to ignore these if they exist.
+.PHONY: c gcc
+
+# The C front end driver.  This is different from the drivers for other
+# front ends, because there is no C language specific driver (i.e. nothing
+# is to cc1 as e.g. g++ is to cc1plus, or gfortran is to f951).
+c/gccspec.o: c/gccspec.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(GCC_H) \
+    $(OPTS_H)
+       (SHLIB='$(SHLIB)'; \
+       $(COMPILER) $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) \
+  $(DRIVER_DEFINES) \
+  -c $(srcdir)/c/gccspec.c $(OUTPUT_OPTION))
+
+# The C compiler itself.
+
+# Language-specific object files for C and Objective C.
+C_AND_OBJC_OBJS = attribs.o c/c-errors.o c/c-decl.o c/c-typeck.o \
+  c/c-convert.o c/c-aux-info.o c/c-objc-common.o c/c-parser.o \
+  $(C_COMMON_OBJS) $(C_TARGET_OBJS)
+
+# Language-specific object files for C.
+C_OBJS = c/c-lang.o c-family/stub-objc.o $(C_AND_OBJC_OBJS)
+c_OBJS = $(C_OBJS) cc1-checksum.o c/gccspec.o
+
+# Use strict warnings for this front end.
+c-warn = $(STRICT_WARN)
+
+# compute checksum over all object files and the options
+cc1-checksum.c : build/genchecksum$(build_exeext) checksum-options \
+       $(C_OBJS) $(BACKEND) $(LIBDEPS) 
+       build/genchecksum$(build_exeext) $(C_OBJS) $(BACKEND) $(LIBDEPS) \
+                     checksum-options > cc1-checksum.c.tmp &&           \
+       $(srcdir)/../move-if-change cc1-checksum.c.tmp cc1-checksum.c
+
+cc1-checksum.o : cc1-checksum.c $(CONFIG_H) $(SYSTEM_H)
+
+cc1$(exeext): $(C_OBJS) cc1-checksum.o $(BACKEND) $(LIBDEPS)
+       +$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ $(C_OBJS) \
+         cc1-checksum.o $(BACKEND) $(LIBS) $(BACKENDLIBS)
+#\f
+# Build hooks:
+
+c.info:
+c.dvi:
+c.pdf:
+c.html:
+c.install-info:
+c.install-pdf:
+c.install-html:
+c.all.cross:
+c.start.encap:
+c.rest.encap:
+c.srcinfo:
+c.srcextra: gengtype-lex.c
+       -cp -p $^ $(srcdir)
+c.tags: force
+       cd $(srcdir)/c; etags -o TAGS.sub *.c *.h; \
+       etags --include TAGS.sub --include ../TAGS.sub
+c.man:
+c.srcman:
+
+# List of targets that can use the generic check- rule and its // variant.
+lang_checks += check-gcc
+lang_checks_parallelized += check-gcc
+
+# 'make check' in gcc/ looks for check-c.  Redirect it to check-gcc.
+check-c : check-gcc
+
+#\f
+# Install hooks:
+# cc1 is installed elsewhere as part of $(COMPILERS).
+
+c.install-common:
+c.install-man:
+c.install-plugin:
+c.uninstall:
+
+#\f
+# Clean hooks:
+# A lot of the ancillary files are deleted by the main makefile.
+# We just have to delete files specific to us.
+
+c.mostlyclean:
+       -rm -f cc1$(exeext)
+       -rm -f c/*$(objext)
+       -rm -f c/*$(coverageexts)
+c.clean:
+c.distclean:
+       -rm -f c/config.status c/Makefile
+c.maintainer-clean:
+#\f
+# Stage hooks:
+# The main makefile has already created stage?/cp.
+
+c.stage1: stage1-start
+       -mv c/*$(objext) stage1/c
+c.stage2: stage2-start
+       -mv c/*$(objext) stage2/c
+c.stage3: stage3-start
+       -mv c/*$(objext) stage3/c
+c.stage4: stage4-start
+       -mv c/*$(objext) stage4/c
+c.stageprofile: stageprofile-start
+       -mv c/*$(objext) stageprofile/c
+c.stagefeedback: stagefeedback-start
+       -mv c/*$(objext) stagefeedback/c
+
+#\f
+# .o: .h dependencies.
+# C language specific files.
+C_TREE_H = c/c-tree.h $(C_COMMON_H) $(DIAGNOSTIC_H)
+c/c-aux-info.o : c/c-aux-info.c  $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
+       $(C_TREE_H) $(TREE_H) $(FLAGS_H)
+
+c/c-convert.o : c/c-convert.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
+       $(TREE_H) $(C_TREE_H) $(FLAGS_H) $(C_COMMON_H) convert.h \
+       langhooks.h $(TARGET_H)
+
+c/c-decl.o : c/c-decl.c c/c-lang.h $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
+       $(TREE_H) $(C_TREE_H) $(GGC_H) $(TARGET_H) $(FLAGS_H) $(FUNCTION_H) \
+       output.h debug.h toplev.h intl.h $(TM_P_H) $(TREE_INLINE_H) \
+       $(TIMEVAR_H) $(OPTS_H) $(C_PRAGMA_H) gt-c-c-decl.h $(CGRAPH_H) \
+       $(HASHTAB_H) $(LANGHOOKS_DEF_H) \
+       $(TREE_DUMP_H) $(C_COMMON_H) $(CPPLIB_H) $(DIAGNOSTIC_CORE_H) \
+       $(INPUT_H) langhooks.h pointer-set.h tree-iterator.h \
+       $(PLUGIN_H) c-family/c-ada-spec.h c-family/c-objc.h
+
+c/c-errors.o: c/c-errors.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
+       $(C_TREE_H) $(FLAGS_H) $(DIAGNOSTIC_H) $(TM_P_H)
+
+c/c-lang.o : c/c-lang.c c/c-objc-common.h \
+       $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
+       $(C_TREE_H) $(DIAGNOSTIC_CORE_H) \
+       langhooks.h $(LANGHOOKS_DEF_H) $(C_COMMON_H) gtype-c.h \
+       $(C_PRAGMA_H) $(TREE_INLINE_H)
+
+c/c-objc-common.o : c/c-objc-common.c c/c-objc-common.h \
+       $(CONFIG_H) $(SYSTEM_H) coretypes.h \
+       $(TREE_H) $(C_TREE_H) $(FLAGS_H) $(DIAGNOSTIC_H) \
+       langhooks.h $(GGC_H) $(C_PRETTY_PRINT_H) intl.h \
+       $(TREE_PRETTY_PRINT_H)
+
+c/c-parser.o : c/c-parser.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
+       $(TM_H) $(TREE_H) $(C_TREE_H) $(C_COMMON_H) $(C_PRAGMA_H) $(CPPLIB_H) \
+       $(GGC_H) $(TIMEVAR_H) $(INPUT_H) $(FLAGS_H) \
+       gt-c-c-parser.h langhooks.h \
+       $(VEC_H) $(TARGET_H) $(CGRAPH_H) $(PLUGIN_H) \
+       c-family/c-objc.h
+
+c/c-typeck.o : c/c-typeck.c c/c-lang.h $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
+       $(TREE_H) $(C_TREE_H) $(TARGET_H) $(FLAGS_H) intl.h \
+       langhooks.h tree-iterator.h $(BITMAP_H) $(GIMPLE_H) \
+       c-family/c-objc.h
+
diff --git a/gcc/c/c-aux-info.c b/gcc/c/c-aux-info.c
new file mode 100644 (file)
index 0000000..694f9c1
--- /dev/null
@@ -0,0 +1,567 @@
+/* Generate information regarding function declarations and definitions based
+   on information stored in GCC's tree structure.  This code implements the
+   -aux-info option.
+   Copyright (C) 1989, 1991, 1994, 1995, 1997, 1998,
+   1999, 2000, 2003, 2004, 2007, 2010 Free Software Foundation, Inc.
+   Contributed by Ron Guilmette (rfg@segfault.us.com).
+
+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/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "flags.h"
+#include "tree.h"
+#include "c-tree.h"
+
+enum formals_style_enum {
+  ansi,
+  k_and_r_names,
+  k_and_r_decls
+};
+typedef enum formals_style_enum formals_style;
+
+
+static const char *data_type;
+
+static char *affix_data_type (const char *) ATTRIBUTE_MALLOC;
+static const char *gen_formal_list_for_type (tree, formals_style);
+static const char *gen_formal_list_for_func_def (tree, formals_style);
+static const char *gen_type (const char *, tree, formals_style);
+static const char *gen_decl (tree, int, formals_style);
+\f
+/* Given a string representing an entire type or an entire declaration
+   which only lacks the actual "data-type" specifier (at its left end),
+   affix the data-type specifier to the left end of the given type
+   specification or object declaration.
+
+   Because of C language weirdness, the data-type specifier (which normally
+   goes in at the very left end) may have to be slipped in just to the
+   right of any leading "const" or "volatile" qualifiers (there may be more
+   than one).  Actually this may not be strictly necessary because it seems
+   that GCC (at least) accepts `<data-type> const foo;' and treats it the
+   same as `const <data-type> foo;' but people are accustomed to seeing
+   `const char *foo;' and *not* `char const *foo;' so we try to create types
+   that look as expected.  */
+
+static char *
+affix_data_type (const char *param)
+{
+  char *const type_or_decl = ASTRDUP (param);
+  char *p = type_or_decl;
+  char *qualifiers_then_data_type;
+  char saved;
+
+  /* Skip as many leading const's or volatile's as there are.  */
+
+  for (;;)
+    {
+      if (!strncmp (p, "volatile ", 9))
+       {
+         p += 9;
+         continue;
+       }
+      if (!strncmp (p, "const ", 6))
+       {
+         p += 6;
+         continue;
+       }
+      break;
+    }
+
+  /* p now points to the place where we can insert the data type.  We have to
+     add a blank after the data-type of course.  */
+
+  if (p == type_or_decl)
+    return concat (data_type, " ", type_or_decl, NULL);
+
+  saved = *p;
+  *p = '\0';
+  qualifiers_then_data_type = concat (type_or_decl, data_type, NULL);
+  *p = saved;
+  return reconcat (qualifiers_then_data_type,
+                  qualifiers_then_data_type, " ", p, NULL);
+}
+
+/* Given a tree node which represents some "function type", generate the
+   source code version of a formal parameter list (of some given style) for
+   this function type.  Return the whole formal parameter list (including
+   a pair of surrounding parens) as a string.   Note that if the style
+   we are currently aiming for is non-ansi, then we just return a pair
+   of empty parens here.  */
+
+static const char *
+gen_formal_list_for_type (tree fntype, formals_style style)
+{
+  const char *formal_list = "";
+  tree formal_type;
+
+  if (style != ansi)
+    return "()";
+
+  formal_type = TYPE_ARG_TYPES (fntype);
+  while (formal_type && TREE_VALUE (formal_type) != void_type_node)
+    {
+      const char *this_type;
+
+      if (*formal_list)
+       formal_list = concat (formal_list, ", ", NULL);
+
+      this_type = gen_type ("", TREE_VALUE (formal_type), ansi);
+      formal_list
+       = ((strlen (this_type))
+          ? concat (formal_list, affix_data_type (this_type), NULL)
+          : concat (formal_list, data_type, NULL));
+
+      formal_type = TREE_CHAIN (formal_type);
+    }
+
+  /* If we got to here, then we are trying to generate an ANSI style formal
+     parameters list.
+
+     New style prototyped ANSI formal parameter lists should in theory always
+     contain some stuff between the opening and closing parens, even if it is
+     only "void".
+
+     The brutal truth though is that there is lots of old K&R code out there
+     which contains declarations of "pointer-to-function" parameters and
+     these almost never have fully specified formal parameter lists associated
+     with them.  That is, the pointer-to-function parameters are declared
+     with just empty parameter lists.
+
+     In cases such as these, protoize should really insert *something* into
+     the vacant parameter lists, but what?  It has no basis on which to insert
+     anything in particular.
+
+     Here, we make life easy for protoize by trying to distinguish between
+     K&R empty parameter lists and new-style prototyped parameter lists
+     that actually contain "void".  In the latter case we (obviously) want
+     to output the "void" verbatim, and that what we do.  In the former case,
+     we do our best to give protoize something nice to insert.
+
+     This "something nice" should be something that is still valid (when
+     re-compiled) but something that can clearly indicate to the user that
+     more typing information (for the parameter list) should be added (by
+     hand) at some convenient moment.
+
+     The string chosen here is a comment with question marks in it.  */
+
+  if (!*formal_list)
+    {
+      if (prototype_p (fntype))
+       /* assert (TREE_VALUE (TYPE_ARG_TYPES (fntype)) == void_type_node);  */
+       formal_list = "void";
+      else
+       formal_list = "/* ??? */";
+    }
+  else
+    {
+      /* If there were at least some parameters, and if the formals-types-list
+        petered out to a NULL (i.e. without being terminated by a
+        void_type_node) then we need to tack on an ellipsis.  */
+      if (!formal_type)
+       formal_list = concat (formal_list, ", ...", NULL);
+    }
+
+  return concat (" (", formal_list, ")", NULL);
+}
+
+/* Generate a parameter list for a function definition (in some given style).
+
+   Note that this routine has to be separate (and different) from the code that
+   generates the prototype parameter lists for function declarations, because
+   in the case of a function declaration, all we have to go on is a tree node
+   representing the function's own "function type".  This can tell us the types
+   of all of the formal parameters for the function, but it cannot tell us the
+   actual *names* of each of the formal parameters.  We need to output those
+   parameter names for each function definition.
+
+   This routine gets a pointer to a tree node which represents the actual
+   declaration of the given function, and this DECL node has a list of formal
+   parameter (variable) declarations attached to it.  These formal parameter
+   (variable) declaration nodes give us the actual names of the formal
+   parameters for the given function definition.
+
+   This routine returns a string which is the source form for the entire
+   function formal parameter list.  */
+
+static const char *
+gen_formal_list_for_func_def (tree fndecl, formals_style style)
+{
+  const char *formal_list = "";
+  tree formal_decl;
+
+  formal_decl = DECL_ARGUMENTS (fndecl);
+  while (formal_decl)
+    {
+      const char *this_formal;
+
+      if (*formal_list && ((style == ansi) || (style == k_and_r_names)))
+       formal_list = concat (formal_list, ", ", NULL);
+      this_formal = gen_decl (formal_decl, 0, style);
+      if (style == k_and_r_decls)
+       formal_list = concat (formal_list, this_formal, "; ", NULL);
+      else
+       formal_list = concat (formal_list, this_formal, NULL);
+      formal_decl = TREE_CHAIN (formal_decl);
+    }
+  if (style == ansi)
+    {
+      if (!DECL_ARGUMENTS (fndecl))
+       formal_list = concat (formal_list, "void", NULL);
+      if (stdarg_p (TREE_TYPE (fndecl)))
+       formal_list = concat (formal_list, ", ...", NULL);
+    }
+  if ((style == ansi) || (style == k_and_r_names))
+    formal_list = concat (" (", formal_list, ")", NULL);
+  return formal_list;
+}
+
+/* Generate a string which is the source code form for a given type (t).  This
+   routine is ugly and complex because the C syntax for declarations is ugly
+   and complex.  This routine is straightforward so long as *no* pointer types,
+   array types, or function types are involved.
+
+   In the simple cases, this routine will return the (string) value which was
+   passed in as the "ret_val" argument.  Usually, this starts out either as an
+   empty string, or as the name of the declared item (i.e. the formal function
+   parameter variable).
+
+   This routine will also return with the global variable "data_type" set to
+   some string value which is the "basic" data-type of the given complete type.
+   This "data_type" string can be concatenated onto the front of the returned
+   string after this routine returns to its caller.
+
+   In complicated cases involving pointer types, array types, or function
+   types, the C declaration syntax requires an "inside out" approach, i.e. if
+   you have a type which is a "pointer-to-function" type, you need to handle
+   the "pointer" part first, but it also has to be "innermost" (relative to
+   the declaration stuff for the "function" type).  Thus, is this case, you
+   must prepend a "(*" and append a ")" to the name of the item (i.e. formal
+   variable).  Then you must append and prepend the other info for the
+   "function type" part of the overall type.
+
+   To handle the "innermost precedence" rules of complicated C declarators, we
+   do the following (in this routine).  The input parameter called "ret_val"
+   is treated as a "seed".  Each time gen_type is called (perhaps recursively)
+   some additional strings may be appended or prepended (or both) to the "seed"
+   string.  If yet another (lower) level of the GCC tree exists for the given
+   type (as in the case of a pointer type, an array type, or a function type)
+   then the (wrapped) seed is passed to a (recursive) invocation of gen_type()
+   this recursive invocation may again "wrap" the (new) seed with yet more
+   declarator stuff, by appending, prepending (or both).  By the time the
+   recursion bottoms out, the "seed value" at that point will have a value
+   which is (almost) the complete source version of the declarator (except
+   for the data_type info).  Thus, this deepest "seed" value is simply passed
+   back up through all of the recursive calls until it is given (as the return
+   value) to the initial caller of the gen_type() routine.  All that remains
+   to do at this point is for the initial caller to prepend the "data_type"
+   string onto the returned "seed".  */
+
+static const char *
+gen_type (const char *ret_val, tree t, formals_style style)
+{
+  tree chain_p;
+
+  /* If there is a typedef name for this type, use it.  */
+  if (TYPE_NAME (t) && TREE_CODE (TYPE_NAME (t)) == TYPE_DECL)
+    data_type = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (t)));
+  else
+    {
+      switch (TREE_CODE (t))
+       {
+       case POINTER_TYPE:
+         if (TYPE_READONLY (t))
+           ret_val = concat ("const ", ret_val, NULL);
+         if (TYPE_VOLATILE (t))
+           ret_val = concat ("volatile ", ret_val, NULL);
+
+         ret_val = concat ("*", ret_val, NULL);
+
+         if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE || TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE)
+           ret_val = concat ("(", ret_val, ")", NULL);
+
+         ret_val = gen_type (ret_val, TREE_TYPE (t), style);
+
+         return ret_val;
+
+       case ARRAY_TYPE:
+         if (!COMPLETE_TYPE_P (t) || TREE_CODE (TYPE_SIZE (t)) != INTEGER_CST)
+           ret_val = gen_type (concat (ret_val, "[]", NULL),
+                               TREE_TYPE (t), style);
+         else if (int_size_in_bytes (t) == 0)
+           ret_val = gen_type (concat (ret_val, "[0]", NULL),
+                               TREE_TYPE (t), style);
+         else
+           {
+             int size = (int_size_in_bytes (t) / int_size_in_bytes (TREE_TYPE (t)));
+             char buff[10];
+             sprintf (buff, "[%d]", size);
+             ret_val = gen_type (concat (ret_val, buff, NULL),
+                                 TREE_TYPE (t), style);
+           }
+         break;
+
+       case FUNCTION_TYPE:
+         ret_val = gen_type (concat (ret_val,
+                                     gen_formal_list_for_type (t, style),
+                                     NULL),
+                             TREE_TYPE (t), style);
+         break;
+
+       case IDENTIFIER_NODE:
+         data_type = IDENTIFIER_POINTER (t);
+         break;
+
+       /* The following three cases are complicated by the fact that a
+          user may do something really stupid, like creating a brand new
+          "anonymous" type specification in a formal argument list (or as
+          part of a function return type specification).  For example:
+
+               int f (enum { red, green, blue } color);
+
+          In such cases, we have no name that we can put into the prototype
+          to represent the (anonymous) type.  Thus, we have to generate the
+          whole darn type specification.  Yuck!  */
+
+       case RECORD_TYPE:
+         if (TYPE_NAME (t))
+           data_type = IDENTIFIER_POINTER (TYPE_NAME (t));
+         else
+           {
+             data_type = "";
+             chain_p = TYPE_FIELDS (t);
+             while (chain_p)
+               {
+                 data_type = concat (data_type, gen_decl (chain_p, 0, ansi),
+                                     NULL);
+                 chain_p = TREE_CHAIN (chain_p);
+                 data_type = concat (data_type, "; ", NULL);
+               }
+             data_type = concat ("{ ", data_type, "}", NULL);
+           }
+         data_type = concat ("struct ", data_type, NULL);
+         break;
+
+       case UNION_TYPE:
+         if (TYPE_NAME (t))
+           data_type = IDENTIFIER_POINTER (TYPE_NAME (t));
+         else
+           {
+             data_type = "";
+             chain_p = TYPE_FIELDS (t);
+             while (chain_p)
+               {
+                 data_type = concat (data_type, gen_decl (chain_p, 0, ansi),
+                                     NULL);
+                 chain_p = TREE_CHAIN (chain_p);
+                 data_type = concat (data_type, "; ", NULL);
+               }
+             data_type = concat ("{ ", data_type, "}", NULL);
+           }
+         data_type = concat ("union ", data_type, NULL);
+         break;
+
+       case ENUMERAL_TYPE:
+         if (TYPE_NAME (t))
+           data_type = IDENTIFIER_POINTER (TYPE_NAME (t));
+         else
+           {
+             data_type = "";
+             chain_p = TYPE_VALUES (t);
+             while (chain_p)
+               {
+                 data_type = concat (data_type,
+                       IDENTIFIER_POINTER (TREE_PURPOSE (chain_p)), NULL);
+                 chain_p = TREE_CHAIN (chain_p);
+                 if (chain_p)
+                   data_type = concat (data_type, ", ", NULL);
+               }
+             data_type = concat ("{ ", data_type, " }", NULL);
+           }
+         data_type = concat ("enum ", data_type, NULL);
+         break;
+
+       case TYPE_DECL:
+         data_type = IDENTIFIER_POINTER (DECL_NAME (t));
+         break;
+
+       case INTEGER_TYPE:
+       case FIXED_POINT_TYPE:
+         data_type = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (t)));
+         /* Normally, `unsigned' is part of the deal.  Not so if it comes
+            with a type qualifier.  */
+         if (TYPE_UNSIGNED (t) && TYPE_QUALS (t))
+           data_type = concat ("unsigned ", data_type, NULL);
+         break;
+
+       case REAL_TYPE:
+         data_type = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (t)));
+         break;
+
+       case VOID_TYPE:
+         data_type = "void";
+         break;
+
+       case ERROR_MARK:
+         data_type = "[ERROR]";
+         break;
+
+       default:
+         gcc_unreachable ();
+       }
+    }
+  if (TYPE_READONLY (t))
+    ret_val = concat ("const ", ret_val, NULL);
+  if (TYPE_VOLATILE (t))
+    ret_val = concat ("volatile ", ret_val, NULL);
+  if (TYPE_RESTRICT (t))
+    ret_val = concat ("restrict ", ret_val, NULL);
+  return ret_val;
+}
+
+/* Generate a string (source) representation of an entire entity declaration
+   (using some particular style for function types).
+
+   The given entity may be either a variable or a function.
+
+   If the "is_func_definition" parameter is nonzero, assume that the thing
+   we are generating a declaration for is a FUNCTION_DECL node which is
+   associated with a function definition.  In this case, we can assume that
+   an attached list of DECL nodes for function formal arguments is present.  */
+
+static const char *
+gen_decl (tree decl, int is_func_definition, formals_style style)
+{
+  const char *ret_val;
+
+  if (DECL_NAME (decl))
+    ret_val = IDENTIFIER_POINTER (DECL_NAME (decl));
+  else
+    ret_val = "";
+
+  /* If we are just generating a list of names of formal parameters, we can
+     simply return the formal parameter name (with no typing information
+     attached to it) now.  */
+
+  if (style == k_and_r_names)
+    return ret_val;
+
+  /* Note that for the declaration of some entity (either a function or a
+     data object, like for instance a parameter) if the entity itself was
+     declared as either const or volatile, then const and volatile properties
+     are associated with just the declaration of the entity, and *not* with
+     the `type' of the entity.  Thus, for such declared entities, we have to
+     generate the qualifiers here.  */
+
+  if (TREE_THIS_VOLATILE (decl))
+    ret_val = concat ("volatile ", ret_val, NULL);
+  if (TREE_READONLY (decl))
+    ret_val = concat ("const ", ret_val, NULL);
+
+  data_type = "";
+
+  /* For FUNCTION_DECL nodes, there are two possible cases here.  First, if
+     this FUNCTION_DECL node was generated from a function "definition", then
+     we will have a list of DECL_NODE's, one for each of the function's formal
+     parameters.  In this case, we can print out not only the types of each
+     formal, but also each formal's name.  In the second case, this
+     FUNCTION_DECL node came from an actual function declaration (and *not*
+     a definition).  In this case, we do nothing here because the formal
+     argument type-list will be output later, when the "type" of the function
+     is added to the string we are building.  Note that the ANSI-style formal
+     parameter list is considered to be a (suffix) part of the "type" of the
+     function.  */
+
+  if (TREE_CODE (decl) == FUNCTION_DECL && is_func_definition)
+    {
+      ret_val = concat (ret_val, gen_formal_list_for_func_def (decl, ansi),
+                       NULL);
+
+      /* Since we have already added in the formals list stuff, here we don't
+        add the whole "type" of the function we are considering (which
+        would include its parameter-list info), rather, we only add in
+        the "type" of the "type" of the function, which is really just
+        the return-type of the function (and does not include the parameter
+        list info).  */
+
+      ret_val = gen_type (ret_val, TREE_TYPE (TREE_TYPE (decl)), style);
+    }
+  else
+    ret_val = gen_type (ret_val, TREE_TYPE (decl), style);
+
+  ret_val = affix_data_type (ret_val);
+
+  if (TREE_CODE (decl) != FUNCTION_DECL && C_DECL_REGISTER (decl))
+    ret_val = concat ("register ", ret_val, NULL);
+  if (TREE_PUBLIC (decl))
+    ret_val = concat ("extern ", ret_val, NULL);
+  if (TREE_CODE (decl) == FUNCTION_DECL && !TREE_PUBLIC (decl))
+    ret_val = concat ("static ", ret_val, NULL);
+
+  return ret_val;
+}
+
+extern FILE *aux_info_file;
+
+/* Generate and write a new line of info to the aux-info (.X) file.  This
+   routine is called once for each function declaration, and once for each
+   function definition (even the implicit ones).  */
+
+void
+gen_aux_info_record (tree fndecl, int is_definition, int is_implicit,
+                    int is_prototyped)
+{
+  if (flag_gen_aux_info)
+    {
+      static int compiled_from_record = 0;
+      expanded_location xloc = expand_location (DECL_SOURCE_LOCATION (fndecl));
+
+      /* Each output .X file must have a header line.  Write one now if we
+        have not yet done so.  */
+
+      if (!compiled_from_record++)
+       {
+         /* The first line tells which directory file names are relative to.
+            Currently, -aux-info works only for files in the working
+            directory, so just use a `.' as a placeholder for now.  */
+         fprintf (aux_info_file, "/* compiled from: . */\n");
+       }
+
+      /* Write the actual line of auxiliary info.  */
+
+      fprintf (aux_info_file, "/* %s:%d:%c%c */ %s;",
+              xloc.file, xloc.line,
+              (is_implicit) ? 'I' : (is_prototyped) ? 'N' : 'O',
+              (is_definition) ? 'F' : 'C',
+              gen_decl (fndecl, is_definition, ansi));
+
+      /* If this is an explicit function declaration, we need to also write
+        out an old-style (i.e. K&R) function header, just in case the user
+        wants to run unprotoize.  */
+
+      if (is_definition)
+       {
+         fprintf (aux_info_file, " /*%s %s*/",
+                  gen_formal_list_for_func_def (fndecl, k_and_r_names),
+                  gen_formal_list_for_func_def (fndecl, k_and_r_decls));
+       }
+
+      fprintf (aux_info_file, "\n");
+    }
+}
diff --git a/gcc/c/c-convert.c b/gcc/c/c-convert.c
new file mode 100644 (file)
index 0000000..f4583c5
--- /dev/null
@@ -0,0 +1,183 @@
+/* Language-level data type conversion for GNU C.
+   Copyright (C) 1987, 1988, 1991, 1998, 2002, 2003, 2004, 2005, 2007, 2008,
+   2009, 2010 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 file contains the functions for converting C expressions
+   to different data types.  The only entry point is `convert'.
+   Every language front end must have a `convert' function
+   but what kind of conversions it does will depend on the language.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "tree.h"
+#include "flags.h"
+#include "convert.h"
+#include "c-family/c-common.h"
+#include "c-tree.h"
+#include "langhooks.h"
+#include "target.h"
+
+/* Change of width--truncation and extension of integers or reals--
+   is represented with NOP_EXPR.  Proper functioning of many things
+   assumes that no other conversions can be NOP_EXPRs.
+
+   Conversion between integer and pointer is represented with CONVERT_EXPR.
+   Converting integer to real uses FLOAT_EXPR
+   and real to integer uses FIX_TRUNC_EXPR.
+
+   Here is a list of all the functions that assume that widening and
+   narrowing is always done with a NOP_EXPR:
+     In convert.c, convert_to_integer.
+     In c-typeck.c, build_binary_op (boolean ops), and
+       c_common_truthvalue_conversion.
+     In expr.c: expand_expr, for operands of a MULT_EXPR.
+     In fold-const.c: fold.
+     In tree.c: get_narrower and get_unwidened.  */
+\f
+/* Subroutines of `convert'.  */
+
+
+\f
+/* Create an expression whose value is that of EXPR,
+   converted to type TYPE.  The TREE_TYPE of the value
+   is always TYPE.  This function implements all reasonable
+   conversions; callers should filter out those that are
+   not permitted by the language being compiled.  */
+
+tree
+convert (tree type, tree expr)
+{
+  tree e = expr;
+  enum tree_code code = TREE_CODE (type);
+  const char *invalid_conv_diag;
+  tree ret;
+  location_t loc = EXPR_LOCATION (expr);
+
+  if (type == error_mark_node
+      || expr == error_mark_node
+      || TREE_TYPE (expr) == error_mark_node)
+    return error_mark_node;
+
+  if ((invalid_conv_diag
+       = targetm.invalid_conversion (TREE_TYPE (expr), type)))
+    {
+      error (invalid_conv_diag);
+      return error_mark_node;
+    }
+
+  if (type == TREE_TYPE (expr))
+    return expr;
+  ret = targetm.convert_to_type (type, expr);
+  if (ret)
+      return ret;
+
+  STRIP_TYPE_NOPS (e);
+
+  if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (expr)))
+    return fold_convert_loc (loc, type, expr);
+  if (TREE_CODE (TREE_TYPE (expr)) == ERROR_MARK)
+    return error_mark_node;
+  if (TREE_CODE (TREE_TYPE (expr)) == VOID_TYPE)
+    {
+      error ("void value not ignored as it ought to be");
+      return error_mark_node;
+    }
+
+  switch (code)
+    {
+    case VOID_TYPE:
+      return fold_convert_loc (loc, type, e);
+
+    case INTEGER_TYPE:
+    case ENUMERAL_TYPE:
+      ret = convert_to_integer (type, e);
+      goto maybe_fold;
+
+    case BOOLEAN_TYPE:
+      return fold_convert_loc
+       (loc, type, c_objc_common_truthvalue_conversion (input_location, expr));
+
+    case POINTER_TYPE:
+    case REFERENCE_TYPE:
+      ret = convert_to_pointer (type, e);
+      goto maybe_fold;
+
+    case REAL_TYPE:
+      ret = convert_to_real (type, e);
+      goto maybe_fold;
+
+    case FIXED_POINT_TYPE:
+      ret = convert_to_fixed (type, e);
+      goto maybe_fold;
+
+    case COMPLEX_TYPE:
+      /* If converting from COMPLEX_TYPE to a different COMPLEX_TYPE
+        and e is not COMPLEX_EXPR, convert_to_complex uses save_expr,
+        but for the C FE c_save_expr needs to be called instead.  */
+      if (TREE_CODE (TREE_TYPE (e)) == COMPLEX_TYPE)
+       {
+         tree subtype = TREE_TYPE (type);
+         tree elt_type = TREE_TYPE (TREE_TYPE (e));
+
+         if (TYPE_MAIN_VARIANT (elt_type) != TYPE_MAIN_VARIANT (subtype)
+             && TREE_CODE (e) != COMPLEX_EXPR)
+           {
+             if (in_late_binary_op)
+               e = save_expr (e);
+             else
+               e = c_save_expr (e);
+             ret
+               = fold_build2 (COMPLEX_EXPR, type,
+                              convert (subtype,
+                                       fold_build1 (REALPART_EXPR,
+                                                    elt_type, e)),
+                              convert (subtype,
+                                       fold_build1 (IMAGPART_EXPR,
+                                                    elt_type, e)));
+             goto maybe_fold;
+           }
+       }
+      ret = convert_to_complex (type, e);
+      goto maybe_fold;
+
+    case VECTOR_TYPE:
+      ret = convert_to_vector (type, e);
+      goto maybe_fold;
+
+    case RECORD_TYPE:
+    case UNION_TYPE:
+      if (lang_hooks.types_compatible_p (type, TREE_TYPE (expr)))
+       return e;
+      break;
+
+    default:
+      break;
+
+    maybe_fold:
+      if (TREE_CODE (ret) != C_MAYBE_CONST_EXPR)
+       ret = fold (ret);
+      return ret;
+    }
+
+  error ("conversion to non-scalar type requested");
+  return error_mark_node;
+}
diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
new file mode 100644 (file)
index 0000000..711b2dd
--- /dev/null
@@ -0,0 +1,10155 @@
+/* Process declarations and variables for C compiler.
+   Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
+   2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
+   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/>.  */
+
+/* Process declarations and symbol lookup for C front end.
+   Also constructs types; the standard scalar types at initialization,
+   and structure, union, array and enum types when they are declared.  */
+
+/* ??? not all decl nodes are given the most useful possible
+   line numbers.  For example, the CONST_DECLs for enum values.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "input.h"
+#include "tm.h"
+#include "intl.h"
+#include "tree.h"
+#include "tree-inline.h"
+#include "flags.h"
+#include "function.h"
+#include "c-tree.h"
+#include "toplev.h"
+#include "tm_p.h"
+#include "cpplib.h"
+#include "target.h"
+#include "debug.h"
+#include "opts.h"
+#include "timevar.h"
+#include "c-family/c-common.h"
+#include "c-family/c-objc.h"
+#include "c-family/c-pragma.h"
+#include "c-lang.h"
+#include "langhooks.h"
+#include "tree-iterator.h"
+#include "diagnostic-core.h"
+#include "tree-dump.h"
+#include "cgraph.h"
+#include "hashtab.h"
+#include "langhooks-def.h"
+#include "pointer-set.h"
+#include "plugin.h"
+#include "c-family/c-ada-spec.h"
+
+/* In grokdeclarator, distinguish syntactic contexts of declarators.  */
+enum decl_context
+{ NORMAL,                      /* Ordinary declaration */
+  FUNCDEF,                     /* Function definition */
+  PARM,                                /* Declaration of parm before function body */
+  FIELD,                       /* Declaration inside struct or union */
+  TYPENAME};                   /* Typename (inside cast or sizeof)  */
+
+/* States indicating how grokdeclarator() should handle declspecs marked
+   with __attribute__((deprecated)).  An object declared as
+   __attribute__((deprecated)) suppresses warnings of uses of other
+   deprecated items.  */
+
+enum deprecated_states {
+  DEPRECATED_NORMAL,
+  DEPRECATED_SUPPRESS
+};
+
+\f
+/* Nonzero if we have seen an invalid cross reference
+   to a struct, union, or enum, but not yet printed the message.  */
+tree pending_invalid_xref;
+
+/* File and line to appear in the eventual error message.  */
+location_t pending_invalid_xref_location;
+
+/* The file and line that the prototype came from if this is an
+   old-style definition; used for diagnostics in
+   store_parm_decls_oldstyle.  */
+
+static location_t current_function_prototype_locus;
+
+/* Whether this prototype was built-in.  */
+
+static bool current_function_prototype_built_in;
+
+/* The argument type information of this prototype.  */
+
+static tree current_function_prototype_arg_types;
+
+/* The argument information structure for the function currently being
+   defined.  */
+
+static struct c_arg_info *current_function_arg_info;
+
+/* The obstack on which parser and related data structures, which are
+   not live beyond their top-level declaration or definition, are
+   allocated.  */
+struct obstack parser_obstack;
+
+/* The current statement tree.  */
+
+static GTY(()) struct stmt_tree_s c_stmt_tree;
+
+/* State saving variables.  */
+tree c_break_label;
+tree c_cont_label;
+
+/* A list of decls to be made automatically visible in each file scope.  */
+static GTY(()) tree visible_builtins;
+
+/* Set to 0 at beginning of a function definition, set to 1 if
+   a return statement that specifies a return value is seen.  */
+
+int current_function_returns_value;
+
+/* Set to 0 at beginning of a function definition, set to 1 if
+   a return statement with no argument is seen.  */
+
+int current_function_returns_null;
+
+/* Set to 0 at beginning of a function definition, set to 1 if
+   a call to a noreturn function is seen.  */
+
+int current_function_returns_abnormally;
+
+/* Set to nonzero by `grokdeclarator' for a function
+   whose return type is defaulted, if warnings for this are desired.  */
+
+static int warn_about_return_type;
+
+/* Nonzero when the current toplevel function contains a declaration
+   of a nested function which is never defined.  */
+
+static bool undef_nested_function;
+
+/* Mode used to build pointers (VOIDmode means ptr_mode).  */
+
+enum machine_mode c_default_pointer_mode = VOIDmode;
+
+\f
+/* Each c_binding structure describes one binding of an identifier to
+   a decl.  All the decls in a scope - irrespective of namespace - are
+   chained together by the ->prev field, which (as the name implies)
+   runs in reverse order.  All the decls in a given namespace bound to
+   a given identifier are chained by the ->shadowed field, which runs
+   from inner to outer scopes.
+
+   The ->decl field usually points to a DECL node, but there are two
+   exceptions.  In the namespace of type tags, the bound entity is a
+   RECORD_TYPE, UNION_TYPE, or ENUMERAL_TYPE node.  If an undeclared
+   identifier is encountered, it is bound to error_mark_node to
+   suppress further errors about that identifier in the current
+   function.
+
+   The ->u.type field stores the type of the declaration in this scope;
+   if NULL, the type is the type of the ->decl field.  This is only of
+   relevance for objects with external or internal linkage which may
+   be redeclared in inner scopes, forming composite types that only
+   persist for the duration of those scopes.  In the external scope,
+   this stores the composite of all the types declared for this
+   object, visible or not.  The ->inner_comp field (used only at file
+   scope) stores whether an incomplete array type at file scope was
+   completed at an inner scope to an array size other than 1.
+
+   The ->u.label field is used for labels.  It points to a structure
+   which stores additional information used for warnings.
+
+   The depth field is copied from the scope structure that holds this
+   decl.  It is used to preserve the proper ordering of the ->shadowed
+   field (see bind()) and also for a handful of special-case checks.
+   Finally, the invisible bit is true for a decl which should be
+   ignored for purposes of normal name lookup, and the nested bit is
+   true for a decl that's been bound a second time in an inner scope;
+   in all such cases, the binding in the outer scope will have its
+   invisible bit true.  */
+
+struct GTY((chain_next ("%h.prev"))) c_binding {
+  union GTY(()) {              /* first so GTY desc can use decl */
+    tree GTY((tag ("0"))) type; /* the type in this scope */
+    struct c_label_vars * GTY((tag ("1"))) label; /* for warnings */
+  } GTY((desc ("TREE_CODE (%0.decl) == LABEL_DECL"))) u;
+  tree decl;                   /* the decl bound */
+  tree id;                     /* the identifier it's bound to */
+  struct c_binding *prev;      /* the previous decl in this scope */
+  struct c_binding *shadowed;  /* the innermost decl shadowed by this one */
+  unsigned int depth : 28;      /* depth of this scope */
+  BOOL_BITFIELD invisible : 1;  /* normal lookup should ignore this binding */
+  BOOL_BITFIELD nested : 1;     /* do not set DECL_CONTEXT when popping */
+  BOOL_BITFIELD inner_comp : 1; /* incomplete array completed in inner scope */
+  BOOL_BITFIELD in_struct : 1; /* currently defined as struct field */
+  location_t locus;            /* location for nested bindings */
+};
+#define B_IN_SCOPE(b1, b2) ((b1)->depth == (b2)->depth)
+#define B_IN_CURRENT_SCOPE(b) ((b)->depth == current_scope->depth)
+#define B_IN_FILE_SCOPE(b) ((b)->depth == 1 /*file_scope->depth*/)
+#define B_IN_EXTERNAL_SCOPE(b) ((b)->depth == 0 /*external_scope->depth*/)
+
+#define I_SYMBOL_BINDING(node) \
+  (((struct lang_identifier *) IDENTIFIER_NODE_CHECK(node))->symbol_binding)
+#define I_SYMBOL_DECL(node) \
+ (I_SYMBOL_BINDING(node) ? I_SYMBOL_BINDING(node)->decl : 0)
+
+#define I_TAG_BINDING(node) \
+  (((struct lang_identifier *) IDENTIFIER_NODE_CHECK(node))->tag_binding)
+#define I_TAG_DECL(node) \
+ (I_TAG_BINDING(node) ? I_TAG_BINDING(node)->decl : 0)
+
+#define I_LABEL_BINDING(node) \
+  (((struct lang_identifier *) IDENTIFIER_NODE_CHECK(node))->label_binding)
+#define I_LABEL_DECL(node) \
+ (I_LABEL_BINDING(node) ? I_LABEL_BINDING(node)->decl : 0)
+
+/* Each C symbol points to three linked lists of c_binding structures.
+   These describe the values of the identifier in the three different
+   namespaces defined by the language.  */
+
+struct GTY(()) lang_identifier {
+  struct c_common_identifier common_id;
+  struct c_binding *symbol_binding; /* vars, funcs, constants, typedefs */
+  struct c_binding *tag_binding;    /* struct/union/enum tags */
+  struct c_binding *label_binding;  /* labels */
+};
+
+/* Validate c-lang.c's assumptions.  */
+extern char C_SIZEOF_STRUCT_LANG_IDENTIFIER_isnt_accurate
+[(sizeof(struct lang_identifier) == C_SIZEOF_STRUCT_LANG_IDENTIFIER) ? 1 : -1];
+
+/* The resulting tree type.  */
+
+union GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"),
+       chain_next ("(union lang_tree_node *) c_tree_chain_next (&%h.generic)"))) lang_tree_node
+ {
+  union tree_node GTY ((tag ("0"),
+                       desc ("tree_node_structure (&%h)")))
+    generic;
+  struct lang_identifier GTY ((tag ("1"))) identifier;
+};
+
+/* Track bindings and other things that matter for goto warnings.  For
+   efficiency, we do not gather all the decls at the point of
+   definition.  Instead, we point into the bindings structure.  As
+   scopes are popped, we update these structures and gather the decls
+   that matter at that time.  */
+
+struct GTY(()) c_spot_bindings {
+  /* The currently open scope which holds bindings defined when the
+     label was defined or the goto statement was found.  */
+  struct c_scope *scope;
+  /* The bindings in the scope field which were defined at the point
+     of the label or goto.  This lets us look at older or newer
+     bindings in the scope, as appropriate.  */
+  struct c_binding *bindings_in_scope;
+  /* The number of statement expressions that have started since this
+     label or goto statement was defined.  This is zero if we are at
+     the same statement expression level.  It is positive if we are in
+     a statement expression started since this spot.  It is negative
+     if this spot was in a statement expression and we have left
+     it.  */
+  int stmt_exprs;
+  /* Whether we started in a statement expression but are no longer in
+     it.  This is set to true if stmt_exprs ever goes negative.  */
+  bool left_stmt_expr;
+};
+
+/* This structure is used to keep track of bindings seen when a goto
+   statement is defined.  This is only used if we see the goto
+   statement before we see the label.  */
+
+struct GTY(()) c_goto_bindings {
+  /* The location of the goto statement.  */
+  location_t loc;
+  /* The bindings of the goto statement.  */
+  struct c_spot_bindings goto_bindings;
+};
+
+typedef struct c_goto_bindings *c_goto_bindings_p;
+DEF_VEC_P(c_goto_bindings_p);
+DEF_VEC_ALLOC_P(c_goto_bindings_p,gc);
+
+/* The additional information we keep track of for a label binding.
+   These fields are updated as scopes are popped.  */
+
+struct GTY(()) c_label_vars {
+  /* The shadowed c_label_vars, when one label shadows another (which
+     can only happen using a __label__ declaration).  */
+  struct c_label_vars *shadowed;
+  /* The bindings when the label was defined.  */
+  struct c_spot_bindings label_bindings;
+  /* A list of decls that we care about: decls about which we should
+     warn if a goto branches to this label from later in the function.
+     Decls are added to this list as scopes are popped.  We only add
+     the decls that matter.  */
+  VEC(tree,gc) *decls_in_scope;
+  /* A list of goto statements to this label.  This is only used for
+     goto statements seen before the label was defined, so that we can
+     issue appropriate warnings for them.  */
+  VEC(c_goto_bindings_p,gc) *gotos;
+};
+
+/* Each c_scope structure describes the complete contents of one
+   scope.  Four scopes are distinguished specially: the innermost or
+   current scope, the innermost function scope, the file scope (always
+   the second to outermost) and the outermost or external scope.
+
+   Most declarations are recorded in the current scope.
+
+   All normal label declarations are recorded in the innermost
+   function scope, as are bindings of undeclared identifiers to
+   error_mark_node.  (GCC permits nested functions as an extension,
+   hence the 'innermost' qualifier.)  Explicitly declared labels
+   (using the __label__ extension) appear in the current scope.
+
+   Being in the file scope (current_scope == file_scope) causes
+   special behavior in several places below.  Also, under some
+   conditions the Objective-C front end records declarations in the
+   file scope even though that isn't the current scope.
+
+   All declarations with external linkage are recorded in the external
+   scope, even if they aren't visible there; this models the fact that
+   such declarations are visible to the entire program, and (with a
+   bit of cleverness, see pushdecl) allows diagnosis of some violations
+   of C99 6.2.2p7 and 6.2.7p2:
+
+     If, within the same translation unit, the same identifier appears
+     with both internal and external linkage, the behavior is
+     undefined.
+
+     All declarations that refer to the same object or function shall
+     have compatible type; otherwise, the behavior is undefined.
+
+   Initially only the built-in declarations, which describe compiler
+   intrinsic functions plus a subset of the standard library, are in
+   this scope.
+
+   The order of the blocks list matters, and it is frequently appended
+   to.  To avoid having to walk all the way to the end of the list on
+   each insertion, or reverse the list later, we maintain a pointer to
+   the last list entry.  (FIXME: It should be feasible to use a reversed
+   list here.)
+
+   The bindings list is strictly in reverse order of declarations;
+   pop_scope relies on this.  */
+
+
+struct GTY((chain_next ("%h.outer"))) c_scope {
+  /* The scope containing this one.  */
+  struct c_scope *outer;
+
+  /* The next outermost function scope.  */
+  struct c_scope *outer_function;
+
+  /* All bindings in this scope.  */
+  struct c_binding *bindings;
+
+  /* For each scope (except the global one), a chain of BLOCK nodes
+     for all the scopes that were entered and exited one level down.  */
+  tree blocks;
+  tree blocks_last;
+
+  /* The depth of this scope.  Used to keep the ->shadowed chain of
+     bindings sorted innermost to outermost.  */
+  unsigned int depth : 28;
+
+  /* True if we are currently filling this scope with parameter
+     declarations.  */
+  BOOL_BITFIELD parm_flag : 1;
+
+  /* True if we saw [*] in this scope.  Used to give an error messages
+     if these appears in a function definition.  */
+  BOOL_BITFIELD had_vla_unspec : 1;
+
+  /* True if we already complained about forward parameter decls
+     in this scope.  This prevents double warnings on
+     foo (int a; int b; ...)  */
+  BOOL_BITFIELD warned_forward_parm_decls : 1;
+
+  /* True if this is the outermost block scope of a function body.
+     This scope contains the parameters, the local variables declared
+     in the outermost block, and all the labels (except those in
+     nested functions, or declared at block scope with __label__).  */
+  BOOL_BITFIELD function_body : 1;
+
+  /* True means make a BLOCK for this scope no matter what.  */
+  BOOL_BITFIELD keep : 1;
+
+  /* True means that an unsuffixed float constant is _Decimal64.  */
+  BOOL_BITFIELD float_const_decimal64 : 1;
+
+  /* True if this scope has any label bindings.  This is used to speed
+     up searching for labels when popping scopes, particularly since
+     labels are normally only found at function scope.  */
+  BOOL_BITFIELD has_label_bindings : 1;
+
+  /* True if we should issue a warning if a goto statement crosses any
+     of the bindings.  We still need to check the list of bindings to
+     find the specific ones we need to warn about.  This is true if
+     decl_jump_unsafe would return true for any of the bindings.  This
+     is used to avoid looping over all the bindings unnecessarily.  */
+  BOOL_BITFIELD has_jump_unsafe_decl : 1;
+};
+
+/* The scope currently in effect.  */
+
+static GTY(()) struct c_scope *current_scope;
+
+/* The innermost function scope.  Ordinary (not explicitly declared)
+   labels, bindings to error_mark_node, and the lazily-created
+   bindings of __func__ and its friends get this scope.  */
+
+static GTY(()) struct c_scope *current_function_scope;
+
+/* The C file scope.  This is reset for each input translation unit.  */
+
+static GTY(()) struct c_scope *file_scope;
+
+/* The outermost scope.  This is used for all declarations with
+   external linkage, and only these, hence the name.  */
+
+static GTY(()) struct c_scope *external_scope;
+
+/* A chain of c_scope structures awaiting reuse.  */
+
+static GTY((deletable)) struct c_scope *scope_freelist;
+
+/* A chain of c_binding structures awaiting reuse.  */
+
+static GTY((deletable)) struct c_binding *binding_freelist;
+
+/* Append VAR to LIST in scope SCOPE.  */
+#define SCOPE_LIST_APPEND(scope, list, decl) do {      \
+  struct c_scope *s_ = (scope);                                \
+  tree d_ = (decl);                                    \
+  if (s_->list##_last)                                 \
+    BLOCK_CHAIN (s_->list##_last) = d_;                        \
+  else                                                 \
+    s_->list = d_;                                     \
+  s_->list##_last = d_;                                        \
+} while (0)
+
+/* Concatenate FROM in scope FSCOPE onto TO in scope TSCOPE.  */
+#define SCOPE_LIST_CONCAT(tscope, to, fscope, from) do {       \
+  struct c_scope *t_ = (tscope);                               \
+  struct c_scope *f_ = (fscope);                               \
+  if (t_->to##_last)                                           \
+    BLOCK_CHAIN (t_->to##_last) = f_->from;                    \
+  else                                                         \
+    t_->to = f_->from;                                         \
+  t_->to##_last = f_->from##_last;                             \
+} while (0)
+
+/* A c_inline_static structure stores details of a static identifier
+   referenced in a definition of a function that may be an inline
+   definition if no subsequent declaration of that function uses
+   "extern" or does not use "inline".  */
+
+struct GTY((chain_next ("%h.next"))) c_inline_static {
+  /* The location for a diagnostic.  */
+  location_t location;
+
+  /* The function that may be an inline definition.  */
+  tree function;
+
+  /* The object or function referenced.  */
+  tree static_decl;
+
+  /* What sort of reference this is.  */
+  enum c_inline_static_type type;
+
+  /* The next such structure or NULL.  */
+  struct c_inline_static *next;
+};
+
+/* List of static identifiers used or referenced in functions that may
+   be inline definitions.  */
+static GTY(()) struct c_inline_static *c_inline_statics;
+
+/* True means unconditionally make a BLOCK for the next scope pushed.  */
+
+static bool keep_next_level_flag;
+
+/* True means the next call to push_scope will be the outermost scope
+   of a function body, so do not push a new scope, merely cease
+   expecting parameter decls.  */
+
+static bool next_is_function_body;
+
+/* A VEC of pointers to c_binding structures.  */
+
+typedef struct c_binding *c_binding_ptr;
+DEF_VEC_P(c_binding_ptr);
+DEF_VEC_ALLOC_P(c_binding_ptr,heap);
+
+/* Information that we keep for a struct or union while it is being
+   parsed.  */
+
+struct c_struct_parse_info
+{
+  /* If warn_cxx_compat, a list of types defined within this
+     struct.  */
+  VEC(tree,heap) *struct_types;
+  /* If warn_cxx_compat, a list of field names which have bindings,
+     and which are defined in this struct, but which are not defined
+     in any enclosing struct.  This is used to clear the in_struct
+     field of the c_bindings structure.  */
+  VEC(c_binding_ptr,heap) *fields;
+  /* If warn_cxx_compat, a list of typedef names used when defining
+     fields in this struct.  */
+  VEC(tree,heap) *typedefs_seen;
+};
+
+/* Information for the struct or union currently being parsed, or
+   NULL if not parsing a struct or union.  */
+static struct c_struct_parse_info *struct_parse_info;
+
+/* Forward declarations.  */
+static tree lookup_name_in_scope (tree, struct c_scope *);
+static tree c_make_fname_decl (location_t, tree, int);
+static tree grokdeclarator (const struct c_declarator *,
+                           struct c_declspecs *,
+                           enum decl_context, bool, tree *, tree *, tree *,
+                           bool *, enum deprecated_states);
+static tree grokparms (struct c_arg_info *, bool);
+static void layout_array_type (tree);
+\f
+/* T is a statement.  Add it to the statement-tree.  This is the
+   C/ObjC version--C++ has a slightly different version of this
+   function.  */
+
+tree
+add_stmt (tree t)
+{
+  enum tree_code code = TREE_CODE (t);
+
+  if (CAN_HAVE_LOCATION_P (t) && code != LABEL_EXPR)
+    {
+      if (!EXPR_HAS_LOCATION (t))
+       SET_EXPR_LOCATION (t, input_location);
+    }
+
+  if (code == LABEL_EXPR || code == CASE_LABEL_EXPR)
+    STATEMENT_LIST_HAS_LABEL (cur_stmt_list) = 1;
+
+  /* Add T to the statement-tree.  Non-side-effect statements need to be
+     recorded during statement expressions.  */
+  if (!building_stmt_list_p ())
+    push_stmt_list ();
+  append_to_statement_list_force (t, &cur_stmt_list);
+
+  return t;
+}
+\f
+/* Build a pointer type using the default pointer mode.  */
+
+static tree
+c_build_pointer_type (tree to_type)
+{
+  addr_space_t as = to_type == error_mark_node? ADDR_SPACE_GENERIC
+                                             : TYPE_ADDR_SPACE (to_type);
+  enum machine_mode pointer_mode;
+
+  if (as != ADDR_SPACE_GENERIC || c_default_pointer_mode == VOIDmode)
+    pointer_mode = targetm.addr_space.pointer_mode (as);
+  else
+    pointer_mode = c_default_pointer_mode;
+  return build_pointer_type_for_mode (to_type, pointer_mode, false);
+}
+
+\f
+/* Return true if we will want to say something if a goto statement
+   crosses DECL.  */
+
+static bool
+decl_jump_unsafe (tree decl)
+{
+  if (error_operand_p (decl))
+    return false;
+
+  /* Always warn about crossing variably modified types.  */
+  if ((TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == TYPE_DECL)
+      && variably_modified_type_p (TREE_TYPE (decl), NULL_TREE))
+    return true;
+
+  /* Otherwise, only warn if -Wgoto-misses-init and this is an
+     initialized automatic decl.  */
+  if (warn_jump_misses_init
+      && TREE_CODE (decl) == VAR_DECL
+      && !TREE_STATIC (decl)
+      && DECL_INITIAL (decl) != NULL_TREE)
+    return true;
+
+  return false;
+}
+\f
+
+void
+c_print_identifier (FILE *file, tree node, int indent)
+{
+  print_node (file, "symbol", I_SYMBOL_DECL (node), indent + 4);
+  print_node (file, "tag", I_TAG_DECL (node), indent + 4);
+  print_node (file, "label", I_LABEL_DECL (node), indent + 4);
+  if (C_IS_RESERVED_WORD (node) && C_RID_CODE (node) != RID_CXX_COMPAT_WARN)
+    {
+      tree rid = ridpointers[C_RID_CODE (node)];
+      indent_to (file, indent + 4);
+      fprintf (file, "rid " HOST_PTR_PRINTF " \"%s\"",
+              (void *) rid, IDENTIFIER_POINTER (rid));
+    }
+}
+
+/* Establish a binding between NAME, an IDENTIFIER_NODE, and DECL,
+   which may be any of several kinds of DECL or TYPE or error_mark_node,
+   in the scope SCOPE.  */
+static void
+bind (tree name, tree decl, struct c_scope *scope, bool invisible,
+      bool nested, location_t locus)
+{
+  struct c_binding *b, **here;
+
+  if (binding_freelist)
+    {
+      b = binding_freelist;
+      binding_freelist = b->prev;
+    }
+  else
+    b = ggc_alloc_c_binding ();
+
+  b->shadowed = 0;
+  b->decl = decl;
+  b->id = name;
+  b->depth = scope->depth;
+  b->invisible = invisible;
+  b->nested = nested;
+  b->inner_comp = 0;
+  b->in_struct = 0;
+  b->locus = locus;
+
+  b->u.type = NULL;
+
+  b->prev = scope->bindings;
+  scope->bindings = b;
+
+  if (decl_jump_unsafe (decl))
+    scope->has_jump_unsafe_decl = 1;
+
+  if (!name)
+    return;
+
+  switch (TREE_CODE (decl))
+    {
+    case LABEL_DECL:     here = &I_LABEL_BINDING (name);   break;
+    case ENUMERAL_TYPE:
+    case UNION_TYPE:
+    case RECORD_TYPE:    here = &I_TAG_BINDING (name);     break;
+    case VAR_DECL:
+    case FUNCTION_DECL:
+    case TYPE_DECL:
+    case CONST_DECL:
+    case PARM_DECL:
+    case ERROR_MARK:     here = &I_SYMBOL_BINDING (name);  break;
+
+    default:
+      gcc_unreachable ();
+    }
+
+  /* Locate the appropriate place in the chain of shadowed decls
+     to insert this binding.  Normally, scope == current_scope and
+     this does nothing.  */
+  while (*here && (*here)->depth > scope->depth)
+    here = &(*here)->shadowed;
+
+  b->shadowed = *here;
+  *here = b;
+}
+
+/* Clear the binding structure B, stick it on the binding_freelist,
+   and return the former value of b->prev.  This is used by pop_scope
+   and get_parm_info to iterate destructively over all the bindings
+   from a given scope.  */
+static struct c_binding *
+free_binding_and_advance (struct c_binding *b)
+{
+  struct c_binding *prev = b->prev;
+
+  memset (b, 0, sizeof (struct c_binding));
+  b->prev = binding_freelist;
+  binding_freelist = b;
+
+  return prev;
+}
+
+/* Bind a label.  Like bind, but skip fields which aren't used for
+   labels, and add the LABEL_VARS value.  */
+static void
+bind_label (tree name, tree label, struct c_scope *scope,
+           struct c_label_vars *label_vars)
+{
+  struct c_binding *b;
+
+  bind (name, label, scope, /*invisible=*/false, /*nested=*/false,
+       UNKNOWN_LOCATION);
+
+  scope->has_label_bindings = true;
+
+  b = scope->bindings;
+  gcc_assert (b->decl == label);
+  label_vars->shadowed = b->u.label;
+  b->u.label = label_vars;
+}
+\f
+/* Hook called at end of compilation to assume 1 elt
+   for a file-scope tentative array defn that wasn't complete before.  */
+
+void
+c_finish_incomplete_decl (tree decl)
+{
+  if (TREE_CODE (decl) == VAR_DECL)
+    {
+      tree type = TREE_TYPE (decl);
+      if (type != error_mark_node
+         && TREE_CODE (type) == ARRAY_TYPE
+         && !DECL_EXTERNAL (decl)
+         && TYPE_DOMAIN (type) == 0)
+       {
+         warning_at (DECL_SOURCE_LOCATION (decl),
+                     0, "array %q+D assumed to have one element", decl);
+
+         complete_array_type (&TREE_TYPE (decl), NULL_TREE, true);
+
+         relayout_decl (decl);
+       }
+    }
+}
+\f
+/* Record that inline function FUNC contains a reference (location
+   LOC) to static DECL (file-scope or function-local according to
+   TYPE).  */
+
+void
+record_inline_static (location_t loc, tree func, tree decl,
+                     enum c_inline_static_type type)
+{
+  struct c_inline_static *csi = ggc_alloc_c_inline_static ();
+  csi->location = loc;
+  csi->function = func;
+  csi->static_decl = decl;
+  csi->type = type;
+  csi->next = c_inline_statics;
+  c_inline_statics = csi;
+}
+
+/* Check for references to static declarations in inline functions at
+   the end of the translation unit and diagnose them if the functions
+   are still inline definitions.  */
+
+static void
+check_inline_statics (void)
+{
+  struct c_inline_static *csi;
+  for (csi = c_inline_statics; csi; csi = csi->next)
+    {
+      if (DECL_EXTERNAL (csi->function))
+       switch (csi->type)
+         {
+         case csi_internal:
+           pedwarn (csi->location, 0,
+                    "%qD is static but used in inline function %qD "
+                    "which is not static", csi->static_decl, csi->function);
+           break;
+         case csi_modifiable:
+           pedwarn (csi->location, 0,
+                    "%q+D is static but declared in inline function %qD "
+                    "which is not static", csi->static_decl, csi->function);
+           break;
+         default:
+           gcc_unreachable ();
+         }
+    }
+  c_inline_statics = NULL;
+}
+\f
+/* Fill in a c_spot_bindings structure.  If DEFINING is true, set it
+   for the current state, otherwise set it to uninitialized.  */
+
+static void
+set_spot_bindings (struct c_spot_bindings *p, bool defining)
+{
+  if (defining)
+    {
+      p->scope = current_scope;
+      p->bindings_in_scope = current_scope->bindings;
+    }
+  else
+    {
+      p->scope = NULL;
+      p->bindings_in_scope = NULL;
+    }
+  p->stmt_exprs = 0;
+  p->left_stmt_expr = false;
+}
+
+/* Update spot bindings P as we pop out of SCOPE.  Return true if we
+   should push decls for a label.  */
+
+static bool
+update_spot_bindings (struct c_scope *scope, struct c_spot_bindings *p)
+{
+  if (p->scope != scope)
+    {
+      /* This label or goto is defined in some other scope, or it is a
+        label which is not yet defined.  There is nothing to
+        update.  */
+      return false;
+    }
+
+  /* Adjust the spot bindings to refer to the bindings already defined
+     in the enclosing scope.  */
+  p->scope = scope->outer;
+  p->bindings_in_scope = p->scope->bindings;
+
+  return true;
+}
+\f
+/* The Objective-C front-end often needs to determine the current scope.  */
+
+void *
+objc_get_current_scope (void)
+{
+  return current_scope;
+}
+
+/* The following function is used only by Objective-C.  It needs to live here
+   because it accesses the innards of c_scope.  */
+
+void
+objc_mark_locals_volatile (void *enclosing_blk)
+{
+  struct c_scope *scope;
+  struct c_binding *b;
+
+  for (scope = current_scope;
+       scope && scope != enclosing_blk;
+       scope = scope->outer)
+    {
+      for (b = scope->bindings; b; b = b->prev)
+       objc_volatilize_decl (b->decl);
+
+      /* Do not climb up past the current function.  */
+      if (scope->function_body)
+       break;
+    }
+}
+
+/* Return true if we are in the global binding level.  */
+
+bool
+global_bindings_p (void)
+{
+  return current_scope == file_scope;
+}
+
+void
+keep_next_level (void)
+{
+  keep_next_level_flag = true;
+}
+
+/* Set the flag for the FLOAT_CONST_DECIMAL64 pragma being ON.  */
+
+void
+set_float_const_decimal64 (void)
+{
+  current_scope->float_const_decimal64 = true;
+}
+
+/* Clear the flag for the FLOAT_CONST_DECIMAL64 pragma.  */
+
+void
+clear_float_const_decimal64 (void)
+{
+  current_scope->float_const_decimal64 = false;
+}
+
+/* Return nonzero if an unsuffixed float constant is _Decimal64.  */
+
+bool
+float_const_decimal64_p (void)
+{
+  return current_scope->float_const_decimal64;
+}
+
+/* Identify this scope as currently being filled with parameters.  */
+
+void
+declare_parm_level (void)
+{
+  current_scope->parm_flag = true;
+}
+
+void
+push_scope (void)
+{
+  if (next_is_function_body)
+    {
+      /* This is the transition from the parameters to the top level
+        of the function body.  These are the same scope
+        (C99 6.2.1p4,6) so we do not push another scope structure.
+        next_is_function_body is set only by store_parm_decls, which
+        in turn is called when and only when we are about to
+        encounter the opening curly brace for the function body.
+
+        The outermost block of a function always gets a BLOCK node,
+        because the debugging output routines expect that each
+        function has at least one BLOCK.  */
+      current_scope->parm_flag         = false;
+      current_scope->function_body     = true;
+      current_scope->keep              = true;
+      current_scope->outer_function    = current_function_scope;
+      current_function_scope           = current_scope;
+
+      keep_next_level_flag = false;
+      next_is_function_body = false;
+
+      /* The FLOAT_CONST_DECIMAL64 pragma applies to nested scopes.  */
+      if (current_scope->outer)
+       current_scope->float_const_decimal64
+         = current_scope->outer->float_const_decimal64;
+      else
+       current_scope->float_const_decimal64 = false;
+    }
+  else
+    {
+      struct c_scope *scope;
+      if (scope_freelist)
+       {
+         scope = scope_freelist;
+         scope_freelist = scope->outer;
+       }
+      else
+       scope = ggc_alloc_cleared_c_scope ();
+
+      /* The FLOAT_CONST_DECIMAL64 pragma applies to nested scopes.  */
+      if (current_scope)
+       scope->float_const_decimal64 = current_scope->float_const_decimal64;
+      else
+       scope->float_const_decimal64 = false;
+
+      scope->keep          = keep_next_level_flag;
+      scope->outer         = current_scope;
+      scope->depth        = current_scope ? (current_scope->depth + 1) : 0;
+
+      /* Check for scope depth overflow.  Unlikely (2^28 == 268,435,456) but
+        possible.  */
+      if (current_scope && scope->depth == 0)
+       {
+         scope->depth--;
+         sorry ("GCC supports only %u nested scopes", scope->depth);
+       }
+
+      current_scope        = scope;
+      keep_next_level_flag = false;
+    }
+}
+
+/* This is called when we are leaving SCOPE.  For each label defined
+   in SCOPE, add any appropriate decls to its decls_in_scope fields.
+   These are the decls whose initialization will be skipped by a goto
+   later in the function.  */
+
+static void
+update_label_decls (struct c_scope *scope)
+{
+  struct c_scope *s;
+
+  s = scope;
+  while (s != NULL)
+    {
+      if (s->has_label_bindings)
+       {
+         struct c_binding *b;
+
+         for (b = s->bindings; b != NULL; b = b->prev)
+           {
+             struct c_label_vars *label_vars;
+             struct c_binding *b1;
+             bool hjud;
+             unsigned int ix;
+             struct c_goto_bindings *g;
+
+             if (TREE_CODE (b->decl) != LABEL_DECL)
+               continue;
+             label_vars = b->u.label;
+
+             b1 = label_vars->label_bindings.bindings_in_scope;
+             if (label_vars->label_bindings.scope == NULL)
+               hjud = false;
+             else
+               hjud = label_vars->label_bindings.scope->has_jump_unsafe_decl;
+             if (update_spot_bindings (scope, &label_vars->label_bindings))
+               {
+                 /* This label is defined in this scope.  */
+                 if (hjud)
+                   {
+                     for (; b1 != NULL; b1 = b1->prev)
+                       {
+                         /* A goto from later in the function to this
+                            label will never see the initialization
+                            of B1, if any.  Save it to issue a
+                            warning if needed.  */
+                         if (decl_jump_unsafe (b1->decl))
+                           VEC_safe_push (tree, gc,
+                                          label_vars->decls_in_scope,
+                                          b1->decl);
+                       }
+                   }
+               }
+
+             /* Update the bindings of any goto statements associated
+                with this label.  */
+             FOR_EACH_VEC_ELT (c_goto_bindings_p, label_vars->gotos, ix, g)
+               update_spot_bindings (scope, &g->goto_bindings);
+           }
+       }
+
+      /* Don't search beyond the current function.  */
+      if (s == current_function_scope)
+       break;
+
+      s = s->outer;
+    }
+}
+
+/* Set the TYPE_CONTEXT of all of TYPE's variants to CONTEXT.  */
+
+static void
+set_type_context (tree type, tree context)
+{
+  for (type = TYPE_MAIN_VARIANT (type); type;
+       type = TYPE_NEXT_VARIANT (type))
+    TYPE_CONTEXT (type) = context;
+}
+
+/* Exit a scope.  Restore the state of the identifier-decl mappings
+   that were in effect when this scope was entered.  Return a BLOCK
+   node containing all the DECLs in this scope that are of interest
+   to debug info generation.  */
+
+tree
+pop_scope (void)
+{
+  struct c_scope *scope = current_scope;
+  tree block, context, p;
+  struct c_binding *b;
+
+  bool functionbody = scope->function_body;
+  bool keep = functionbody || scope->keep || scope->bindings;
+
+  update_label_decls (scope);
+
+  /* If appropriate, create a BLOCK to record the decls for the life
+     of this function.  */
+  block = 0;
+  if (keep)
+    {
+      block = make_node (BLOCK);
+      BLOCK_SUBBLOCKS (block) = scope->blocks;
+      TREE_USED (block) = 1;
+
+      /* In each subblock, record that this is its superior.  */
+      for (p = scope->blocks; p; p = BLOCK_CHAIN (p))
+       BLOCK_SUPERCONTEXT (p) = block;
+
+      BLOCK_VARS (block) = 0;
+    }
+
+  /* The TYPE_CONTEXTs for all of the tagged types belonging to this
+     scope must be set so that they point to the appropriate
+     construct, i.e.  either to the current FUNCTION_DECL node, or
+     else to the BLOCK node we just constructed.
+
+     Note that for tagged types whose scope is just the formal
+     parameter list for some function type specification, we can't
+     properly set their TYPE_CONTEXTs here, because we don't have a
+     pointer to the appropriate FUNCTION_TYPE node readily available
+     to us.  For those cases, the TYPE_CONTEXTs of the relevant tagged
+     type nodes get set in `grokdeclarator' as soon as we have created
+     the FUNCTION_TYPE node which will represent the "scope" for these
+     "parameter list local" tagged types.  */
+  if (scope->function_body)
+    context = current_function_decl;
+  else if (scope == file_scope)
+    {
+      tree file_decl = build_translation_unit_decl (NULL_TREE);
+      context = file_decl;
+    }
+  else
+    context = block;
+
+  /* Clear all bindings in this scope.  */
+  for (b = scope->bindings; b; b = free_binding_and_advance (b))
+    {
+      p = b->decl;
+      switch (TREE_CODE (p))
+       {
+       case LABEL_DECL:
+         /* Warnings for unused labels, errors for undefined labels.  */
+         if (TREE_USED (p) && !DECL_INITIAL (p))
+           {
+             error ("label %q+D used but not defined", p);
+             DECL_INITIAL (p) = error_mark_node;
+           }
+         else
+           warn_for_unused_label (p);
+
+         /* Labels go in BLOCK_VARS.  */
+         DECL_CHAIN (p) = BLOCK_VARS (block);
+         BLOCK_VARS (block) = p;
+         gcc_assert (I_LABEL_BINDING (b->id) == b);
+         I_LABEL_BINDING (b->id) = b->shadowed;
+
+         /* Also pop back to the shadowed label_vars.  */
+         release_tree_vector (b->u.label->decls_in_scope);
+         b->u.label = b->u.label->shadowed;
+         break;
+
+       case ENUMERAL_TYPE:
+       case UNION_TYPE:
+       case RECORD_TYPE:
+         set_type_context (p, context);
+
+         /* Types may not have tag-names, in which case the type
+            appears in the bindings list with b->id NULL.  */
+         if (b->id)
+           {
+             gcc_assert (I_TAG_BINDING (b->id) == b);
+             I_TAG_BINDING (b->id) = b->shadowed;
+           }
+         break;
+
+       case FUNCTION_DECL:
+         /* Propagate TREE_ADDRESSABLE from nested functions to their
+            containing functions.  */
+         if (!TREE_ASM_WRITTEN (p)
+             && DECL_INITIAL (p) != 0
+             && TREE_ADDRESSABLE (p)
+             && DECL_ABSTRACT_ORIGIN (p) != 0
+             && DECL_ABSTRACT_ORIGIN (p) != p)
+           TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (p)) = 1;
+         if (!DECL_EXTERNAL (p)
+             && !DECL_INITIAL (p)
+             && scope != file_scope
+             && scope != external_scope)
+           {
+             error ("nested function %q+D declared but never defined", p);
+             undef_nested_function = true;
+           }
+         else if (DECL_DECLARED_INLINE_P (p)
+                  && TREE_PUBLIC (p)
+                  && !DECL_INITIAL (p))
+           {
+             /* C99 6.7.4p6: "a function with external linkage... declared
+                with an inline function specifier ... shall also be defined
+                in the same translation unit."  */
+             if (!flag_gnu89_inline)
+               pedwarn (input_location, 0,
+                        "inline function %q+D declared but never defined", p);
+             DECL_EXTERNAL (p) = 1;
+           }
+
+         goto common_symbol;
+
+       case VAR_DECL:
+         /* Warnings for unused variables.  */
+         if ((!TREE_USED (p) || !DECL_READ_P (p))
+             && !TREE_NO_WARNING (p)
+             && !DECL_IN_SYSTEM_HEADER (p)
+             && DECL_NAME (p)
+             && !DECL_ARTIFICIAL (p)
+             && scope != file_scope
+             && scope != external_scope)
+           {
+             if (!TREE_USED (p))
+               warning (OPT_Wunused_variable, "unused variable %q+D", p);
+             else if (DECL_CONTEXT (p) == current_function_decl)
+               warning_at (DECL_SOURCE_LOCATION (p),
+                           OPT_Wunused_but_set_variable,
+                           "variable %qD set but not used", p);
+           }
+
+         if (b->inner_comp)
+           {
+             error ("type of array %q+D completed incompatibly with"
+                    " implicit initialization", p);
+           }
+
+         /* Fall through.  */
+       case TYPE_DECL:
+       case CONST_DECL:
+       common_symbol:
+         /* All of these go in BLOCK_VARS, but only if this is the
+            binding in the home scope.  */
+         if (!b->nested)
+           {
+             DECL_CHAIN (p) = BLOCK_VARS (block);
+             BLOCK_VARS (block) = p;
+           }
+         else if (VAR_OR_FUNCTION_DECL_P (p) && scope != file_scope)
+           {
+             /* For block local externs add a special
+                DECL_EXTERNAL decl for debug info generation.  */
+             tree extp = copy_node (p);
+
+             DECL_EXTERNAL (extp) = 1;
+             TREE_STATIC (extp) = 0;
+             TREE_PUBLIC (extp) = 1;
+             DECL_INITIAL (extp) = NULL_TREE;
+             DECL_LANG_SPECIFIC (extp) = NULL;
+             DECL_CONTEXT (extp) = current_function_decl;
+             if (TREE_CODE (p) == FUNCTION_DECL)
+               {
+                 DECL_RESULT (extp) = NULL_TREE;
+                 DECL_SAVED_TREE (extp) = NULL_TREE;
+                 DECL_STRUCT_FUNCTION (extp) = NULL;
+               }
+             if (b->locus != UNKNOWN_LOCATION)
+               DECL_SOURCE_LOCATION (extp) = b->locus;
+             DECL_CHAIN (extp) = BLOCK_VARS (block);
+             BLOCK_VARS (block) = extp;
+           }
+         /* If this is the file scope set DECL_CONTEXT of each decl to
+            the TRANSLATION_UNIT_DECL.  This makes same_translation_unit_p
+            work.  */
+         if (scope == file_scope)
+           {
+             DECL_CONTEXT (p) = context;
+             if (TREE_CODE (p) == TYPE_DECL
+                 && TREE_TYPE (p) != error_mark_node)
+               set_type_context (TREE_TYPE (p), context);
+           }
+
+         /* Fall through.  */
+         /* Parameters go in DECL_ARGUMENTS, not BLOCK_VARS, and have
+            already been put there by store_parm_decls.  Unused-
+            parameter warnings are handled by function.c.
+            error_mark_node obviously does not go in BLOCK_VARS and
+            does not get unused-variable warnings.  */
+       case PARM_DECL:
+       case ERROR_MARK:
+         /* It is possible for a decl not to have a name.  We get
+            here with b->id NULL in this case.  */
+         if (b->id)
+           {
+             gcc_assert (I_SYMBOL_BINDING (b->id) == b);
+             I_SYMBOL_BINDING (b->id) = b->shadowed;
+             if (b->shadowed && b->shadowed->u.type)
+               TREE_TYPE (b->shadowed->decl) = b->shadowed->u.type;
+           }
+         break;
+
+       default:
+         gcc_unreachable ();
+       }
+    }
+
+
+  /* Dispose of the block that we just made inside some higher level.  */
+  if ((scope->function_body || scope == file_scope) && context)
+    {
+      DECL_INITIAL (context) = block;
+      BLOCK_SUPERCONTEXT (block) = context;
+    }
+  else if (scope->outer)
+    {
+      if (block)
+       SCOPE_LIST_APPEND (scope->outer, blocks, block);
+      /* If we did not make a block for the scope just exited, any
+        blocks made for inner scopes must be carried forward so they
+        will later become subblocks of something else.  */
+      else if (scope->blocks)
+       SCOPE_LIST_CONCAT (scope->outer, blocks, scope, blocks);
+    }
+
+  /* Pop the current scope, and free the structure for reuse.  */
+  current_scope = scope->outer;
+  if (scope->function_body)
+    current_function_scope = scope->outer_function;
+
+  memset (scope, 0, sizeof (struct c_scope));
+  scope->outer = scope_freelist;
+  scope_freelist = scope;
+
+  return block;
+}
+
+void
+push_file_scope (void)
+{
+  tree decl;
+
+  if (file_scope)
+    return;
+
+  push_scope ();
+  file_scope = current_scope;
+
+  start_fname_decls ();
+
+  for (decl = visible_builtins; decl; decl = DECL_CHAIN (decl))
+    bind (DECL_NAME (decl), decl, file_scope,
+         /*invisible=*/false, /*nested=*/true, DECL_SOURCE_LOCATION (decl));
+}
+
+void
+pop_file_scope (void)
+{
+  /* In case there were missing closebraces, get us back to the global
+     binding level.  */
+  while (current_scope != file_scope)
+    pop_scope ();
+
+  /* __FUNCTION__ is defined at file scope ("").  This
+     call may not be necessary as my tests indicate it
+     still works without it.  */
+  finish_fname_decls ();
+
+  check_inline_statics ();
+
+  /* This is the point to write out a PCH if we're doing that.
+     In that case we do not want to do anything else.  */
+  if (pch_file)
+    {
+      c_common_write_pch ();
+      return;
+    }
+
+  /* Pop off the file scope and close this translation unit.  */
+  pop_scope ();
+  file_scope = 0;
+
+  maybe_apply_pending_pragma_weaks ();
+}
+\f
+/* Adjust the bindings for the start of a statement expression.  */
+
+void
+c_bindings_start_stmt_expr (struct c_spot_bindings* switch_bindings)
+{
+  struct c_scope *scope;
+
+  for (scope = current_scope; scope != NULL; scope = scope->outer)
+    {
+      struct c_binding *b;
+
+      if (!scope->has_label_bindings)
+       continue;
+
+      for (b = scope->bindings; b != NULL; b = b->prev)
+       {
+         struct c_label_vars *label_vars;
+         unsigned int ix;
+         struct c_goto_bindings *g;
+
+         if (TREE_CODE (b->decl) != LABEL_DECL)
+           continue;
+         label_vars = b->u.label;
+         ++label_vars->label_bindings.stmt_exprs;
+         FOR_EACH_VEC_ELT (c_goto_bindings_p, label_vars->gotos, ix, g)
+           ++g->goto_bindings.stmt_exprs;
+       }
+    }
+
+  if (switch_bindings != NULL)
+    ++switch_bindings->stmt_exprs;
+}
+
+/* Adjust the bindings for the end of a statement expression.  */
+
+void
+c_bindings_end_stmt_expr (struct c_spot_bindings *switch_bindings)
+{
+  struct c_scope *scope;
+
+  for (scope = current_scope; scope != NULL; scope = scope->outer)
+    {
+      struct c_binding *b;
+
+      if (!scope->has_label_bindings)
+       continue;
+
+      for (b = scope->bindings; b != NULL; b = b->prev)
+       {
+         struct c_label_vars *label_vars;
+         unsigned int ix;
+         struct c_goto_bindings *g;
+
+         if (TREE_CODE (b->decl) != LABEL_DECL)
+           continue;
+         label_vars = b->u.label;
+         --label_vars->label_bindings.stmt_exprs;
+         if (label_vars->label_bindings.stmt_exprs < 0)
+           {
+             label_vars->label_bindings.left_stmt_expr = true;
+             label_vars->label_bindings.stmt_exprs = 0;
+           }
+         FOR_EACH_VEC_ELT (c_goto_bindings_p, label_vars->gotos, ix, g)
+           {
+             --g->goto_bindings.stmt_exprs;
+             if (g->goto_bindings.stmt_exprs < 0)
+               {
+                 g->goto_bindings.left_stmt_expr = true;
+                 g->goto_bindings.stmt_exprs = 0;
+               }
+           }
+       }
+    }
+
+  if (switch_bindings != NULL)
+    {
+      --switch_bindings->stmt_exprs;
+      gcc_assert (switch_bindings->stmt_exprs >= 0);
+    }
+}
+\f
+/* Push a definition or a declaration of struct, union or enum tag "name".
+   "type" should be the type node.
+   We assume that the tag "name" is not already defined, and has a location
+   of LOC.
+
+   Note that the definition may really be just a forward reference.
+   In that case, the TYPE_SIZE will be zero.  */
+
+static void
+pushtag (location_t loc, tree name, tree type)
+{
+  /* Record the identifier as the type's name if it has none.  */
+  if (name && !TYPE_NAME (type))
+    TYPE_NAME (type) = name;
+  bind (name, type, current_scope, /*invisible=*/false, /*nested=*/false, loc);
+
+  /* Create a fake NULL-named TYPE_DECL node whose TREE_TYPE will be the
+     tagged type we just added to the current scope.  This fake
+     NULL-named TYPE_DECL node helps dwarfout.c to know when it needs
+     to output a representation of a tagged type, and it also gives
+     us a convenient place to record the "scope start" address for the
+     tagged type.  */
+
+  TYPE_STUB_DECL (type) = pushdecl (build_decl (loc,
+                                               TYPE_DECL, NULL_TREE, type));
+
+  /* An approximation for now, so we can tell this is a function-scope tag.
+     This will be updated in pop_scope.  */
+  TYPE_CONTEXT (type) = DECL_CONTEXT (TYPE_STUB_DECL (type));
+
+  if (warn_cxx_compat && name != NULL_TREE)
+    {
+      struct c_binding *b = I_SYMBOL_BINDING (name);
+
+      if (b != NULL
+         && b->decl != NULL_TREE
+         && TREE_CODE (b->decl) == TYPE_DECL
+         && (B_IN_CURRENT_SCOPE (b)
+             || (current_scope == file_scope && B_IN_EXTERNAL_SCOPE (b)))
+         && (TYPE_MAIN_VARIANT (TREE_TYPE (b->decl))
+             != TYPE_MAIN_VARIANT (type)))
+       {
+         warning_at (loc, OPT_Wc___compat,
+                     ("using %qD as both a typedef and a tag is "
+                      "invalid in C++"),
+                     b->decl);
+         if (b->locus != UNKNOWN_LOCATION)
+           inform (b->locus, "originally defined here");
+       }
+    }
+}
+\f
+/* Subroutine of compare_decls.  Allow harmless mismatches in return
+   and argument types provided that the type modes match.  This function
+   return a unified type given a suitable match, and 0 otherwise.  */
+
+static tree
+match_builtin_function_types (tree newtype, tree oldtype)
+{
+  tree newrettype, oldrettype;
+  tree newargs, oldargs;
+  tree trytype, tryargs;
+
+  /* Accept the return type of the new declaration if same modes.  */
+  oldrettype = TREE_TYPE (oldtype);
+  newrettype = TREE_TYPE (newtype);
+
+  if (TYPE_MODE (oldrettype) != TYPE_MODE (newrettype))
+    return 0;
+
+  oldargs = TYPE_ARG_TYPES (oldtype);
+  newargs = TYPE_ARG_TYPES (newtype);
+  tryargs = newargs;
+
+  while (oldargs || newargs)
+    {
+      if (!oldargs
+         || !newargs
+         || !TREE_VALUE (oldargs)
+         || !TREE_VALUE (newargs)
+         || TYPE_MODE (TREE_VALUE (oldargs))
+            != TYPE_MODE (TREE_VALUE (newargs)))
+       return 0;
+
+      oldargs = TREE_CHAIN (oldargs);
+      newargs = TREE_CHAIN (newargs);
+    }
+
+  trytype = build_function_type (newrettype, tryargs);
+  return build_type_attribute_variant (trytype, TYPE_ATTRIBUTES (oldtype));
+}
+
+/* Subroutine of diagnose_mismatched_decls.  Check for function type
+   mismatch involving an empty arglist vs a nonempty one and give clearer
+   diagnostics.  */
+static void
+diagnose_arglist_conflict (tree newdecl, tree olddecl,
+                          tree newtype, tree oldtype)
+{
+  tree t;
+
+  if (TREE_CODE (olddecl) != FUNCTION_DECL
+      || !comptypes (TREE_TYPE (oldtype), TREE_TYPE (newtype))
+      || !((!prototype_p (oldtype) && DECL_INITIAL (olddecl) == 0)
+          || (!prototype_p (newtype) && DECL_INITIAL (newdecl) == 0)))
+    return;
+
+  t = TYPE_ARG_TYPES (oldtype);
+  if (t == 0)
+    t = TYPE_ARG_TYPES (newtype);
+  for (; t; t = TREE_CHAIN (t))
+    {
+      tree type = TREE_VALUE (t);
+
+      if (TREE_CHAIN (t) == 0
+         && TYPE_MAIN_VARIANT (type) != void_type_node)
+       {
+         inform (input_location, "a parameter list with an ellipsis can%'t match "
+                 "an empty parameter name list declaration");
+         break;
+       }
+
+      if (c_type_promotes_to (type) != type)
+       {
+         inform (input_location, "an argument type that has a default promotion can%'t match "
+                 "an empty parameter name list declaration");
+         break;
+       }
+    }
+}
+
+/* Another subroutine of diagnose_mismatched_decls.  OLDDECL is an
+   old-style function definition, NEWDECL is a prototype declaration.
+   Diagnose inconsistencies in the argument list.  Returns TRUE if
+   the prototype is compatible, FALSE if not.  */
+static bool
+validate_proto_after_old_defn (tree newdecl, tree newtype, tree oldtype)
+{
+  tree newargs, oldargs;
+  int i;
+
+#define END_OF_ARGLIST(t) ((t) == void_type_node)
+
+  oldargs = TYPE_ACTUAL_ARG_TYPES (oldtype);
+  newargs = TYPE_ARG_TYPES (newtype);
+  i = 1;
+
+  for (;;)
+    {
+      tree oldargtype = TREE_VALUE (oldargs);
+      tree newargtype = TREE_VALUE (newargs);
+
+      if (oldargtype == error_mark_node || newargtype == error_mark_node)
+       return false;
+
+      oldargtype = TYPE_MAIN_VARIANT (oldargtype);
+      newargtype = TYPE_MAIN_VARIANT (newargtype);
+
+      if (END_OF_ARGLIST (oldargtype) && END_OF_ARGLIST (newargtype))
+       break;
+
+      /* Reaching the end of just one list means the two decls don't
+        agree on the number of arguments.  */
+      if (END_OF_ARGLIST (oldargtype))
+       {
+         error ("prototype for %q+D declares more arguments "
+                "than previous old-style definition", newdecl);
+         return false;
+       }
+      else if (END_OF_ARGLIST (newargtype))
+       {
+         error ("prototype for %q+D declares fewer arguments "
+                "than previous old-style definition", newdecl);
+         return false;
+       }
+
+      /* Type for passing arg must be consistent with that declared
+        for the arg.  */
+      else if (!comptypes (oldargtype, newargtype))
+       {
+         error ("prototype for %q+D declares argument %d"
+                " with incompatible type",
+                newdecl, i);
+         return false;
+       }
+
+      oldargs = TREE_CHAIN (oldargs);
+      newargs = TREE_CHAIN (newargs);
+      i++;
+    }
+
+  /* If we get here, no errors were found, but do issue a warning
+     for this poor-style construct.  */
+  warning (0, "prototype for %q+D follows non-prototype definition",
+          newdecl);
+  return true;
+#undef END_OF_ARGLIST
+}
+
+/* Subroutine of diagnose_mismatched_decls.  Report the location of DECL,
+   first in a pair of mismatched declarations, using the diagnostic
+   function DIAG.  */
+static void
+locate_old_decl (tree decl)
+{
+  if (TREE_CODE (decl) == FUNCTION_DECL && DECL_BUILT_IN (decl))
+    ;
+  else if (DECL_INITIAL (decl))
+    inform (input_location, "previous definition of %q+D was here", decl);
+  else if (C_DECL_IMPLICIT (decl))
+    inform (input_location, "previous implicit declaration of %q+D was here", decl);
+  else
+    inform (input_location, "previous declaration of %q+D was here", decl);
+}
+
+/* Subroutine of duplicate_decls.  Compare NEWDECL to OLDDECL.
+   Returns true if the caller should proceed to merge the two, false
+   if OLDDECL should simply be discarded.  As a side effect, issues
+   all necessary diagnostics for invalid or poor-style combinations.
+   If it returns true, writes the types of NEWDECL and OLDDECL to
+   *NEWTYPEP and *OLDTYPEP - these may have been adjusted from
+   TREE_TYPE (NEWDECL, OLDDECL) respectively.  */
+
+static bool
+diagnose_mismatched_decls (tree newdecl, tree olddecl,
+                          tree *newtypep, tree *oldtypep)
+{
+  tree newtype, oldtype;
+  bool pedwarned = false;
+  bool warned = false;
+  bool retval = true;
+
+#define DECL_EXTERN_INLINE(DECL) (DECL_DECLARED_INLINE_P (DECL)  \
+                                 && DECL_EXTERNAL (DECL))
+
+  /* If we have error_mark_node for either decl or type, just discard
+     the previous decl - we're in an error cascade already.  */
+  if (olddecl == error_mark_node || newdecl == error_mark_node)
+    return false;
+  *oldtypep = oldtype = TREE_TYPE (olddecl);
+  *newtypep = newtype = TREE_TYPE (newdecl);
+  if (oldtype == error_mark_node || newtype == error_mark_node)
+    return false;
+
+  /* Two different categories of symbol altogether.  This is an error
+     unless OLDDECL is a builtin.  OLDDECL will be discarded in any case.  */
+  if (TREE_CODE (olddecl) != TREE_CODE (newdecl))
+    {
+      if (!(TREE_CODE (olddecl) == FUNCTION_DECL
+           && DECL_BUILT_IN (olddecl)
+           && !C_DECL_DECLARED_BUILTIN (olddecl)))
+       {
+         error ("%q+D redeclared as different kind of symbol", newdecl);
+         locate_old_decl (olddecl);
+       }
+      else if (TREE_PUBLIC (newdecl))
+       warning (0, "built-in function %q+D declared as non-function",
+                newdecl);
+      else
+       warning (OPT_Wshadow, "declaration of %q+D shadows "
+                "a built-in function", newdecl);
+      return false;
+    }
+
+  /* Enumerators have no linkage, so may only be declared once in a
+     given scope.  */
+  if (TREE_CODE (olddecl) == CONST_DECL)
+    {
+      error ("redeclaration of enumerator %q+D", newdecl);
+      locate_old_decl (olddecl);
+      return false;
+    }
+
+  if (!comptypes (oldtype, newtype))
+    {
+      if (TREE_CODE (olddecl) == FUNCTION_DECL
+         && DECL_BUILT_IN (olddecl) && !C_DECL_DECLARED_BUILTIN (olddecl))
+       {
+         /* Accept harmless mismatch in function types.
+            This is for the ffs and fprintf builtins.  */
+         tree trytype = match_builtin_function_types (newtype, oldtype);
+
+         if (trytype && comptypes (newtype, trytype))
+           *oldtypep = oldtype = trytype;
+         else
+           {
+             /* If types don't match for a built-in, throw away the
+                built-in.  No point in calling locate_old_decl here, it
+                won't print anything.  */
+             warning (0, "conflicting types for built-in function %q+D",
+                      newdecl);
+             return false;
+           }
+       }
+      else if (TREE_CODE (olddecl) == FUNCTION_DECL
+              && DECL_IS_BUILTIN (olddecl))
+       {
+         /* A conflicting function declaration for a predeclared
+            function that isn't actually built in.  Objective C uses
+            these.  The new declaration silently overrides everything
+            but the volatility (i.e. noreturn) indication.  See also
+            below.  FIXME: Make Objective C use normal builtins.  */
+         TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl);
+         return false;
+       }
+      /* Permit void foo (...) to match int foo (...) if the latter is
+        the definition and implicit int was used.  See
+        c-torture/compile/920625-2.c.  */
+      else if (TREE_CODE (newdecl) == FUNCTION_DECL && DECL_INITIAL (newdecl)
+              && TYPE_MAIN_VARIANT (TREE_TYPE (oldtype)) == void_type_node
+              && TYPE_MAIN_VARIANT (TREE_TYPE (newtype)) == integer_type_node
+              && C_FUNCTION_IMPLICIT_INT (newdecl) && !DECL_INITIAL (olddecl))
+       {
+         pedwarned = pedwarn (input_location, 0,
+                              "conflicting types for %q+D", newdecl);
+         /* Make sure we keep void as the return type.  */
+         TREE_TYPE (newdecl) = *newtypep = newtype = oldtype;
+         C_FUNCTION_IMPLICIT_INT (newdecl) = 0;
+       }
+      /* Permit void foo (...) to match an earlier call to foo (...) with
+        no declared type (thus, implicitly int).  */
+      else if (TREE_CODE (newdecl) == FUNCTION_DECL
+              && TYPE_MAIN_VARIANT (TREE_TYPE (newtype)) == void_type_node
+              && TYPE_MAIN_VARIANT (TREE_TYPE (oldtype)) == integer_type_node
+              && C_DECL_IMPLICIT (olddecl) && !DECL_INITIAL (olddecl))
+       {
+         pedwarned = pedwarn (input_location, 0,
+                              "conflicting types for %q+D", newdecl);
+         /* Make sure we keep void as the return type.  */
+         TREE_TYPE (olddecl) = *oldtypep = oldtype = newtype;
+       }
+      else
+       {
+         int new_quals = TYPE_QUALS (newtype);
+         int old_quals = TYPE_QUALS (oldtype);
+
+         if (new_quals != old_quals)
+           {
+             addr_space_t new_addr = DECODE_QUAL_ADDR_SPACE (new_quals);
+             addr_space_t old_addr = DECODE_QUAL_ADDR_SPACE (old_quals);
+             if (new_addr != old_addr)
+               {
+                 if (ADDR_SPACE_GENERIC_P (new_addr))
+                   error ("conflicting named address spaces (generic vs %s) "
+                          "for %q+D",
+                          c_addr_space_name (old_addr), newdecl);
+                 else if (ADDR_SPACE_GENERIC_P (old_addr))
+                   error ("conflicting named address spaces (%s vs generic) "
+                          "for %q+D",
+                          c_addr_space_name (new_addr), newdecl);
+                 else
+                   error ("conflicting named address spaces (%s vs %s) "
+                          "for %q+D",
+                          c_addr_space_name (new_addr),
+                          c_addr_space_name (old_addr),
+                          newdecl);
+               }
+
+             if (CLEAR_QUAL_ADDR_SPACE (new_quals)
+                 != CLEAR_QUAL_ADDR_SPACE (old_quals))
+               error ("conflicting type qualifiers for %q+D", newdecl);
+           }
+         else
+           error ("conflicting types for %q+D", newdecl);
+         diagnose_arglist_conflict (newdecl, olddecl, newtype, oldtype);
+         locate_old_decl (olddecl);
+         return false;
+       }
+    }
+
+  /* Redeclaration of a type is a constraint violation (6.7.2.3p1),
+     but silently ignore the redeclaration if either is in a system
+     header.  (Conflicting redeclarations were handled above.)  This
+     is allowed for C11 if the types are the same, not just
+     compatible.  */
+  if (TREE_CODE (newdecl) == TYPE_DECL)
+    {
+      bool types_different = false;
+      int comptypes_result;
+
+      comptypes_result
+       = comptypes_check_different_types (oldtype, newtype, &types_different);
+
+      if (comptypes_result != 1 || types_different)
+       {
+         error ("redefinition of typedef %q+D with different type", newdecl);
+         locate_old_decl (olddecl);
+         return false;
+       }
+
+      if (DECL_IN_SYSTEM_HEADER (newdecl)
+         || DECL_IN_SYSTEM_HEADER (olddecl)
+         || TREE_NO_WARNING (newdecl)
+         || TREE_NO_WARNING (olddecl))
+       return true;  /* Allow OLDDECL to continue in use.  */
+
+      if (variably_modified_type_p (newtype, NULL))
+       {
+         error ("redefinition of typedef %q+D with variably modified type",
+                newdecl);
+         locate_old_decl (olddecl);
+       }
+      else if (pedantic && !flag_isoc11)
+       {
+         pedwarn (input_location, OPT_Wpedantic,
+                  "redefinition of typedef %q+D", newdecl);
+         locate_old_decl (olddecl);
+       }
+
+      return true;
+    }
+
+  /* Function declarations can either be 'static' or 'extern' (no
+     qualifier is equivalent to 'extern' - C99 6.2.2p5) and therefore
+     can never conflict with each other on account of linkage
+     (6.2.2p4).  Multiple definitions are not allowed (6.9p3,5) but
+     gnu89 mode permits two definitions if one is 'extern inline' and
+     one is not.  The non- extern-inline definition supersedes the
+     extern-inline definition.  */
+
+  else if (TREE_CODE (newdecl) == FUNCTION_DECL)
+    {
+      /* If you declare a built-in function name as static, or
+        define the built-in with an old-style definition (so we
+        can't validate the argument list) the built-in definition is
+        overridden, but optionally warn this was a bad choice of name.  */
+      if (DECL_BUILT_IN (olddecl)
+         && !C_DECL_DECLARED_BUILTIN (olddecl)
+         && (!TREE_PUBLIC (newdecl)
+             || (DECL_INITIAL (newdecl)
+                 && !prototype_p (TREE_TYPE (newdecl)))))
+       {
+         warning (OPT_Wshadow, "declaration of %q+D shadows "
+                  "a built-in function", newdecl);
+         /* Discard the old built-in function.  */
+         return false;
+       }
+
+      if (DECL_INITIAL (newdecl))
+       {
+         if (DECL_INITIAL (olddecl))
+           {
+             /* If both decls are in the same TU and the new declaration
+                isn't overriding an extern inline reject the new decl.
+                In c99, no overriding is allowed in the same translation
+                unit.  */
+             if ((!DECL_EXTERN_INLINE (olddecl)
+                  || DECL_EXTERN_INLINE (newdecl)
+                  || (!flag_gnu89_inline
+                      && (!DECL_DECLARED_INLINE_P (olddecl)
+                          || !lookup_attribute ("gnu_inline",
+                                                DECL_ATTRIBUTES (olddecl)))
+                      && (!DECL_DECLARED_INLINE_P (newdecl)
+                          || !lookup_attribute ("gnu_inline",
+                                                DECL_ATTRIBUTES (newdecl))))
+                 )
+                 && same_translation_unit_p (newdecl, olddecl))
+               {
+                 error ("redefinition of %q+D", newdecl);
+                 locate_old_decl (olddecl);
+                 return false;
+               }
+           }
+       }
+      /* If we have a prototype after an old-style function definition,
+        the argument types must be checked specially.  */
+      else if (DECL_INITIAL (olddecl)
+              && !prototype_p (oldtype) && prototype_p (newtype)
+              && TYPE_ACTUAL_ARG_TYPES (oldtype)
+              && !validate_proto_after_old_defn (newdecl, newtype, oldtype))
+       {
+         locate_old_decl (olddecl);
+         return false;
+       }
+      /* A non-static declaration (even an "extern") followed by a
+        static declaration is undefined behavior per C99 6.2.2p3-5,7.
+        The same is true for a static forward declaration at block
+        scope followed by a non-static declaration/definition at file
+        scope.  Static followed by non-static at the same scope is
+        not undefined behavior, and is the most convenient way to get
+        some effects (see e.g.  what unwind-dw2-fde-glibc.c does to
+        the definition of _Unwind_Find_FDE in unwind-dw2-fde.c), but
+        we do diagnose it if -Wtraditional.  */
+      if (TREE_PUBLIC (olddecl) && !TREE_PUBLIC (newdecl))
+       {
+         /* Two exceptions to the rule.  If olddecl is an extern
+            inline, or a predeclared function that isn't actually
+            built in, newdecl silently overrides olddecl.  The latter
+            occur only in Objective C; see also above.  (FIXME: Make
+            Objective C use normal builtins.)  */
+         if (!DECL_IS_BUILTIN (olddecl)
+             && !DECL_EXTERN_INLINE (olddecl))
+           {
+             error ("static declaration of %q+D follows "
+                    "non-static declaration", newdecl);
+             locate_old_decl (olddecl);
+           }
+         return false;
+       }
+      else if (TREE_PUBLIC (newdecl) && !TREE_PUBLIC (olddecl))
+       {
+         if (DECL_CONTEXT (olddecl))
+           {
+             error ("non-static declaration of %q+D follows "
+                    "static declaration", newdecl);
+             locate_old_decl (olddecl);
+             return false;
+           }
+         else if (warn_traditional)
+           {
+             warned |= warning (OPT_Wtraditional,
+                                "non-static declaration of %q+D "
+                                "follows static declaration", newdecl);
+           }
+       }
+
+      /* Make sure gnu_inline attribute is either not present, or
+        present on all inline decls.  */
+      if (DECL_DECLARED_INLINE_P (olddecl)
+         && DECL_DECLARED_INLINE_P (newdecl))
+       {
+         bool newa = lookup_attribute ("gnu_inline",
+                                       DECL_ATTRIBUTES (newdecl)) != NULL;
+         bool olda = lookup_attribute ("gnu_inline",
+                                       DECL_ATTRIBUTES (olddecl)) != NULL;
+         if (newa != olda)
+           {
+             error_at (input_location, "%<gnu_inline%> attribute present on %q+D",
+                       newa ? newdecl : olddecl);
+             error_at (DECL_SOURCE_LOCATION (newa ? olddecl : newdecl),
+                       "but not here");
+           }
+       }
+    }
+  else if (TREE_CODE (newdecl) == VAR_DECL)
+    {
+      /* Only variables can be thread-local, and all declarations must
+        agree on this property.  */
+      if (C_DECL_THREADPRIVATE_P (olddecl) && !DECL_THREAD_LOCAL_P (newdecl))
+       {
+         /* Nothing to check.  Since OLDDECL is marked threadprivate
+            and NEWDECL does not have a thread-local attribute, we
+            will merge the threadprivate attribute into NEWDECL.  */
+         ;
+       }
+      else if (DECL_THREAD_LOCAL_P (newdecl) != DECL_THREAD_LOCAL_P (olddecl))
+       {
+         if (DECL_THREAD_LOCAL_P (newdecl))
+           error ("thread-local declaration of %q+D follows "
+                  "non-thread-local declaration", newdecl);
+         else
+           error ("non-thread-local declaration of %q+D follows "
+                  "thread-local declaration", newdecl);
+
+         locate_old_decl (olddecl);
+         return false;
+       }
+
+      /* Multiple initialized definitions are not allowed (6.9p3,5).  */
+      if (DECL_INITIAL (newdecl) && DECL_INITIAL (olddecl))
+       {
+         error ("redefinition of %q+D", newdecl);
+         locate_old_decl (olddecl);
+         return false;
+       }
+
+      /* Objects declared at file scope: if the first declaration had
+        external linkage (even if it was an external reference) the
+        second must have external linkage as well, or the behavior is
+        undefined.  If the first declaration had internal linkage, then
+        the second must too, or else be an external reference (in which
+        case the composite declaration still has internal linkage).
+        As for function declarations, we warn about the static-then-
+        extern case only for -Wtraditional.  See generally 6.2.2p3-5,7.  */
+      if (DECL_FILE_SCOPE_P (newdecl)
+         && TREE_PUBLIC (newdecl) != TREE_PUBLIC (olddecl))
+       {
+         if (DECL_EXTERNAL (newdecl))
+           {
+             if (!DECL_FILE_SCOPE_P (olddecl))
+               {
+                 error ("extern declaration of %q+D follows "
+                        "declaration with no linkage", newdecl);
+                 locate_old_decl (olddecl);
+                 return false;
+               }
+             else if (warn_traditional)
+               {
+                 warned |= warning (OPT_Wtraditional,
+                                    "non-static declaration of %q+D "
+                                    "follows static declaration", newdecl);
+               }
+           }
+         else
+           {
+             if (TREE_PUBLIC (newdecl))
+               error ("non-static declaration of %q+D follows "
+                      "static declaration", newdecl);
+             else
+               error ("static declaration of %q+D follows "
+                      "non-static declaration", newdecl);
+
+             locate_old_decl (olddecl);
+             return false;
+           }
+       }
+      /* Two objects with the same name declared at the same block
+        scope must both be external references (6.7p3).  */
+      else if (!DECL_FILE_SCOPE_P (newdecl))
+       {
+         if (DECL_EXTERNAL (newdecl))
+           {
+             /* Extern with initializer at block scope, which will
+                already have received an error.  */
+           }
+         else if (DECL_EXTERNAL (olddecl))
+           {
+             error ("declaration of %q+D with no linkage follows "
+                    "extern declaration", newdecl);
+             locate_old_decl (olddecl);
+           }
+         else
+           {
+             error ("redeclaration of %q+D with no linkage", newdecl);
+             locate_old_decl (olddecl);
+           }
+
+         return false;
+       }
+
+      /* C++ does not permit a decl to appear multiple times at file
+        scope.  */
+      if (warn_cxx_compat
+         && DECL_FILE_SCOPE_P (newdecl)
+         && !DECL_EXTERNAL (newdecl)
+         && !DECL_EXTERNAL (olddecl))
+       warned |= warning_at (DECL_SOURCE_LOCATION (newdecl),
+                             OPT_Wc___compat,
+                             ("duplicate declaration of %qD is "
+                              "invalid in C++"),
+                             newdecl);
+    }
+
+  /* warnings */
+  /* All decls must agree on a visibility.  */
+  if (CODE_CONTAINS_STRUCT (TREE_CODE (newdecl), TS_DECL_WITH_VIS)
+      && DECL_VISIBILITY_SPECIFIED (newdecl) && DECL_VISIBILITY_SPECIFIED (olddecl)
+      && DECL_VISIBILITY (newdecl) != DECL_VISIBILITY (olddecl))
+    {
+      warned |= warning (0, "redeclaration of %q+D with different visibility "
+                        "(old visibility preserved)", newdecl);
+    }
+
+  if (TREE_CODE (newdecl) == FUNCTION_DECL)
+    {
+      /* Diagnose inline __attribute__ ((noinline)) which is silly.  */
+      if (DECL_DECLARED_INLINE_P (newdecl)
+         && lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
+       {
+         warned |= warning (OPT_Wattributes,
+                            "inline declaration of %qD follows "
+                            "declaration with attribute noinline", newdecl);
+       }
+      else if (DECL_DECLARED_INLINE_P (olddecl)
+              && lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl)))
+       {
+         warned |= warning (OPT_Wattributes,
+                            "declaration of %q+D with attribute "
+                            "noinline follows inline declaration ", newdecl);
+       }
+    }
+  else /* PARM_DECL, VAR_DECL */
+    {
+      /* Redeclaration of a parameter is a constraint violation (this is
+        not explicitly stated, but follows from C99 6.7p3 [no more than
+        one declaration of the same identifier with no linkage in the
+        same scope, except type tags] and 6.2.2p6 [parameters have no
+        linkage]).  We must check for a forward parameter declaration,
+        indicated by TREE_ASM_WRITTEN on the old declaration - this is
+        an extension, the mandatory diagnostic for which is handled by
+        mark_forward_parm_decls.  */
+
+      if (TREE_CODE (newdecl) == PARM_DECL
+         && (!TREE_ASM_WRITTEN (olddecl) || TREE_ASM_WRITTEN (newdecl)))
+       {
+         error ("redefinition of parameter %q+D", newdecl);
+         locate_old_decl (olddecl);
+         return false;
+       }
+    }
+
+  /* Optional warning for completely redundant decls.  */
+  if (!warned && !pedwarned
+      && warn_redundant_decls
+      /* Don't warn about a function declaration followed by a
+        definition.  */
+      && !(TREE_CODE (newdecl) == FUNCTION_DECL
+          && DECL_INITIAL (newdecl) && !DECL_INITIAL (olddecl))
+      /* Don't warn about redundant redeclarations of builtins.  */
+      && !(TREE_CODE (newdecl) == FUNCTION_DECL
+          && !DECL_BUILT_IN (newdecl)
+          && DECL_BUILT_IN (olddecl)
+          && !C_DECL_DECLARED_BUILTIN (olddecl))
+      /* Don't warn about an extern followed by a definition.  */
+      && !(DECL_EXTERNAL (olddecl) && !DECL_EXTERNAL (newdecl))
+      /* Don't warn about forward parameter decls.  */
+      && !(TREE_CODE (newdecl) == PARM_DECL
+          && TREE_ASM_WRITTEN (olddecl) && !TREE_ASM_WRITTEN (newdecl))
+      /* Don't warn about a variable definition following a declaration.  */
+      && !(TREE_CODE (newdecl) == VAR_DECL
+          && DECL_INITIAL (newdecl) && !DECL_INITIAL (olddecl)))
+    {
+      warned = warning (OPT_Wredundant_decls, "redundant redeclaration of %q+D",
+                       newdecl);
+    }
+
+  /* Report location of previous decl/defn.  */
+  if (warned || pedwarned)
+    locate_old_decl (olddecl);
+
+#undef DECL_EXTERN_INLINE
+
+  return retval;
+}
+
+/* Subroutine of duplicate_decls.  NEWDECL has been found to be
+   consistent with OLDDECL, but carries new information.  Merge the
+   new information into OLDDECL.  This function issues no
+   diagnostics.  */
+
+static void
+merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
+{
+  bool new_is_definition = (TREE_CODE (newdecl) == FUNCTION_DECL
+                           && DECL_INITIAL (newdecl) != 0);
+  bool new_is_prototype = (TREE_CODE (newdecl) == FUNCTION_DECL
+                          && prototype_p (TREE_TYPE (newdecl)));
+  bool old_is_prototype = (TREE_CODE (olddecl) == FUNCTION_DECL
+                          && prototype_p (TREE_TYPE (olddecl)));
+
+  /* For real parm decl following a forward decl, rechain the old decl
+     in its new location and clear TREE_ASM_WRITTEN (it's not a
+     forward decl anymore).  */
+  if (TREE_CODE (newdecl) == PARM_DECL
+      && TREE_ASM_WRITTEN (olddecl) && !TREE_ASM_WRITTEN (newdecl))
+    {
+      struct c_binding *b, **here;
+
+      for (here = &current_scope->bindings; *here; here = &(*here)->prev)
+       if ((*here)->decl == olddecl)
+         goto found;
+      gcc_unreachable ();
+
+    found:
+      b = *here;
+      *here = b->prev;
+      b->prev = current_scope->bindings;
+      current_scope->bindings = b;
+
+      TREE_ASM_WRITTEN (olddecl) = 0;
+    }
+
+  DECL_ATTRIBUTES (newdecl)
+    = targetm.merge_decl_attributes (olddecl, newdecl);
+
+  /* Merge the data types specified in the two decls.  */
+  TREE_TYPE (newdecl)
+    = TREE_TYPE (olddecl)
+    = composite_type (newtype, oldtype);
+
+  /* Lay the type out, unless already done.  */
+  if (!comptypes (oldtype, TREE_TYPE (newdecl)))
+    {
+      if (TREE_TYPE (newdecl) != error_mark_node)
+       layout_type (TREE_TYPE (newdecl));
+      if (TREE_CODE (newdecl) != FUNCTION_DECL
+         && TREE_CODE (newdecl) != TYPE_DECL
+         && TREE_CODE (newdecl) != CONST_DECL)
+       layout_decl (newdecl, 0);
+    }
+  else
+    {
+      /* Since the type is OLDDECL's, make OLDDECL's size go with.  */
+      DECL_SIZE (newdecl) = DECL_SIZE (olddecl);
+      DECL_SIZE_UNIT (newdecl) = DECL_SIZE_UNIT (olddecl);
+      DECL_MODE (newdecl) = DECL_MODE (olddecl);
+      if (DECL_ALIGN (olddecl) > DECL_ALIGN (newdecl))
+       {
+         DECL_ALIGN (newdecl) = DECL_ALIGN (olddecl);
+         DECL_USER_ALIGN (newdecl) |= DECL_USER_ALIGN (olddecl);
+       }
+    }
+
+  /* Keep the old rtl since we can safely use it.  */
+  if (HAS_RTL_P (olddecl))
+    COPY_DECL_RTL (olddecl, newdecl);
+
+  /* Merge the type qualifiers.  */
+  if (TREE_READONLY (newdecl))
+    TREE_READONLY (olddecl) = 1;
+
+  if (TREE_THIS_VOLATILE (newdecl))
+    TREE_THIS_VOLATILE (olddecl) = 1;
+
+  /* Merge deprecatedness.  */
+  if (TREE_DEPRECATED (newdecl))
+    TREE_DEPRECATED (olddecl) = 1;
+
+  /* If a decl is in a system header and the other isn't, keep the one on the
+     system header. Otherwise, keep source location of definition rather than
+     declaration and of prototype rather than non-prototype unless that
+     prototype is built-in.  */
+  if (CODE_CONTAINS_STRUCT (TREE_CODE (olddecl), TS_DECL_WITH_VIS)
+      && DECL_IN_SYSTEM_HEADER (olddecl)
+      && !DECL_IN_SYSTEM_HEADER (newdecl) )
+    DECL_SOURCE_LOCATION (newdecl) = DECL_SOURCE_LOCATION (olddecl);
+  else if (CODE_CONTAINS_STRUCT (TREE_CODE (olddecl), TS_DECL_WITH_VIS)
+          && DECL_IN_SYSTEM_HEADER (newdecl)
+          && !DECL_IN_SYSTEM_HEADER (olddecl))
+    DECL_SOURCE_LOCATION (olddecl) = DECL_SOURCE_LOCATION (newdecl);
+  else if ((DECL_INITIAL (newdecl) == 0 && DECL_INITIAL (olddecl) != 0)
+          || (old_is_prototype && !new_is_prototype
+              && !C_DECL_BUILTIN_PROTOTYPE (olddecl)))
+    DECL_SOURCE_LOCATION (newdecl) = DECL_SOURCE_LOCATION (olddecl);
+
+  /* Merge the initialization information.  */
+   if (DECL_INITIAL (newdecl) == 0)
+    DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
+
+  /* Merge the threadprivate attribute.  */
+  if (TREE_CODE (olddecl) == VAR_DECL && C_DECL_THREADPRIVATE_P (olddecl))
+    {
+      DECL_TLS_MODEL (newdecl) = DECL_TLS_MODEL (olddecl);
+      C_DECL_THREADPRIVATE_P (newdecl) = 1;
+    }
+
+  if (CODE_CONTAINS_STRUCT (TREE_CODE (olddecl), TS_DECL_WITH_VIS))
+    {
+      /* Merge the section attribute.
+        We want to issue an error if the sections conflict but that
+        must be done later in decl_attributes since we are called
+        before attributes are assigned.  */
+      if (DECL_SECTION_NAME (newdecl) == NULL_TREE)
+       DECL_SECTION_NAME (newdecl) = DECL_SECTION_NAME (olddecl);
+
+      /* Copy the assembler name.
+        Currently, it can only be defined in the prototype.  */
+      COPY_DECL_ASSEMBLER_NAME (olddecl, newdecl);
+
+      /* Use visibility of whichever declaration had it specified */
+      if (DECL_VISIBILITY_SPECIFIED (olddecl))
+       {
+         DECL_VISIBILITY (newdecl) = DECL_VISIBILITY (olddecl);
+         DECL_VISIBILITY_SPECIFIED (newdecl) = 1;
+       }
+
+      if (TREE_CODE (newdecl) == FUNCTION_DECL)
+       {
+         DECL_STATIC_CONSTRUCTOR(newdecl) |= DECL_STATIC_CONSTRUCTOR(olddecl);
+         DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl);
+         DECL_NO_LIMIT_STACK (newdecl) |= DECL_NO_LIMIT_STACK (olddecl);
+         DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (newdecl)
+           |= DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (olddecl);
+         TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl);
+         DECL_IS_MALLOC (newdecl) |= DECL_IS_MALLOC (olddecl);
+         DECL_IS_OPERATOR_NEW (newdecl) |= DECL_IS_OPERATOR_NEW (olddecl);
+         TREE_READONLY (newdecl) |= TREE_READONLY (olddecl);
+         DECL_PURE_P (newdecl) |= DECL_PURE_P (olddecl);
+         DECL_IS_NOVOPS (newdecl) |= DECL_IS_NOVOPS (olddecl);
+       }
+
+      /* Merge the storage class information.  */
+      merge_weak (newdecl, olddecl);
+
+      /* For functions, static overrides non-static.  */
+      if (TREE_CODE (newdecl) == FUNCTION_DECL)
+       {
+         TREE_PUBLIC (newdecl) &= TREE_PUBLIC (olddecl);
+         /* This is since we don't automatically
+            copy the attributes of NEWDECL into OLDDECL.  */
+         TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
+         /* If this clears `static', clear it in the identifier too.  */
+         if (!TREE_PUBLIC (olddecl))
+           TREE_PUBLIC (DECL_NAME (olddecl)) = 0;
+       }
+    }
+
+  /* In c99, 'extern' declaration before (or after) 'inline' means this
+     function is not DECL_EXTERNAL, unless 'gnu_inline' attribute
+     is present.  */
+  if (TREE_CODE (newdecl) == FUNCTION_DECL
+      && !flag_gnu89_inline
+      && (DECL_DECLARED_INLINE_P (newdecl)
+         || DECL_DECLARED_INLINE_P (olddecl))
+      && (!DECL_DECLARED_INLINE_P (newdecl)
+         || !DECL_DECLARED_INLINE_P (olddecl)
+         || !DECL_EXTERNAL (olddecl))
+      && DECL_EXTERNAL (newdecl)
+      && !lookup_attribute ("gnu_inline", DECL_ATTRIBUTES (newdecl))
+      && !current_function_decl)
+    DECL_EXTERNAL (newdecl) = 0;
+
+  if (DECL_EXTERNAL (newdecl))
+    {
+      TREE_STATIC (newdecl) = TREE_STATIC (olddecl);
+      DECL_EXTERNAL (newdecl) = DECL_EXTERNAL (olddecl);
+
+      /* An extern decl does not override previous storage class.  */
+      TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl);
+      if (!DECL_EXTERNAL (newdecl))
+       {
+         DECL_CONTEXT (newdecl) = DECL_CONTEXT (olddecl);
+         DECL_COMMON (newdecl) = DECL_COMMON (olddecl);
+       }
+    }
+  else
+    {
+      TREE_STATIC (olddecl) = TREE_STATIC (newdecl);
+      TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
+    }
+
+  if (TREE_CODE (newdecl) == FUNCTION_DECL)
+    {
+      /* If we're redefining a function previously defined as extern
+        inline, make sure we emit debug info for the inline before we
+        throw it away, in case it was inlined into a function that
+        hasn't been written out yet.  */
+      if (new_is_definition && DECL_INITIAL (olddecl))
+       /* The new defn must not be inline.  */
+       DECL_UNINLINABLE (newdecl) = 1;
+      else
+       {
+         /* If either decl says `inline', this fn is inline, unless
+            its definition was passed already.  */
+         if (DECL_DECLARED_INLINE_P (newdecl)
+             || DECL_DECLARED_INLINE_P (olddecl))
+           DECL_DECLARED_INLINE_P (newdecl) = 1;
+
+         DECL_UNINLINABLE (newdecl) = DECL_UNINLINABLE (olddecl)
+           = (DECL_UNINLINABLE (newdecl) || DECL_UNINLINABLE (olddecl));
+
+         DECL_DISREGARD_INLINE_LIMITS (newdecl)
+           = DECL_DISREGARD_INLINE_LIMITS (olddecl)
+           = (DECL_DISREGARD_INLINE_LIMITS (newdecl)
+              || DECL_DISREGARD_INLINE_LIMITS (olddecl));
+       }
+
+      if (DECL_BUILT_IN (olddecl))
+       {
+         /* If redeclaring a builtin function, it stays built in.
+            But it gets tagged as having been declared.  */
+         DECL_BUILT_IN_CLASS (newdecl) = DECL_BUILT_IN_CLASS (olddecl);
+         DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
+         C_DECL_DECLARED_BUILTIN (newdecl) = 1;
+         if (new_is_prototype)
+           {
+             C_DECL_BUILTIN_PROTOTYPE (newdecl) = 0;
+             if (DECL_BUILT_IN_CLASS (newdecl) == BUILT_IN_NORMAL)
+               {
+                 enum built_in_function fncode = DECL_FUNCTION_CODE (newdecl);
+                 switch (fncode)
+                   {
+                     /* If a compatible prototype of these builtin functions
+                        is seen, assume the runtime implements it with the
+                        expected semantics.  */
+                   case BUILT_IN_STPCPY:
+                     if (builtin_decl_explicit_p (fncode))
+                       set_builtin_decl_implicit_p (fncode, true);
+                     break;
+                   default:
+                     break;
+                   }
+               }
+           }
+         else
+           C_DECL_BUILTIN_PROTOTYPE (newdecl)
+             = C_DECL_BUILTIN_PROTOTYPE (olddecl);
+       }
+
+      /* Preserve function specific target and optimization options */
+      if (DECL_FUNCTION_SPECIFIC_TARGET (olddecl)
+         && !DECL_FUNCTION_SPECIFIC_TARGET (newdecl))
+       DECL_FUNCTION_SPECIFIC_TARGET (newdecl)
+         = DECL_FUNCTION_SPECIFIC_TARGET (olddecl);
+
+      if (DECL_FUNCTION_SPECIFIC_OPTIMIZATION (olddecl)
+         && !DECL_FUNCTION_SPECIFIC_OPTIMIZATION (newdecl))
+       DECL_FUNCTION_SPECIFIC_OPTIMIZATION (newdecl)
+         = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (olddecl);
+
+      /* Also preserve various other info from the definition.  */
+      if (!new_is_definition)
+       {
+         tree t;
+         DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
+         DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
+         DECL_STRUCT_FUNCTION (newdecl) = DECL_STRUCT_FUNCTION (olddecl);
+         DECL_SAVED_TREE (newdecl) = DECL_SAVED_TREE (olddecl);
+         DECL_ARGUMENTS (newdecl) = copy_list (DECL_ARGUMENTS (olddecl));
+         for (t = DECL_ARGUMENTS (newdecl); t ; t = DECL_CHAIN (t))
+           DECL_CONTEXT (t) = newdecl;
+
+         /* See if we've got a function to instantiate from.  */
+         if (DECL_SAVED_TREE (olddecl))
+           DECL_ABSTRACT_ORIGIN (newdecl)
+             = DECL_ABSTRACT_ORIGIN (olddecl);
+       }
+    }
+
+  /* Merge the USED information.  */
+  if (TREE_USED (olddecl))
+    TREE_USED (newdecl) = 1;
+  else if (TREE_USED (newdecl))
+    TREE_USED (olddecl) = 1;
+  if (TREE_CODE (olddecl) == VAR_DECL || TREE_CODE (olddecl) == PARM_DECL)
+    DECL_READ_P (newdecl) |= DECL_READ_P (olddecl);
+  if (DECL_PRESERVE_P (olddecl))
+    DECL_PRESERVE_P (newdecl) = 1;
+  else if (DECL_PRESERVE_P (newdecl))
+    DECL_PRESERVE_P (olddecl) = 1;
+
+  /* Copy most of the decl-specific fields of NEWDECL into OLDDECL.
+     But preserve OLDDECL's DECL_UID, DECL_CONTEXT and
+     DECL_ARGUMENTS (if appropriate).  */
+  {
+    unsigned olddecl_uid = DECL_UID (olddecl);
+    tree olddecl_context = DECL_CONTEXT (olddecl);
+    tree olddecl_arguments = NULL;
+    if (TREE_CODE (olddecl) == FUNCTION_DECL)
+      olddecl_arguments = DECL_ARGUMENTS (olddecl);
+
+    memcpy ((char *) olddecl + sizeof (struct tree_common),
+           (char *) newdecl + sizeof (struct tree_common),
+           sizeof (struct tree_decl_common) - sizeof (struct tree_common));
+    DECL_USER_ALIGN (olddecl) = DECL_USER_ALIGN (newdecl);
+    switch (TREE_CODE (olddecl))
+      {
+      case FUNCTION_DECL:
+      case FIELD_DECL:
+      case VAR_DECL:
+      case PARM_DECL:
+      case LABEL_DECL:
+      case RESULT_DECL:
+      case CONST_DECL:
+      case TYPE_DECL:
+       memcpy ((char *) olddecl + sizeof (struct tree_decl_common),
+               (char *) newdecl + sizeof (struct tree_decl_common),
+               tree_code_size (TREE_CODE (olddecl)) - sizeof (struct tree_decl_common));
+       break;
+
+      default:
+
+       memcpy ((char *) olddecl + sizeof (struct tree_decl_common),
+               (char *) newdecl + sizeof (struct tree_decl_common),
+               sizeof (struct tree_decl_non_common) - sizeof (struct tree_decl_common));
+      }
+    DECL_UID (olddecl) = olddecl_uid;
+    DECL_CONTEXT (olddecl) = olddecl_context;
+    if (TREE_CODE (olddecl) == FUNCTION_DECL)
+      DECL_ARGUMENTS (olddecl) = olddecl_arguments;
+  }
+
+  /* If OLDDECL had its DECL_RTL instantiated, re-invoke make_decl_rtl
+     so that encode_section_info has a chance to look at the new decl
+     flags and attributes.  */
+  if (DECL_RTL_SET_P (olddecl)
+      && (TREE_CODE (olddecl) == FUNCTION_DECL
+         || (TREE_CODE (olddecl) == VAR_DECL
+             && TREE_STATIC (olddecl))))
+    make_decl_rtl (olddecl);
+}
+
+/* Handle when a new declaration NEWDECL has the same name as an old
+   one OLDDECL in the same binding contour.  Prints an error message
+   if appropriate.
+
+   If safely possible, alter OLDDECL to look like NEWDECL, and return
+   true.  Otherwise, return false.  */
+
+static bool
+duplicate_decls (tree newdecl, tree olddecl)
+{
+  tree newtype = NULL, oldtype = NULL;
+
+  if (!diagnose_mismatched_decls (newdecl, olddecl, &newtype, &oldtype))
+    {
+      /* Avoid `unused variable' and other warnings for OLDDECL.  */
+      TREE_NO_WARNING (olddecl) = 1;
+      return false;
+    }
+
+  merge_decls (newdecl, olddecl, newtype, oldtype);
+  return true;
+}
+
+\f
+/* Check whether decl-node NEW_DECL shadows an existing declaration.  */
+static void
+warn_if_shadowing (tree new_decl)
+{
+  struct c_binding *b;
+
+  /* Shadow warnings wanted?  */
+  if (!warn_shadow
+      /* No shadow warnings for internally generated vars.  */
+      || DECL_IS_BUILTIN (new_decl)
+      /* No shadow warnings for vars made for inlining.  */
+      || DECL_FROM_INLINE (new_decl))
+    return;
+
+  /* Is anything being shadowed?  Invisible decls do not count.  */
+  for (b = I_SYMBOL_BINDING (DECL_NAME (new_decl)); b; b = b->shadowed)
+    if (b->decl && b->decl != new_decl && !b->invisible
+       && (b->decl == error_mark_node
+           || diagnostic_report_warnings_p (global_dc,
+                                            DECL_SOURCE_LOCATION (b->decl))))
+      {
+       tree old_decl = b->decl;
+
+       if (old_decl == error_mark_node)
+         {
+           warning (OPT_Wshadow, "declaration of %q+D shadows previous "
+                    "non-variable", new_decl);
+           break;
+         }
+       else if (TREE_CODE (old_decl) == PARM_DECL)
+         warning (OPT_Wshadow, "declaration of %q+D shadows a parameter",
+                  new_decl);
+       else if (DECL_FILE_SCOPE_P (old_decl))
+         warning (OPT_Wshadow, "declaration of %q+D shadows a global "
+                  "declaration", new_decl);
+       else if (TREE_CODE (old_decl) == FUNCTION_DECL
+                && DECL_BUILT_IN (old_decl))
+         {
+           warning (OPT_Wshadow, "declaration of %q+D shadows "
+                    "a built-in function", new_decl);
+           break;
+         }
+       else
+         warning (OPT_Wshadow, "declaration of %q+D shadows a previous local",
+                  new_decl);
+
+       warning_at (DECL_SOURCE_LOCATION (old_decl), OPT_Wshadow,
+                   "shadowed declaration is here");
+
+       break;
+      }
+}
+
+/* Record a decl-node X as belonging to the current lexical scope.
+   Check for errors (such as an incompatible declaration for the same
+   name already seen in the same scope).
+
+   Returns either X or an old decl for the same name.
+   If an old decl is returned, it may have been smashed
+   to agree with what X says.  */
+
+tree
+pushdecl (tree x)
+{
+  tree name = DECL_NAME (x);
+  struct c_scope *scope = current_scope;
+  struct c_binding *b;
+  bool nested = false;
+  location_t locus = DECL_SOURCE_LOCATION (x);
+
+  /* Must set DECL_CONTEXT for everything not at file scope or
+     DECL_FILE_SCOPE_P won't work.  Local externs don't count
+     unless they have initializers (which generate code).  */
+  if (current_function_decl
+      && ((TREE_CODE (x) != FUNCTION_DECL && TREE_CODE (x) != VAR_DECL)
+         || DECL_INITIAL (x) || !DECL_EXTERNAL (x)))
+    DECL_CONTEXT (x) = current_function_decl;
+
+  /* Anonymous decls are just inserted in the scope.  */
+  if (!name)
+    {
+      bind (name, x, scope, /*invisible=*/false, /*nested=*/false,
+           locus);
+      return x;
+    }
+
+  /* First, see if there is another declaration with the same name in
+     the current scope.  If there is, duplicate_decls may do all the
+     work for us.  If duplicate_decls returns false, that indicates
+     two incompatible decls in the same scope; we are to silently
+     replace the old one (duplicate_decls has issued all appropriate
+     diagnostics).  In particular, we should not consider possible
+     duplicates in the external scope, or shadowing.  */
+  b = I_SYMBOL_BINDING (name);
+  if (b && B_IN_SCOPE (b, scope))
+    {
+      struct c_binding *b_ext, *b_use;
+      tree type = TREE_TYPE (x);
+      tree visdecl = b->decl;
+      tree vistype = TREE_TYPE (visdecl);
+      if (TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE
+         && COMPLETE_TYPE_P (TREE_TYPE (x)))
+       b->inner_comp = false;
+      b_use = b;
+      b_ext = b;
+      /* If this is an external linkage declaration, we should check
+        for compatibility with the type in the external scope before
+        setting the type at this scope based on the visible
+        information only.  */
+      if (TREE_PUBLIC (x) && TREE_PUBLIC (visdecl))
+       {
+         while (b_ext && !B_IN_EXTERNAL_SCOPE (b_ext))
+           b_ext = b_ext->shadowed;
+         if (b_ext)
+           {
+             b_use = b_ext;
+             if (b_use->u.type)
+               TREE_TYPE (b_use->decl) = b_use->u.type;
+           }
+       }
+      if (duplicate_decls (x, b_use->decl))
+       {
+         if (b_use != b)
+           {
+             /* Save the updated type in the external scope and
+                restore the proper type for this scope.  */
+             tree thistype;
+             if (comptypes (vistype, type))
+               thistype = composite_type (vistype, type);
+             else
+               thistype = TREE_TYPE (b_use->decl);
+             b_use->u.type = TREE_TYPE (b_use->decl);
+             if (TREE_CODE (b_use->decl) == FUNCTION_DECL
+                 && DECL_BUILT_IN (b_use->decl))
+               thistype
+                 = build_type_attribute_variant (thistype,
+                                                 TYPE_ATTRIBUTES
+                                                 (b_use->u.type));
+             TREE_TYPE (b_use->decl) = thistype;
+           }
+         return b_use->decl;
+       }
+      else
+       goto skip_external_and_shadow_checks;
+    }
+
+  /* All declarations with external linkage, and all external
+     references, go in the external scope, no matter what scope is
+     current.  However, the binding in that scope is ignored for
+     purposes of normal name lookup.  A separate binding structure is
+     created in the requested scope; this governs the normal
+     visibility of the symbol.
+
+     The binding in the externals scope is used exclusively for
+     detecting duplicate declarations of the same object, no matter
+     what scope they are in; this is what we do here.  (C99 6.2.7p2:
+     All declarations that refer to the same object or function shall
+     have compatible type; otherwise, the behavior is undefined.)  */
+  if (DECL_EXTERNAL (x) || scope == file_scope)
+    {
+      tree type = TREE_TYPE (x);
+      tree vistype = 0;
+      tree visdecl = 0;
+      bool type_saved = false;
+      if (b && !B_IN_EXTERNAL_SCOPE (b)
+         && (TREE_CODE (b->decl) == FUNCTION_DECL
+             || TREE_CODE (b->decl) == VAR_DECL)
+         && DECL_FILE_SCOPE_P (b->decl))
+       {
+         visdecl = b->decl;
+         vistype = TREE_TYPE (visdecl);
+       }
+      if (scope != file_scope
+         && !DECL_IN_SYSTEM_HEADER (x))
+       warning (OPT_Wnested_externs, "nested extern declaration of %qD", x);
+
+      while (b && !B_IN_EXTERNAL_SCOPE (b))
+       {
+         /* If this decl might be modified, save its type.  This is
+            done here rather than when the decl is first bound
+            because the type may change after first binding, through
+            being completed or through attributes being added.  If we
+            encounter multiple such decls, only the first should have
+            its type saved; the others will already have had their
+            proper types saved and the types will not have changed as
+            their scopes will not have been re-entered.  */
+         if (DECL_P (b->decl) && DECL_FILE_SCOPE_P (b->decl) && !type_saved)
+           {
+             b->u.type = TREE_TYPE (b->decl);
+             type_saved = true;
+           }
+         if (B_IN_FILE_SCOPE (b)
+             && TREE_CODE (b->decl) == VAR_DECL
+             && TREE_STATIC (b->decl)
+             && TREE_CODE (TREE_TYPE (b->decl)) == ARRAY_TYPE
+             && !TYPE_DOMAIN (TREE_TYPE (b->decl))
+             && TREE_CODE (type) == ARRAY_TYPE
+             && TYPE_DOMAIN (type)
+             && TYPE_MAX_VALUE (TYPE_DOMAIN (type))
+             && !integer_zerop (TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
+           {
+             /* Array type completed in inner scope, which should be
+                diagnosed if the completion does not have size 1 and
+                it does not get completed in the file scope.  */
+             b->inner_comp = true;
+           }
+         b = b->shadowed;
+       }
+
+      /* If a matching external declaration has been found, set its
+        type to the composite of all the types of that declaration.
+        After the consistency checks, it will be reset to the
+        composite of the visible types only.  */
+      if (b && (TREE_PUBLIC (x) || same_translation_unit_p (x, b->decl))
+         && b->u.type)
+       TREE_TYPE (b->decl) = b->u.type;
+
+      /* The point of the same_translation_unit_p check here is,
+        we want to detect a duplicate decl for a construct like
+        foo() { extern bar(); } ... static bar();  but not if
+        they are in different translation units.  In any case,
+        the static does not go in the externals scope.  */
+      if (b
+         && (TREE_PUBLIC (x) || same_translation_unit_p (x, b->decl))
+         && duplicate_decls (x, b->decl))
+       {
+         tree thistype;
+         if (vistype)
+           {
+             if (comptypes (vistype, type))
+               thistype = composite_type (vistype, type);
+             else
+               thistype = TREE_TYPE (b->decl);
+           }
+         else
+           thistype = type;
+         b->u.type = TREE_TYPE (b->decl);
+         if (TREE_CODE (b->decl) == FUNCTION_DECL && DECL_BUILT_IN (b->decl))
+           thistype
+             = build_type_attribute_variant (thistype,
+                                             TYPE_ATTRIBUTES (b->u.type));
+         TREE_TYPE (b->decl) = thistype;
+         bind (name, b->decl, scope, /*invisible=*/false, /*nested=*/true,
+               locus);
+         return b->decl;
+       }
+      else if (TREE_PUBLIC (x))
+       {
+         if (visdecl && !b && duplicate_decls (x, visdecl))
+           {
+             /* An external declaration at block scope referring to a
+                visible entity with internal linkage.  The composite
+                type will already be correct for this scope, so we
+                just need to fall through to make the declaration in
+                this scope.  */
+             nested = true;
+             x = visdecl;
+           }
+         else
+           {
+             bind (name, x, external_scope, /*invisible=*/true,
+                   /*nested=*/false, locus);
+             nested = true;
+           }
+       }
+    }
+
+  if (TREE_CODE (x) != PARM_DECL)
+    warn_if_shadowing (x);
+
+ skip_external_and_shadow_checks:
+  if (TREE_CODE (x) == TYPE_DECL)
+    {
+      /* So this is a typedef, set its underlying type.  */
+      set_underlying_type (x);
+
+      /* If X is a typedef defined in the current function, record it
+        for the purpose of implementing the -Wunused-local-typedefs
+        warning.  */
+      record_locally_defined_typedef (x);
+    }
+
+  bind (name, x, scope, /*invisible=*/false, nested, locus);
+
+  /* If x's type is incomplete because it's based on a
+     structure or union which has not yet been fully declared,
+     attach it to that structure or union type, so we can go
+     back and complete the variable declaration later, if the
+     structure or union gets fully declared.
+
+     If the input is erroneous, we can have error_mark in the type
+     slot (e.g. "f(void a, ...)") - that doesn't count as an
+     incomplete type.  */
+  if (TREE_TYPE (x) != error_mark_node
+      && !COMPLETE_TYPE_P (TREE_TYPE (x)))
+    {
+      tree element = TREE_TYPE (x);
+
+      while (TREE_CODE (element) == ARRAY_TYPE)
+       element = TREE_TYPE (element);
+      element = TYPE_MAIN_VARIANT (element);
+
+      if ((TREE_CODE (element) == RECORD_TYPE
+          || TREE_CODE (element) == UNION_TYPE)
+         && (TREE_CODE (x) != TYPE_DECL
+             || TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE)
+         && !COMPLETE_TYPE_P (element))
+       C_TYPE_INCOMPLETE_VARS (element)
+         = tree_cons (NULL_TREE, x, C_TYPE_INCOMPLETE_VARS (element));
+    }
+  return x;
+}
+
+/* Record X as belonging to file scope.
+   This is used only internally by the Objective-C front end,
+   and is limited to its needs.  duplicate_decls is not called;
+   if there is any preexisting decl for this identifier, it is an ICE.  */
+
+tree
+pushdecl_top_level (tree x)
+{
+  tree name;
+  bool nested = false;
+  gcc_assert (TREE_CODE (x) == VAR_DECL || TREE_CODE (x) == CONST_DECL);
+
+  name = DECL_NAME (x);
+
+ gcc_assert (TREE_CODE (x) == CONST_DECL || !I_SYMBOL_BINDING (name));
+
+  if (TREE_PUBLIC (x))
+    {
+      bind (name, x, external_scope, /*invisible=*/true, /*nested=*/false,
+           UNKNOWN_LOCATION);
+      nested = true;
+    }
+  if (file_scope)
+    bind (name, x, file_scope, /*invisible=*/false, nested, UNKNOWN_LOCATION);
+
+  return x;
+}
+\f
+static void
+implicit_decl_warning (tree id, tree olddecl)
+{
+  if (warn_implicit_function_declaration)
+    {
+      bool warned;
+
+      if (flag_isoc99)
+       warned = pedwarn (input_location, OPT_Wimplicit_function_declaration,
+                         "implicit declaration of function %qE", id);
+      else
+       warned = warning (OPT_Wimplicit_function_declaration,
+                         G_("implicit declaration of function %qE"), id);
+      if (olddecl && warned)
+       locate_old_decl (olddecl);
+    }
+}
+
+/* Generate an implicit declaration for identifier FUNCTIONID at LOC as a
+   function of type int ().  */
+
+tree
+implicitly_declare (location_t loc, tree functionid)
+{
+  struct c_binding *b;
+  tree decl = 0;
+  tree asmspec_tree;
+
+  for (b = I_SYMBOL_BINDING (functionid); b; b = b->shadowed)
+    {
+      if (B_IN_SCOPE (b, external_scope))
+       {
+         decl = b->decl;
+         break;
+       }
+    }
+
+  if (decl)
+    {
+      if (decl == error_mark_node)
+       return decl;
+
+      /* FIXME: Objective-C has weird not-really-builtin functions
+        which are supposed to be visible automatically.  They wind up
+        in the external scope because they're pushed before the file
+        scope gets created.  Catch this here and rebind them into the
+        file scope.  */
+      if (!DECL_BUILT_IN (decl) && DECL_IS_BUILTIN (decl))
+       {
+         bind (functionid, decl, file_scope,
+               /*invisible=*/false, /*nested=*/true,
+               DECL_SOURCE_LOCATION (decl));
+         return decl;
+       }
+      else
+       {
+         tree newtype = default_function_type;
+         if (b->u.type)
+           TREE_TYPE (decl) = b->u.type;
+         /* Implicit declaration of a function already declared
+            (somehow) in a different scope, or as a built-in.
+            If this is the first time this has happened, warn;
+            then recycle the old declaration but with the new type.  */
+         if (!C_DECL_IMPLICIT (decl))
+           {
+             implicit_decl_warning (functionid, decl);
+             C_DECL_IMPLICIT (decl) = 1;
+           }
+         if (DECL_BUILT_IN (decl))
+           {
+             newtype = build_type_attribute_variant (newtype,
+                                                     TYPE_ATTRIBUTES
+                                                     (TREE_TYPE (decl)));
+             if (!comptypes (newtype, TREE_TYPE (decl)))
+               {
+                 warning_at (loc, 0, "incompatible implicit declaration of "
+                             "built-in function %qD", decl);
+                 newtype = TREE_TYPE (decl);
+               }
+           }
+         else
+           {
+             if (!comptypes (newtype, TREE_TYPE (decl)))
+               {
+                 error_at (loc, "incompatible implicit declaration of function %qD", decl);
+                 locate_old_decl (decl);
+               }
+           }
+         b->u.type = TREE_TYPE (decl);
+         TREE_TYPE (decl) = newtype;
+         bind (functionid, decl, current_scope,
+               /*invisible=*/false, /*nested=*/true,
+               DECL_SOURCE_LOCATION (decl));
+         return decl;
+       }
+    }
+
+  /* Not seen before.  */
+  decl = build_decl (loc, FUNCTION_DECL, functionid, default_function_type);
+  DECL_EXTERNAL (decl) = 1;
+  TREE_PUBLIC (decl) = 1;
+  C_DECL_IMPLICIT (decl) = 1;
+  implicit_decl_warning (functionid, 0);
+  asmspec_tree = maybe_apply_renaming_pragma (decl, /*asmname=*/NULL);
+  if (asmspec_tree)
+    set_user_assembler_name (decl, TREE_STRING_POINTER (asmspec_tree));
+
+  /* C89 says implicit declarations are in the innermost block.
+     So we record the decl in the standard fashion.  */
+  decl = pushdecl (decl);
+
+  /* No need to call objc_check_decl here - it's a function type.  */
+  rest_of_decl_compilation (decl, 0, 0);
+
+  /* Write a record describing this implicit function declaration
+     to the prototypes file (if requested).  */
+  gen_aux_info_record (decl, 0, 1, 0);
+
+  /* Possibly apply some default attributes to this implicit declaration.  */
+  decl_attributes (&decl, NULL_TREE, 0);
+
+  return decl;
+}
+
+/* Issue an error message for a reference to an undeclared variable
+   ID, including a reference to a builtin outside of function-call
+   context.  Establish a binding of the identifier to error_mark_node
+   in an appropriate scope, which will suppress further errors for the
+   same identifier.  The error message should be given location LOC.  */
+void
+undeclared_variable (location_t loc, tree id)
+{
+  static bool already = false;
+  struct c_scope *scope;
+
+  if (current_function_decl == 0)
+    {
+      error_at (loc, "%qE undeclared here (not in a function)", id);
+      scope = current_scope;
+    }
+  else
+    {
+      if (!objc_diagnose_private_ivar (id))
+        error_at (loc, "%qE undeclared (first use in this function)", id);
+      if (!already)
+       {
+          inform (loc, "each undeclared identifier is reported only"
+                  " once for each function it appears in");
+         already = true;
+       }
+
+      /* If we are parsing old-style parameter decls, current_function_decl
+        will be nonnull but current_function_scope will be null.  */
+      scope = current_function_scope ? current_function_scope : current_scope;
+    }
+  bind (id, error_mark_node, scope, /*invisible=*/false, /*nested=*/false,
+       UNKNOWN_LOCATION);
+}
+\f
+/* Subroutine of lookup_label, declare_label, define_label: construct a
+   LABEL_DECL with all the proper frills.  Also create a struct
+   c_label_vars initialized for the current scope.  */
+
+static tree
+make_label (location_t location, tree name, bool defining,
+           struct c_label_vars **p_label_vars)
+{
+  tree label = build_decl (location, LABEL_DECL, name, void_type_node);
+  struct c_label_vars *label_vars;
+
+  DECL_CONTEXT (label) = current_function_decl;
+  DECL_MODE (label) = VOIDmode;
+
+  label_vars = ggc_alloc_c_label_vars ();
+  label_vars->shadowed = NULL;
+  set_spot_bindings (&label_vars->label_bindings, defining);
+  label_vars->decls_in_scope = make_tree_vector ();
+  label_vars->gotos = VEC_alloc (c_goto_bindings_p, gc, 0);
+  *p_label_vars = label_vars;
+
+  return label;
+}
+
+/* Get the LABEL_DECL corresponding to identifier NAME as a label.
+   Create one if none exists so far for the current function.
+   This is called when a label is used in a goto expression or
+   has its address taken.  */
+
+tree
+lookup_label (tree name)
+{
+  tree label;
+  struct c_label_vars *label_vars;
+
+  if (current_function_scope == 0)
+    {
+      error ("label %qE referenced outside of any function", name);
+      return 0;
+    }
+
+  /* Use a label already defined or ref'd with this name, but not if
+     it is inherited from a containing function and wasn't declared
+     using __label__.  */
+  label = I_LABEL_DECL (name);
+  if (label && (DECL_CONTEXT (label) == current_function_decl
+               || C_DECLARED_LABEL_FLAG (label)))
+    {
+      /* If the label has only been declared, update its apparent
+        location to point here, for better diagnostics if it
+        turns out not to have been defined.  */
+      if (DECL_INITIAL (label) == NULL_TREE)
+       DECL_SOURCE_LOCATION (label) = input_location;
+      return label;
+    }
+
+  /* No label binding for that identifier; make one.  */
+  label = make_label (input_location, name, false, &label_vars);
+
+  /* Ordinary labels go in the current function scope.  */
+  bind_label (name, label, current_function_scope, label_vars);
+
+  return label;
+}
+
+/* Issue a warning about DECL for a goto statement at GOTO_LOC going
+   to LABEL.  */
+
+static void
+warn_about_goto (location_t goto_loc, tree label, tree decl)
+{
+  if (variably_modified_type_p (TREE_TYPE (decl), NULL_TREE))
+    error_at (goto_loc,
+             "jump into scope of identifier with variably modified type");
+  else
+    warning_at (goto_loc, OPT_Wjump_misses_init,
+               "jump skips variable initialization");
+  inform (DECL_SOURCE_LOCATION (label), "label %qD defined here", label);
+  inform (DECL_SOURCE_LOCATION (decl), "%qD declared here", decl);
+}
+
+/* Look up a label because of a goto statement.  This is like
+   lookup_label, but also issues any appropriate warnings.  */
+
+tree
+lookup_label_for_goto (location_t loc, tree name)
+{
+  tree label;
+  struct c_label_vars *label_vars;
+  unsigned int ix;
+  tree decl;
+
+  label = lookup_label (name);
+  if (label == NULL_TREE)
+    return NULL_TREE;
+
+  /* If we are jumping to a different function, we can't issue any
+     useful warnings.  */
+  if (DECL_CONTEXT (label) != current_function_decl)
+    {
+      gcc_assert (C_DECLARED_LABEL_FLAG (label));
+      return label;
+    }
+
+  label_vars = I_LABEL_BINDING (name)->u.label;
+
+  /* If the label has not yet been defined, then push this goto on a
+     list for possible later warnings.  */
+  if (label_vars->label_bindings.scope == NULL)
+    {
+      struct c_goto_bindings *g;
+
+      g = ggc_alloc_c_goto_bindings ();
+      g->loc = loc;
+      set_spot_bindings (&g->goto_bindings, true);
+      VEC_safe_push (c_goto_bindings_p, gc, label_vars->gotos, g);
+      return label;
+    }
+
+  /* If there are any decls in label_vars->decls_in_scope, then this
+     goto has missed the declaration of the decl.  This happens for a
+     case like
+       int i = 1;
+      lab:
+       ...
+       goto lab;
+     Issue a warning or error.  */
+  FOR_EACH_VEC_ELT (tree, label_vars->decls_in_scope, ix, decl)
+    warn_about_goto (loc, label, decl);
+
+  if (label_vars->label_bindings.left_stmt_expr)
+    {
+      error_at (loc, "jump into statement expression");
+      inform (DECL_SOURCE_LOCATION (label), "label %qD defined here", label);
+    }
+
+  return label;
+}
+
+/* Make a label named NAME in the current function, shadowing silently
+   any that may be inherited from containing functions or containing
+   scopes.  This is called for __label__ declarations.  */
+
+tree
+declare_label (tree name)
+{
+  struct c_binding *b = I_LABEL_BINDING (name);
+  tree label;
+  struct c_label_vars *label_vars;
+
+  /* Check to make sure that the label hasn't already been declared
+     at this scope */
+  if (b && B_IN_CURRENT_SCOPE (b))
+    {
+      error ("duplicate label declaration %qE", name);
+      locate_old_decl (b->decl);
+
+      /* Just use the previous declaration.  */
+      return b->decl;
+    }
+
+  label = make_label (input_location, name, false, &label_vars);
+  C_DECLARED_LABEL_FLAG (label) = 1;
+
+  /* Declared labels go in the current scope.  */
+  bind_label (name, label, current_scope, label_vars);
+
+  return label;
+}
+
+/* When we define a label, issue any appropriate warnings if there are
+   any gotos earlier in the function which jump to this label.  */
+
+static void
+check_earlier_gotos (tree label, struct c_label_vars* label_vars)
+{
+  unsigned int ix;
+  struct c_goto_bindings *g;
+
+  FOR_EACH_VEC_ELT (c_goto_bindings_p, label_vars->gotos, ix, g)
+    {
+      struct c_binding *b;
+      struct c_scope *scope;
+
+      /* We have a goto to this label.  The goto is going forward.  In
+        g->scope, the goto is going to skip any binding which was
+        defined after g->bindings_in_scope.  */
+      if (g->goto_bindings.scope->has_jump_unsafe_decl)
+       {
+         for (b = g->goto_bindings.scope->bindings;
+              b != g->goto_bindings.bindings_in_scope;
+              b = b->prev)
+           {
+             if (decl_jump_unsafe (b->decl))
+               warn_about_goto (g->loc, label, b->decl);
+           }
+       }
+
+      /* We also need to warn about decls defined in any scopes
+        between the scope of the label and the scope of the goto.  */
+      for (scope = label_vars->label_bindings.scope;
+          scope != g->goto_bindings.scope;
+          scope = scope->outer)
+       {
+         gcc_assert (scope != NULL);
+         if (scope->has_jump_unsafe_decl)
+           {
+             if (scope == label_vars->label_bindings.scope)
+               b = label_vars->label_bindings.bindings_in_scope;
+             else
+               b = scope->bindings;
+             for (; b != NULL; b = b->prev)
+               {
+                 if (decl_jump_unsafe (b->decl))
+                   warn_about_goto (g->loc, label, b->decl);
+               }
+           }
+       }
+
+      if (g->goto_bindings.stmt_exprs > 0)
+       {
+         error_at (g->loc, "jump into statement expression");
+         inform (DECL_SOURCE_LOCATION (label), "label %qD defined here",
+                 label);
+       }
+    }
+
+  /* Now that the label is defined, we will issue warnings about
+     subsequent gotos to this label when we see them.  */
+  VEC_truncate (c_goto_bindings_p, label_vars->gotos, 0);
+  label_vars->gotos = NULL;
+}
+
+/* Define a label, specifying the location in the source file.
+   Return the LABEL_DECL node for the label, if the definition is valid.
+   Otherwise return 0.  */
+
+tree
+define_label (location_t location, tree name)
+{
+  /* Find any preexisting label with this name.  It is an error
+     if that label has already been defined in this function, or
+     if there is a containing function with a declared label with
+     the same name.  */
+  tree label = I_LABEL_DECL (name);
+
+  if (label
+      && ((DECL_CONTEXT (label) == current_function_decl
+          && DECL_INITIAL (label) != 0)
+         || (DECL_CONTEXT (label) != current_function_decl
+             && C_DECLARED_LABEL_FLAG (label))))
+    {
+      error_at (location, "duplicate label %qD", label);
+      locate_old_decl (label);
+      return 0;
+    }
+  else if (label && DECL_CONTEXT (label) == current_function_decl)
+    {
+      struct c_label_vars *label_vars = I_LABEL_BINDING (name)->u.label;
+
+      /* The label has been used or declared already in this function,
+        but not defined.  Update its location to point to this
+        definition.  */
+      DECL_SOURCE_LOCATION (label) = location;
+      set_spot_bindings (&label_vars->label_bindings, true);
+
+      /* Issue warnings as required about any goto statements from
+        earlier in the function.  */
+      check_earlier_gotos (label, label_vars);
+    }
+  else
+    {
+      struct c_label_vars *label_vars;
+
+      /* No label binding for that identifier; make one.  */
+      label = make_label (location, name, true, &label_vars);
+
+      /* Ordinary labels go in the current function scope.  */
+      bind_label (name, label, current_function_scope, label_vars);
+    }
+
+  if (!in_system_header && lookup_name (name))
+    warning_at (location, OPT_Wtraditional,
+               "traditional C lacks a separate namespace "
+               "for labels, identifier %qE conflicts", name);
+
+  /* Mark label as having been defined.  */
+  DECL_INITIAL (label) = error_mark_node;
+  return label;
+}
+\f
+/* Get the bindings for a new switch statement.  This is used to issue
+   warnings as appropriate for jumps from the switch to case or
+   default labels.  */
+
+struct c_spot_bindings *
+c_get_switch_bindings (void)
+{
+  struct c_spot_bindings *switch_bindings;
+
+  switch_bindings = XNEW (struct c_spot_bindings);
+  set_spot_bindings (switch_bindings, true);
+  return switch_bindings;
+}
+
+void
+c_release_switch_bindings (struct c_spot_bindings *bindings)
+{
+  gcc_assert (bindings->stmt_exprs == 0 && !bindings->left_stmt_expr);
+  XDELETE (bindings);
+}
+
+/* This is called at the point of a case or default label to issue
+   warnings about decls as needed.  It returns true if it found an
+   error, not just a warning.  */
+
+bool
+c_check_switch_jump_warnings (struct c_spot_bindings *switch_bindings,
+                             location_t switch_loc, location_t case_loc)
+{
+  bool saw_error;
+  struct c_scope *scope;
+
+  saw_error = false;
+  for (scope = current_scope;
+       scope != switch_bindings->scope;
+       scope = scope->outer)
+    {
+      struct c_binding *b;
+
+      gcc_assert (scope != NULL);
+
+      if (!scope->has_jump_unsafe_decl)
+       continue;
+
+      for (b = scope->bindings; b != NULL; b = b->prev)
+       {
+         if (decl_jump_unsafe (b->decl))
+           {
+             if (variably_modified_type_p (TREE_TYPE (b->decl), NULL_TREE))
+               {
+                 saw_error = true;
+                 error_at (case_loc,
+                           ("switch jumps into scope of identifier with "
+                            "variably modified type"));
+               }
+             else
+               warning_at (case_loc, OPT_Wjump_misses_init,
+                           "switch jumps over variable initialization");
+             inform (switch_loc, "switch starts here");
+             inform (DECL_SOURCE_LOCATION (b->decl), "%qD declared here",
+                     b->decl);
+           }
+       }
+    }
+
+  if (switch_bindings->stmt_exprs > 0)
+    {
+      saw_error = true;
+      error_at (case_loc, "switch jumps into statement expression");
+      inform (switch_loc, "switch starts here");
+    }
+
+  return saw_error;
+}
+\f
+/* Given NAME, an IDENTIFIER_NODE,
+   return the structure (or union or enum) definition for that name.
+   If THISLEVEL_ONLY is nonzero, searches only the current_scope.
+   CODE says which kind of type the caller wants;
+   it is RECORD_TYPE or UNION_TYPE or ENUMERAL_TYPE.
+   If PLOC is not NULL and this returns non-null, it sets *PLOC to the
+   location where the tag was defined.
+   If the wrong kind of type is found, an error is reported.  */
+
+static tree
+lookup_tag (enum tree_code code, tree name, int thislevel_only,
+           location_t *ploc)
+{
+  struct c_binding *b = I_TAG_BINDING (name);
+  int thislevel = 0;
+
+  if (!b || !b->decl)
+    return 0;
+
+  /* We only care about whether it's in this level if
+     thislevel_only was set or it might be a type clash.  */
+  if (thislevel_only || TREE_CODE (b->decl) != code)
+    {
+      /* For our purposes, a tag in the external scope is the same as
+        a tag in the file scope.  (Primarily relevant to Objective-C
+        and its builtin structure tags, which get pushed before the
+        file scope is created.)  */
+      if (B_IN_CURRENT_SCOPE (b)
+         || (current_scope == file_scope && B_IN_EXTERNAL_SCOPE (b)))
+       thislevel = 1;
+    }
+
+  if (thislevel_only && !thislevel)
+    return 0;
+
+  if (TREE_CODE (b->decl) != code)
+    {
+      /* Definition isn't the kind we were looking for.  */
+      pending_invalid_xref = name;
+      pending_invalid_xref_location = input_location;
+
+      /* If in the same binding level as a declaration as a tag
+        of a different type, this must not be allowed to
+        shadow that tag, so give the error immediately.
+        (For example, "struct foo; union foo;" is invalid.)  */
+      if (thislevel)
+       pending_xref_error ();
+    }
+
+  if (ploc != NULL)
+    *ploc = b->locus;
+
+  return b->decl;
+}
+
+/* Print an error message now
+   for a recent invalid struct, union or enum cross reference.
+   We don't print them immediately because they are not invalid
+   when used in the `struct foo;' construct for shadowing.  */
+
+void
+pending_xref_error (void)
+{
+  if (pending_invalid_xref != 0)
+    error_at (pending_invalid_xref_location, "%qE defined as wrong kind of tag",
+             pending_invalid_xref);
+  pending_invalid_xref = 0;
+}
+
+\f
+/* Look up NAME in the current scope and its superiors
+   in the namespace of variables, functions and typedefs.
+   Return a ..._DECL node of some kind representing its definition,
+   or return 0 if it is undefined.  */
+
+tree
+lookup_name (tree name)
+{
+  struct c_binding *b = I_SYMBOL_BINDING (name);
+  if (b && !b->invisible)
+    {
+      maybe_record_typedef_use (b->decl);
+      return b->decl;
+    }
+  return 0;
+}
+
+/* Similar to `lookup_name' but look only at the indicated scope.  */
+
+static tree
+lookup_name_in_scope (tree name, struct c_scope *scope)
+{
+  struct c_binding *b;
+
+  for (b = I_SYMBOL_BINDING (name); b; b = b->shadowed)
+    if (B_IN_SCOPE (b, scope))
+      return b->decl;
+  return 0;
+}
+\f
+/* Create the predefined scalar types of C,
+   and some nodes representing standard constants (0, 1, (void *) 0).
+   Initialize the global scope.
+   Make definitions for built-in primitive functions.  */
+
+void
+c_init_decl_processing (void)
+{
+  location_t save_loc = input_location;
+
+  /* Initialize reserved words for parser.  */
+  c_parse_init ();
+
+  current_function_decl = 0;
+
+  gcc_obstack_init (&parser_obstack);
+
+  /* Make the externals scope.  */
+  push_scope ();
+  external_scope = current_scope;
+
+  /* Declarations from c_common_nodes_and_builtins must not be associated
+     with this input file, lest we get differences between using and not
+     using preprocessed headers.  */
+  input_location = BUILTINS_LOCATION;
+
+  c_common_nodes_and_builtins ();
+
+  /* In C, comparisons and TRUTH_* expressions have type int.  */
+  truthvalue_type_node = integer_type_node;
+  truthvalue_true_node = integer_one_node;
+  truthvalue_false_node = integer_zero_node;
+
+  /* Even in C99, which has a real boolean type.  */
+  pushdecl (build_decl (UNKNOWN_LOCATION, TYPE_DECL, get_identifier ("_Bool"),
+                       boolean_type_node));
+
+  input_location = save_loc;
+
+  pedantic_lvalues = true;
+
+  make_fname_decl = c_make_fname_decl;
+  start_fname_decls ();
+}
+
+/* Create the VAR_DECL at LOC for __FUNCTION__ etc. ID is the name to
+   give the decl, NAME is the initialization string and TYPE_DEP
+   indicates whether NAME depended on the type of the function.  As we
+   don't yet implement delayed emission of static data, we mark the
+   decl as emitted so it is not placed in the output.  Anything using
+   it must therefore pull out the STRING_CST initializer directly.
+   FIXME.  */
+
+static tree
+c_make_fname_decl (location_t loc, tree id, int type_dep)
+{
+  const char *name = fname_as_string (type_dep);
+  tree decl, type, init;
+  size_t length = strlen (name);
+
+  type = build_array_type (char_type_node,
+                          build_index_type (size_int (length)));
+  type = c_build_qualified_type (type, TYPE_QUAL_CONST);
+
+  decl = build_decl (loc, VAR_DECL, id, type);
+
+  TREE_STATIC (decl) = 1;
+  TREE_READONLY (decl) = 1;
+  DECL_ARTIFICIAL (decl) = 1;
+
+  init = build_string (length + 1, name);
+  free (CONST_CAST (char *, name));
+  TREE_TYPE (init) = type;
+  DECL_INITIAL (decl) = init;
+
+  TREE_USED (decl) = 1;
+
+  if (current_function_decl
+      /* For invalid programs like this:
+
+         void foo()
+         const char* p = __FUNCTION__;
+
+        the __FUNCTION__ is believed to appear in K&R style function
+        parameter declarator.  In that case we still don't have
+        function_scope.  */
+      && (!seen_error () || current_function_scope))
+    {
+      DECL_CONTEXT (decl) = current_function_decl;
+      bind (id, decl, current_function_scope,
+           /*invisible=*/false, /*nested=*/false, UNKNOWN_LOCATION);
+    }
+
+  finish_decl (decl, loc, init, NULL_TREE, NULL_TREE);
+
+  return decl;
+}
+
+tree
+c_builtin_function (tree decl)
+{
+  tree type = TREE_TYPE (decl);
+  tree   id = DECL_NAME (decl);
+
+  const char *name = IDENTIFIER_POINTER (id);
+  C_DECL_BUILTIN_PROTOTYPE (decl) = prototype_p (type);
+
+  /* Should never be called on a symbol with a preexisting meaning.  */
+  gcc_assert (!I_SYMBOL_BINDING (id));
+
+  bind (id, decl, external_scope, /*invisible=*/true, /*nested=*/false,
+       UNKNOWN_LOCATION);
+
+  /* Builtins in the implementation namespace are made visible without
+     needing to be explicitly declared.  See push_file_scope.  */
+  if (name[0] == '_' && (name[1] == '_' || ISUPPER (name[1])))
+    {
+      DECL_CHAIN (decl) = visible_builtins;
+      visible_builtins = decl;
+    }
+
+  return decl;
+}
+
+tree
+c_builtin_function_ext_scope (tree decl)
+{
+  tree type = TREE_TYPE (decl);
+  tree   id = DECL_NAME (decl);
+
+  const char *name = IDENTIFIER_POINTER (id);
+  C_DECL_BUILTIN_PROTOTYPE (decl) = prototype_p (type);
+
+  /* Should never be called on a symbol with a preexisting meaning.  */
+  gcc_assert (!I_SYMBOL_BINDING (id));
+
+  bind (id, decl, external_scope, /*invisible=*/false, /*nested=*/false,
+       UNKNOWN_LOCATION);
+
+  /* Builtins in the implementation namespace are made visible without
+     needing to be explicitly declared.  See push_file_scope.  */
+  if (name[0] == '_' && (name[1] == '_' || ISUPPER (name[1])))
+    {
+      DECL_CHAIN (decl) = visible_builtins;
+      visible_builtins = decl;
+    }
+
+  return decl;
+}
+\f
+/* Called when a declaration is seen that contains no names to declare.
+   If its type is a reference to a structure, union or enum inherited
+   from a containing scope, shadow that tag name for the current scope
+   with a forward reference.
+   If its type defines a new named structure or union
+   or defines an enum, it is valid but we need not do anything here.
+   Otherwise, it is an error.  */
+
+void
+shadow_tag (const struct c_declspecs *declspecs)
+{
+  shadow_tag_warned (declspecs, 0);
+}
+
+/* WARNED is 1 if we have done a pedwarn, 2 if we have done a warning,
+   but no pedwarn.  */
+void
+shadow_tag_warned (const struct c_declspecs *declspecs, int warned)
+{
+  bool found_tag = false;
+
+  if (declspecs->type && !declspecs->default_int_p && !declspecs->typedef_p)
+    {
+      tree value = declspecs->type;
+      enum tree_code code = TREE_CODE (value);
+
+      if (code == RECORD_TYPE || code == UNION_TYPE || code == ENUMERAL_TYPE)
+       /* Used to test also that TYPE_SIZE (value) != 0.
+          That caused warning for `struct foo;' at top level in the file.  */
+       {
+         tree name = TYPE_NAME (value);
+         tree t;
+
+         found_tag = true;
+
+         if (declspecs->restrict_p)
+           {
+             error ("invalid use of %<restrict%>");
+             warned = 1;
+           }
+
+         if (name == 0)
+           {
+             if (warned != 1 && code != ENUMERAL_TYPE)
+               /* Empty unnamed enum OK */
+               {
+                 pedwarn (input_location, 0,
+                          "unnamed struct/union that defines no instances");
+                 warned = 1;
+               }
+           }
+         else if (declspecs->typespec_kind != ctsk_tagdef
+                   && declspecs->typespec_kind != ctsk_tagfirstref
+                  && declspecs->storage_class != csc_none)
+           {
+             if (warned != 1)
+               pedwarn (input_location, 0,
+                        "empty declaration with storage class specifier "
+                        "does not redeclare tag");
+             warned = 1;
+             pending_xref_error ();
+           }
+         else if (declspecs->typespec_kind != ctsk_tagdef
+                   && declspecs->typespec_kind != ctsk_tagfirstref
+                  && (declspecs->const_p
+                      || declspecs->volatile_p
+                      || declspecs->restrict_p
+                      || declspecs->address_space))
+           {
+             if (warned != 1)
+               pedwarn (input_location, 0,
+                        "empty declaration with type qualifier "
+                         "does not redeclare tag");
+             warned = 1;
+             pending_xref_error ();
+           }
+         else if (declspecs->typespec_kind != ctsk_tagdef
+                   && declspecs->typespec_kind != ctsk_tagfirstref
+                  && declspecs->alignas_p)
+           {
+             if (warned != 1)
+               pedwarn (input_location, 0,
+                        "empty declaration with %<_Alignas%> "
+                         "does not redeclare tag");
+             warned = 1;
+             pending_xref_error ();
+           }
+         else
+           {
+             pending_invalid_xref = 0;
+             t = lookup_tag (code, name, 1, NULL);
+
+             if (t == 0)
+               {
+                 t = make_node (code);
+                 pushtag (input_location, name, t);
+               }
+           }
+       }
+      else
+       {
+         if (warned != 1 && !in_system_header)
+           {
+             pedwarn (input_location, 0,
+                      "useless type name in empty declaration");
+             warned = 1;
+           }
+       }
+    }
+  else if (warned != 1 && !in_system_header && declspecs->typedef_p)
+    {
+      pedwarn (input_location, 0, "useless type name in empty declaration");
+      warned = 1;
+    }
+
+  pending_invalid_xref = 0;
+
+  if (declspecs->inline_p)
+    {
+      error ("%<inline%> in empty declaration");
+      warned = 1;
+    }
+
+  if (declspecs->noreturn_p)
+    {
+      error ("%<_Noreturn%> in empty declaration");
+      warned = 1;
+    }
+
+  if (current_scope == file_scope && declspecs->storage_class == csc_auto)
+    {
+      error ("%<auto%> in file-scope empty declaration");
+      warned = 1;
+    }
+
+  if (current_scope == file_scope && declspecs->storage_class == csc_register)
+    {
+      error ("%<register%> in file-scope empty declaration");
+      warned = 1;
+    }
+
+  if (!warned && !in_system_header && declspecs->storage_class != csc_none)
+    {
+      warning (0, "useless storage class specifier in empty declaration");
+      warned = 2;
+    }
+
+  if (!warned && !in_system_header && declspecs->thread_p)
+    {
+      warning (0, "useless %<__thread%> in empty declaration");
+      warned = 2;
+    }
+
+  if (!warned && !in_system_header && (declspecs->const_p
+                                      || declspecs->volatile_p
+                                      || declspecs->restrict_p
+                                      || declspecs->address_space))
+    {
+      warning (0, "useless type qualifier in empty declaration");
+      warned = 2;
+    }
+
+  if (!warned && !in_system_header && declspecs->alignas_p)
+    {
+      warning (0, "useless %<_Alignas%> in empty declaration");
+      warned = 2;
+    }
+
+  if (warned != 1)
+    {
+      if (!found_tag)
+       pedwarn (input_location, 0, "empty declaration");
+    }
+}
+\f
+
+/* Return the qualifiers from SPECS as a bitwise OR of TYPE_QUAL_*
+   bits.  SPECS represents declaration specifiers that the grammar
+   only permits to contain type qualifiers and attributes.  */
+
+int
+quals_from_declspecs (const struct c_declspecs *specs)
+{
+  int quals = ((specs->const_p ? TYPE_QUAL_CONST : 0)
+              | (specs->volatile_p ? TYPE_QUAL_VOLATILE : 0)
+              | (specs->restrict_p ? TYPE_QUAL_RESTRICT : 0)
+              | (ENCODE_QUAL_ADDR_SPACE (specs->address_space)));
+  gcc_assert (!specs->type
+             && !specs->decl_attr
+             && specs->typespec_word == cts_none
+             && specs->storage_class == csc_none
+             && !specs->typedef_p
+             && !specs->explicit_signed_p
+             && !specs->deprecated_p
+             && !specs->long_p
+             && !specs->long_long_p
+             && !specs->short_p
+             && !specs->signed_p
+             && !specs->unsigned_p
+             && !specs->complex_p
+             && !specs->inline_p
+             && !specs->noreturn_p
+             && !specs->thread_p);
+  return quals;
+}
+
+/* Construct an array declarator.  LOC is the location of the
+   beginning of the array (usually the opening brace).  EXPR is the
+   expression inside [], or NULL_TREE.  QUALS are the type qualifiers
+   inside the [] (to be applied to the pointer to which a parameter
+   array is converted).  STATIC_P is true if "static" is inside the
+   [], false otherwise.  VLA_UNSPEC_P is true if the array is [*], a
+   VLA of unspecified length which is nevertheless a complete type,
+   false otherwise.  The field for the contained declarator is left to
+   be filled in by set_array_declarator_inner.  */
+
+struct c_declarator *
+build_array_declarator (location_t loc,
+                       tree expr, struct c_declspecs *quals, bool static_p,
+                       bool vla_unspec_p)
+{
+  struct c_declarator *declarator = XOBNEW (&parser_obstack,
+                                           struct c_declarator);
+  declarator->id_loc = loc;
+  declarator->kind = cdk_array;
+  declarator->declarator = 0;
+  declarator->u.array.dimen = expr;
+  if (quals)
+    {
+      declarator->u.array.attrs = quals->attrs;
+      declarator->u.array.quals = quals_from_declspecs (quals);
+    }
+  else
+    {
+      declarator->u.array.attrs = NULL_TREE;
+      declarator->u.array.quals = 0;
+    }
+  declarator->u.array.static_p = static_p;
+  declarator->u.array.vla_unspec_p = vla_unspec_p;
+  if (!flag_isoc99)
+    {
+      if (static_p || quals != NULL)
+       pedwarn (loc, OPT_Wpedantic,
+                "ISO C90 does not support %<static%> or type "
+                "qualifiers in parameter array declarators");
+      if (vla_unspec_p)
+       pedwarn (loc, OPT_Wpedantic,
+                "ISO C90 does not support %<[*]%> array declarators");
+    }
+  if (vla_unspec_p)
+    {
+      if (!current_scope->parm_flag)
+       {
+         /* C99 6.7.5.2p4 */
+         error_at (loc, "%<[*]%> not allowed in other than "
+                   "function prototype scope");
+         declarator->u.array.vla_unspec_p = false;
+         return NULL;
+       }
+      current_scope->had_vla_unspec = true;
+    }
+  return declarator;
+}
+
+/* Set the contained declarator of an array declarator.  DECL is the
+   declarator, as constructed by build_array_declarator; INNER is what
+   appears on the left of the [].  */
+
+struct c_declarator *
+set_array_declarator_inner (struct c_declarator *decl,
+                           struct c_declarator *inner)
+{
+  decl->declarator = inner;
+  return decl;
+}
+
+/* INIT is a constructor that forms DECL's initializer.  If the final
+   element initializes a flexible array field, add the size of that
+   initializer to DECL's size.  */
+
+static void
+add_flexible_array_elts_to_size (tree decl, tree init)
+{
+  tree elt, type;
+
+  if (VEC_empty (constructor_elt, CONSTRUCTOR_ELTS (init)))
+    return;
+
+  elt = VEC_last (constructor_elt, CONSTRUCTOR_ELTS (init))->value;
+  type = TREE_TYPE (elt);
+  if (TREE_CODE (type) == ARRAY_TYPE
+      && TYPE_SIZE (type) == NULL_TREE
+      && TYPE_DOMAIN (type) != NULL_TREE
+      && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL_TREE)
+    {
+      complete_array_type (&type, elt, false);
+      DECL_SIZE (decl)
+       = size_binop (PLUS_EXPR, DECL_SIZE (decl), TYPE_SIZE (type));
+      DECL_SIZE_UNIT (decl)
+       = size_binop (PLUS_EXPR, DECL_SIZE_UNIT (decl), TYPE_SIZE_UNIT (type));
+    }
+}
+\f
+/* Decode a "typename", such as "int **", returning a ..._TYPE node.
+   Set *EXPR, if EXPR not NULL, to any expression to be evaluated
+   before the type name, and set *EXPR_CONST_OPERANDS, if
+   EXPR_CONST_OPERANDS not NULL, to indicate whether the type name may
+   appear in a constant expression.  */
+
+tree
+groktypename (struct c_type_name *type_name, tree *expr,
+             bool *expr_const_operands)
+{
+  tree type;
+  tree attrs = type_name->specs->attrs;
+
+  type_name->specs->attrs = NULL_TREE;
+
+  type = grokdeclarator (type_name->declarator, type_name->specs, TYPENAME,
+                        false, NULL, &attrs, expr, expr_const_operands,
+                        DEPRECATED_NORMAL);
+
+  /* Apply attributes.  */
+  decl_attributes (&type, attrs, 0);
+
+  return type;
+}
+
+/* Decode a declarator in an ordinary declaration or data definition.
+   This is called as soon as the type information and variable name
+   have been parsed, before parsing the initializer if any.
+   Here we create the ..._DECL node, fill in its type,
+   and put it on the list of decls for the current context.
+   The ..._DECL node is returned as the value.
+
+   Exception: for arrays where the length is not specified,
+   the type is left null, to be filled in by `finish_decl'.
+
+   Function definitions do not come here; they go to start_function
+   instead.  However, external and forward declarations of functions
+   do go through here.  Structure field declarations are done by
+   grokfield and not through here.  */
+
+tree
+start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs,
+           bool initialized, tree attributes)
+{
+  tree decl;
+  tree tem;
+  tree expr = NULL_TREE;
+  enum deprecated_states deprecated_state = DEPRECATED_NORMAL;
+
+  /* An object declared as __attribute__((deprecated)) suppresses
+     warnings of uses of other deprecated items.  */
+  if (lookup_attribute ("deprecated", attributes))
+    deprecated_state = DEPRECATED_SUPPRESS;
+
+  decl = grokdeclarator (declarator, declspecs,
+                        NORMAL, initialized, NULL, &attributes, &expr, NULL,
+                        deprecated_state);
+  if (!decl)
+    return 0;
+
+  if (expr)
+    add_stmt (fold_convert (void_type_node, expr));
+
+  if (TREE_CODE (decl) != FUNCTION_DECL && MAIN_NAME_P (DECL_NAME (decl)))
+    warning (OPT_Wmain, "%q+D is usually a function", decl);
+
+  if (initialized)
+    /* Is it valid for this decl to have an initializer at all?
+       If not, set INITIALIZED to zero, which will indirectly
+       tell 'finish_decl' to ignore the initializer once it is parsed.  */
+    switch (TREE_CODE (decl))
+      {
+      case TYPE_DECL:
+       error ("typedef %qD is initialized (use __typeof__ instead)", decl);
+       initialized = 0;
+       break;
+
+      case FUNCTION_DECL:
+       error ("function %qD is initialized like a variable", decl);
+       initialized = 0;
+       break;
+
+      case PARM_DECL:
+       /* DECL_INITIAL in a PARM_DECL is really DECL_ARG_TYPE.  */
+       error ("parameter %qD is initialized", decl);
+       initialized = 0;
+       break;
+
+      default:
+       /* Don't allow initializations for incomplete types except for
+          arrays which might be completed by the initialization.  */
+
+       /* This can happen if the array size is an undefined macro.
+          We already gave a warning, so we don't need another one.  */
+       if (TREE_TYPE (decl) == error_mark_node)
+         initialized = 0;
+       else if (COMPLETE_TYPE_P (TREE_TYPE (decl)))
+         {
+           /* A complete type is ok if size is fixed.  */
+
+           if (TREE_CODE (TYPE_SIZE (TREE_TYPE (decl))) != INTEGER_CST
+               || C_DECL_VARIABLE_SIZE (decl))
+             {
+               error ("variable-sized object may not be initialized");
+               initialized = 0;
+             }
+         }
+       else if (TREE_CODE (TREE_TYPE (decl)) != ARRAY_TYPE)
+         {
+           error ("variable %qD has initializer but incomplete type", decl);
+           initialized = 0;
+         }
+       else if (C_DECL_VARIABLE_SIZE (decl))
+         {
+           /* Although C99 is unclear about whether incomplete arrays
+              of VLAs themselves count as VLAs, it does not make
+              sense to permit them to be initialized given that
+              ordinary VLAs may not be initialized.  */
+           error ("variable-sized object may not be initialized");
+           initialized = 0;
+         }
+      }
+
+  if (initialized)
+    {
+      if (current_scope == file_scope)
+       TREE_STATIC (decl) = 1;
+
+      /* Tell 'pushdecl' this is an initialized decl
+        even though we don't yet have the initializer expression.
+        Also tell 'finish_decl' it may store the real initializer.  */
+      DECL_INITIAL (decl) = error_mark_node;
+    }
+
+  /* If this is a function declaration, write a record describing it to the
+     prototypes file (if requested).  */
+
+  if (TREE_CODE (decl) == FUNCTION_DECL)
+    gen_aux_info_record (decl, 0, 0, prototype_p (TREE_TYPE (decl)));
+
+  /* ANSI specifies that a tentative definition which is not merged with
+     a non-tentative definition behaves exactly like a definition with an
+     initializer equal to zero.  (Section 3.7.2)
+
+     -fno-common gives strict ANSI behavior, though this tends to break
+     a large body of code that grew up without this rule.
+
+     Thread-local variables are never common, since there's no entrenched
+     body of code to break, and it allows more efficient variable references
+     in the presence of dynamic linking.  */
+
+  if (TREE_CODE (decl) == VAR_DECL
+      && !initialized
+      && TREE_PUBLIC (decl)
+      && !DECL_THREAD_LOCAL_P (decl)
+      && !flag_no_common)
+    DECL_COMMON (decl) = 1;
+
+  /* Set attributes here so if duplicate decl, will have proper attributes.  */
+  decl_attributes (&decl, attributes, 0);
+
+  /* Handle gnu_inline attribute.  */
+  if (declspecs->inline_p
+      && !flag_gnu89_inline
+      && TREE_CODE (decl) == FUNCTION_DECL
+      && (lookup_attribute ("gnu_inline", DECL_ATTRIBUTES (decl))
+         || current_function_decl))
+    {
+      if (declspecs->storage_class == csc_auto && current_scope != file_scope)
+       ;
+      else if (declspecs->storage_class != csc_static)
+       DECL_EXTERNAL (decl) = !DECL_EXTERNAL (decl);
+    }
+
+  if (TREE_CODE (decl) == FUNCTION_DECL
+      && targetm.calls.promote_prototypes (TREE_TYPE (decl)))
+    {
+      struct c_declarator *ce = declarator;
+
+      if (ce->kind == cdk_pointer)
+       ce = declarator->declarator;
+      if (ce->kind == cdk_function)
+       {
+         tree args = ce->u.arg_info->parms;
+         for (; args; args = DECL_CHAIN (args))
+           {
+             tree type = TREE_TYPE (args);
+             if (type && INTEGRAL_TYPE_P (type)
+                 && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
+               DECL_ARG_TYPE (args) = integer_type_node;
+           }
+       }
+    }
+
+  if (TREE_CODE (decl) == FUNCTION_DECL
+      && DECL_DECLARED_INLINE_P (decl)
+      && DECL_UNINLINABLE (decl)
+      && lookup_attribute ("noinline", DECL_ATTRIBUTES (decl)))
+    warning (OPT_Wattributes, "inline function %q+D given attribute noinline",
+            decl);
+
+  /* C99 6.7.4p3: An inline definition of a function with external
+     linkage shall not contain a definition of a modifiable object
+     with static storage duration...  */
+  if (TREE_CODE (decl) == VAR_DECL
+      && current_scope != file_scope
+      && TREE_STATIC (decl)
+      && !TREE_READONLY (decl)
+      && DECL_DECLARED_INLINE_P (current_function_decl)
+      && DECL_EXTERNAL (current_function_decl))
+    record_inline_static (input_location, current_function_decl,
+                         decl, csi_modifiable);
+
+  if (c_dialect_objc () 
+      && (TREE_CODE (decl) == VAR_DECL
+          || TREE_CODE (decl) == FUNCTION_DECL))
+      objc_check_global_decl (decl);
+
+  /* Add this decl to the current scope.
+     TEM may equal DECL or it may be a previous decl of the same name.  */
+  tem = pushdecl (decl);
+
+  if (initialized && DECL_EXTERNAL (tem))
+    {
+      DECL_EXTERNAL (tem) = 0;
+      TREE_STATIC (tem) = 1;
+    }
+
+  return tem;
+}
+
+/* Subroutine of finish_decl. TYPE is the type of an uninitialized object
+   DECL or the non-array element type if DECL is an uninitialized array.
+   If that type has a const member, diagnose this. */
+
+static void
+diagnose_uninitialized_cst_member (tree decl, tree type)
+{
+  tree field;
+  for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+    {
+      tree field_type;
+      if (TREE_CODE (field) != FIELD_DECL)
+       continue;
+      field_type = strip_array_types (TREE_TYPE (field));
+
+      if (TYPE_QUALS (field_type) & TYPE_QUAL_CONST)
+       {
+         warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wc___compat,
+                     "uninitialized const member in %qT is invalid in C++",
+                     strip_array_types (TREE_TYPE (decl)));
+         inform (DECL_SOURCE_LOCATION (field), "%qD should be initialized", field);
+       }
+
+      if (TREE_CODE (field_type) == RECORD_TYPE
+         || TREE_CODE (field_type) == UNION_TYPE)
+       diagnose_uninitialized_cst_member (decl, field_type);
+    }
+}
+
+/* Finish processing of a declaration;
+   install its initial value.
+   If ORIGTYPE is not NULL_TREE, it is the original type of INIT.
+   If the length of an array type is not known before,
+   it must be determined now, from the initial value, or it is an error.
+
+   INIT_LOC is the location of the initial value.  */
+
+void
+finish_decl (tree decl, location_t init_loc, tree init,
+            tree origtype, tree asmspec_tree)
+{
+  tree type;
+  bool was_incomplete = (DECL_SIZE (decl) == 0);
+  const char *asmspec = 0;
+
+  /* If a name was specified, get the string.  */
+  if ((TREE_CODE (decl) == FUNCTION_DECL || TREE_CODE (decl) == VAR_DECL)
+      && DECL_FILE_SCOPE_P (decl))
+    asmspec_tree = maybe_apply_renaming_pragma (decl, asmspec_tree);
+  if (asmspec_tree)
+    asmspec = TREE_STRING_POINTER (asmspec_tree);
+
+  if (TREE_CODE (decl) == VAR_DECL
+      && TREE_STATIC (decl)
+      && global_bindings_p ())
+    /* So decl is a global variable. Record the types it uses
+       so that we can decide later to emit debug info for them.  */
+    record_types_used_by_current_var_decl (decl);
+
+  /* If `start_decl' didn't like having an initialization, ignore it now.  */
+  if (init != 0 && DECL_INITIAL (decl) == 0)
+    init = 0;
+
+  /* Don't crash if parm is initialized.  */
+  if (TREE_CODE (decl) == PARM_DECL)
+    init = 0;
+
+  if (init)
+    store_init_value (init_loc, decl, init, origtype);
+
+  if (c_dialect_objc () && (TREE_CODE (decl) == VAR_DECL
+                           || TREE_CODE (decl) == FUNCTION_DECL
+                           || TREE_CODE (decl) == FIELD_DECL))
+    objc_check_decl (decl);
+
+  type = TREE_TYPE (decl);
+
+  /* Deduce size of array from initialization, if not already known.  */
+  if (TREE_CODE (type) == ARRAY_TYPE
+      && TYPE_DOMAIN (type) == 0
+      && TREE_CODE (decl) != TYPE_DECL)
+    {
+      bool do_default
+       = (TREE_STATIC (decl)
+          /* Even if pedantic, an external linkage array
+             may have incomplete type at first.  */
+          ? pedantic && !TREE_PUBLIC (decl)
+          : !DECL_EXTERNAL (decl));
+      int failure
+       = complete_array_type (&TREE_TYPE (decl), DECL_INITIAL (decl),
+                              do_default);
+
+      /* Get the completed type made by complete_array_type.  */
+      type = TREE_TYPE (decl);
+
+      switch (failure)
+       {
+       case 1:
+         error ("initializer fails to determine size of %q+D", decl);
+         break;
+
+       case 2:
+         if (do_default)
+           error ("array size missing in %q+D", decl);
+         /* If a `static' var's size isn't known,
+            make it extern as well as static, so it does not get
+            allocated.
+            If it is not `static', then do not mark extern;
+            finish_incomplete_decl will give it a default size
+            and it will get allocated.  */
+         else if (!pedantic && TREE_STATIC (decl) && !TREE_PUBLIC (decl))
+           DECL_EXTERNAL (decl) = 1;
+         break;
+
+       case 3:
+         error ("zero or negative size array %q+D", decl);
+         break;
+
+       case 0:
+         /* For global variables, update the copy of the type that
+            exists in the binding.  */
+         if (TREE_PUBLIC (decl))
+           {
+             struct c_binding *b_ext = I_SYMBOL_BINDING (DECL_NAME (decl));
+             while (b_ext && !B_IN_EXTERNAL_SCOPE (b_ext))
+               b_ext = b_ext->shadowed;
+             if (b_ext)
+               {
+                 if (b_ext->u.type && comptypes (b_ext->u.type, type))
+                   b_ext->u.type = composite_type (b_ext->u.type, type);
+                 else
+                   b_ext->u.type = type;
+               }
+           }
+         break;
+
+       default:
+         gcc_unreachable ();
+       }
+
+      if (DECL_INITIAL (decl))
+       TREE_TYPE (DECL_INITIAL (decl)) = type;
+
+      relayout_decl (decl);
+    }
+
+  if (TREE_CODE (decl) == VAR_DECL)
+    {
+      if (init && TREE_CODE (init) == CONSTRUCTOR)
+       add_flexible_array_elts_to_size (decl, init);
+
+      if (DECL_SIZE (decl) == 0 && TREE_TYPE (decl) != error_mark_node
+         && COMPLETE_TYPE_P (TREE_TYPE (decl)))
+       layout_decl (decl, 0);
+
+      if (DECL_SIZE (decl) == 0
+         /* Don't give an error if we already gave one earlier.  */
+         && TREE_TYPE (decl) != error_mark_node
+         && (TREE_STATIC (decl)
+             /* A static variable with an incomplete type
+                is an error if it is initialized.
+                Also if it is not file scope.
+                Otherwise, let it through, but if it is not `extern'
+                then it may cause an error message later.  */
+             ? (DECL_INITIAL (decl) != 0
+                || !DECL_FILE_SCOPE_P (decl))
+             /* An automatic variable with an incomplete type
+                is an error.  */
+             : !DECL_EXTERNAL (decl)))
+        {
+          error ("storage size of %q+D isn%'t known", decl);
+          TREE_TYPE (decl) = error_mark_node;
+        }
+
+      if ((DECL_EXTERNAL (decl) || TREE_STATIC (decl))
+         && DECL_SIZE (decl) != 0)
+       {
+         if (TREE_CODE (DECL_SIZE (decl)) == INTEGER_CST)
+           constant_expression_warning (DECL_SIZE (decl));
+         else
+           {
+             error ("storage size of %q+D isn%'t constant", decl);
+             TREE_TYPE (decl) = error_mark_node;
+           }
+       }
+
+      if (TREE_USED (type))
+       {
+         TREE_USED (decl) = 1;
+         DECL_READ_P (decl) = 1;
+       }
+    }
+
+  /* If this is a function and an assembler name is specified, reset DECL_RTL
+     so we can give it its new name.  Also, update builtin_decl if it
+     was a normal built-in.  */
+  if (TREE_CODE (decl) == FUNCTION_DECL && asmspec)
+    {
+      if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL)
+       set_builtin_user_assembler_name (decl, asmspec);
+      set_user_assembler_name (decl, asmspec);
+    }
+
+  /* If #pragma weak was used, mark the decl weak now.  */
+  maybe_apply_pragma_weak (decl);
+
+  /* Output the assembler code and/or RTL code for variables and functions,
+     unless the type is an undefined structure or union.
+     If not, it will get done when the type is completed.  */
+
+  if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL)
+    {
+      /* Determine the ELF visibility.  */
+      if (TREE_PUBLIC (decl))
+       c_determine_visibility (decl);
+
+      /* This is a no-op in c-lang.c or something real in objc-act.c.  */
+      if (c_dialect_objc ())
+       objc_check_decl (decl);
+
+      if (asmspec)
+       {
+         /* If this is not a static variable, issue a warning.
+            It doesn't make any sense to give an ASMSPEC for an
+            ordinary, non-register local variable.  Historically,
+            GCC has accepted -- but ignored -- the ASMSPEC in
+            this case.  */
+         if (!DECL_FILE_SCOPE_P (decl)
+             && TREE_CODE (decl) == VAR_DECL
+             && !C_DECL_REGISTER (decl)
+             && !TREE_STATIC (decl))
+           warning (0, "ignoring asm-specifier for non-static local "
+                    "variable %q+D", decl);
+         else
+           set_user_assembler_name (decl, asmspec);
+       }
+
+      if (DECL_FILE_SCOPE_P (decl))
+       {
+         if (DECL_INITIAL (decl) == NULL_TREE
+             || DECL_INITIAL (decl) == error_mark_node)
+           /* Don't output anything
+              when a tentative file-scope definition is seen.
+              But at end of compilation, do output code for them.  */
+           DECL_DEFER_OUTPUT (decl) = 1;
+         if (asmspec && C_DECL_REGISTER (decl))
+           DECL_HARD_REGISTER (decl) = 1;
+         rest_of_decl_compilation (decl, true, 0);
+       }
+      else
+       {
+         /* In conjunction with an ASMSPEC, the `register'
+            keyword indicates that we should place the variable
+            in a particular register.  */
+         if (asmspec && C_DECL_REGISTER (decl))
+           {
+             DECL_HARD_REGISTER (decl) = 1;
+             /* This cannot be done for a structure with volatile
+                fields, on which DECL_REGISTER will have been
+                reset.  */
+             if (!DECL_REGISTER (decl))
+               error ("cannot put object with volatile field into register");
+           }
+
+         if (TREE_CODE (decl) != FUNCTION_DECL)
+           {
+             /* If we're building a variable sized type, and we might be
+                reachable other than via the top of the current binding
+                level, then create a new BIND_EXPR so that we deallocate
+                the object at the right time.  */
+             /* Note that DECL_SIZE can be null due to errors.  */
+             if (DECL_SIZE (decl)
+                 && !TREE_CONSTANT (DECL_SIZE (decl))
+                 && STATEMENT_LIST_HAS_LABEL (cur_stmt_list))
+               {
+                 tree bind;
+                 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
+                 TREE_SIDE_EFFECTS (bind) = 1;
+                 add_stmt (bind);
+                 BIND_EXPR_BODY (bind) = push_stmt_list ();
+               }
+             add_stmt (build_stmt (DECL_SOURCE_LOCATION (decl),
+                                   DECL_EXPR, decl));
+           }
+       }
+
+
+      if (!DECL_FILE_SCOPE_P (decl))
+       {
+         /* Recompute the RTL of a local array now
+            if it used to be an incomplete type.  */
+         if (was_incomplete
+             && !TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
+           {
+             /* If we used it already as memory, it must stay in memory.  */
+             TREE_ADDRESSABLE (decl) = TREE_USED (decl);
+             /* If it's still incomplete now, no init will save it.  */
+             if (DECL_SIZE (decl) == 0)
+               DECL_INITIAL (decl) = 0;
+           }
+       }
+    }
+
+  if (TREE_CODE (decl) == TYPE_DECL)
+    {
+      if (!DECL_FILE_SCOPE_P (decl)
+         && variably_modified_type_p (TREE_TYPE (decl), NULL_TREE))
+       add_stmt (build_stmt (DECL_SOURCE_LOCATION (decl), DECL_EXPR, decl));
+
+      rest_of_decl_compilation (decl, DECL_FILE_SCOPE_P (decl), 0);
+    }
+
+  /* Install a cleanup (aka destructor) if one was given.  */
+  if (TREE_CODE (decl) == VAR_DECL && !TREE_STATIC (decl))
+    {
+      tree attr = lookup_attribute ("cleanup", DECL_ATTRIBUTES (decl));
+      if (attr)
+       {
+         tree cleanup_id = TREE_VALUE (TREE_VALUE (attr));
+         tree cleanup_decl = lookup_name (cleanup_id);
+         tree cleanup;
+         VEC(tree,gc) *vec;
+
+         /* Build "cleanup(&decl)" for the destructor.  */
+         cleanup = build_unary_op (input_location, ADDR_EXPR, decl, 0);
+         vec = VEC_alloc (tree, gc, 1);
+         VEC_quick_push (tree, vec, cleanup);
+         cleanup = build_function_call_vec (DECL_SOURCE_LOCATION (decl),
+                                            cleanup_decl, vec, NULL);
+         VEC_free (tree, gc, vec);
+
+         /* Don't warn about decl unused; the cleanup uses it.  */
+         TREE_USED (decl) = 1;
+         TREE_USED (cleanup_decl) = 1;
+         DECL_READ_P (decl) = 1;
+
+         push_cleanup (decl, cleanup, false);
+       }
+    }
+
+  if (warn_cxx_compat
+      && TREE_CODE (decl) == VAR_DECL
+      && !DECL_EXTERNAL (decl)
+      && DECL_INITIAL (decl) == NULL_TREE)
+    {
+      type = strip_array_types (type);
+      if (TREE_READONLY (decl))
+       warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wc___compat,
+                   "uninitialized const %qD is invalid in C++", decl);
+      else if ((TREE_CODE (type) == RECORD_TYPE
+               || TREE_CODE (type) == UNION_TYPE)
+              && C_TYPE_FIELDS_READONLY (type))
+       diagnose_uninitialized_cst_member (decl, type);
+    }
+
+       invoke_plugin_callbacks (PLUGIN_FINISH_DECL, decl);
+}
+
+/* Given a parsed parameter declaration, decode it into a PARM_DECL.
+   EXPR is NULL or a pointer to an expression that needs to be
+   evaluated for the side effects of array size expressions in the
+   parameters.  */
+
+tree
+grokparm (const struct c_parm *parm, tree *expr)
+{
+  tree attrs = parm->attrs;
+  tree decl = grokdeclarator (parm->declarator, parm->specs, PARM, false,
+                             NULL, &attrs, expr, NULL, DEPRECATED_NORMAL);
+
+  decl_attributes (&decl, attrs, 0);
+
+  return decl;
+}
+
+/* Given a parsed parameter declaration, decode it into a PARM_DECL
+   and push that on the current scope.  EXPR is a pointer to an
+   expression that needs to be evaluated for the side effects of array
+   size expressions in the parameters.  */
+
+void
+push_parm_decl (const struct c_parm *parm, tree *expr)
+{
+  tree attrs = parm->attrs;
+  tree decl;
+
+  decl = grokdeclarator (parm->declarator, parm->specs, PARM, false, NULL,
+                        &attrs, expr, NULL, DEPRECATED_NORMAL);
+  decl_attributes (&decl, attrs, 0);
+
+  decl = pushdecl (decl);
+
+  finish_decl (decl, input_location, NULL_TREE, NULL_TREE, NULL_TREE);
+}
+
+/* Mark all the parameter declarations to date as forward decls.
+   Also diagnose use of this extension.  */
+
+void
+mark_forward_parm_decls (void)
+{
+  struct c_binding *b;
+
+  if (pedantic && !current_scope->warned_forward_parm_decls)
+    {
+      pedwarn (input_location, OPT_Wpedantic,
+              "ISO C forbids forward parameter declarations");
+      current_scope->warned_forward_parm_decls = true;
+    }
+
+  for (b = current_scope->bindings; b; b = b->prev)
+    if (TREE_CODE (b->decl) == PARM_DECL)
+      TREE_ASM_WRITTEN (b->decl) = 1;
+}
+\f
+/* Build a COMPOUND_LITERAL_EXPR.  TYPE is the type given in the compound
+   literal, which may be an incomplete array type completed by the
+   initializer; INIT is a CONSTRUCTOR at LOC that initializes the compound
+   literal.  NON_CONST is true if the initializers contain something
+   that cannot occur in a constant expression.  */
+
+tree
+build_compound_literal (location_t loc, tree type, tree init, bool non_const)
+{
+  /* We do not use start_decl here because we have a type, not a declarator;
+     and do not use finish_decl because the decl should be stored inside
+     the COMPOUND_LITERAL_EXPR rather than added elsewhere as a DECL_EXPR.  */
+  tree decl;
+  tree complit;
+  tree stmt;
+
+  if (type == error_mark_node
+      || init == error_mark_node)
+    return error_mark_node;
+
+  decl = build_decl (loc, VAR_DECL, NULL_TREE, type);
+  DECL_EXTERNAL (decl) = 0;
+  TREE_PUBLIC (decl) = 0;
+  TREE_STATIC (decl) = (current_scope == file_scope);
+  DECL_CONTEXT (decl) = current_function_decl;
+  TREE_USED (decl) = 1;
+  DECL_READ_P (decl) = 1;
+  TREE_TYPE (decl) = type;
+  TREE_READONLY (decl) = (TYPE_READONLY (type)
+                         || (TREE_CODE (type) == ARRAY_TYPE
+                             && TYPE_READONLY (TREE_TYPE (type))));
+  store_init_value (loc, decl, init, NULL_TREE);
+
+  if (TREE_CODE (type) == ARRAY_TYPE && !COMPLETE_TYPE_P (type))
+    {
+      int failure = complete_array_type (&TREE_TYPE (decl),
+                                        DECL_INITIAL (decl), true);
+      gcc_assert (!failure);
+
+      type = TREE_TYPE (decl);
+      TREE_TYPE (DECL_INITIAL (decl)) = type;
+    }
+
+  if (type == error_mark_node || !COMPLETE_TYPE_P (type))
+    {
+      c_incomplete_type_error (NULL_TREE, type);
+      return error_mark_node;
+    }
+
+  stmt = build_stmt (DECL_SOURCE_LOCATION (decl), DECL_EXPR, decl);
+  complit = build1 (COMPOUND_LITERAL_EXPR, type, stmt);
+  TREE_SIDE_EFFECTS (complit) = 1;
+
+  layout_decl (decl, 0);
+
+  if (TREE_STATIC (decl))
+    {
+      /* This decl needs a name for the assembler output.  */
+      set_compound_literal_name (decl);
+      DECL_DEFER_OUTPUT (decl) = 1;
+      DECL_COMDAT (decl) = 1;
+      DECL_ARTIFICIAL (decl) = 1;
+      DECL_IGNORED_P (decl) = 1;
+      pushdecl (decl);
+      rest_of_decl_compilation (decl, 1, 0);
+    }
+
+  if (non_const)
+    {
+      complit = build2 (C_MAYBE_CONST_EXPR, type, NULL, complit);
+      C_MAYBE_CONST_EXPR_NON_CONST (complit) = 1;
+    }
+
+  return complit;
+}
+
+/* Check the type of a compound literal.  Here we just check that it
+   is valid for C++.  */
+
+void
+check_compound_literal_type (location_t loc, struct c_type_name *type_name)
+{
+  if (warn_cxx_compat
+      && (type_name->specs->typespec_kind == ctsk_tagdef
+          || type_name->specs->typespec_kind == ctsk_tagfirstref))
+    warning_at (loc, OPT_Wc___compat,
+               "defining a type in a compound literal is invalid in C++");
+}
+\f
+/* Determine whether TYPE is a structure with a flexible array member,
+   or a union containing such a structure (possibly recursively).  */
+
+static bool
+flexible_array_type_p (tree type)
+{
+  tree x;
+  switch (TREE_CODE (type))
+    {
+    case RECORD_TYPE:
+      x = TYPE_FIELDS (type);
+      if (x == NULL_TREE)
+       return false;
+      while (DECL_CHAIN (x) != NULL_TREE)
+       x = DECL_CHAIN (x);
+      if (TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE
+         && TYPE_SIZE (TREE_TYPE (x)) == NULL_TREE
+         && TYPE_DOMAIN (TREE_TYPE (x)) != NULL_TREE
+         && TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (x))) == NULL_TREE)
+       return true;
+      return false;
+    case UNION_TYPE:
+      for (x = TYPE_FIELDS (type); x != NULL_TREE; x = DECL_CHAIN (x))
+       {
+         if (flexible_array_type_p (TREE_TYPE (x)))
+           return true;
+       }
+      return false;
+    default:
+    return false;
+  }
+}
+\f
+/* Performs sanity checks on the TYPE and WIDTH of the bit-field NAME,
+   replacing with appropriate values if they are invalid.  */
+static void
+check_bitfield_type_and_width (tree *type, tree *width, tree orig_name)
+{
+  tree type_mv;
+  unsigned int max_width;
+  unsigned HOST_WIDE_INT w;
+  const char *name = (orig_name
+                     ? identifier_to_locale (IDENTIFIER_POINTER (orig_name))
+                     : _("<anonymous>"));
+
+  /* Detect and ignore out of range field width and process valid
+     field widths.  */
+  if (!INTEGRAL_TYPE_P (TREE_TYPE (*width)))
+    {
+      error ("bit-field %qs width not an integer constant", name);
+      *width = integer_one_node;
+    }
+  else
+    {
+      if (TREE_CODE (*width) != INTEGER_CST)
+       {
+         *width = c_fully_fold (*width, false, NULL);
+         if (TREE_CODE (*width) == INTEGER_CST)
+           pedwarn (input_location, OPT_Wpedantic,
+                    "bit-field %qs width not an integer constant expression",
+                    name);
+       }
+      if (TREE_CODE (*width) != INTEGER_CST)
+       {
+         error ("bit-field %qs width not an integer constant", name);
+         *width = integer_one_node;
+       }
+      constant_expression_warning (*width);
+      if (tree_int_cst_sgn (*width) < 0)
+       {
+         error ("negative width in bit-field %qs", name);
+         *width = integer_one_node;
+       }
+      else if (integer_zerop (*width) && orig_name)
+       {
+         error ("zero width for bit-field %qs", name);
+         *width = integer_one_node;
+       }
+    }
+
+  /* Detect invalid bit-field type.  */
+  if (TREE_CODE (*type) != INTEGER_TYPE
+      && TREE_CODE (*type) != BOOLEAN_TYPE
+      && TREE_CODE (*type) != ENUMERAL_TYPE)
+    {
+      error ("bit-field %qs has invalid type", name);
+      *type = unsigned_type_node;
+    }
+
+  type_mv = TYPE_MAIN_VARIANT (*type);
+  if (!in_system_header
+      && type_mv != integer_type_node
+      && type_mv != unsigned_type_node
+      && type_mv != boolean_type_node)
+    pedwarn (input_location, OPT_Wpedantic,
+            "type of bit-field %qs is a GCC extension", name);
+
+  max_width = TYPE_PRECISION (*type);
+
+  if (0 < compare_tree_int (*width, max_width))
+    {
+      error ("width of %qs exceeds its type", name);
+      w = max_width;
+      *width = build_int_cst (integer_type_node, w);
+    }
+  else
+    w = tree_low_cst (*width, 1);
+
+  if (TREE_CODE (*type) == ENUMERAL_TYPE)
+    {
+      struct lang_type *lt = TYPE_LANG_SPECIFIC (*type);
+      if (!lt
+         || w < tree_int_cst_min_precision (lt->enum_min, TYPE_UNSIGNED (*type))
+         || w < tree_int_cst_min_precision (lt->enum_max, TYPE_UNSIGNED (*type)))
+       warning (0, "%qs is narrower than values of its type", name);
+    }
+}
+
+\f
+
+/* Print warning about variable length array if necessary.  */
+
+static void
+warn_variable_length_array (tree name, tree size)
+{
+  int const_size = TREE_CONSTANT (size);
+
+  if (!flag_isoc99 && pedantic && warn_vla != 0)
+    {
+      if (const_size)
+       {
+         if (name)
+           pedwarn (input_location, OPT_Wvla,
+                    "ISO C90 forbids array %qE whose size "
+                    "can%'t be evaluated",
+                    name);
+         else
+           pedwarn (input_location, OPT_Wvla, "ISO C90 forbids array whose size "
+                    "can%'t be evaluated");
+       }
+      else
+       {
+         if (name)
+           pedwarn (input_location, OPT_Wvla,
+                    "ISO C90 forbids variable length array %qE",
+                    name);
+         else
+           pedwarn (input_location, OPT_Wvla, "ISO C90 forbids variable length array");
+       }
+    }
+  else if (warn_vla > 0)
+    {
+      if (const_size)
+        {
+         if (name)
+           warning (OPT_Wvla,
+                    "the size of array %qE can"
+                    "%'t be evaluated", name);
+         else
+           warning (OPT_Wvla,
+                    "the size of array can %'t be evaluated");
+       }
+      else
+       {
+         if (name)
+           warning (OPT_Wvla,
+                    "variable length array %qE is used",
+                    name);
+         else
+           warning (OPT_Wvla,
+                    "variable length array is used");
+       }
+    }
+}
+
+/* Given declspecs and a declarator,
+   determine the name and type of the object declared
+   and construct a ..._DECL node for it.
+   (In one case we can return a ..._TYPE node instead.
+    For invalid input we sometimes return 0.)
+
+   DECLSPECS is a c_declspecs structure for the declaration specifiers.
+
+   DECL_CONTEXT says which syntactic context this declaration is in:
+     NORMAL for most contexts.  Make a VAR_DECL or FUNCTION_DECL or TYPE_DECL.
+     FUNCDEF for a function definition.  Like NORMAL but a few different
+      error messages in each case.  Return value may be zero meaning
+      this definition is too screwy to try to parse.
+     PARM for a parameter declaration (either within a function prototype
+      or before a function body).  Make a PARM_DECL, or return void_type_node.
+     TYPENAME if for a typename (in a cast or sizeof).
+      Don't make a DECL node; just return the ..._TYPE node.
+     FIELD for a struct or union field; make a FIELD_DECL.
+   INITIALIZED is true if the decl has an initializer.
+   WIDTH is non-NULL for bit-fields, and is a pointer to an INTEGER_CST node
+   representing the width of the bit-field.
+   DECL_ATTRS points to the list of attributes that should be added to this
+     decl.  Any nested attributes that belong on the decl itself will be
+     added to this list.
+   If EXPR is not NULL, any expressions that need to be evaluated as
+     part of evaluating variably modified types will be stored in *EXPR.
+   If EXPR_CONST_OPERANDS is not NULL, *EXPR_CONST_OPERANDS will be
+     set to indicate whether operands in *EXPR can be used in constant
+     expressions.
+   DEPRECATED_STATE is a deprecated_states value indicating whether
+   deprecation warnings should be suppressed.
+
+   In the TYPENAME case, DECLARATOR is really an absolute declarator.
+   It may also be so in the PARM case, for a prototype where the
+   argument type is specified but not the name.
+
+   This function is where the complicated C meanings of `static'
+   and `extern' are interpreted.  */
+
+static tree
+grokdeclarator (const struct c_declarator *declarator,
+               struct c_declspecs *declspecs,
+               enum decl_context decl_context, bool initialized, tree *width,
+               tree *decl_attrs, tree *expr, bool *expr_const_operands,
+               enum deprecated_states deprecated_state)
+{
+  tree type = declspecs->type;
+  bool threadp = declspecs->thread_p;
+  enum c_storage_class storage_class = declspecs->storage_class;
+  int constp;
+  int restrictp;
+  int volatilep;
+  int type_quals = TYPE_UNQUALIFIED;
+  tree name = NULL_TREE;
+  bool funcdef_flag = false;
+  bool funcdef_syntax = false;
+  bool size_varies = false;
+  tree decl_attr = declspecs->decl_attr;
+  int array_ptr_quals = TYPE_UNQUALIFIED;
+  tree array_ptr_attrs = NULL_TREE;
+  int array_parm_static = 0;
+  bool array_parm_vla_unspec_p = false;
+  tree returned_attrs = NULL_TREE;
+  bool bitfield = width != NULL;
+  tree element_type;
+  struct c_arg_info *arg_info = 0;
+  addr_space_t as1, as2, address_space;
+  location_t loc = UNKNOWN_LOCATION;
+  const char *errmsg;
+  tree expr_dummy;
+  bool expr_const_operands_dummy;
+  enum c_declarator_kind first_non_attr_kind;
+  unsigned int alignas_align = 0;
+
+  if (TREE_CODE (type) == ERROR_MARK)
+    return error_mark_node;
+  if (expr == NULL)
+    expr = &expr_dummy;
+  if (expr_const_operands == NULL)
+    expr_const_operands = &expr_const_operands_dummy;
+
+  *expr = declspecs->expr;
+  *expr_const_operands = declspecs->expr_const_operands;
+
+  if (decl_context == FUNCDEF)
+    funcdef_flag = true, decl_context = NORMAL;
+
+  /* Look inside a declarator for the name being declared
+     and get it as an IDENTIFIER_NODE, for an error message.  */
+  {
+    const struct c_declarator *decl = declarator;
+
+    first_non_attr_kind = cdk_attrs;
+    while (decl)
+      switch (decl->kind)
+       {
+       case cdk_array:
+         loc = decl->id_loc;
+         /* FALL THRU.  */
+
+       case cdk_function:
+       case cdk_pointer:
+         funcdef_syntax = (decl->kind == cdk_function);
+         decl = decl->declarator;
+         if (first_non_attr_kind == cdk_attrs)
+           first_non_attr_kind = decl->kind;
+         break;
+
+       case cdk_attrs:
+         decl = decl->declarator;
+         break;
+
+       case cdk_id:
+         loc = decl->id_loc;
+         if (decl->u.id)
+           name = decl->u.id;
+         if (first_non_attr_kind == cdk_attrs)
+           first_non_attr_kind = decl->kind;
+         decl = 0;
+         break;
+
+       default:
+         gcc_unreachable ();
+       }
+    if (name == 0)
+      {
+       gcc_assert (decl_context == PARM
+                   || decl_context == TYPENAME
+                   || (decl_context == FIELD
+                       && declarator->kind == cdk_id));
+       gcc_assert (!initialized);
+      }
+  }
+
+  /* A function definition's declarator must have the form of
+     a function declarator.  */
+
+  if (funcdef_flag && !funcdef_syntax)
+    return 0;
+
+  /* If this looks like a function definition, make it one,
+     even if it occurs where parms are expected.
+     Then store_parm_decls will reject it and not use it as a parm.  */
+  if (decl_context == NORMAL && !funcdef_flag && current_scope->parm_flag)
+    decl_context = PARM;
+
+  if (declspecs->deprecated_p && deprecated_state != DEPRECATED_SUPPRESS)
+    warn_deprecated_use (declspecs->type, declspecs->decl_attr);
+
+  if ((decl_context == NORMAL || decl_context == FIELD)
+      && current_scope == file_scope
+      && variably_modified_type_p (type, NULL_TREE))
+    {
+      if (name)
+       error_at (loc, "variably modified %qE at file scope", name);
+      else
+       error_at (loc, "variably modified field at file scope");
+      type = integer_type_node;
+    }
+
+  size_varies = C_TYPE_VARIABLE_SIZE (type) != 0;
+
+  /* Diagnose defaulting to "int".  */
+
+  if (declspecs->default_int_p && !in_system_header)
+    {
+      /* Issue a warning if this is an ISO C 99 program or if
+        -Wreturn-type and this is a function, or if -Wimplicit;
+        prefer the former warning since it is more explicit.  */
+      if ((warn_implicit_int || warn_return_type || flag_isoc99)
+         && funcdef_flag)
+       warn_about_return_type = 1;
+      else
+       {
+         if (name)
+           pedwarn_c99 (loc, flag_isoc99 ? 0 : OPT_Wimplicit_int,
+                        "type defaults to %<int%> in declaration of %qE",
+                        name);
+         else
+           pedwarn_c99 (input_location, flag_isoc99 ? 0 : OPT_Wimplicit_int,
+                        "type defaults to %<int%> in type name");
+       }
+    }
+
+  /* Adjust the type if a bit-field is being declared,
+     -funsigned-bitfields applied and the type is not explicitly
+     "signed".  */
+  if (bitfield && !flag_signed_bitfields && !declspecs->explicit_signed_p
+      && TREE_CODE (type) == INTEGER_TYPE)
+    type = unsigned_type_for (type);
+
+  /* Figure out the type qualifiers for the declaration.  There are
+     two ways a declaration can become qualified.  One is something
+     like `const int i' where the `const' is explicit.  Another is
+     something like `typedef const int CI; CI i' where the type of the
+     declaration contains the `const'.  A third possibility is that
+     there is a type qualifier on the element type of a typedefed
+     array type, in which case we should extract that qualifier so
+     that c_apply_type_quals_to_decl receives the full list of
+     qualifiers to work with (C90 is not entirely clear about whether
+     duplicate qualifiers should be diagnosed in this case, but it
+     seems most appropriate to do so).  */
+  element_type = strip_array_types (type);
+  constp = declspecs->const_p + TYPE_READONLY (element_type);
+  restrictp = declspecs->restrict_p + TYPE_RESTRICT (element_type);
+  volatilep = declspecs->volatile_p + TYPE_VOLATILE (element_type);
+  as1 = declspecs->address_space;
+  as2 = TYPE_ADDR_SPACE (element_type);
+  address_space = ADDR_SPACE_GENERIC_P (as1)? as2 : as1;
+
+  if (pedantic && !flag_isoc99)
+    {
+      if (constp > 1)
+       pedwarn (loc, OPT_Wpedantic, "duplicate %<const%>");
+      if (restrictp > 1)
+       pedwarn (loc, OPT_Wpedantic, "duplicate %<restrict%>");
+      if (volatilep > 1)
+       pedwarn (loc, OPT_Wpedantic, "duplicate %<volatile%>");
+    }
+
+  if (!ADDR_SPACE_GENERIC_P (as1) && !ADDR_SPACE_GENERIC_P (as2) && as1 != as2)
+    error_at (loc, "conflicting named address spaces (%s vs %s)",
+             c_addr_space_name (as1), c_addr_space_name (as2));
+
+  if ((TREE_CODE (type) == ARRAY_TYPE
+       || first_non_attr_kind == cdk_array)
+      && TYPE_QUALS (element_type))
+    type = TYPE_MAIN_VARIANT (type);
+  type_quals = ((constp ? TYPE_QUAL_CONST : 0)
+               | (restrictp ? TYPE_QUAL_RESTRICT : 0)
+               | (volatilep ? TYPE_QUAL_VOLATILE : 0)
+               | ENCODE_QUAL_ADDR_SPACE (address_space));
+
+  /* Warn about storage classes that are invalid for certain
+     kinds of declarations (parameters, typenames, etc.).  */
+
+  if (funcdef_flag
+      && (threadp
+         || storage_class == csc_auto
+         || storage_class == csc_register
+         || storage_class == csc_typedef))
+    {
+      if (storage_class == csc_auto)
+       pedwarn (loc,
+                (current_scope == file_scope) ? 0 : OPT_Wpedantic,
+                "function definition declared %<auto%>");
+      if (storage_class == csc_register)
+       error_at (loc, "function definition declared %<register%>");
+      if (storage_class == csc_typedef)
+       error_at (loc, "function definition declared %<typedef%>");
+      if (threadp)
+       error_at (loc, "function definition declared %<__thread%>");
+      threadp = false;
+      if (storage_class == csc_auto
+         || storage_class == csc_register
+         || storage_class == csc_typedef)
+       storage_class = csc_none;
+    }
+  else if (decl_context != NORMAL && (storage_class != csc_none || threadp))
+    {
+      if (decl_context == PARM && storage_class == csc_register)
+       ;
+      else
+       {
+         switch (decl_context)
+           {
+           case FIELD:
+             if (name)
+               error_at (loc, "storage class specified for structure "
+                         "field %qE", name);
+             else
+               error_at (loc, "storage class specified for structure field");
+             break;
+           case PARM:
+             if (name)
+               error_at (loc, "storage class specified for parameter %qE",
+                         name);
+             else
+               error_at (loc, "storage class specified for unnamed parameter");
+             break;
+           default:
+             error_at (loc, "storage class specified for typename");
+             break;
+           }
+         storage_class = csc_none;
+         threadp = false;
+       }
+    }
+  else if (storage_class == csc_extern
+          && initialized
+          && !funcdef_flag)
+    {
+      /* 'extern' with initialization is invalid if not at file scope.  */
+       if (current_scope == file_scope)
+         {
+           /* It is fine to have 'extern const' when compiling at C
+              and C++ intersection.  */
+           if (!(warn_cxx_compat && constp))
+             warning_at (loc, 0, "%qE initialized and declared %<extern%>",
+                        name);
+         }
+      else
+       error_at (loc, "%qE has both %<extern%> and initializer", name);
+    }
+  else if (current_scope == file_scope)
+    {
+      if (storage_class == csc_auto)
+       error_at (loc, "file-scope declaration of %qE specifies %<auto%>",
+                 name);
+      if (pedantic && storage_class == csc_register)
+       pedwarn (input_location, OPT_Wpedantic,
+                "file-scope declaration of %qE specifies %<register%>", name);
+    }
+  else
+    {
+      if (storage_class == csc_extern && funcdef_flag)
+       error_at (loc, "nested function %qE declared %<extern%>", name);
+      else if (threadp && storage_class == csc_none)
+       {
+         error_at (loc, "function-scope %qE implicitly auto and declared "
+                   "%<__thread%>",
+                   name);
+         threadp = false;
+       }
+    }
+
+  /* Now figure out the structure of the declarator proper.
+     Descend through it, creating more complex types, until we reach
+     the declared identifier (or NULL_TREE, in an absolute declarator).
+     At each stage we maintain an unqualified version of the type
+     together with any qualifiers that should be applied to it with
+     c_build_qualified_type; this way, array types including
+     multidimensional array types are first built up in unqualified
+     form and then the qualified form is created with
+     TYPE_MAIN_VARIANT pointing to the unqualified form.  */
+
+  while (declarator && declarator->kind != cdk_id)
+    {
+      if (type == error_mark_node)
+       {
+         declarator = declarator->declarator;
+         continue;
+       }
+
+      /* Each level of DECLARATOR is either a cdk_array (for ...[..]),
+        a cdk_pointer (for *...),
+        a cdk_function (for ...(...)),
+        a cdk_attrs (for nested attributes),
+        or a cdk_id (for the name being declared
+        or the place in an absolute declarator
+        where the name was omitted).
+        For the last case, we have just exited the loop.
+
+        At this point, TYPE is the type of elements of an array,
+        or for a function to return, or for a pointer to point to.
+        After this sequence of ifs, TYPE is the type of the
+        array or function or pointer, and DECLARATOR has had its
+        outermost layer removed.  */
+
+      if (array_ptr_quals != TYPE_UNQUALIFIED
+         || array_ptr_attrs != NULL_TREE
+         || array_parm_static)
+       {
+         /* Only the innermost declarator (making a parameter be of
+            array type which is converted to pointer type)
+            may have static or type qualifiers.  */
+         error_at (loc, "static or type qualifiers in non-parameter array declarator");
+         array_ptr_quals = TYPE_UNQUALIFIED;
+         array_ptr_attrs = NULL_TREE;
+         array_parm_static = 0;
+       }
+
+      switch (declarator->kind)
+       {
+       case cdk_attrs:
+         {
+           /* A declarator with embedded attributes.  */
+           tree attrs = declarator->u.attrs;
+           const struct c_declarator *inner_decl;
+           int attr_flags = 0;
+           declarator = declarator->declarator;
+           inner_decl = declarator;
+           while (inner_decl->kind == cdk_attrs)
+             inner_decl = inner_decl->declarator;
+           if (inner_decl->kind == cdk_id)
+             attr_flags |= (int) ATTR_FLAG_DECL_NEXT;
+           else if (inner_decl->kind == cdk_function)
+             attr_flags |= (int) ATTR_FLAG_FUNCTION_NEXT;
+           else if (inner_decl->kind == cdk_array)
+             attr_flags |= (int) ATTR_FLAG_ARRAY_NEXT;
+           returned_attrs = decl_attributes (&type,
+                                             chainon (returned_attrs, attrs),
+                                             attr_flags);
+           break;
+         }
+       case cdk_array:
+         {
+           tree itype = NULL_TREE;
+           tree size = declarator->u.array.dimen;
+           /* The index is a signed object `sizetype' bits wide.  */
+           tree index_type = c_common_signed_type (sizetype);
+
+           array_ptr_quals = declarator->u.array.quals;
+           array_ptr_attrs = declarator->u.array.attrs;
+           array_parm_static = declarator->u.array.static_p;
+           array_parm_vla_unspec_p = declarator->u.array.vla_unspec_p;
+
+           declarator = declarator->declarator;
+
+           /* Check for some types that there cannot be arrays of.  */
+
+           if (VOID_TYPE_P (type))
+             {
+               if (name)
+                 error_at (loc, "declaration of %qE as array of voids", name);
+               else
+                 error_at (loc, "declaration of type name as array of voids");
+               type = error_mark_node;
+             }
+
+           if (TREE_CODE (type) == FUNCTION_TYPE)
+             {
+               if (name)
+                 error_at (loc, "declaration of %qE as array of functions",
+                           name);
+               else
+                 error_at (loc, "declaration of type name as array of "
+                           "functions");
+               type = error_mark_node;
+             }
+
+           if (pedantic && !in_system_header && flexible_array_type_p (type))
+             pedwarn (loc, OPT_Wpedantic,
+                      "invalid use of structure with flexible array member");
+
+           if (size == error_mark_node)
+             type = error_mark_node;
+
+           if (type == error_mark_node)
+             continue;
+
+           /* If size was specified, set ITYPE to a range-type for
+              that size.  Otherwise, ITYPE remains null.  finish_decl
+              may figure it out from an initial value.  */
+
+           if (size)
+             {
+               bool size_maybe_const = true;
+               bool size_int_const = (TREE_CODE (size) == INTEGER_CST
+                                      && !TREE_OVERFLOW (size));
+               bool this_size_varies = false;
+
+               /* Strip NON_LVALUE_EXPRs since we aren't using as an
+                  lvalue.  */
+               STRIP_TYPE_NOPS (size);
+
+               if (!INTEGRAL_TYPE_P (TREE_TYPE (size)))
+                 {
+                   if (name)
+                     error_at (loc, "size of array %qE has non-integer type",
+                               name);
+                   else
+                     error_at (loc,
+                               "size of unnamed array has non-integer type");
+                   size = integer_one_node;
+                 }
+
+               size = c_fully_fold (size, false, &size_maybe_const);
+
+               if (pedantic && size_maybe_const && integer_zerop (size))
+                 {
+                   if (name)
+                     pedwarn (loc, OPT_Wpedantic,
+                              "ISO C forbids zero-size array %qE", name);
+                   else
+                     pedwarn (loc, OPT_Wpedantic,
+                              "ISO C forbids zero-size array");
+                 }
+
+               if (TREE_CODE (size) == INTEGER_CST && size_maybe_const)
+                 {
+                   constant_expression_warning (size);
+                   if (tree_int_cst_sgn (size) < 0)
+                     {
+                       if (name)
+                         error_at (loc, "size of array %qE is negative", name);
+                       else
+                         error_at (loc, "size of unnamed array is negative");
+                       size = integer_one_node;
+                     }
+                   /* Handle a size folded to an integer constant but
+                      not an integer constant expression.  */
+                   if (!size_int_const)
+                     {
+                       /* If this is a file scope declaration of an
+                          ordinary identifier, this is invalid code;
+                          diagnosing it here and not subsequently
+                          treating the type as variable-length avoids
+                          more confusing diagnostics later.  */
+                       if ((decl_context == NORMAL || decl_context == FIELD)
+                           && current_scope == file_scope)
+                         pedwarn (input_location, 0,
+                                  "variably modified %qE at file scope",
+                                  name);
+                       else
+                         this_size_varies = size_varies = true;
+                       warn_variable_length_array (name, size);
+                     }
+                 }
+               else if ((decl_context == NORMAL || decl_context == FIELD)
+                        && current_scope == file_scope)
+                 {
+                   error_at (loc, "variably modified %qE at file scope", name);
+                   size = integer_one_node;
+                 }
+               else
+                 {
+                   /* Make sure the array size remains visibly
+                      nonconstant even if it is (eg) a const variable
+                      with known value.  */
+                   this_size_varies = size_varies = true;
+                   warn_variable_length_array (name, size);
+                 }
+
+               if (integer_zerop (size) && !this_size_varies)
+                 {
+                   /* A zero-length array cannot be represented with
+                      an unsigned index type, which is what we'll
+                      get with build_index_type.  Create an
+                      open-ended range instead.  */
+                   itype = build_range_type (sizetype, size, NULL_TREE);
+                 }
+               else
+                 {
+                   /* Arrange for the SAVE_EXPR on the inside of the
+                      MINUS_EXPR, which allows the -1 to get folded
+                      with the +1 that happens when building TYPE_SIZE.  */
+                   if (size_varies)
+                     size = save_expr (size);
+                   if (this_size_varies && TREE_CODE (size) == INTEGER_CST)
+                     size = build2 (COMPOUND_EXPR, TREE_TYPE (size),
+                                    integer_zero_node, size);
+
+                   /* Compute the maximum valid index, that is, size
+                      - 1.  Do the calculation in index_type, so that
+                      if it is a variable the computations will be
+                      done in the proper mode.  */
+                   itype = fold_build2_loc (loc, MINUS_EXPR, index_type,
+                                            convert (index_type, size),
+                                            convert (index_type,
+                                                     size_one_node));
+
+                   /* The above overflows when size does not fit
+                      in index_type.
+                      ???  While a size of INT_MAX+1 technically shouldn't
+                      cause an overflow (because we subtract 1), handling
+                      this case seems like an unnecessary complication.  */
+                   if (TREE_CODE (size) == INTEGER_CST
+                       && !int_fits_type_p (size, index_type))
+                     {
+                       if (name)
+                         error_at (loc, "size of array %qE is too large",
+                                   name);
+                       else
+                         error_at (loc, "size of unnamed array is too large");
+                       type = error_mark_node;
+                       continue;
+                     }
+
+                   itype = build_index_type (itype);
+                 }
+               if (this_size_varies)
+                 {
+                   if (*expr)
+                     *expr = build2 (COMPOUND_EXPR, TREE_TYPE (size),
+                                     *expr, size);
+                   else
+                     *expr = size;
+                   *expr_const_operands &= size_maybe_const;
+                 }
+             }
+           else if (decl_context == FIELD)
+             {
+               bool flexible_array_member = false;
+               if (array_parm_vla_unspec_p)
+                 /* Field names can in fact have function prototype
+                    scope so [*] is disallowed here through making
+                    the field variably modified, not through being
+                    something other than a declaration with function
+                    prototype scope.  */
+                 size_varies = true;
+               else
+                 {
+                   const struct c_declarator *t = declarator;
+                   while (t->kind == cdk_attrs)
+                     t = t->declarator;
+                   flexible_array_member = (t->kind == cdk_id);
+                 }
+               if (flexible_array_member
+                   && pedantic && !flag_isoc99 && !in_system_header)
+                 pedwarn (loc, OPT_Wpedantic,
+                          "ISO C90 does not support flexible array members");
+
+               /* ISO C99 Flexible array members are effectively
+                  identical to GCC's zero-length array extension.  */
+               if (flexible_array_member || array_parm_vla_unspec_p)
+                 itype = build_range_type (sizetype, size_zero_node,
+                                           NULL_TREE);
+             }
+           else if (decl_context == PARM)
+             {
+               if (array_parm_vla_unspec_p)
+                 {
+                   itype = build_range_type (sizetype, size_zero_node, NULL_TREE);
+                   size_varies = true;
+                 }
+             }
+           else if (decl_context == TYPENAME)
+             {
+               if (array_parm_vla_unspec_p)
+                 {
+                   /* C99 6.7.5.2p4 */
+                   warning (0, "%<[*]%> not in a declaration");
+                   /* We use this to avoid messing up with incomplete
+                      array types of the same type, that would
+                      otherwise be modified below.  */
+                   itype = build_range_type (sizetype, size_zero_node,
+                                             NULL_TREE);
+                   size_varies = true;
+                 }
+             }
+
+           /* Complain about arrays of incomplete types.  */
+           if (!COMPLETE_TYPE_P (type))
+             {
+               error_at (loc, "array type has incomplete element type");
+               type = error_mark_node;
+             }
+           else
+           /* When itype is NULL, a shared incomplete array type is
+              returned for all array of a given type.  Elsewhere we
+              make sure we don't complete that type before copying
+              it, but here we want to make sure we don't ever
+              modify the shared type, so we gcc_assert (itype)
+              below.  */
+             {
+               addr_space_t as = DECODE_QUAL_ADDR_SPACE (type_quals);
+               if (!ADDR_SPACE_GENERIC_P (as) && as != TYPE_ADDR_SPACE (type))
+                 type = build_qualified_type (type,
+                                              ENCODE_QUAL_ADDR_SPACE (as));
+
+               type = build_array_type (type, itype);
+             }
+
+           if (type != error_mark_node)
+             {
+               if (size_varies)
+                 {
+                   /* It is ok to modify type here even if itype is
+                      NULL: if size_varies, we're in a
+                      multi-dimensional array and the inner type has
+                      variable size, so the enclosing shared array type
+                      must too.  */
+                   if (size && TREE_CODE (size) == INTEGER_CST)
+                     type
+                       = build_distinct_type_copy (TYPE_MAIN_VARIANT (type));
+                   C_TYPE_VARIABLE_SIZE (type) = 1;
+                 }
+
+               /* The GCC extension for zero-length arrays differs from
+                  ISO flexible array members in that sizeof yields
+                  zero.  */
+               if (size && integer_zerop (size))
+                 {
+                   gcc_assert (itype);
+                   type = build_distinct_type_copy (TYPE_MAIN_VARIANT (type));
+                   TYPE_SIZE (type) = bitsize_zero_node;
+                   TYPE_SIZE_UNIT (type) = size_zero_node;
+                   SET_TYPE_STRUCTURAL_EQUALITY (type);
+                 }
+               if (array_parm_vla_unspec_p)
+                 {
+                   gcc_assert (itype);
+                   /* The type is complete.  C99 6.7.5.2p4  */
+                   type = build_distinct_type_copy (TYPE_MAIN_VARIANT (type));
+                   TYPE_SIZE (type) = bitsize_zero_node;
+                   TYPE_SIZE_UNIT (type) = size_zero_node;
+                   SET_TYPE_STRUCTURAL_EQUALITY (type);
+                 }
+             }
+
+           if (decl_context != PARM
+               && (array_ptr_quals != TYPE_UNQUALIFIED
+                   || array_ptr_attrs != NULL_TREE
+                   || array_parm_static))
+             {
+               error_at (loc, "static or type qualifiers in non-parameter array declarator");
+               array_ptr_quals = TYPE_UNQUALIFIED;
+               array_ptr_attrs = NULL_TREE;
+               array_parm_static = 0;
+             }
+           break;
+         }
+       case cdk_function:
+         {
+           /* Say it's a definition only for the declarator closest
+              to the identifier, apart possibly from some
+              attributes.  */
+           bool really_funcdef = false;
+           tree arg_types;
+           if (funcdef_flag)
+             {
+               const struct c_declarator *t = declarator->declarator;
+               while (t->kind == cdk_attrs)
+                 t = t->declarator;
+               really_funcdef = (t->kind == cdk_id);
+             }
+
+           /* Declaring a function type.  Make sure we have a valid
+              type for the function to return.  */
+           if (type == error_mark_node)
+             continue;
+
+           size_varies = false;
+
+           /* Warn about some types functions can't return.  */
+           if (TREE_CODE (type) == FUNCTION_TYPE)
+             {
+               if (name)
+                 error_at (loc, "%qE declared as function returning a "
+                                "function", name);
+               else
+                 error_at (loc, "type name declared as function "
+                           "returning a function");
+               type = integer_type_node;
+             }
+           if (TREE_CODE (type) == ARRAY_TYPE)
+             {
+               if (name)
+                 error_at (loc, "%qE declared as function returning an array",
+                           name);
+               else
+                 error_at (loc, "type name declared as function returning "
+                           "an array");
+               type = integer_type_node;
+             }
+           errmsg = targetm.invalid_return_type (type);
+           if (errmsg)
+             {
+               error (errmsg);
+               type = integer_type_node;
+             }
+
+           /* Construct the function type and go to the next
+              inner layer of declarator.  */
+           arg_info = declarator->u.arg_info;
+           arg_types = grokparms (arg_info, really_funcdef);
+
+           /* Type qualifiers before the return type of the function
+              qualify the return type, not the function type.  */
+           if (type_quals)
+             {
+               /* Type qualifiers on a function return type are
+                  normally permitted by the standard but have no
+                  effect, so give a warning at -Wreturn-type.
+                  Qualifiers on a void return type are banned on
+                  function definitions in ISO C; GCC used to used
+                  them for noreturn functions.  */
+               if (VOID_TYPE_P (type) && really_funcdef)
+                 pedwarn (loc, 0,
+                          "function definition has qualified void return type");
+               else
+                 warning_at (loc, OPT_Wignored_qualifiers,
+                          "type qualifiers ignored on function return type");
+
+               type = c_build_qualified_type (type, type_quals);
+             }
+           type_quals = TYPE_UNQUALIFIED;
+
+           type = build_function_type (type, arg_types);
+           declarator = declarator->declarator;
+
+           /* Set the TYPE_CONTEXTs for each tagged type which is local to
+              the formal parameter list of this FUNCTION_TYPE to point to
+              the FUNCTION_TYPE node itself.  */
+           {
+             c_arg_tag *tag;
+             unsigned ix;
+
+             FOR_EACH_VEC_ELT_REVERSE (c_arg_tag, arg_info->tags, ix, tag)
+               TYPE_CONTEXT (tag->type) = type;
+           }
+           break;
+         }
+       case cdk_pointer:
+         {
+           /* Merge any constancy or volatility into the target type
+              for the pointer.  */
+
+           if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
+               && type_quals)
+             pedwarn (loc, OPT_Wpedantic,
+                      "ISO C forbids qualified function types");
+           if (type_quals)
+             type = c_build_qualified_type (type, type_quals);
+           size_varies = false;
+
+           /* When the pointed-to type involves components of variable size,
+              care must be taken to ensure that the size evaluation code is
+              emitted early enough to dominate all the possible later uses
+              and late enough for the variables on which it depends to have
+              been assigned.
+
+              This is expected to happen automatically when the pointed-to
+              type has a name/declaration of it's own, but special attention
+              is required if the type is anonymous.
+
+              We handle the NORMAL and FIELD contexts here by attaching an
+              artificial TYPE_DECL to such pointed-to type.  This forces the
+              sizes evaluation at a safe point and ensures it is not deferred
+              until e.g. within a deeper conditional context.
+
+              We expect nothing to be needed here for PARM or TYPENAME.
+              Pushing a TYPE_DECL at this point for TYPENAME would actually
+              be incorrect, as we might be in the middle of an expression
+              with side effects on the pointed-to type size "arguments" prior
+              to the pointer declaration point and the fake TYPE_DECL in the
+              enclosing context would force the size evaluation prior to the
+              side effects.  */
+
+           if (!TYPE_NAME (type)
+               && (decl_context == NORMAL || decl_context == FIELD)
+               && variably_modified_type_p (type, NULL_TREE))
+             {
+               tree decl = build_decl (loc, TYPE_DECL, NULL_TREE, type);
+               DECL_ARTIFICIAL (decl) = 1;
+               pushdecl (decl);
+               finish_decl (decl, loc, NULL_TREE, NULL_TREE, NULL_TREE);
+               TYPE_NAME (type) = decl;
+             }
+
+           type = c_build_pointer_type (type);
+
+           /* Process type qualifiers (such as const or volatile)
+              that were given inside the `*'.  */
+           type_quals = declarator->u.pointer_quals;
+
+           declarator = declarator->declarator;
+           break;
+         }
+       default:
+         gcc_unreachable ();
+       }
+    }
+  *decl_attrs = chainon (returned_attrs, *decl_attrs);
+
+  /* Now TYPE has the actual type, apart from any qualifiers in
+     TYPE_QUALS.  */
+
+  /* Warn about address space used for things other than static memory or
+     pointers.  */
+  address_space = DECODE_QUAL_ADDR_SPACE (type_quals);
+  if (!ADDR_SPACE_GENERIC_P (address_space))
+    {
+      if (decl_context == NORMAL)
+       {
+         switch (storage_class)
+           {
+           case csc_auto:
+             error ("%qs combined with %<auto%> qualifier for %qE",
+                    c_addr_space_name (address_space), name);
+             break;
+           case csc_register:
+             error ("%qs combined with %<register%> qualifier for %qE",
+                    c_addr_space_name (address_space), name);
+             break;
+           case csc_none:
+             if (current_function_scope)
+               {
+                 error ("%qs specified for auto variable %qE",
+                        c_addr_space_name (address_space), name);
+                 break;
+               }
+             break;
+           case csc_static:
+           case csc_extern:
+           case csc_typedef:
+             break;
+           default:
+             gcc_unreachable ();
+           }
+       }
+      else if (decl_context == PARM && TREE_CODE (type) != ARRAY_TYPE)
+       {
+         if (name)
+           error ("%qs specified for parameter %qE",
+                  c_addr_space_name (address_space), name);
+         else
+           error ("%qs specified for unnamed parameter",
+                  c_addr_space_name (address_space));
+       }
+      else if (decl_context == FIELD)
+       {
+         if (name)
+           error ("%qs specified for structure field %qE",
+                  c_addr_space_name (address_space), name);
+         else
+           error ("%qs specified for structure field",
+                  c_addr_space_name (address_space));
+       }
+    }
+
+  /* Check the type and width of a bit-field.  */
+  if (bitfield)
+    check_bitfield_type_and_width (&type, width, name);
+
+  /* Reject invalid uses of _Alignas.  */
+  if (declspecs->alignas_p)
+    {
+      if (storage_class == csc_typedef)
+       error_at (loc, "alignment specified for typedef %qE", name);
+      else if (storage_class == csc_register)
+       error_at (loc, "alignment specified for %<register%> object %qE",
+                 name);
+      else if (decl_context == PARM)
+       {
+         if (name)
+           error_at (loc, "alignment specified for parameter %qE", name);
+         else
+           error_at (loc, "alignment specified for unnamed parameter");
+       }
+      else if (bitfield)
+       {
+         if (name)
+           error_at (loc, "alignment specified for bit-field %qE", name);
+         else
+           error_at (loc, "alignment specified for unnamed bit-field");
+       }
+      else if (TREE_CODE (type) == FUNCTION_TYPE)
+       error_at (loc, "alignment specified for function %qE", name);
+      else if (declspecs->align_log != -1)
+       {
+         alignas_align = 1U << declspecs->align_log;
+         if (alignas_align < TYPE_ALIGN_UNIT (type))
+           {
+             if (name)
+               error_at (loc, "%<_Alignas%> specifiers cannot reduce "
+                         "alignment of %qE", name);
+             else
+               error_at (loc, "%<_Alignas%> specifiers cannot reduce "
+                         "alignment of unnamed field");
+             alignas_align = 0;
+           }
+       }
+    }
+
+  /* Did array size calculations overflow or does the array cover more
+     than half of the address-space?  */
+  if (TREE_CODE (type) == ARRAY_TYPE
+      && COMPLETE_TYPE_P (type)
+      && TREE_CODE (TYPE_SIZE_UNIT (type)) == INTEGER_CST
+      && ! valid_constant_size_p (TYPE_SIZE_UNIT (type)))
+    {
+      if (name)
+       error_at (loc, "size of array %qE is too large", name);
+      else
+       error_at (loc, "size of unnamed array is too large");
+      /* If we proceed with the array type as it is, we'll eventually
+        crash in tree_low_cst().  */
+      type = error_mark_node;
+    }
+
+  /* If this is declaring a typedef name, return a TYPE_DECL.  */
+
+  if (storage_class == csc_typedef)
+    {
+      tree decl;
+      if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
+         && type_quals)
+       pedwarn (loc, OPT_Wpedantic,
+                "ISO C forbids qualified function types");
+      if (type_quals)
+       type = c_build_qualified_type (type, type_quals);
+      decl = build_decl (declarator->id_loc,
+                        TYPE_DECL, declarator->u.id, type);
+      if (declspecs->explicit_signed_p)
+       C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1;
+      if (declspecs->inline_p)
+       pedwarn (loc, 0,"typedef %q+D declared %<inline%>", decl);
+      if (declspecs->noreturn_p)
+       pedwarn (loc, 0,"typedef %q+D declared %<_Noreturn%>", decl);
+
+      if (warn_cxx_compat && declarator->u.id != NULL_TREE)
+       {
+         struct c_binding *b = I_TAG_BINDING (declarator->u.id);
+
+         if (b != NULL
+             && b->decl != NULL_TREE
+             && (B_IN_CURRENT_SCOPE (b)
+                 || (current_scope == file_scope && B_IN_EXTERNAL_SCOPE (b)))
+             && TYPE_MAIN_VARIANT (b->decl) != TYPE_MAIN_VARIANT (type))
+           {
+             warning_at (declarator->id_loc, OPT_Wc___compat,
+                         ("using %qD as both a typedef and a tag is "
+                          "invalid in C++"),
+                         decl);
+             if (b->locus != UNKNOWN_LOCATION)
+               inform (b->locus, "originally defined here");
+           }
+       }
+
+      return decl;
+    }
+
+  /* If this is a type name (such as, in a cast or sizeof),
+     compute the type and return it now.  */
+
+  if (decl_context == TYPENAME)
+    {
+      /* Note that the grammar rejects storage classes in typenames
+        and fields.  */
+      gcc_assert (storage_class == csc_none && !threadp
+                 && !declspecs->inline_p && !declspecs->noreturn_p);
+      if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
+         && type_quals)
+       pedwarn (loc, OPT_Wpedantic,
+                "ISO C forbids const or volatile function types");
+      if (type_quals)
+       type = c_build_qualified_type (type, type_quals);
+      return type;
+    }
+
+  if (pedantic && decl_context == FIELD
+      && variably_modified_type_p (type, NULL_TREE))
+    {
+      /* C99 6.7.2.1p8 */
+      pedwarn (loc, OPT_Wpedantic, "a member of a structure or union cannot "
+              "have a variably modified type");
+    }
+
+  /* Aside from typedefs and type names (handle above),
+     `void' at top level (not within pointer)
+     is allowed only in public variables.
+     We don't complain about parms either, but that is because
+     a better error message can be made later.  */
+
+  if (VOID_TYPE_P (type) && decl_context != PARM
+      && !((decl_context != FIELD && TREE_CODE (type) != FUNCTION_TYPE)
+           && (storage_class == csc_extern
+               || (current_scope == file_scope
+                   && !(storage_class == csc_static
+                        || storage_class == csc_register)))))
+    {
+      error_at (loc, "variable or field %qE declared void", name);
+      type = integer_type_node;
+    }
+
+  /* Now create the decl, which may be a VAR_DECL, a PARM_DECL
+     or a FUNCTION_DECL, depending on DECL_CONTEXT and TYPE.  */
+
+  {
+    tree decl;
+
+    if (decl_context == PARM)
+      {
+       tree promoted_type;
+
+       /* A parameter declared as an array of T is really a pointer to T.
+          One declared as a function is really a pointer to a function.  */
+
+       if (TREE_CODE (type) == ARRAY_TYPE)
+         {
+           /* Transfer const-ness of array into that of type pointed to.  */
+           type = TREE_TYPE (type);
+           if (type_quals)
+             type = c_build_qualified_type (type, type_quals);
+           type = c_build_pointer_type (type);
+           type_quals = array_ptr_quals;
+           if (type_quals)
+             type = c_build_qualified_type (type, type_quals);
+
+           /* We don't yet implement attributes in this context.  */
+           if (array_ptr_attrs != NULL_TREE)
+             warning_at (loc, OPT_Wattributes,
+                         "attributes in parameter array declarator ignored");
+
+           size_varies = false;
+         }
+       else if (TREE_CODE (type) == FUNCTION_TYPE)
+         {
+           if (type_quals)
+             pedwarn (loc, OPT_Wpedantic,
+                      "ISO C forbids qualified function types");
+           if (type_quals)
+             type = c_build_qualified_type (type, type_quals);
+           type = c_build_pointer_type (type);
+           type_quals = TYPE_UNQUALIFIED;
+         }
+       else if (type_quals)
+         type = c_build_qualified_type (type, type_quals);
+
+       decl = build_decl (declarator->id_loc,
+                          PARM_DECL, declarator->u.id, type);
+       if (size_varies)
+         C_DECL_VARIABLE_SIZE (decl) = 1;
+
+       /* Compute the type actually passed in the parmlist,
+          for the case where there is no prototype.
+          (For example, shorts and chars are passed as ints.)
+          When there is a prototype, this is overridden later.  */
+
+       if (type == error_mark_node)
+         promoted_type = type;
+       else
+         promoted_type = c_type_promotes_to (type);
+
+       DECL_ARG_TYPE (decl) = promoted_type;
+       if (declspecs->inline_p)
+         pedwarn (loc, 0, "parameter %q+D declared %<inline%>", decl);
+       if (declspecs->noreturn_p)
+         pedwarn (loc, 0, "parameter %q+D declared %<_Noreturn%>", decl);
+      }
+    else if (decl_context == FIELD)
+      {
+       /* Note that the grammar rejects storage classes in typenames
+          and fields.  */
+       gcc_assert (storage_class == csc_none && !threadp
+                   && !declspecs->inline_p && !declspecs->noreturn_p);
+
+       /* Structure field.  It may not be a function.  */
+
+       if (TREE_CODE (type) == FUNCTION_TYPE)
+         {
+           error_at (loc, "field %qE declared as a function", name);
+           type = build_pointer_type (type);
+         }
+       else if (TREE_CODE (type) != ERROR_MARK
+                && !COMPLETE_OR_UNBOUND_ARRAY_TYPE_P (type))
+         {
+           if (name)
+             error_at (loc, "field %qE has incomplete type", name);
+           else
+             error_at (loc, "unnamed field has incomplete type");
+           type = error_mark_node;
+         }
+       type = c_build_qualified_type (type, type_quals);
+       decl = build_decl (declarator->id_loc,
+                          FIELD_DECL, declarator->u.id, type);
+       DECL_NONADDRESSABLE_P (decl) = bitfield;
+       if (bitfield && !declarator->u.id)
+         TREE_NO_WARNING (decl) = 1;
+
+       if (size_varies)
+         C_DECL_VARIABLE_SIZE (decl) = 1;
+      }
+    else if (TREE_CODE (type) == FUNCTION_TYPE)
+      {
+       if (storage_class == csc_register || threadp)
+         {
+           error_at (loc, "invalid storage class for function %qE", name);
+         }
+       else if (current_scope != file_scope)
+         {
+           /* Function declaration not at file scope.  Storage
+              classes other than `extern' are not allowed, C99
+              6.7.1p5, and `extern' makes no difference.  However,
+              GCC allows 'auto', perhaps with 'inline', to support
+              nested functions.  */
+           if (storage_class == csc_auto)
+               pedwarn (loc, OPT_Wpedantic,
+                        "invalid storage class for function %qE", name);
+           else if (storage_class == csc_static)
+             {
+               error_at (loc, "invalid storage class for function %qE", name);
+               if (funcdef_flag)
+                 storage_class = declspecs->storage_class = csc_none;
+               else
+                 return 0;
+             }
+         }
+
+       decl = build_decl (declarator->id_loc,
+                          FUNCTION_DECL, declarator->u.id, type);
+       decl = build_decl_attribute_variant (decl, decl_attr);
+
+       if (pedantic && type_quals && !DECL_IN_SYSTEM_HEADER (decl))
+         pedwarn (loc, OPT_Wpedantic,
+                  "ISO C forbids qualified function types");
+
+       /* Every function declaration is an external reference
+          (DECL_EXTERNAL) except for those which are not at file
+          scope and are explicitly declared "auto".  This is
+          forbidden by standard C (C99 6.7.1p5) and is interpreted by
+          GCC to signify a forward declaration of a nested function.  */
+       if (storage_class == csc_auto && current_scope != file_scope)
+         DECL_EXTERNAL (decl) = 0;
+       /* In C99, a function which is declared 'inline' with 'extern'
+          is not an external reference (which is confusing).  It
+          means that the later definition of the function must be output
+          in this file, C99 6.7.4p6.  In GNU C89, a function declared
+          'extern inline' is an external reference.  */
+       else if (declspecs->inline_p && storage_class != csc_static)
+         DECL_EXTERNAL (decl) = ((storage_class == csc_extern)
+                                 == flag_gnu89_inline);
+       else
+         DECL_EXTERNAL (decl) = !initialized;
+
+       /* Record absence of global scope for `static' or `auto'.  */
+       TREE_PUBLIC (decl)
+         = !(storage_class == csc_static || storage_class == csc_auto);
+
+       /* For a function definition, record the argument information
+          block where store_parm_decls will look for it.  */
+       if (funcdef_flag)
+         current_function_arg_info = arg_info;
+
+       if (declspecs->default_int_p)
+         C_FUNCTION_IMPLICIT_INT (decl) = 1;
+
+       /* Record presence of `inline' and `_Noreturn', if it is
+          reasonable.  */
+       if (flag_hosted && MAIN_NAME_P (declarator->u.id))
+         {
+           if (declspecs->inline_p)
+             pedwarn (loc, 0, "cannot inline function %<main%>");
+           if (declspecs->noreturn_p)
+             pedwarn (loc, 0, "%<main%> declared %<_Noreturn%>");
+         }
+       else
+         {
+           if (declspecs->inline_p)
+             /* Record that the function is declared `inline'.  */
+             DECL_DECLARED_INLINE_P (decl) = 1;
+           if (declspecs->noreturn_p)
+             {
+               if (!flag_isoc11)
+                 {
+                   if (flag_isoc99)
+                     pedwarn (loc, OPT_Wpedantic,
+                              "ISO C99 does not support %<_Noreturn%>");
+                   else
+                     pedwarn (loc, OPT_Wpedantic,
+                              "ISO C90 does not support %<_Noreturn%>");
+                 }
+               TREE_THIS_VOLATILE (decl) = 1;
+             }
+         }
+      }
+    else
+      {
+       /* It's a variable.  */
+       /* An uninitialized decl with `extern' is a reference.  */
+       int extern_ref = !initialized && storage_class == csc_extern;
+
+       type = c_build_qualified_type (type, type_quals);
+
+       /* C99 6.2.2p7: It is invalid (compile-time undefined
+          behavior) to create an 'extern' declaration for a
+          variable if there is a global declaration that is
+          'static' and the global declaration is not visible.
+          (If the static declaration _is_ currently visible,
+          the 'extern' declaration is taken to refer to that decl.) */
+       if (extern_ref && current_scope != file_scope)
+         {
+           tree global_decl  = identifier_global_value (declarator->u.id);
+           tree visible_decl = lookup_name (declarator->u.id);
+
+           if (global_decl
+               && global_decl != visible_decl
+               && TREE_CODE (global_decl) == VAR_DECL
+               && !TREE_PUBLIC (global_decl))
+             error_at (loc, "variable previously declared %<static%> "
+                       "redeclared %<extern%>");
+         }
+
+       decl = build_decl (declarator->id_loc,
+                          VAR_DECL, declarator->u.id, type);
+       if (size_varies)
+         C_DECL_VARIABLE_SIZE (decl) = 1;
+
+       if (declspecs->inline_p)
+         pedwarn (loc, 0, "variable %q+D declared %<inline%>", decl);
+       if (declspecs->noreturn_p)
+         pedwarn (loc, 0, "variable %q+D declared %<_Noreturn%>", decl);
+
+       /* At file scope, an initialized extern declaration may follow
+          a static declaration.  In that case, DECL_EXTERNAL will be
+          reset later in start_decl.  */
+       DECL_EXTERNAL (decl) = (storage_class == csc_extern);
+
+       /* At file scope, the presence of a `static' or `register' storage
+          class specifier, or the absence of all storage class specifiers
+          makes this declaration a definition (perhaps tentative).  Also,
+          the absence of `static' makes it public.  */
+       if (current_scope == file_scope)
+         {
+           TREE_PUBLIC (decl) = storage_class != csc_static;
+           TREE_STATIC (decl) = !extern_ref;
+         }
+       /* Not at file scope, only `static' makes a static definition.  */
+       else
+         {
+           TREE_STATIC (decl) = (storage_class == csc_static);
+           TREE_PUBLIC (decl) = extern_ref;
+         }
+
+       if (threadp)
+         DECL_TLS_MODEL (decl) = decl_default_tls_model (decl);
+      }
+
+    if ((storage_class == csc_extern
+        || (storage_class == csc_none
+            && TREE_CODE (type) == FUNCTION_TYPE
+            && !funcdef_flag))
+       && variably_modified_type_p (type, NULL_TREE))
+      {
+       /* C99 6.7.5.2p2 */
+       if (TREE_CODE (type) == FUNCTION_TYPE)
+         error_at (loc, "non-nested function with variably modified type");
+       else
+         error_at (loc, "object with variably modified type must have "
+                   "no linkage");
+      }
+
+    /* Record `register' declaration for warnings on &
+       and in case doing stupid register allocation.  */
+
+    if (storage_class == csc_register)
+      {
+       C_DECL_REGISTER (decl) = 1;
+       DECL_REGISTER (decl) = 1;
+      }
+
+    /* Record constancy and volatility.  */
+    c_apply_type_quals_to_decl (type_quals, decl);
+
+    /* Apply _Alignas specifiers.  */
+    if (alignas_align)
+      {
+       DECL_ALIGN (decl) = alignas_align * BITS_PER_UNIT;
+       DECL_USER_ALIGN (decl) = 1;
+      }
+
+    /* If a type has volatile components, it should be stored in memory.
+       Otherwise, the fact that those components are volatile
+       will be ignored, and would even crash the compiler.
+       Of course, this only makes sense on  VAR,PARM, and RESULT decl's.   */
+    if (C_TYPE_FIELDS_VOLATILE (TREE_TYPE (decl))
+       && (TREE_CODE (decl) == VAR_DECL ||  TREE_CODE (decl) == PARM_DECL
+         || TREE_CODE (decl) == RESULT_DECL))
+      {
+       /* It is not an error for a structure with volatile fields to
+          be declared register, but reset DECL_REGISTER since it
+          cannot actually go in a register.  */
+       int was_reg = C_DECL_REGISTER (decl);
+       C_DECL_REGISTER (decl) = 0;
+       DECL_REGISTER (decl) = 0;
+       c_mark_addressable (decl);
+       C_DECL_REGISTER (decl) = was_reg;
+      }
+
+  /* This is the earliest point at which we might know the assembler
+     name of a variable.  Thus, if it's known before this, die horribly.  */
+    gcc_assert (!DECL_ASSEMBLER_NAME_SET_P (decl));
+
+    if (warn_cxx_compat
+       && TREE_CODE (decl) == VAR_DECL
+       && TREE_PUBLIC (decl)
+       && TREE_STATIC (decl)
+       && (TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE
+           || TREE_CODE (TREE_TYPE (decl)) == UNION_TYPE
+           || TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE)
+       && TYPE_NAME (TREE_TYPE (decl)) == NULL_TREE)
+      warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wc___compat,
+                 ("non-local variable %qD with anonymous type is "
+                  "questionable in C++"),
+                 decl);
+
+    return decl;
+  }
+}
+\f
+/* Decode the parameter-list info for a function type or function definition.
+   The argument is the value returned by `get_parm_info' (or made in c-parse.c
+   if there is an identifier list instead of a parameter decl list).
+   These two functions are separate because when a function returns
+   or receives functions then each is called multiple times but the order
+   of calls is different.  The last call to `grokparms' is always the one
+   that contains the formal parameter names of a function definition.
+
+   Return a list of arg types to use in the FUNCTION_TYPE for this function.
+
+   FUNCDEF_FLAG is true for a function definition, false for
+   a mere declaration.  A nonempty identifier-list gets an error message
+   when FUNCDEF_FLAG is false.  */
+
+static tree
+grokparms (struct c_arg_info *arg_info, bool funcdef_flag)
+{
+  tree arg_types = arg_info->types;
+
+  if (funcdef_flag && arg_info->had_vla_unspec)
+    {
+      /* A function definition isn't function prototype scope C99 6.2.1p4.  */
+      /* C99 6.7.5.2p4 */
+      error ("%<[*]%> not allowed in other than function prototype scope");
+    }
+
+  if (arg_types == 0 && !funcdef_flag && !in_system_header)
+    warning (OPT_Wstrict_prototypes,
+            "function declaration isn%'t a prototype");
+
+  if (arg_types == error_mark_node)
+    return 0;  /* don't set TYPE_ARG_TYPES in this case */
+
+  else if (arg_types && TREE_CODE (TREE_VALUE (arg_types)) == IDENTIFIER_NODE)
+    {
+      if (!funcdef_flag)
+       {
+         pedwarn (input_location, 0, "parameter names (without types) in function declaration");
+         arg_info->parms = NULL_TREE;
+       }
+      else
+       arg_info->parms = arg_info->types;
+
+      arg_info->types = 0;
+      return 0;
+    }
+  else
+    {
+      tree parm, type, typelt;
+      unsigned int parmno;
+      const char *errmsg;
+
+      /* If there is a parameter of incomplete type in a definition,
+        this is an error.  In a declaration this is valid, and a
+        struct or union type may be completed later, before any calls
+        or definition of the function.  In the case where the tag was
+        first declared within the parameter list, a warning has
+        already been given.  If a parameter has void type, then
+        however the function cannot be defined or called, so
+        warn.  */
+
+      for (parm = arg_info->parms, typelt = arg_types, parmno = 1;
+          parm;
+          parm = DECL_CHAIN (parm), typelt = TREE_CHAIN (typelt), parmno++)
+       {
+         type = TREE_VALUE (typelt);
+         if (type == error_mark_node)
+           continue;
+
+         if (!COMPLETE_TYPE_P (type))
+           {
+             if (funcdef_flag)
+               {
+                 if (DECL_NAME (parm))
+                   error_at (input_location,
+                             "parameter %u (%q+D) has incomplete type",
+                             parmno, parm);
+                 else
+                   error_at (DECL_SOURCE_LOCATION (parm),
+                             "parameter %u has incomplete type",
+                             parmno);
+
+                 TREE_VALUE (typelt) = error_mark_node;
+                 TREE_TYPE (parm) = error_mark_node;
+                 arg_types = NULL_TREE;
+               }
+             else if (VOID_TYPE_P (type))
+               {
+                 if (DECL_NAME (parm))
+                   warning_at (input_location, 0,
+                               "parameter %u (%q+D) has void type",
+                               parmno, parm);
+                 else
+                   warning_at (DECL_SOURCE_LOCATION (parm), 0,
+                               "parameter %u has void type",
+                               parmno);
+               }
+           }
+
+         errmsg = targetm.invalid_parameter_type (type);
+         if (errmsg)
+           {
+             error (errmsg);
+             TREE_VALUE (typelt) = error_mark_node;
+             TREE_TYPE (parm) = error_mark_node;
+             arg_types = NULL_TREE;
+           }
+
+         if (DECL_NAME (parm) && TREE_USED (parm))
+           warn_if_shadowing (parm);
+       }
+      return arg_types;
+    }
+}
+
+/* Allocate and initialize a c_arg_info structure from the parser's
+   obstack.  */
+
+struct c_arg_info *
+build_arg_info (void)
+{
+  struct c_arg_info *ret = XOBNEW (&parser_obstack, struct c_arg_info);
+  ret->parms = NULL_TREE;
+  ret->tags = NULL;
+  ret->types = NULL_TREE;
+  ret->others = NULL_TREE;
+  ret->pending_sizes = NULL;
+  ret->had_vla_unspec = 0;
+  return ret;
+}
+
+/* Take apart the current scope and return a c_arg_info structure with
+   info on a parameter list just parsed.
+
+   This structure is later fed to 'grokparms' and 'store_parm_decls'.
+
+   ELLIPSIS being true means the argument list ended in '...' so don't
+   append a sentinel (void_list_node) to the end of the type-list.
+
+   EXPR is NULL or an expression that needs to be evaluated for the
+   side effects of array size expressions in the parameters.  */
+
+struct c_arg_info *
+get_parm_info (bool ellipsis, tree expr)
+{
+  struct c_binding *b = current_scope->bindings;
+  struct c_arg_info *arg_info = build_arg_info ();
+
+  tree parms    = 0;
+  VEC(c_arg_tag,gc) *tags = NULL;
+  tree types    = 0;
+  tree others   = 0;
+
+  static bool explained_incomplete_types = false;
+  bool gave_void_only_once_err = false;
+
+  arg_info->had_vla_unspec = current_scope->had_vla_unspec;
+
+  /* The bindings in this scope must not get put into a block.
+     We will take care of deleting the binding nodes.  */
+  current_scope->bindings = 0;
+
+  /* This function is only called if there was *something* on the
+     parameter list.  */
+  gcc_assert (b);
+
+  /* A parameter list consisting solely of 'void' indicates that the
+     function takes no arguments.  But if the 'void' is qualified
+     (by 'const' or 'volatile'), or has a storage class specifier
+     ('register'), then the behavior is undefined; issue an error.
+     Typedefs for 'void' are OK (see DR#157).  */
+  if (b->prev == 0                         /* one binding */
+      && TREE_CODE (b->decl) == PARM_DECL   /* which is a parameter */
+      && !DECL_NAME (b->decl)               /* anonymous */
+      && VOID_TYPE_P (TREE_TYPE (b->decl))) /* of void type */
+    {
+      if (TREE_THIS_VOLATILE (b->decl)
+         || TREE_READONLY (b->decl)
+         || C_DECL_REGISTER (b->decl))
+       error ("%<void%> as only parameter may not be qualified");
+
+      /* There cannot be an ellipsis.  */
+      if (ellipsis)
+       error ("%<void%> must be the only parameter");
+
+      arg_info->types = void_list_node;
+      return arg_info;
+    }
+
+  if (!ellipsis)
+    types = void_list_node;
+
+  /* Break up the bindings list into parms, tags, types, and others;
+     apply sanity checks; purge the name-to-decl bindings.  */
+  while (b)
+    {
+      tree decl = b->decl;
+      tree type = TREE_TYPE (decl);
+      c_arg_tag *tag;
+      const char *keyword;
+
+      switch (TREE_CODE (decl))
+       {
+       case PARM_DECL:
+         if (b->id)
+           {
+             gcc_assert (I_SYMBOL_BINDING (b->id) == b);
+             I_SYMBOL_BINDING (b->id) = b->shadowed;
+           }
+
+         /* Check for forward decls that never got their actual decl.  */
+         if (TREE_ASM_WRITTEN (decl))
+           error ("parameter %q+D has just a forward declaration", decl);
+         /* Check for (..., void, ...) and issue an error.  */
+         else if (VOID_TYPE_P (type) && !DECL_NAME (decl))
+           {
+             if (!gave_void_only_once_err)
+               {
+                 error ("%<void%> must be the only parameter");
+                 gave_void_only_once_err = true;
+               }
+           }
+         else
+           {
+             /* Valid parameter, add it to the list.  */
+             DECL_CHAIN (decl) = parms;
+             parms = decl;
+
+             /* Since there is a prototype, args are passed in their
+                declared types.  The back end may override this later.  */
+             DECL_ARG_TYPE (decl) = type;
+             types = tree_cons (0, type, types);
+           }
+         break;
+
+       case ENUMERAL_TYPE: keyword = "enum"; goto tag;
+       case UNION_TYPE:    keyword = "union"; goto tag;
+       case RECORD_TYPE:   keyword = "struct"; goto tag;
+       tag:
+         /* Types may not have tag-names, in which case the type
+            appears in the bindings list with b->id NULL.  */
+         if (b->id)
+           {
+             gcc_assert (I_TAG_BINDING (b->id) == b);
+             I_TAG_BINDING (b->id) = b->shadowed;
+           }
+
+         /* Warn about any struct, union or enum tags defined in a
+            parameter list.  The scope of such types is limited to
+            the parameter list, which is rarely if ever desirable
+            (it's impossible to call such a function with type-
+            correct arguments).  An anonymous union parm type is
+            meaningful as a GNU extension, so don't warn for that.  */
+         if (TREE_CODE (decl) != UNION_TYPE || b->id != 0)
+           {
+             if (b->id)
+               /* The %s will be one of 'struct', 'union', or 'enum'.  */
+               warning (0, "%<%s %E%> declared inside parameter list",
+                        keyword, b->id);
+             else
+               /* The %s will be one of 'struct', 'union', or 'enum'.  */
+               warning (0, "anonymous %s declared inside parameter list",
+                        keyword);
+
+             if (!explained_incomplete_types)
+               {
+                 warning (0, "its scope is only this definition or declaration,"
+                          " which is probably not what you want");
+                 explained_incomplete_types = true;
+               }
+           }
+
+         tag = VEC_safe_push (c_arg_tag, gc, tags, NULL);
+         tag->id = b->id;
+         tag->type = decl;
+         break;
+
+       case CONST_DECL:
+       case TYPE_DECL:
+       case FUNCTION_DECL:
+         /* CONST_DECLs appear here when we have an embedded enum,
+            and TYPE_DECLs appear here when we have an embedded struct
+            or union.  No warnings for this - we already warned about the
+            type itself.  FUNCTION_DECLs appear when there is an implicit
+            function declaration in the parameter list.  */
+
+         /* When we reinsert this decl in the function body, we need
+            to reconstruct whether it was marked as nested.  */
+         gcc_assert (TREE_CODE (decl) == FUNCTION_DECL
+                     ? b->nested
+                     : !b->nested);
+         DECL_CHAIN (decl) = others;
+         others = decl;
+         /* fall through */
+
+       case ERROR_MARK:
+         /* error_mark_node appears here when we have an undeclared
+            variable.  Just throw it away.  */
+         if (b->id)
+           {
+             gcc_assert (I_SYMBOL_BINDING (b->id) == b);
+             I_SYMBOL_BINDING (b->id) = b->shadowed;
+           }
+         break;
+
+         /* Other things that might be encountered.  */
+       case LABEL_DECL:
+       case VAR_DECL:
+       default:
+         gcc_unreachable ();
+       }
+
+      b = free_binding_and_advance (b);
+    }
+
+  arg_info->parms = parms;
+  arg_info->tags = tags;
+  arg_info->types = types;
+  arg_info->others = others;
+  arg_info->pending_sizes = expr;
+  return arg_info;
+}
+\f
+/* Get the struct, enum or union (CODE says which) with tag NAME.
+   Define the tag as a forward-reference with location LOC if it is
+   not defined.  Return a c_typespec structure for the type
+   specifier.  */
+
+struct c_typespec
+parser_xref_tag (location_t loc, enum tree_code code, tree name)
+{
+  struct c_typespec ret;
+  tree ref;
+  location_t refloc;
+
+  ret.expr = NULL_TREE;
+  ret.expr_const_operands = true;
+
+  /* If a cross reference is requested, look up the type
+     already defined for this tag and return it.  */
+
+  ref = lookup_tag (code, name, 0, &refloc);
+  /* If this is the right type of tag, return what we found.
+     (This reference will be shadowed by shadow_tag later if appropriate.)
+     If this is the wrong type of tag, do not return it.  If it was the
+     wrong type in the same scope, we will have had an error
+     message already; if in a different scope and declaring
+     a name, pending_xref_error will give an error message; but if in a
+     different scope and not declaring a name, this tag should
+     shadow the previous declaration of a different type of tag, and
+     this would not work properly if we return the reference found.
+     (For example, with "struct foo" in an outer scope, "union foo;"
+     must shadow that tag with a new one of union type.)  */
+  ret.kind = (ref ? ctsk_tagref : ctsk_tagfirstref);
+  if (ref && TREE_CODE (ref) == code)
+    {
+      if (C_TYPE_DEFINED_IN_STRUCT (ref)
+         && loc != UNKNOWN_LOCATION
+         && warn_cxx_compat)
+       {
+         switch (code)
+           {
+           case ENUMERAL_TYPE:
+             warning_at (loc, OPT_Wc___compat,
+                         ("enum type defined in struct or union "
+                          "is not visible in C++"));
+             inform (refloc, "enum type defined here");
+             break;
+           case RECORD_TYPE:
+             warning_at (loc, OPT_Wc___compat,
+                         ("struct defined in struct or union "
+                          "is not visible in C++"));
+             inform (refloc, "struct defined here");
+             break;
+           case UNION_TYPE:
+             warning_at (loc, OPT_Wc___compat,
+                         ("union defined in struct or union "
+                          "is not visible in C++"));
+             inform (refloc, "union defined here");
+             break;
+           default:
+             gcc_unreachable();
+           }
+       }
+
+      ret.spec = ref;
+      return ret;
+    }
+
+  /* If no such tag is yet defined, create a forward-reference node
+     and record it as the "definition".
+     When a real declaration of this type is found,
+     the forward-reference will be altered into a real type.  */
+
+  ref = make_node (code);
+  if (code == ENUMERAL_TYPE)
+    {
+      /* Give the type a default layout like unsigned int
+        to avoid crashing if it does not get defined.  */
+      SET_TYPE_MODE (ref, TYPE_MODE (unsigned_type_node));
+      TYPE_ALIGN (ref) = TYPE_ALIGN (unsigned_type_node);
+      TYPE_USER_ALIGN (ref) = 0;
+      TYPE_UNSIGNED (ref) = 1;
+      TYPE_PRECISION (ref) = TYPE_PRECISION (unsigned_type_node);
+      TYPE_MIN_VALUE (ref) = TYPE_MIN_VALUE (unsigned_type_node);
+      TYPE_MAX_VALUE (ref) = TYPE_MAX_VALUE (unsigned_type_node);
+    }
+
+  pushtag (loc, name, ref);
+
+  ret.spec = ref;
+  return ret;
+}
+
+/* Get the struct, enum or union (CODE says which) with tag NAME.
+   Define the tag as a forward-reference if it is not defined.
+   Return a tree for the type.  */
+
+tree
+xref_tag (enum tree_code code, tree name)
+{
+  return parser_xref_tag (input_location, code, name).spec;
+}
+\f
+/* Make sure that the tag NAME is defined *in the current scope*
+   at least as a forward reference.
+   LOC is the location of the struct's definition.
+   CODE says which kind of tag NAME ought to be.
+
+   This stores the current value of the file static STRUCT_PARSE_INFO
+   in *ENCLOSING_STRUCT_PARSE_INFO, and points STRUCT_PARSE_INFO at a
+   new c_struct_parse_info structure.  The old value of
+   STRUCT_PARSE_INFO is restored in finish_struct.  */
+
+tree
+start_struct (location_t loc, enum tree_code code, tree name,
+             struct c_struct_parse_info **enclosing_struct_parse_info)
+{
+  /* If there is already a tag defined at this scope
+     (as a forward reference), just return it.  */
+
+  tree ref = NULL_TREE;
+  location_t refloc = UNKNOWN_LOCATION;
+
+  if (name != NULL_TREE)
+    ref = lookup_tag (code, name, 1, &refloc);
+  if (ref && TREE_CODE (ref) == code)
+    {
+      if (TYPE_SIZE (ref))
+       {
+         if (code == UNION_TYPE)
+           error_at (loc, "redefinition of %<union %E%>", name);
+         else
+           error_at (loc, "redefinition of %<struct %E%>", name);
+         if (refloc != UNKNOWN_LOCATION)
+           inform (refloc, "originally defined here");
+         /* Don't create structures using a name already in use.  */
+         ref = NULL_TREE;
+       }
+      else if (C_TYPE_BEING_DEFINED (ref))
+       {
+         if (code == UNION_TYPE)
+           error_at (loc, "nested redefinition of %<union %E%>", name);
+         else
+           error_at (loc, "nested redefinition of %<struct %E%>", name);
+         /* Don't bother to report "originally defined here" for a
+            nested redefinition; the original definition should be
+            obvious.  */
+         /* Don't create structures that contain themselves.  */
+         ref = NULL_TREE;
+       }
+    }
+
+  /* Otherwise create a forward-reference just so the tag is in scope.  */
+
+  if (ref == NULL_TREE || TREE_CODE (ref) != code)
+    {
+      ref = make_node (code);
+      pushtag (loc, name, ref);
+    }
+
+  C_TYPE_BEING_DEFINED (ref) = 1;
+  TYPE_PACKED (ref) = flag_pack_struct;
+
+  *enclosing_struct_parse_info = struct_parse_info;
+  struct_parse_info = XNEW (struct c_struct_parse_info);
+  struct_parse_info->struct_types = VEC_alloc (tree, heap, 0);
+  struct_parse_info->fields = VEC_alloc (c_binding_ptr, heap, 0);
+  struct_parse_info->typedefs_seen = VEC_alloc (tree, heap, 0);
+
+  /* FIXME: This will issue a warning for a use of a type defined
+     within a statement expr used within sizeof, et. al.  This is not
+     terribly serious as C++ doesn't permit statement exprs within
+     sizeof anyhow.  */
+  if (warn_cxx_compat && (in_sizeof || in_typeof || in_alignof))
+    warning_at (loc, OPT_Wc___compat,
+               "defining type in %qs expression is invalid in C++",
+               (in_sizeof
+                ? "sizeof"
+                : (in_typeof ? "typeof" : "alignof")));
+
+  return ref;
+}
+
+/* Process the specs, declarator and width (NULL if omitted)
+   of a structure component, returning a FIELD_DECL node.
+   WIDTH is non-NULL for bit-fields only, and is an INTEGER_CST node.
+   DECL_ATTRS is as for grokdeclarator.
+
+   LOC is the location of the structure component.
+
+   This is done during the parsing of the struct declaration.
+   The FIELD_DECL nodes are chained together and the lot of them
+   are ultimately passed to `build_struct' to make the RECORD_TYPE node.  */
+
+tree
+grokfield (location_t loc,
+          struct c_declarator *declarator, struct c_declspecs *declspecs,
+          tree width, tree *decl_attrs)
+{
+  tree value;
+
+  if (declarator->kind == cdk_id && declarator->u.id == NULL_TREE
+      && width == NULL_TREE)
+    {
+      /* This is an unnamed decl.
+
+        If we have something of the form "union { list } ;" then this
+        is the anonymous union extension.  Similarly for struct.
+
+        If this is something of the form "struct foo;", then
+          If MS or Plan 9 extensions are enabled, this is handled as
+            an anonymous struct.
+          Otherwise this is a forward declaration of a structure tag.
+
+        If this is something of the form "foo;" and foo is a TYPE_DECL, then
+          If foo names a structure or union without a tag, then this
+            is an anonymous struct (this is permitted by C11).
+          If MS or Plan 9 extensions are enabled and foo names a
+            structure, then again this is an anonymous struct.
+          Otherwise this is an error.
+
+        Oh what a horrid tangled web we weave.  I wonder if MS consciously
+        took this from Plan 9 or if it was an accident of implementation
+        that took root before someone noticed the bug...  */
+
+      tree type = declspecs->type;
+      bool type_ok = (TREE_CODE (type) == RECORD_TYPE
+                     || TREE_CODE (type) == UNION_TYPE);
+      bool ok = false;
+
+      if (type_ok
+         && (flag_ms_extensions
+             || flag_plan9_extensions
+             || !declspecs->typedef_p))
+       {
+         if (flag_ms_extensions || flag_plan9_extensions)
+           ok = true;
+         else if (TYPE_NAME (type) == NULL)
+           ok = true;
+         else
+           ok = false;
+       }
+      if (!ok)
+       {
+         pedwarn (loc, 0, "declaration does not declare anything");
+         return NULL_TREE;
+       }
+      if (!flag_isoc11)
+       {
+         if (flag_isoc99)
+           pedwarn (loc, OPT_Wpedantic,
+                    "ISO C99 doesn%'t support unnamed structs/unions");
+         else
+           pedwarn (loc, OPT_Wpedantic,
+                    "ISO C90 doesn%'t support unnamed structs/unions");
+       }
+    }
+
+  value = grokdeclarator (declarator, declspecs, FIELD, false,
+                         width ? &width : NULL, decl_attrs, NULL, NULL,
+                         DEPRECATED_NORMAL);
+
+  finish_decl (value, loc, NULL_TREE, NULL_TREE, NULL_TREE);
+  DECL_INITIAL (value) = width;
+
+  if (warn_cxx_compat && DECL_NAME (value) != NULL_TREE)
+    {
+      /* If we currently have a binding for this field, set the
+        in_struct field in the binding, so that we warn about lookups
+        which find it.  */
+      struct c_binding *b = I_SYMBOL_BINDING (DECL_NAME (value));
+      if (b != NULL)
+       {
+         /* If the in_struct field is not yet set, push it on a list
+            to be cleared when this struct is finished.  */
+         if (!b->in_struct)
+           {
+             VEC_safe_push (c_binding_ptr, heap,
+                            struct_parse_info->fields, b);
+             b->in_struct = 1;
+           }
+       }
+    }
+
+  return value;
+}
+\f
+/* Subroutine of detect_field_duplicates: return whether X and Y,
+   which are both fields in the same struct, have duplicate field
+   names.  */
+
+static bool
+is_duplicate_field (tree x, tree y)
+{
+  if (DECL_NAME (x) != NULL_TREE && DECL_NAME (x) == DECL_NAME (y))
+    return true;
+
+  /* When using -fplan9-extensions, an anonymous field whose name is a
+     typedef can duplicate a field name.  */
+  if (flag_plan9_extensions
+      && (DECL_NAME (x) == NULL_TREE || DECL_NAME (y) == NULL_TREE))
+    {
+      tree xt, xn, yt, yn;
+
+      xt = TREE_TYPE (x);
+      if (DECL_NAME (x) != NULL_TREE)
+       xn = DECL_NAME (x);
+      else if ((TREE_CODE (xt) == RECORD_TYPE || TREE_CODE (xt) == UNION_TYPE)
+              && TYPE_NAME (xt) != NULL_TREE
+              && TREE_CODE (TYPE_NAME (xt)) == TYPE_DECL)
+       xn = DECL_NAME (TYPE_NAME (xt));
+      else
+       xn = NULL_TREE;
+
+      yt = TREE_TYPE (y);
+      if (DECL_NAME (y) != NULL_TREE)
+       yn = DECL_NAME (y);
+      else if ((TREE_CODE (yt) == RECORD_TYPE || TREE_CODE (yt) == UNION_TYPE)
+              && TYPE_NAME (yt) != NULL_TREE
+              && TREE_CODE (TYPE_NAME (yt)) == TYPE_DECL)
+       yn = DECL_NAME (TYPE_NAME (yt));
+      else
+       yn = NULL_TREE;
+
+      if (xn != NULL_TREE && xn == yn)
+       return true;
+    }
+
+  return false;
+}
+
+/* Subroutine of detect_field_duplicates: add the fields of FIELDLIST
+   to HTAB, giving errors for any duplicates.  */
+
+static void
+detect_field_duplicates_hash (tree fieldlist, htab_t htab)
+{
+  tree x, y;
+  void **slot;
+
+  for (x = fieldlist; x ; x = DECL_CHAIN (x))
+    if ((y = DECL_NAME (x)) != 0)
+      {
+       slot = htab_find_slot (htab, y, INSERT);
+       if (*slot)
+         {
+           error ("duplicate member %q+D", x);
+           DECL_NAME (x) = NULL_TREE;
+         }
+       *slot = y;
+      }
+    else if (TREE_CODE (TREE_TYPE (x)) == RECORD_TYPE
+            || TREE_CODE (TREE_TYPE (x)) == UNION_TYPE)
+      {
+       detect_field_duplicates_hash (TYPE_FIELDS (TREE_TYPE (x)), htab);
+
+       /* When using -fplan9-extensions, an anonymous field whose
+          name is a typedef can duplicate a field name.  */
+       if (flag_plan9_extensions
+           && TYPE_NAME (TREE_TYPE (x)) != NULL_TREE
+           && TREE_CODE (TYPE_NAME (TREE_TYPE (x))) == TYPE_DECL)
+         {
+           tree xn = DECL_NAME (TYPE_NAME (TREE_TYPE (x)));
+           slot = htab_find_slot (htab, xn, INSERT);
+           if (*slot)
+             error ("duplicate member %q+D", TYPE_NAME (TREE_TYPE (x)));
+           *slot = xn;
+         }
+      }
+}
+
+/* Generate an error for any duplicate field names in FIELDLIST.  Munge
+   the list such that this does not present a problem later.  */
+
+static void
+detect_field_duplicates (tree fieldlist)
+{
+  tree x, y;
+  int timeout = 10;
+
+  /* If the struct is the list of instance variables of an Objective-C
+     class, then we need to check all the instance variables of
+     superclasses when checking for duplicates (since you can't have
+     an instance variable in a subclass with the same name as an
+     instance variable in a superclass).  We pass on this job to the
+     Objective-C compiler.  objc_detect_field_duplicates() will return
+     false if we are not checking the list of instance variables and
+     the C frontend should proceed with the standard field duplicate
+     checks.  If we are checking the list of instance variables, the
+     ObjC frontend will do the check, emit the errors if needed, and
+     then return true.  */
+  if (c_dialect_objc ())
+    if (objc_detect_field_duplicates (false))
+      return;
+
+  /* First, see if there are more than "a few" fields.
+     This is trivially true if there are zero or one fields.  */
+  if (!fieldlist || !DECL_CHAIN (fieldlist))
+    return;
+  x = fieldlist;
+  do {
+    timeout--;
+    if (DECL_NAME (x) == NULL_TREE
+       && (TREE_CODE (TREE_TYPE (x)) == RECORD_TYPE
+           || TREE_CODE (TREE_TYPE (x)) == UNION_TYPE))
+      timeout = 0;
+    x = DECL_CHAIN (x);
+  } while (timeout > 0 && x);
+
+  /* If there were "few" fields and no anonymous structures or unions,
+     avoid the overhead of allocating a hash table.  Instead just do
+     the nested traversal thing.  */
+  if (timeout > 0)
+    {
+      for (x = DECL_CHAIN (fieldlist); x; x = DECL_CHAIN (x))
+       /* When using -fplan9-extensions, we can have duplicates
+          between typedef names and fields.  */
+       if (DECL_NAME (x)
+           || (flag_plan9_extensions
+               && DECL_NAME (x) == NULL_TREE
+               && (TREE_CODE (TREE_TYPE (x)) == RECORD_TYPE
+                   || TREE_CODE (TREE_TYPE (x)) == UNION_TYPE)
+               && TYPE_NAME (TREE_TYPE (x)) != NULL_TREE
+               && TREE_CODE (TYPE_NAME (TREE_TYPE (x))) == TYPE_DECL))
+         {
+           for (y = fieldlist; y != x; y = TREE_CHAIN (y))
+             if (is_duplicate_field (y, x))
+               {
+                 error ("duplicate member %q+D", x);
+                 DECL_NAME (x) = NULL_TREE;
+               }
+         }
+    }
+  else
+    {
+      htab_t htab = htab_create (37, htab_hash_pointer, htab_eq_pointer, NULL);
+
+      detect_field_duplicates_hash (fieldlist, htab);
+      htab_delete (htab);
+    }
+}
+
+/* Finish up struct info used by -Wc++-compat.  */
+
+static void
+warn_cxx_compat_finish_struct (tree fieldlist)
+{
+  unsigned int ix;
+  tree x;
+  struct c_binding *b;
+
+  /* Set the C_TYPE_DEFINED_IN_STRUCT flag for each type defined in
+     the current struct.  We do this now at the end of the struct
+     because the flag is used to issue visibility warnings, and we
+     only want to issue those warnings if the type is referenced
+     outside of the struct declaration.  */
+  FOR_EACH_VEC_ELT (tree, struct_parse_info->struct_types, ix, x)
+    C_TYPE_DEFINED_IN_STRUCT (x) = 1;
+
+  /* The TYPEDEFS_SEEN field of STRUCT_PARSE_INFO is a list of
+     typedefs used when declaring fields in this struct.  If the name
+     of any of the fields is also a typedef name then the struct would
+     not parse in C++, because the C++ lookup rules say that the
+     typedef name would be looked up in the context of the struct, and
+     would thus be the field rather than the typedef.  */
+  if (!VEC_empty (tree, struct_parse_info->typedefs_seen)
+      && fieldlist != NULL_TREE)
+    {
+      /* Use a pointer_set using the name of the typedef.  We can use
+        a pointer_set because identifiers are interned.  */
+      struct pointer_set_t *tset = pointer_set_create ();
+
+      FOR_EACH_VEC_ELT (tree, struct_parse_info->typedefs_seen, ix, x)
+       pointer_set_insert (tset, DECL_NAME (x));
+
+      for (x = fieldlist; x != NULL_TREE; x = DECL_CHAIN (x))
+       {
+         if (DECL_NAME (x) != NULL_TREE
+             && pointer_set_contains (tset, DECL_NAME (x)))
+           {
+             warning_at (DECL_SOURCE_LOCATION (x), OPT_Wc___compat,
+                         ("using %qD as both field and typedef name is "
+                          "invalid in C++"),
+                         x);
+             /* FIXME: It would be nice to report the location where
+                the typedef name is used.  */
+           }
+       }
+
+      pointer_set_destroy (tset);
+    }
+
+  /* For each field which has a binding and which was not defined in
+     an enclosing struct, clear the in_struct field.  */
+  FOR_EACH_VEC_ELT (c_binding_ptr, struct_parse_info->fields, ix, b)
+    b->in_struct = 0;
+}
+
+/* Fill in the fields of a RECORD_TYPE or UNION_TYPE node, T.
+   LOC is the location of the RECORD_TYPE or UNION_TYPE's definition.
+   FIELDLIST is a chain of FIELD_DECL nodes for the fields.
+   ATTRIBUTES are attributes to be applied to the structure.
+
+   ENCLOSING_STRUCT_PARSE_INFO is the value of STRUCT_PARSE_INFO when
+   the struct was started.  */
+
+tree
+finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
+              struct c_struct_parse_info *enclosing_struct_parse_info)
+{
+  tree x;
+  bool toplevel = file_scope == current_scope;
+  int saw_named_field;
+
+  /* If this type was previously laid out as a forward reference,
+     make sure we lay it out again.  */
+
+  TYPE_SIZE (t) = 0;
+
+  decl_attributes (&t, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE);
+
+  if (pedantic)
+    {
+      for (x = fieldlist; x; x = DECL_CHAIN (x))
+       {
+         if (DECL_NAME (x) != 0)
+           break;
+         if (flag_isoc11
+             && (TREE_CODE (TREE_TYPE (x)) == RECORD_TYPE
+                 || TREE_CODE (TREE_TYPE (x)) == UNION_TYPE))
+           break;
+       }
+
+      if (x == 0)
+       {
+         if (TREE_CODE (t) == UNION_TYPE)
+           {
+             if (fieldlist)
+               pedwarn (loc, OPT_Wpedantic, "union has no named members");
+             else
+               pedwarn (loc, OPT_Wpedantic, "union has no members");
+           }
+         else
+           {
+             if (fieldlist)
+               pedwarn (loc, OPT_Wpedantic, "struct has no named members");
+             else
+               pedwarn (loc, OPT_Wpedantic, "struct has no members");
+           }
+       }
+    }
+
+  /* Install struct as DECL_CONTEXT of each field decl.
+     Also process specified field sizes, found in the DECL_INITIAL,
+     storing 0 there after the type has been changed to precision equal
+     to its width, rather than the precision of the specified standard
+     type.  (Correct layout requires the original type to have been preserved
+     until now.)  */
+
+  saw_named_field = 0;
+  for (x = fieldlist; x; x = DECL_CHAIN (x))
+    {
+      if (TREE_TYPE (x) == error_mark_node)
+       continue;
+
+      DECL_CONTEXT (x) = t;
+
+      /* If any field is const, the structure type is pseudo-const.  */
+      if (TREE_READONLY (x))
+       C_TYPE_FIELDS_READONLY (t) = 1;
+      else
+       {
+         /* A field that is pseudo-const makes the structure likewise.  */
+         tree t1 = strip_array_types (TREE_TYPE (x));
+         if ((TREE_CODE (t1) == RECORD_TYPE || TREE_CODE (t1) == UNION_TYPE)
+             && C_TYPE_FIELDS_READONLY (t1))
+           C_TYPE_FIELDS_READONLY (t) = 1;
+       }
+
+      /* Any field that is volatile means variables of this type must be
+        treated in some ways as volatile.  */
+      if (TREE_THIS_VOLATILE (x))
+       C_TYPE_FIELDS_VOLATILE (t) = 1;
+
+      /* Any field of nominal variable size implies structure is too.  */
+      if (C_DECL_VARIABLE_SIZE (x))
+       C_TYPE_VARIABLE_SIZE (t) = 1;
+
+      if (DECL_INITIAL (x))
+       {
+         unsigned HOST_WIDE_INT width = tree_low_cst (DECL_INITIAL (x), 1);
+         DECL_SIZE (x) = bitsize_int (width);
+         DECL_BIT_FIELD (x) = 1;
+         SET_DECL_C_BIT_FIELD (x);
+       }
+
+      if (TYPE_PACKED (t)
+         && (DECL_BIT_FIELD (x)
+             || TYPE_ALIGN (TREE_TYPE (x)) > BITS_PER_UNIT))
+       DECL_PACKED (x) = 1;
+
+      /* Detect flexible array member in an invalid context.  */
+      if (TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE
+         && TYPE_SIZE (TREE_TYPE (x)) == NULL_TREE
+         && TYPE_DOMAIN (TREE_TYPE (x)) != NULL_TREE
+         && TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (x))) == NULL_TREE)
+       {
+         if (TREE_CODE (t) == UNION_TYPE)
+           {
+             error_at (DECL_SOURCE_LOCATION (x),
+                       "flexible array member in union");
+             TREE_TYPE (x) = error_mark_node;
+           }
+         else if (DECL_CHAIN (x) != NULL_TREE)
+           {
+             error_at (DECL_SOURCE_LOCATION (x),
+                       "flexible array member not at end of struct");
+             TREE_TYPE (x) = error_mark_node;
+           }
+         else if (!saw_named_field)
+           {
+             error_at (DECL_SOURCE_LOCATION (x),
+                       "flexible array member in otherwise empty struct");
+             TREE_TYPE (x) = error_mark_node;
+           }
+       }
+
+      if (pedantic && TREE_CODE (t) == RECORD_TYPE
+         && flexible_array_type_p (TREE_TYPE (x)))
+       pedwarn (DECL_SOURCE_LOCATION (x), OPT_Wpedantic,
+                "invalid use of structure with flexible array member");
+
+      if (DECL_NAME (x)
+         || TREE_CODE (TREE_TYPE (x)) == RECORD_TYPE
+         || TREE_CODE (TREE_TYPE (x)) == UNION_TYPE)
+       saw_named_field = 1;
+    }
+
+  detect_field_duplicates (fieldlist);
+
+  /* Now we have the nearly final fieldlist.  Record it,
+     then lay out the structure or union (including the fields).  */
+
+  TYPE_FIELDS (t) = fieldlist;
+
+  layout_type (t);
+
+  /* Give bit-fields their proper types.  */
+  {
+    tree *fieldlistp = &fieldlist;
+    while (*fieldlistp)
+      if (TREE_CODE (*fieldlistp) == FIELD_DECL && DECL_INITIAL (*fieldlistp)
+         && TREE_TYPE (*fieldlistp) != error_mark_node)
+       {
+         unsigned HOST_WIDE_INT width
+           = tree_low_cst (DECL_INITIAL (*fieldlistp), 1);
+         tree type = TREE_TYPE (*fieldlistp);
+         if (width != TYPE_PRECISION (type))
+           {
+             TREE_TYPE (*fieldlistp)
+               = c_build_bitfield_integer_type (width, TYPE_UNSIGNED (type));
+             DECL_MODE (*fieldlistp) = TYPE_MODE (TREE_TYPE (*fieldlistp));
+           }
+         DECL_INITIAL (*fieldlistp) = 0;
+       }
+      else
+       fieldlistp = &DECL_CHAIN (*fieldlistp);
+  }
+
+  /* Now we have the truly final field list.
+     Store it in this type and in the variants.  */
+
+  TYPE_FIELDS (t) = fieldlist;
+
+  /* If there are lots of fields, sort so we can look through them fast.
+     We arbitrarily consider 16 or more elts to be "a lot".  */
+
+  {
+    int len = 0;
+
+    for (x = fieldlist; x; x = DECL_CHAIN (x))
+      {
+       if (len > 15 || DECL_NAME (x) == NULL)
+         break;
+       len += 1;
+      }
+
+    if (len > 15)
+      {
+       tree *field_array;
+       struct lang_type *space;
+       struct sorted_fields_type *space2;
+
+       len += list_length (x);
+
+       /* Use the same allocation policy here that make_node uses, to
+         ensure that this lives as long as the rest of the struct decl.
+         All decls in an inline function need to be saved.  */
+
+       space = ggc_alloc_cleared_lang_type (sizeof (struct lang_type));
+       space2 = ggc_alloc_sorted_fields_type
+         (sizeof (struct sorted_fields_type) + len * sizeof (tree));
+
+       len = 0;
+       space->s = space2;
+       field_array = &space2->elts[0];
+       for (x = fieldlist; x; x = DECL_CHAIN (x))
+         {
+           field_array[len++] = x;
+
+           /* If there is anonymous struct or union, break out of the loop.  */
+           if (DECL_NAME (x) == NULL)
+             break;
+         }
+       /* Found no anonymous struct/union.  Add the TYPE_LANG_SPECIFIC.  */
+       if (x == NULL)
+         {
+           TYPE_LANG_SPECIFIC (t) = space;
+           TYPE_LANG_SPECIFIC (t)->s->len = len;
+           field_array = TYPE_LANG_SPECIFIC (t)->s->elts;
+           qsort (field_array, len, sizeof (tree), field_decl_cmp);
+         }
+      }
+  }
+
+  for (x = TYPE_MAIN_VARIANT (t); x; x = TYPE_NEXT_VARIANT (x))
+    {
+      TYPE_FIELDS (x) = TYPE_FIELDS (t);
+      TYPE_LANG_SPECIFIC (x) = TYPE_LANG_SPECIFIC (t);
+      C_TYPE_FIELDS_READONLY (x) = C_TYPE_FIELDS_READONLY (t);
+      C_TYPE_FIELDS_VOLATILE (x) = C_TYPE_FIELDS_VOLATILE (t);
+      C_TYPE_VARIABLE_SIZE (x) = C_TYPE_VARIABLE_SIZE (t);
+    }
+
+  /* If this was supposed to be a transparent union, but we can't
+     make it one, warn and turn off the flag.  */
+  if (TREE_CODE (t) == UNION_TYPE
+      && TYPE_TRANSPARENT_AGGR (t)
+      && (!TYPE_FIELDS (t) || TYPE_MODE (t) != DECL_MODE (TYPE_FIELDS (t))))
+    {
+      TYPE_TRANSPARENT_AGGR (t) = 0;
+      warning_at (loc, 0, "union cannot be made transparent");
+    }
+
+  /* If this structure or union completes the type of any previous
+     variable declaration, lay it out and output its rtl.  */
+  for (x = C_TYPE_INCOMPLETE_VARS (TYPE_MAIN_VARIANT (t));
+       x;
+       x = TREE_CHAIN (x))
+    {
+      tree decl = TREE_VALUE (x);
+      if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
+       layout_array_type (TREE_TYPE (decl));
+      if (TREE_CODE (decl) != TYPE_DECL)
+       {
+         layout_decl (decl, 0);
+         if (c_dialect_objc ())
+           objc_check_decl (decl);
+         rest_of_decl_compilation (decl, toplevel, 0);
+       }
+    }
+  C_TYPE_INCOMPLETE_VARS (TYPE_MAIN_VARIANT (t)) = 0;
+
+  /* Update type location to the one of the definition, instead of e.g.
+     a forward declaration.  */
+  if (TYPE_STUB_DECL (t))
+    DECL_SOURCE_LOCATION (TYPE_STUB_DECL (t)) = loc;
+
+  /* Finish debugging output for this type.  */
+  rest_of_type_compilation (t, toplevel);
+
+  /* If we're inside a function proper, i.e. not file-scope and not still
+     parsing parameters, then arrange for the size of a variable sized type
+     to be bound now.  */
+  if (building_stmt_list_p () && variably_modified_type_p (t, NULL_TREE))
+    add_stmt (build_stmt (loc,
+                         DECL_EXPR, build_decl (loc, TYPE_DECL, NULL, t)));
+
+  if (warn_cxx_compat)
+    warn_cxx_compat_finish_struct (fieldlist);
+
+  VEC_free (tree, heap, struct_parse_info->struct_types);
+  VEC_free (c_binding_ptr, heap, struct_parse_info->fields);
+  VEC_free (tree, heap, struct_parse_info->typedefs_seen);
+  XDELETE (struct_parse_info);
+
+  struct_parse_info = enclosing_struct_parse_info;
+
+  /* If this struct is defined inside a struct, add it to
+     struct_types.  */
+  if (warn_cxx_compat
+      && struct_parse_info != NULL
+      && !in_sizeof && !in_typeof && !in_alignof)
+    VEC_safe_push (tree, heap, struct_parse_info->struct_types, t);
+
+  return t;
+}
+
+/* Lay out the type T, and its element type, and so on.  */
+
+static void
+layout_array_type (tree t)
+{
+  if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE)
+    layout_array_type (TREE_TYPE (t));
+  layout_type (t);
+}
+\f
+/* Begin compiling the definition of an enumeration type.
+   NAME is its name (or null if anonymous).
+   LOC is the enum's location.
+   Returns the type object, as yet incomplete.
+   Also records info about it so that build_enumerator
+   may be used to declare the individual values as they are read.  */
+
+tree
+start_enum (location_t loc, struct c_enum_contents *the_enum, tree name)
+{
+  tree enumtype = NULL_TREE;
+  location_t enumloc = UNKNOWN_LOCATION;
+
+  /* If this is the real definition for a previous forward reference,
+     fill in the contents in the same object that used to be the
+     forward reference.  */
+
+  if (name != NULL_TREE)
+    enumtype = lookup_tag (ENUMERAL_TYPE, name, 1, &enumloc);
+
+  if (enumtype == 0 || TREE_CODE (enumtype) != ENUMERAL_TYPE)
+    {
+      enumtype = make_node (ENUMERAL_TYPE);
+      pushtag (loc, name, enumtype);
+    }
+
+  if (C_TYPE_BEING_DEFINED (enumtype))
+    error_at (loc, "nested redefinition of %<enum %E%>", name);
+
+  C_TYPE_BEING_DEFINED (enumtype) = 1;
+
+  if (TYPE_VALUES (enumtype) != 0)
+    {
+      /* This enum is a named one that has been declared already.  */
+      error_at (loc, "redeclaration of %<enum %E%>", name);
+      if (enumloc != UNKNOWN_LOCATION)
+       inform (enumloc, "originally defined here");
+
+      /* Completely replace its old definition.
+        The old enumerators remain defined, however.  */
+      TYPE_VALUES (enumtype) = 0;
+    }
+
+  the_enum->enum_next_value = integer_zero_node;
+  the_enum->enum_overflow = 0;
+
+  if (flag_short_enums)
+    TYPE_PACKED (enumtype) = 1;
+
+  /* FIXME: This will issue a warning for a use of a type defined
+     within sizeof in a statement expr.  This is not terribly serious
+     as C++ doesn't permit statement exprs within sizeof anyhow.  */
+  if (warn_cxx_compat && (in_sizeof || in_typeof || in_alignof))
+    warning_at (loc, OPT_Wc___compat,
+               "defining type in %qs expression is invalid in C++",
+               (in_sizeof
+                ? "sizeof"
+                : (in_typeof ? "typeof" : "alignof")));
+
+  return enumtype;
+}
+
+/* After processing and defining all the values of an enumeration type,
+   install their decls in the enumeration type and finish it off.
+   ENUMTYPE is the type object, VALUES a list of decl-value pairs,
+   and ATTRIBUTES are the specified attributes.
+   Returns ENUMTYPE.  */
+
+tree
+finish_enum (tree enumtype, tree values, tree attributes)
+{
+  tree pair, tem;
+  tree minnode = 0, maxnode = 0;
+  int precision, unsign;
+  bool toplevel = (file_scope == current_scope);
+  struct lang_type *lt;
+
+  decl_attributes (&enumtype, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE);
+
+  /* Calculate the maximum value of any enumerator in this type.  */
+
+  if (values == error_mark_node)
+    minnode = maxnode = integer_zero_node;
+  else
+    {
+      minnode = maxnode = TREE_VALUE (values);
+      for (pair = TREE_CHAIN (values); pair; pair = TREE_CHAIN (pair))
+       {
+         tree value = TREE_VALUE (pair);
+         if (tree_int_cst_lt (maxnode, value))
+           maxnode = value;
+         if (tree_int_cst_lt (value, minnode))
+           minnode = value;
+       }
+    }
+
+  /* Construct the final type of this enumeration.  It is the same
+     as one of the integral types - the narrowest one that fits, except
+     that normally we only go as narrow as int - and signed iff any of
+     the values are negative.  */
+  unsign = (tree_int_cst_sgn (minnode) >= 0);
+  precision = MAX (tree_int_cst_min_precision (minnode, unsign),
+                  tree_int_cst_min_precision (maxnode, unsign));
+
+  if (TYPE_PACKED (enumtype) || precision > TYPE_PRECISION (integer_type_node))
+    {
+      tem = c_common_type_for_size (precision, unsign);
+      if (tem == NULL)
+       {
+         warning (0, "enumeration values exceed range of largest integer");
+         tem = long_long_integer_type_node;
+       }
+    }
+  else
+    tem = unsign ? unsigned_type_node : integer_type_node;
+
+  TYPE_MIN_VALUE (enumtype) = TYPE_MIN_VALUE (tem);
+  TYPE_MAX_VALUE (enumtype) = TYPE_MAX_VALUE (tem);
+  TYPE_UNSIGNED (enumtype) = TYPE_UNSIGNED (tem);
+  TYPE_SIZE (enumtype) = 0;
+
+  /* If the precision of the type was specific with an attribute and it
+     was too small, give an error.  Otherwise, use it.  */
+  if (TYPE_PRECISION (enumtype))
+    {
+      if (precision > TYPE_PRECISION (enumtype))
+       error ("specified mode too small for enumeral values");
+    }
+  else
+    TYPE_PRECISION (enumtype) = TYPE_PRECISION (tem);
+
+  layout_type (enumtype);
+
+  if (values != error_mark_node)
+    {
+      /* Change the type of the enumerators to be the enum type.  We
+        need to do this irrespective of the size of the enum, for
+        proper type checking.  Replace the DECL_INITIALs of the
+        enumerators, and the value slots of the list, with copies
+        that have the enum type; they cannot be modified in place
+        because they may be shared (e.g.  integer_zero_node) Finally,
+        change the purpose slots to point to the names of the decls.  */
+      for (pair = values; pair; pair = TREE_CHAIN (pair))
+       {
+         tree enu = TREE_PURPOSE (pair);
+         tree ini = DECL_INITIAL (enu);
+
+         TREE_TYPE (enu) = enumtype;
+
+         /* The ISO C Standard mandates enumerators to have type int,
+            even though the underlying type of an enum type is
+            unspecified.  However, GCC allows enumerators of any
+            integer type as an extensions.  build_enumerator()
+            converts any enumerators that fit in an int to type int,
+            to avoid promotions to unsigned types when comparing
+            integers with enumerators that fit in the int range.
+            When -pedantic is given, build_enumerator() would have
+            already warned about those that don't fit. Here we
+            convert the rest to the enumerator type. */
+         if (TREE_TYPE (ini) != integer_type_node)
+           ini = convert (enumtype, ini);
+
+         DECL_INITIAL (enu) = ini;
+         TREE_PURPOSE (pair) = DECL_NAME (enu);
+         TREE_VALUE (pair) = ini;
+       }
+
+      TYPE_VALUES (enumtype) = values;
+    }
+
+  /* Record the min/max values so that we can warn about bit-field
+     enumerations that are too small for the values.  */
+  lt = ggc_alloc_cleared_lang_type (sizeof (struct lang_type));
+  lt->enum_min = minnode;
+  lt->enum_max = maxnode;
+  TYPE_LANG_SPECIFIC (enumtype) = lt;
+
+  /* Fix up all variant types of this enum type.  */
+  for (tem = TYPE_MAIN_VARIANT (enumtype); tem; tem = TYPE_NEXT_VARIANT (tem))
+    {
+      if (tem == enumtype)
+       continue;
+      TYPE_VALUES (tem) = TYPE_VALUES (enumtype);
+      TYPE_MIN_VALUE (tem) = TYPE_MIN_VALUE (enumtype);
+      TYPE_MAX_VALUE (tem) = TYPE_MAX_VALUE (enumtype);
+      TYPE_SIZE (tem) = TYPE_SIZE (enumtype);
+      TYPE_SIZE_UNIT (tem) = TYPE_SIZE_UNIT (enumtype);
+      SET_TYPE_MODE (tem, TYPE_MODE (enumtype));
+      TYPE_PRECISION (tem) = TYPE_PRECISION (enumtype);
+      TYPE_ALIGN (tem) = TYPE_ALIGN (enumtype);
+      TYPE_USER_ALIGN (tem) = TYPE_USER_ALIGN (enumtype);
+      TYPE_UNSIGNED (tem) = TYPE_UNSIGNED (enumtype);
+      TYPE_LANG_SPECIFIC (tem) = TYPE_LANG_SPECIFIC (enumtype);
+    }
+
+  /* Finish debugging output for this type.  */
+  rest_of_type_compilation (enumtype, toplevel);
+
+  /* If this enum is defined inside a struct, add it to
+     struct_types.  */
+  if (warn_cxx_compat
+      && struct_parse_info != NULL
+      && !in_sizeof && !in_typeof && !in_alignof)
+    VEC_safe_push (tree, heap, struct_parse_info->struct_types, enumtype);
+
+  return enumtype;
+}
+
+/* Build and install a CONST_DECL for one value of the
+   current enumeration type (one that was begun with start_enum).
+   DECL_LOC is the location of the enumerator.
+   LOC is the location of the '=' operator if any, DECL_LOC otherwise.
+   Return a tree-list containing the CONST_DECL and its value.
+   Assignment of sequential values by default is handled here.  */
+
+tree
+build_enumerator (location_t decl_loc, location_t loc,
+                 struct c_enum_contents *the_enum, tree name, tree value)
+{
+  tree decl, type;
+
+  /* Validate and default VALUE.  */
+
+  if (value != 0)
+    {
+      /* Don't issue more errors for error_mark_node (i.e. an
+        undeclared identifier) - just ignore the value expression.  */
+      if (value == error_mark_node)
+       value = 0;
+      else if (!INTEGRAL_TYPE_P (TREE_TYPE (value)))
+       {
+         error_at (loc, "enumerator value for %qE is not an integer constant",
+                   name);
+         value = 0;
+       }
+      else
+       {
+         if (TREE_CODE (value) != INTEGER_CST)
+           {
+             value = c_fully_fold (value, false, NULL);
+             if (TREE_CODE (value) == INTEGER_CST)
+               pedwarn (loc, OPT_Wpedantic,
+                        "enumerator value for %qE is not an integer "
+                        "constant expression", name);
+           }
+         if (TREE_CODE (value) != INTEGER_CST)
+           {
+             error ("enumerator value for %qE is not an integer constant",
+                    name);
+             value = 0;
+           }
+         else
+           {
+             value = default_conversion (value);
+             constant_expression_warning (value);
+           }
+       }
+    }
+
+  /* Default based on previous value.  */
+  /* It should no longer be possible to have NON_LVALUE_EXPR
+     in the default.  */
+  if (value == 0)
+    {
+      value = the_enum->enum_next_value;
+      if (the_enum->enum_overflow)
+       error_at (loc, "overflow in enumeration values");
+    }
+  /* Even though the underlying type of an enum is unspecified, the
+     type of enumeration constants is explicitly defined as int
+     (6.4.4.3/2 in the C99 Standard).  GCC allows any integer type as
+     an extension.  */
+  else if (!int_fits_type_p (value, integer_type_node))
+    pedwarn (loc, OPT_Wpedantic,
+            "ISO C restricts enumerator values to range of %<int%>");
+
+  /* The ISO C Standard mandates enumerators to have type int, even
+     though the underlying type of an enum type is unspecified.
+     However, GCC allows enumerators of any integer type as an
+     extensions.  Here we convert any enumerators that fit in an int
+     to type int, to avoid promotions to unsigned types when comparing
+     integers with enumerators that fit in the int range.  When
+     -pedantic is given, we would have already warned about those that
+     don't fit. We have to do this here rather than in finish_enum
+     because this value may be used to define more enumerators.  */
+  if (int_fits_type_p (value, integer_type_node))
+    value = convert (integer_type_node, value);
+
+  /* Set basis for default for next value.  */
+  the_enum->enum_next_value
+    = build_binary_op (EXPR_LOC_OR_HERE (value),
+                      PLUS_EXPR, value, integer_one_node, 0);
+  the_enum->enum_overflow = tree_int_cst_lt (the_enum->enum_next_value, value);
+
+  /* Now create a declaration for the enum value name.  */
+
+  type = TREE_TYPE (value);
+  type = c_common_type_for_size (MAX (TYPE_PRECISION (type),
+                                     TYPE_PRECISION (integer_type_node)),
+                                (TYPE_PRECISION (type)
+                                 >= TYPE_PRECISION (integer_type_node)
+                                 && TYPE_UNSIGNED (type)));
+
+  decl = build_decl (decl_loc, CONST_DECL, name, type);
+  DECL_INITIAL (decl) = convert (type, value);
+  pushdecl (decl);
+
+  return tree_cons (decl, value, NULL_TREE);
+}
+
+\f
+/* Create the FUNCTION_DECL for a function definition.
+   DECLSPECS, DECLARATOR and ATTRIBUTES are the parts of
+   the declaration; they describe the function's name and the type it returns,
+   but twisted together in a fashion that parallels the syntax of C.
+
+   This function creates a binding context for the function body
+   as well as setting up the FUNCTION_DECL in current_function_decl.
+
+   Returns 1 on success.  If the DECLARATOR is not suitable for a function
+   (it defines a datum instead), we return 0, which tells
+   yyparse to report a parse error.  */
+
+int
+start_function (struct c_declspecs *declspecs, struct c_declarator *declarator,
+               tree attributes)
+{
+  tree decl1, old_decl;
+  tree restype, resdecl;
+  location_t loc;
+
+  current_function_returns_value = 0;  /* Assume, until we see it does.  */
+  current_function_returns_null = 0;
+  current_function_returns_abnormally = 0;
+  warn_about_return_type = 0;
+  c_switch_stack = NULL;
+
+  /* Indicate no valid break/continue context by setting these variables
+     to some non-null, non-label value.  We'll notice and emit the proper
+     error message in c_finish_bc_stmt.  */
+  c_break_label = c_cont_label = size_zero_node;
+
+  decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, true, NULL,
+                         &attributes, NULL, NULL, DEPRECATED_NORMAL);
+
+  /* If the declarator is not suitable for a function definition,
+     cause a syntax error.  */
+  if (decl1 == 0
+      || TREE_CODE (decl1) != FUNCTION_DECL)
+    return 0;
+
+  loc = DECL_SOURCE_LOCATION (decl1);
+
+  decl_attributes (&decl1, attributes, 0);
+
+  if (DECL_DECLARED_INLINE_P (decl1)
+      && DECL_UNINLINABLE (decl1)
+      && lookup_attribute ("noinline", DECL_ATTRIBUTES (decl1)))
+    warning_at (loc, OPT_Wattributes,
+               "inline function %qD given attribute noinline",
+               decl1);
+
+  /* Handle gnu_inline attribute.  */
+  if (declspecs->inline_p
+      && !flag_gnu89_inline
+      && TREE_CODE (decl1) == FUNCTION_DECL
+      && (lookup_attribute ("gnu_inline", DECL_ATTRIBUTES (decl1))
+         || current_function_decl))
+    {
+      if (declspecs->storage_class != csc_static)
+       DECL_EXTERNAL (decl1) = !DECL_EXTERNAL (decl1);
+    }
+
+  announce_function (decl1);
+
+  if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl1))))
+    {
+      error_at (loc, "return type is an incomplete type");
+      /* Make it return void instead.  */
+      TREE_TYPE (decl1)
+       = build_function_type (void_type_node,
+                              TYPE_ARG_TYPES (TREE_TYPE (decl1)));
+    }
+
+  if (warn_about_return_type)
+    pedwarn_c99 (loc, flag_isoc99 ? 0
+                : (warn_return_type ? OPT_Wreturn_type : OPT_Wimplicit_int),
+                "return type defaults to %<int%>");
+
+  /* Make the init_value nonzero so pushdecl knows this is not tentative.
+     error_mark_node is replaced below (in pop_scope) with the BLOCK.  */
+  DECL_INITIAL (decl1) = error_mark_node;
+
+  /* A nested function is not global.  */
+  if (current_function_decl != 0)
+    TREE_PUBLIC (decl1) = 0;
+
+  /* If this definition isn't a prototype and we had a prototype declaration
+     before, copy the arg type info from that prototype.  */
+  old_decl = lookup_name_in_scope (DECL_NAME (decl1), current_scope);
+  if (old_decl && TREE_CODE (old_decl) != FUNCTION_DECL)
+    old_decl = 0;
+  current_function_prototype_locus = UNKNOWN_LOCATION;
+  current_function_prototype_built_in = false;
+  current_function_prototype_arg_types = NULL_TREE;
+  if (!prototype_p (TREE_TYPE (decl1)))
+    {
+      if (old_decl != 0 && TREE_CODE (TREE_TYPE (old_decl)) == FUNCTION_TYPE
+         && comptypes (TREE_TYPE (TREE_TYPE (decl1)),
+                       TREE_TYPE (TREE_TYPE (old_decl))))
+       {
+         TREE_TYPE (decl1) = composite_type (TREE_TYPE (old_decl),
+                                             TREE_TYPE (decl1));
+         current_function_prototype_locus = DECL_SOURCE_LOCATION (old_decl);
+         current_function_prototype_built_in
+           = C_DECL_BUILTIN_PROTOTYPE (old_decl);
+         current_function_prototype_arg_types
+           = TYPE_ARG_TYPES (TREE_TYPE (decl1));
+       }
+      if (TREE_PUBLIC (decl1))
+       {
+         /* If there is an external prototype declaration of this
+            function, record its location but do not copy information
+            to this decl.  This may be an invisible declaration
+            (built-in or in a scope which has finished) or simply
+            have more refined argument types than any declaration
+            found above.  */
+         struct c_binding *b;
+         for (b = I_SYMBOL_BINDING (DECL_NAME (decl1)); b; b = b->shadowed)
+           if (B_IN_SCOPE (b, external_scope))
+             break;
+         if (b)
+           {
+             tree ext_decl, ext_type;
+             ext_decl = b->decl;
+             ext_type = b->u.type ? b->u.type : TREE_TYPE (ext_decl);
+             if (TREE_CODE (ext_type) == FUNCTION_TYPE
+                 && comptypes (TREE_TYPE (TREE_TYPE (decl1)),
+                               TREE_TYPE (ext_type)))
+               {
+                 current_function_prototype_locus
+                   = DECL_SOURCE_LOCATION (ext_decl);
+                 current_function_prototype_built_in
+                   = C_DECL_BUILTIN_PROTOTYPE (ext_decl);
+                 current_function_prototype_arg_types
+                   = TYPE_ARG_TYPES (ext_type);
+               }
+           }
+       }
+    }
+
+  /* Optionally warn of old-fashioned def with no previous prototype.  */
+  if (warn_strict_prototypes
+      && old_decl != error_mark_node
+      && !prototype_p (TREE_TYPE (decl1))
+      && C_DECL_ISNT_PROTOTYPE (old_decl))
+    warning_at (loc, OPT_Wstrict_prototypes,
+               "function declaration isn%'t a prototype");
+  /* Optionally warn of any global def with no previous prototype.  */
+  else if (warn_missing_prototypes
+          && old_decl != error_mark_node
+          && TREE_PUBLIC (decl1)
+          && !MAIN_NAME_P (DECL_NAME (decl1))
+          && C_DECL_ISNT_PROTOTYPE (old_decl))
+    warning_at (loc, OPT_Wmissing_prototypes,
+               "no previous prototype for %qD", decl1);
+  /* Optionally warn of any def with no previous prototype
+     if the function has already been used.  */
+  else if (warn_missing_prototypes
+          && old_decl != 0
+          && old_decl != error_mark_node
+          && TREE_USED (old_decl)
+          && !prototype_p (TREE_TYPE (old_decl)))
+    warning_at (loc, OPT_Wmissing_prototypes,
+               "%qD was used with no prototype before its definition", decl1);
+  /* Optionally warn of any global def with no previous declaration.  */
+  else if (warn_missing_declarations
+          && TREE_PUBLIC (decl1)
+          && old_decl == 0
+          && !MAIN_NAME_P (DECL_NAME (decl1)))
+    warning_at (loc, OPT_Wmissing_declarations,
+               "no previous declaration for %qD",
+               decl1);
+  /* Optionally warn of any def with no previous declaration
+     if the function has already been used.  */
+  else if (warn_missing_declarations
+          && old_decl != 0
+          && old_decl != error_mark_node
+          && TREE_USED (old_decl)
+          && C_DECL_IMPLICIT (old_decl))
+    warning_at (loc, OPT_Wmissing_declarations,
+               "%qD was used with no declaration before its definition", decl1);
+
+  /* This function exists in static storage.
+     (This does not mean `static' in the C sense!)  */
+  TREE_STATIC (decl1) = 1;
+
+  /* This is the earliest point at which we might know the assembler
+     name of the function.  Thus, if it's set before this, die horribly.  */
+  gcc_assert (!DECL_ASSEMBLER_NAME_SET_P (decl1));
+
+  /* If #pragma weak was used, mark the decl weak now.  */
+  if (current_scope == file_scope)
+    maybe_apply_pragma_weak (decl1);
+
+  /* Warn for unlikely, improbable, or stupid declarations of `main'.  */
+  if (warn_main && MAIN_NAME_P (DECL_NAME (decl1)))
+    {
+      if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (decl1)))
+         != integer_type_node)
+       pedwarn (loc, OPT_Wmain, "return type of %qD is not %<int%>", decl1);
+
+      check_main_parameter_types (decl1);
+
+      if (!TREE_PUBLIC (decl1))
+       pedwarn (loc, OPT_Wmain,
+                "%qD is normally a non-static function", decl1);
+    }
+
+  /* Record the decl so that the function name is defined.
+     If we already have a decl for this name, and it is a FUNCTION_DECL,
+     use the old decl.  */
+
+  current_function_decl = pushdecl (decl1);
+
+  push_scope ();
+  declare_parm_level ();
+
+  restype = TREE_TYPE (TREE_TYPE (current_function_decl));
+  resdecl = build_decl (loc, RESULT_DECL, NULL_TREE, restype);
+  DECL_ARTIFICIAL (resdecl) = 1;
+  DECL_IGNORED_P (resdecl) = 1;
+  DECL_RESULT (current_function_decl) = resdecl;
+
+  start_fname_decls ();
+
+  return 1;
+}
+\f
+/* Subroutine of store_parm_decls which handles new-style function
+   definitions (prototype format). The parms already have decls, so we
+   need only record them as in effect and complain if any redundant
+   old-style parm decls were written.  */
+static void
+store_parm_decls_newstyle (tree fndecl, const struct c_arg_info *arg_info)
+{
+  tree decl;
+  c_arg_tag *tag;
+  unsigned ix;
+
+  if (current_scope->bindings)
+    {
+      error_at (DECL_SOURCE_LOCATION (fndecl),
+               "old-style parameter declarations in prototyped "
+               "function definition");
+
+      /* Get rid of the old-style declarations.  */
+      pop_scope ();
+      push_scope ();
+    }
+  /* Don't issue this warning for nested functions, and don't issue this
+     warning if we got here because ARG_INFO_TYPES was error_mark_node
+     (this happens when a function definition has just an ellipsis in
+     its parameter list).  */
+  else if (!in_system_header && !current_function_scope
+          && arg_info->types != error_mark_node)
+    warning_at (DECL_SOURCE_LOCATION (fndecl), OPT_Wtraditional,
+               "traditional C rejects ISO C style function definitions");
+
+  /* Now make all the parameter declarations visible in the function body.
+     We can bypass most of the grunt work of pushdecl.  */
+  for (decl = arg_info->parms; decl; decl = DECL_CHAIN (decl))
+    {
+      DECL_CONTEXT (decl) = current_function_decl;
+      if (DECL_NAME (decl))
+       {
+         bind (DECL_NAME (decl), decl, current_scope,
+               /*invisible=*/false, /*nested=*/false,
+               UNKNOWN_LOCATION);
+         if (!TREE_USED (decl))
+           warn_if_shadowing (decl);
+       }
+      else
+       error_at (DECL_SOURCE_LOCATION (decl), "parameter name omitted");
+    }
+
+  /* Record the parameter list in the function declaration.  */
+  DECL_ARGUMENTS (fndecl) = arg_info->parms;
+
+  /* Now make all the ancillary declarations visible, likewise.  */
+  for (decl = arg_info->others; decl; decl = DECL_CHAIN (decl))
+    {
+      DECL_CONTEXT (decl) = current_function_decl;
+      if (DECL_NAME (decl))
+       bind (DECL_NAME (decl), decl, current_scope,
+             /*invisible=*/false,
+             /*nested=*/(TREE_CODE (decl) == FUNCTION_DECL),
+             UNKNOWN_LOCATION);
+    }
+
+  /* And all the tag declarations.  */
+  FOR_EACH_VEC_ELT_REVERSE (c_arg_tag, arg_info->tags, ix, tag)
+    if (tag->id)
+      bind (tag->id, tag->type, current_scope,
+           /*invisible=*/false, /*nested=*/false, UNKNOWN_LOCATION);
+}
+
+/* Subroutine of store_parm_decls which handles old-style function
+   definitions (separate parameter list and declarations).  */
+
+static void
+store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
+{
+  struct c_binding *b;
+  tree parm, decl, last;
+  tree parmids = arg_info->parms;
+  struct pointer_set_t *seen_args = pointer_set_create ();
+
+  if (!in_system_header)
+    warning_at (DECL_SOURCE_LOCATION (fndecl),
+               OPT_Wold_style_definition, "old-style function definition");
+
+  /* Match each formal parameter name with its declaration.  Save each
+     decl in the appropriate TREE_PURPOSE slot of the parmids chain.  */
+  for (parm = parmids; parm; parm = TREE_CHAIN (parm))
+    {
+      if (TREE_VALUE (parm) == 0)
+       {
+         error_at (DECL_SOURCE_LOCATION (fndecl),
+                   "parameter name missing from parameter list");
+         TREE_PURPOSE (parm) = 0;
+         continue;
+       }
+
+      b = I_SYMBOL_BINDING (TREE_VALUE (parm));
+      if (b && B_IN_CURRENT_SCOPE (b))
+       {
+         decl = b->decl;
+         /* Skip erroneous parameters.  */
+         if (decl == error_mark_node)
+           continue;
+         /* If we got something other than a PARM_DECL it is an error.  */
+         if (TREE_CODE (decl) != PARM_DECL)
+           error_at (DECL_SOURCE_LOCATION (decl),
+                     "%qD declared as a non-parameter", decl);
+         /* If the declaration is already marked, we have a duplicate
+            name.  Complain and ignore the duplicate.  */
+         else if (pointer_set_contains (seen_args, decl))
+           {
+             error_at (DECL_SOURCE_LOCATION (decl),
+                       "multiple parameters named %qD", decl);
+             TREE_PURPOSE (parm) = 0;
+             continue;
+           }
+         /* If the declaration says "void", complain and turn it into
+            an int.  */
+         else if (VOID_TYPE_P (TREE_TYPE (decl)))
+           {
+             error_at (DECL_SOURCE_LOCATION (decl),
+                       "parameter %qD declared with void type", decl);
+             TREE_TYPE (decl) = integer_type_node;
+             DECL_ARG_TYPE (decl) = integer_type_node;
+             layout_decl (decl, 0);
+           }
+         warn_if_shadowing (decl);
+       }
+      /* If no declaration found, default to int.  */
+      else
+       {
+         /* FIXME diagnostics: This should be the location of the argument,
+            not the FNDECL.  E.g., for an old-style declaration
+
+              int f10(v) { blah; }
+
+            We should use the location of the V, not the F10.
+            Unfortunately, the V is an IDENTIFIER_NODE which has no
+            location.  In the future we need locations for c_arg_info
+            entries.
+
+            See gcc.dg/Wshadow-3.c for an example of this problem. */
+         decl = build_decl (DECL_SOURCE_LOCATION (fndecl),
+                            PARM_DECL, TREE_VALUE (parm), integer_type_node);
+         DECL_ARG_TYPE (decl) = TREE_TYPE (decl);
+         pushdecl (decl);
+         warn_if_shadowing (decl);
+
+         if (flag_isoc99)
+           pedwarn (DECL_SOURCE_LOCATION (decl),
+                    0, "type of %qD defaults to %<int%>", decl);
+         else
+           warning_at (DECL_SOURCE_LOCATION (decl),
+                       OPT_Wmissing_parameter_type,
+                       "type of %qD defaults to %<int%>", decl);
+       }
+
+      TREE_PURPOSE (parm) = decl;
+      pointer_set_insert (seen_args, decl);
+    }
+
+  /* Now examine the parms chain for incomplete declarations
+     and declarations with no corresponding names.  */
+
+  for (b = current_scope->bindings; b; b = b->prev)
+    {
+      parm = b->decl;
+      if (TREE_CODE (parm) != PARM_DECL)
+       continue;
+
+      if (TREE_TYPE (parm) != error_mark_node
+         && !COMPLETE_TYPE_P (TREE_TYPE (parm)))
+       {
+         error_at (DECL_SOURCE_LOCATION (parm),
+                   "parameter %qD has incomplete type", parm);
+         TREE_TYPE (parm) = error_mark_node;
+       }
+
+      if (!pointer_set_contains (seen_args, parm))
+       {
+         error_at (DECL_SOURCE_LOCATION (parm),
+                   "declaration for parameter %qD but no such parameter",
+                   parm);
+
+         /* Pretend the parameter was not missing.
+            This gets us to a standard state and minimizes
+            further error messages.  */
+         parmids = chainon (parmids, tree_cons (parm, 0, 0));
+       }
+    }
+
+  /* Chain the declarations together in the order of the list of
+     names.  Store that chain in the function decl, replacing the
+     list of names.  Update the current scope to match.  */
+  DECL_ARGUMENTS (fndecl) = 0;
+
+  for (parm = parmids; parm; parm = TREE_CHAIN (parm))
+    if (TREE_PURPOSE (parm))
+      break;
+  if (parm && TREE_PURPOSE (parm))
+    {
+      last = TREE_PURPOSE (parm);
+      DECL_ARGUMENTS (fndecl) = last;
+
+      for (parm = TREE_CHAIN (parm); parm; parm = TREE_CHAIN (parm))
+       if (TREE_PURPOSE (parm))
+         {
+           DECL_CHAIN (last) = TREE_PURPOSE (parm);
+           last = TREE_PURPOSE (parm);
+         }
+      DECL_CHAIN (last) = 0;
+    }
+
+  pointer_set_destroy (seen_args);
+
+  /* If there was a previous prototype,
+     set the DECL_ARG_TYPE of each argument according to
+     the type previously specified, and report any mismatches.  */
+
+  if (current_function_prototype_arg_types)
+    {
+      tree type;
+      for (parm = DECL_ARGUMENTS (fndecl),
+            type = current_function_prototype_arg_types;
+          parm || (type && TREE_VALUE (type) != error_mark_node
+                   && (TYPE_MAIN_VARIANT (TREE_VALUE (type)) != void_type_node));
+          parm = DECL_CHAIN (parm), type = TREE_CHAIN (type))
+       {
+         if (parm == 0 || type == 0
+             || TYPE_MAIN_VARIANT (TREE_VALUE (type)) == void_type_node)
+           {
+             if (current_function_prototype_built_in)
+               warning_at (DECL_SOURCE_LOCATION (fndecl),
+                           0, "number of arguments doesn%'t match "
+                           "built-in prototype");
+             else
+               {
+                 /* FIXME diagnostics: This should be the location of
+                    FNDECL, but there is bug when a prototype is
+                    declared inside function context, but defined
+                    outside of it (e.g., gcc.dg/pr15698-2.c).  In
+                    which case FNDECL gets the location of the
+                    prototype, not the definition.  */
+                 error_at (input_location,
+                           "number of arguments doesn%'t match prototype");
+
+                 error_at (current_function_prototype_locus,
+                           "prototype declaration");
+               }
+             break;
+           }
+         /* Type for passing arg must be consistent with that
+            declared for the arg.  ISO C says we take the unqualified
+            type for parameters declared with qualified type.  */
+         if (TREE_TYPE (parm) != error_mark_node
+             && TREE_TYPE (type) != error_mark_node
+             && !comptypes (TYPE_MAIN_VARIANT (DECL_ARG_TYPE (parm)),
+                            TYPE_MAIN_VARIANT (TREE_VALUE (type))))
+           {
+             if (TYPE_MAIN_VARIANT (TREE_TYPE (parm))
+                 == TYPE_MAIN_VARIANT (TREE_VALUE (type)))
+               {
+                 /* Adjust argument to match prototype.  E.g. a previous
+                    `int foo(float);' prototype causes
+                    `int foo(x) float x; {...}' to be treated like
+                    `int foo(float x) {...}'.  This is particularly
+                    useful for argument types like uid_t.  */
+                 DECL_ARG_TYPE (parm) = TREE_TYPE (parm);
+
+                 if (targetm.calls.promote_prototypes (TREE_TYPE (current_function_decl))
+                     && INTEGRAL_TYPE_P (TREE_TYPE (parm))
+                     && TYPE_PRECISION (TREE_TYPE (parm))
+                     < TYPE_PRECISION (integer_type_node))
+                   DECL_ARG_TYPE (parm) = integer_type_node;
+
+                 /* ??? Is it possible to get here with a
+                    built-in prototype or will it always have
+                    been diagnosed as conflicting with an
+                    old-style definition and discarded?  */
+                 if (current_function_prototype_built_in)
+                   warning_at (DECL_SOURCE_LOCATION (parm),
+                               OPT_Wpedantic, "promoted argument %qD "
+                               "doesn%'t match built-in prototype", parm);
+                 else
+                   {
+                     pedwarn (DECL_SOURCE_LOCATION (parm),
+                              OPT_Wpedantic, "promoted argument %qD "
+                              "doesn%'t match prototype", parm);
+                     pedwarn (current_function_prototype_locus, OPT_Wpedantic,
+                              "prototype declaration");
+                   }
+               }
+             else
+               {
+                 if (current_function_prototype_built_in)
+                   warning_at (DECL_SOURCE_LOCATION (parm),
+                               0, "argument %qD doesn%'t match "
+                               "built-in prototype", parm);
+                 else
+                   {
+                     error_at (DECL_SOURCE_LOCATION (parm),
+                               "argument %qD doesn%'t match prototype", parm);
+                     error_at (current_function_prototype_locus,
+                               "prototype declaration");
+                   }
+               }
+           }
+       }
+      TYPE_ACTUAL_ARG_TYPES (TREE_TYPE (fndecl)) = 0;
+    }
+
+  /* Otherwise, create a prototype that would match.  */
+
+  else
+    {
+      tree actual = 0, last = 0, type;
+
+      for (parm = DECL_ARGUMENTS (fndecl); parm; parm = DECL_CHAIN (parm))
+       {
+         type = tree_cons (NULL_TREE, DECL_ARG_TYPE (parm), NULL_TREE);
+         if (last)
+           TREE_CHAIN (last) = type;
+         else
+           actual = type;
+         last = type;
+       }
+      type = tree_cons (NULL_TREE, void_type_node, NULL_TREE);
+      if (last)
+       TREE_CHAIN (last) = type;
+      else
+       actual = type;
+
+      /* We are going to assign a new value for the TYPE_ACTUAL_ARG_TYPES
+        of the type of this function, but we need to avoid having this
+        affect the types of other similarly-typed functions, so we must
+        first force the generation of an identical (but separate) type
+        node for the relevant function type.  The new node we create
+        will be a variant of the main variant of the original function
+        type.  */
+
+      TREE_TYPE (fndecl) = build_variant_type_copy (TREE_TYPE (fndecl));
+
+      TYPE_ACTUAL_ARG_TYPES (TREE_TYPE (fndecl)) = actual;
+    }
+}
+
+/* Store parameter declarations passed in ARG_INFO into the current
+   function declaration.  */
+
+void
+store_parm_decls_from (struct c_arg_info *arg_info)
+{
+  current_function_arg_info = arg_info;
+  store_parm_decls ();
+}
+
+/* Store the parameter declarations into the current function declaration.
+   This is called after parsing the parameter declarations, before
+   digesting the body of the function.
+
+   For an old-style definition, construct a prototype out of the old-style
+   parameter declarations and inject it into the function's type.  */
+
+void
+store_parm_decls (void)
+{
+  tree fndecl = current_function_decl;
+  bool proto;
+
+  /* The argument information block for FNDECL.  */
+  struct c_arg_info *arg_info = current_function_arg_info;
+  current_function_arg_info = 0;
+
+  /* True if this definition is written with a prototype.  Note:
+     despite C99 6.7.5.3p14, we can *not* treat an empty argument
+     list in a function definition as equivalent to (void) -- an
+     empty argument list specifies the function has no parameters,
+     but only (void) sets up a prototype for future calls.  */
+  proto = arg_info->types != 0;
+
+  if (proto)
+    store_parm_decls_newstyle (fndecl, arg_info);
+  else
+    store_parm_decls_oldstyle (fndecl, arg_info);
+
+  /* The next call to push_scope will be a function body.  */
+
+  next_is_function_body = true;
+
+  /* Write a record describing this function definition to the prototypes
+     file (if requested).  */
+
+  gen_aux_info_record (fndecl, 1, 0, proto);
+
+  /* Initialize the RTL code for the function.  */
+  allocate_struct_function (fndecl, false);
+
+  if (warn_unused_local_typedefs)
+    cfun->language = ggc_alloc_cleared_language_function ();
+
+  /* Begin the statement tree for this function.  */
+  DECL_SAVED_TREE (fndecl) = push_stmt_list ();
+
+  /* ??? Insert the contents of the pending sizes list into the function
+     to be evaluated.  The only reason left to have this is
+       void foo(int n, int array[n++])
+     because we throw away the array type in favor of a pointer type, and
+     thus won't naturally see the SAVE_EXPR containing the increment.  All
+     other pending sizes would be handled by gimplify_parameters.  */
+  if (arg_info->pending_sizes)
+    add_stmt (arg_info->pending_sizes);
+}
+\f
+
+/* Finish up a function declaration and compile that function
+   all the way to assembler language output.  Then free the storage
+   for the function definition.
+
+   This is called after parsing the body of the function definition.  */
+
+void
+finish_function (void)
+{
+  tree fndecl = current_function_decl;
+  
+  if (c_dialect_objc ())
+    objc_finish_function ();
+
+  if (TREE_CODE (fndecl) == FUNCTION_DECL
+      && targetm.calls.promote_prototypes (TREE_TYPE (fndecl)))
+    {
+      tree args = DECL_ARGUMENTS (fndecl);
+      for (; args; args = DECL_CHAIN (args))
+       {
+         tree type = TREE_TYPE (args);
+         if (INTEGRAL_TYPE_P (type)
+             && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
+           DECL_ARG_TYPE (args) = integer_type_node;
+       }
+    }
+
+  if (DECL_INITIAL (fndecl) && DECL_INITIAL (fndecl) != error_mark_node)
+    BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
+
+  /* Must mark the RESULT_DECL as being in this function.  */
+
+  if (DECL_RESULT (fndecl) && DECL_RESULT (fndecl) != error_mark_node)
+    DECL_CONTEXT (DECL_RESULT (fndecl)) = fndecl;
+
+  if (MAIN_NAME_P (DECL_NAME (fndecl)) && flag_hosted
+      && TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (fndecl)))
+      == integer_type_node && flag_isoc99)
+    {
+      /* Hack.  We don't want the middle-end to warn that this return
+        is unreachable, so we mark its location as special.  Using
+        UNKNOWN_LOCATION has the problem that it gets clobbered in
+        annotate_one_with_locus.  A cleaner solution might be to
+        ensure ! should_carry_locus_p (stmt), but that needs a flag.
+      */
+      c_finish_return (BUILTINS_LOCATION, integer_zero_node, NULL_TREE);
+    }
+
+  /* Tie off the statement tree for this function.  */
+  DECL_SAVED_TREE (fndecl) = pop_stmt_list (DECL_SAVED_TREE (fndecl));
+
+  finish_fname_decls ();
+
+  /* Complain if there's just no return statement.  */
+  if (warn_return_type
+      && TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE
+      && !current_function_returns_value && !current_function_returns_null
+      /* Don't complain if we are no-return.  */
+      && !current_function_returns_abnormally
+      /* Don't complain if we are declared noreturn.  */
+      && !TREE_THIS_VOLATILE (fndecl)
+      /* Don't warn for main().  */
+      && !MAIN_NAME_P (DECL_NAME (fndecl))
+      /* Or if they didn't actually specify a return type.  */
+      && !C_FUNCTION_IMPLICIT_INT (fndecl)
+      /* Normally, with -Wreturn-type, flow will complain, but we might
+         optimize out static functions.  */
+      && !TREE_PUBLIC (fndecl))
+    {
+      warning (OPT_Wreturn_type,
+              "no return statement in function returning non-void");
+      TREE_NO_WARNING (fndecl) = 1;
+    }
+
+  /* Complain about parameters that are only set, but never otherwise used.  */
+  if (warn_unused_but_set_parameter)
+    {
+      tree decl;
+
+      for (decl = DECL_ARGUMENTS (fndecl);
+          decl;
+          decl = DECL_CHAIN (decl))
+       if (TREE_USED (decl)
+           && TREE_CODE (decl) == PARM_DECL
+           && !DECL_READ_P (decl)
+           && DECL_NAME (decl)
+           && !DECL_ARTIFICIAL (decl)
+           && !TREE_NO_WARNING (decl))
+         warning_at (DECL_SOURCE_LOCATION (decl),
+                     OPT_Wunused_but_set_parameter,
+                     "parameter %qD set but not used", decl);
+    }
+
+  /* Complain about locally defined typedefs that are not used in this
+     function.  */
+  maybe_warn_unused_local_typedefs ();
+
+  /* Store the end of the function, so that we get good line number
+     info for the epilogue.  */
+  cfun->function_end_locus = input_location;
+
+  /* Finalize the ELF visibility for the function.  */
+  c_determine_visibility (fndecl);
+
+  /* For GNU C extern inline functions disregard inline limits.  */
+  if (DECL_EXTERNAL (fndecl)
+      && DECL_DECLARED_INLINE_P (fndecl))
+    DECL_DISREGARD_INLINE_LIMITS (fndecl) = 1;
+
+  /* Genericize before inlining.  Delay genericizing nested functions
+     until their parent function is genericized.  Since finalizing
+     requires GENERIC, delay that as well.  */
+
+  if (DECL_INITIAL (fndecl) && DECL_INITIAL (fndecl) != error_mark_node
+      && !undef_nested_function)
+    {
+      if (!decl_function_context (fndecl))
+       {
+         invoke_plugin_callbacks (PLUGIN_PRE_GENERICIZE, fndecl);
+         c_genericize (fndecl);
+
+         /* ??? Objc emits functions after finalizing the compilation unit.
+            This should be cleaned up later and this conditional removed.  */
+         if (cgraph_global_info_ready)
+           {
+             cgraph_add_new_function (fndecl, false);
+             return;
+           }
+         cgraph_finalize_function (fndecl, false);
+       }
+      else
+       {
+         /* Register this function with cgraph just far enough to get it
+           added to our parent's nested function list.  Handy, since the
+           C front end doesn't have such a list.  */
+         (void) cgraph_get_create_node (fndecl);
+       }
+    }
+
+  if (!decl_function_context (fndecl))
+    undef_nested_function = false;
+
+  if (cfun->language != NULL)
+    {
+      ggc_free (cfun->language);
+      cfun->language = NULL;
+    }
+
+  /* We're leaving the context of this function, so zap cfun.
+     It's still in DECL_STRUCT_FUNCTION, and we'll restore it in
+     tree_rest_of_compilation.  */
+  set_cfun (NULL);
+  current_function_decl = NULL;
+}
+\f
+/* Check the declarations given in a for-loop for satisfying the C99
+   constraints.  If exactly one such decl is found, return it.  LOC is
+   the location of the opening parenthesis of the for loop.  The last
+   parameter allows you to control the "for loop initial declarations
+   are only allowed in C99 mode".  Normally, you should pass
+   flag_isoc99 as that parameter.  But in some cases (Objective-C
+   foreach loop, for example) we want to run the checks in this
+   function even if not in C99 mode, so we allow the caller to turn
+   off the error about not being in C99 mode.
+*/
+
+tree
+check_for_loop_decls (location_t loc, bool turn_off_iso_c99_error)
+{
+  struct c_binding *b;
+  tree one_decl = NULL_TREE;
+  int n_decls = 0;
+
+  if (!turn_off_iso_c99_error)
+    {
+      static bool hint = true;
+      /* If we get here, declarations have been used in a for loop without
+        the C99 for loop scope.  This doesn't make much sense, so don't
+        allow it.  */
+      error_at (loc, "%<for%> loop initial declarations "
+               "are only allowed in C99 mode");
+      if (hint)
+       {
+         inform (loc,
+                 "use option -std=c99 or -std=gnu99 to compile your code");
+         hint = false;
+       }
+      return NULL_TREE;
+    }
+  /* C99 subclause 6.8.5 paragraph 3:
+
+       [#3]  The  declaration  part  of  a for statement shall only
+       declare identifiers for objects having storage class auto or
+       register.
+
+     It isn't clear whether, in this sentence, "identifiers" binds to
+     "shall only declare" or to "objects" - that is, whether all identifiers
+     declared must be identifiers for objects, or whether the restriction
+     only applies to those that are.  (A question on this in comp.std.c
+     in November 2000 received no answer.)  We implement the strictest
+     interpretation, to avoid creating an extension which later causes
+     problems.  */
+
+  for (b = current_scope->bindings; b; b = b->prev)
+    {
+      tree id = b->id;
+      tree decl = b->decl;
+
+      if (!id)
+       continue;
+
+      switch (TREE_CODE (decl))
+       {
+       case VAR_DECL:
+         {
+           location_t decl_loc = DECL_SOURCE_LOCATION (decl);
+           if (TREE_STATIC (decl))
+             error_at (decl_loc,
+                       "declaration of static variable %qD in %<for%> loop "
+                       "initial declaration", decl);
+           else if (DECL_EXTERNAL (decl))
+             error_at (decl_loc,
+                       "declaration of %<extern%> variable %qD in %<for%> loop "
+                       "initial declaration", decl);
+         }
+         break;
+
+       case RECORD_TYPE:
+         error_at (loc,
+                   "%<struct %E%> declared in %<for%> loop initial "
+                   "declaration", id);
+         break;
+       case UNION_TYPE:
+         error_at (loc,
+                   "%<union %E%> declared in %<for%> loop initial declaration",
+                   id);
+         break;
+       case ENUMERAL_TYPE:
+         error_at (loc, "%<enum %E%> declared in %<for%> loop "
+                   "initial declaration", id);
+         break;
+       default:
+         error_at (loc, "declaration of non-variable "
+                   "%qD in %<for%> loop initial declaration", decl);
+       }
+
+      n_decls++;
+      one_decl = decl;
+    }
+
+  return n_decls == 1 ? one_decl : NULL_TREE;
+}
+\f
+/* Save and reinitialize the variables
+   used during compilation of a C function.  */
+
+void
+c_push_function_context (void)
+{
+  struct language_function *p = cfun->language;
+  /* cfun->language might have been already allocated by the use of
+     -Wunused-local-typedefs.  In that case, just re-use it.  */
+  if (p == NULL)
+    cfun->language = p = ggc_alloc_cleared_language_function ();
+
+  p->base.x_stmt_tree = c_stmt_tree;
+  c_stmt_tree.x_cur_stmt_list
+    = VEC_copy (tree, gc, c_stmt_tree.x_cur_stmt_list);
+  p->x_break_label = c_break_label;
+  p->x_cont_label = c_cont_label;
+  p->x_switch_stack = c_switch_stack;
+  p->arg_info = current_function_arg_info;
+  p->returns_value = current_function_returns_value;
+  p->returns_null = current_function_returns_null;
+  p->returns_abnormally = current_function_returns_abnormally;
+  p->warn_about_return_type = warn_about_return_type;
+
+  push_function_context ();
+}
+
+/* Restore the variables used during compilation of a C function.  */
+
+void
+c_pop_function_context (void)
+{
+  struct language_function *p;
+
+  pop_function_context ();
+  p = cfun->language;
+
+  /* When -Wunused-local-typedefs is in effect, cfun->languages is
+     used to store data throughout the life time of the current cfun,
+     So don't deallocate it.  */
+  if (!warn_unused_local_typedefs)
+    cfun->language = NULL;
+
+  if (DECL_STRUCT_FUNCTION (current_function_decl) == 0
+      && DECL_SAVED_TREE (current_function_decl) == NULL_TREE)
+    {
+      /* Stop pointing to the local nodes about to be freed.  */
+      /* But DECL_INITIAL must remain nonzero so we know this
+        was an actual function definition.  */
+      DECL_INITIAL (current_function_decl) = error_mark_node;
+      DECL_ARGUMENTS (current_function_decl) = 0;
+    }
+
+  c_stmt_tree = p->base.x_stmt_tree;
+  p->base.x_stmt_tree.x_cur_stmt_list = NULL;
+  c_break_label = p->x_break_label;
+  c_cont_label = p->x_cont_label;
+  c_switch_stack = p->x_switch_stack;
+  current_function_arg_info = p->arg_info;
+  current_function_returns_value = p->returns_value;
+  current_function_returns_null = p->returns_null;
+  current_function_returns_abnormally = p->returns_abnormally;
+  warn_about_return_type = p->warn_about_return_type;
+}
+
+/* The functions below are required for functionality of doing
+   function at once processing in the C front end. Currently these
+   functions are not called from anywhere in the C front end, but as
+   these changes continue, that will change.  */
+
+/* Returns the stmt_tree (if any) to which statements are currently
+   being added.  If there is no active statement-tree, NULL is
+   returned.  */
+
+stmt_tree
+current_stmt_tree (void)
+{
+  return &c_stmt_tree;
+}
+
+/* Return the global value of T as a symbol.  */
+
+tree
+identifier_global_value        (tree t)
+{
+  struct c_binding *b;
+
+  for (b = I_SYMBOL_BINDING (t); b; b = b->shadowed)
+    if (B_IN_FILE_SCOPE (b) || B_IN_EXTERNAL_SCOPE (b))
+      return b->decl;
+
+  return 0;
+}
+
+/* In C, the only C-linkage public declaration is at file scope.  */
+
+tree
+c_linkage_bindings (tree name)
+{
+  return identifier_global_value (name);
+}
+
+/* Record a builtin type for C.  If NAME is non-NULL, it is the name used;
+   otherwise the name is found in ridpointers from RID_INDEX.  */
+
+void
+record_builtin_type (enum rid rid_index, const char *name, tree type)
+{
+  tree id, decl;
+  if (name == 0)
+    id = ridpointers[(int) rid_index];
+  else
+    id = get_identifier (name);
+  decl = build_decl (UNKNOWN_LOCATION, TYPE_DECL, id, type);
+  pushdecl (decl);
+  if (debug_hooks->type_decl)
+    debug_hooks->type_decl (decl, false);
+}
+
+/* Build the void_list_node (void_type_node having been created).  */
+tree
+build_void_list_node (void)
+{
+  tree t = build_tree_list (NULL_TREE, void_type_node);
+  return t;
+}
+
+/* Return a c_parm structure with the given SPECS, ATTRS and DECLARATOR.  */
+
+struct c_parm *
+build_c_parm (struct c_declspecs *specs, tree attrs,
+             struct c_declarator *declarator)
+{
+  struct c_parm *ret = XOBNEW (&parser_obstack, struct c_parm);
+  ret->specs = specs;
+  ret->attrs = attrs;
+  ret->declarator = declarator;
+  return ret;
+}
+
+/* Return a declarator with nested attributes.  TARGET is the inner
+   declarator to which these attributes apply.  ATTRS are the
+   attributes.  */
+
+struct c_declarator *
+build_attrs_declarator (tree attrs, struct c_declarator *target)
+{
+  struct c_declarator *ret = XOBNEW (&parser_obstack, struct c_declarator);
+  ret->kind = cdk_attrs;
+  ret->declarator = target;
+  ret->u.attrs = attrs;
+  return ret;
+}
+
+/* Return a declarator for a function with arguments specified by ARGS
+   and return type specified by TARGET.  */
+
+struct c_declarator *
+build_function_declarator (struct c_arg_info *args,
+                          struct c_declarator *target)
+{
+  struct c_declarator *ret = XOBNEW (&parser_obstack, struct c_declarator);
+  ret->kind = cdk_function;
+  ret->declarator = target;
+  ret->u.arg_info = args;
+  return ret;
+}
+
+/* Return a declarator for the identifier IDENT (which may be
+   NULL_TREE for an abstract declarator).  */
+
+struct c_declarator *
+build_id_declarator (tree ident)
+{
+  struct c_declarator *ret = XOBNEW (&parser_obstack, struct c_declarator);
+  ret->kind = cdk_id;
+  ret->declarator = 0;
+  ret->u.id = ident;
+  /* Default value - may get reset to a more precise location. */
+  ret->id_loc = input_location;
+  return ret;
+}
+
+/* Return something to represent absolute declarators containing a *.
+   TARGET is the absolute declarator that the * contains.
+   TYPE_QUALS_ATTRS is a structure for type qualifiers and attributes
+   to apply to the pointer type.  */
+
+struct c_declarator *
+make_pointer_declarator (struct c_declspecs *type_quals_attrs,
+                        struct c_declarator *target)
+{
+  tree attrs;
+  int quals = 0;
+  struct c_declarator *itarget = target;
+  struct c_declarator *ret = XOBNEW (&parser_obstack, struct c_declarator);
+  if (type_quals_attrs)
+    {
+      attrs = type_quals_attrs->attrs;
+      quals = quals_from_declspecs (type_quals_attrs);
+      if (attrs != NULL_TREE)
+       itarget = build_attrs_declarator (attrs, target);
+    }
+  ret->kind = cdk_pointer;
+  ret->declarator = itarget;
+  ret->u.pointer_quals = quals;
+  return ret;
+}
+
+/* Return a pointer to a structure for an empty list of declaration
+   specifiers.  */
+
+struct c_declspecs *
+build_null_declspecs (void)
+{
+  struct c_declspecs *ret = XOBNEW (&parser_obstack, struct c_declspecs);
+  memset (&ret->locations, 0, cdw_number_of_elements);
+  ret->type = 0;
+  ret->expr = 0;
+  ret->decl_attr = 0;
+  ret->attrs = 0;
+  ret->align_log = -1;
+  ret->typespec_word = cts_none;
+  ret->storage_class = csc_none;
+  ret->expr_const_operands = true;
+  ret->declspecs_seen_p = false;
+  ret->typespec_kind = ctsk_none;
+  ret->non_sc_seen_p = false;
+  ret->typedef_p = false;
+  ret->explicit_signed_p = false;
+  ret->deprecated_p = false;
+  ret->default_int_p = false;
+  ret->long_p = false;
+  ret->long_long_p = false;
+  ret->short_p = false;
+  ret->signed_p = false;
+  ret->unsigned_p = false;
+  ret->complex_p = false;
+  ret->inline_p = false;
+  ret->noreturn_p = false;
+  ret->thread_p = false;
+  ret->const_p = false;
+  ret->volatile_p = false;
+  ret->restrict_p = false;
+  ret->saturating_p = false;
+  ret->alignas_p = false;
+  ret->address_space = ADDR_SPACE_GENERIC;
+  return ret;
+}
+
+/* Add the address space ADDRSPACE to the declaration specifiers
+   SPECS, returning SPECS.  */
+
+struct c_declspecs *
+declspecs_add_addrspace (source_location location,
+                        struct c_declspecs *specs, addr_space_t as)
+{
+  specs->non_sc_seen_p = true;
+  specs->declspecs_seen_p = true;
+
+  if (!ADDR_SPACE_GENERIC_P (specs->address_space)
+      && specs->address_space != as)
+    error ("incompatible address space qualifiers %qs and %qs",
+          c_addr_space_name (as),
+          c_addr_space_name (specs->address_space));
+  else
+    {
+      specs->address_space = as;
+      specs->locations[cdw_address_space] = location;
+    }
+  return specs;
+}
+
+/* Add the type qualifier QUAL to the declaration specifiers SPECS,
+   returning SPECS.  */
+
+struct c_declspecs *
+declspecs_add_qual (source_location loc,
+                   struct c_declspecs *specs, tree qual)
+{
+  enum rid i;
+  bool dupe = false;
+  specs->non_sc_seen_p = true;
+  specs->declspecs_seen_p = true;
+  gcc_assert (TREE_CODE (qual) == IDENTIFIER_NODE
+             && C_IS_RESERVED_WORD (qual));
+  i = C_RID_CODE (qual);
+  switch (i)
+    {
+    case RID_CONST:
+      dupe = specs->const_p;
+      specs->const_p = true;
+      specs->locations[cdw_const] = loc;
+      break;
+    case RID_VOLATILE:
+      dupe = specs->volatile_p;
+      specs->volatile_p = true;
+      specs->locations[cdw_volatile] = loc;
+      break;
+    case RID_RESTRICT:
+      dupe = specs->restrict_p;
+      specs->restrict_p = true;
+      specs->locations[cdw_restrict] = loc;
+      break;
+    default:
+      gcc_unreachable ();
+    }
+  if (dupe && !flag_isoc99)
+    pedwarn (loc, OPT_Wpedantic, "duplicate %qE", qual);
+  return specs;
+}
+
+/* Add the type specifier TYPE to the declaration specifiers SPECS,
+   returning SPECS.  */
+
+struct c_declspecs *
+declspecs_add_type (location_t loc, struct c_declspecs *specs,
+                   struct c_typespec spec)
+{
+  tree type = spec.spec;
+  specs->non_sc_seen_p = true;
+  specs->declspecs_seen_p = true;
+  specs->typespec_kind = spec.kind;
+  if (TREE_DEPRECATED (type))
+    specs->deprecated_p = true;
+
+  /* Handle type specifier keywords.  */
+  if (TREE_CODE (type) == IDENTIFIER_NODE
+      && C_IS_RESERVED_WORD (type)
+      && C_RID_CODE (type) != RID_CXX_COMPAT_WARN)
+    {
+      enum rid i = C_RID_CODE (type);
+      if (specs->type)
+       {
+         error_at (loc, "two or more data types in declaration specifiers");
+         return specs;
+       }
+      if ((int) i <= (int) RID_LAST_MODIFIER)
+       {
+         /* "long", "short", "signed", "unsigned", "_Complex" or "_Sat".  */
+         bool dupe = false;
+         switch (i)
+           {
+           case RID_LONG:
+             if (specs->long_long_p)
+               {
+                 error_at (loc, "%<long long long%> is too long for GCC");
+                 break;
+               }
+             if (specs->long_p)
+               {
+                 if (specs->typespec_word == cts_double)
+                   {
+                     error_at (loc,
+                               ("both %<long long%> and %<double%> in "
+                                "declaration specifiers"));
+                     break;
+                   }
+                 pedwarn_c90 (loc, OPT_Wlong_long,
+                              "ISO C90 does not support %<long long%>");
+                 specs->long_long_p = 1;
+                 specs->locations[cdw_long_long] = loc;
+                 break;
+               }
+             if (specs->short_p)
+               error_at (loc,
+                         ("both %<long%> and %<short%> in "
+                          "declaration specifiers"));
+             else if (specs->typespec_word == cts_void)
+               error_at (loc,
+                         ("both %<long%> and %<void%> in "
+                          "declaration specifiers"));
+             else if (specs->typespec_word == cts_int128)
+                 error_at (loc,
+                           ("both %<long%> and %<__int128%> in "
+                            "declaration specifiers"));
+             else if (specs->typespec_word == cts_bool)
+               error_at (loc,
+                         ("both %<long%> and %<_Bool%> in "
+                          "declaration specifiers"));
+             else if (specs->typespec_word == cts_char)
+               error_at (loc,
+                         ("both %<long%> and %<char%> in "
+                          "declaration specifiers"));
+             else if (specs->typespec_word == cts_float)
+               error_at (loc,
+                         ("both %<long%> and %<float%> in "
+                          "declaration specifiers"));
+             else if (specs->typespec_word == cts_dfloat32)
+               error_at (loc,
+                         ("both %<long%> and %<_Decimal32%> in "
+                          "declaration specifiers"));
+             else if (specs->typespec_word == cts_dfloat64)
+               error_at (loc,
+                         ("both %<long%> and %<_Decimal64%> in "
+                          "declaration specifiers"));
+             else if (specs->typespec_word == cts_dfloat128)
+               error_at (loc,
+                         ("both %<long%> and %<_Decimal128%> in "
+                          "declaration specifiers"));
+             else
+               {
+                 specs->long_p = true;
+                 specs->locations[cdw_long] = loc;
+               }
+             break;
+           case RID_SHORT:
+             dupe = specs->short_p;
+             if (specs->long_p)
+               error_at (loc,
+                         ("both %<long%> and %<short%> in "
+                          "declaration specifiers"));
+             else if (specs->typespec_word == cts_void)
+               error_at (loc,
+                         ("both %<short%> and %<void%> in "
+                          "declaration specifiers"));
+             else if (specs->typespec_word == cts_int128)
+               error_at (loc,
+                         ("both %<short%> and %<__int128%> in "
+                          "declaration specifiers"));
+             else if (specs->typespec_word == cts_bool)
+               error_at (loc,
+                         ("both %<short%> and %<_Bool%> in "
+                          "declaration specifiers"));
+             else if (specs->typespec_word == cts_char)
+               error_at (loc,
+                         ("both %<short%> and %<char%> in "
+                          "declaration specifiers"));
+             else if (specs->typespec_word == cts_float)
+               error_at (loc,
+                         ("both %<short%> and %<float%> in "
+                          "declaration specifiers"));
+             else if (specs->typespec_word == cts_double)
+               error_at (loc,
+                         ("both %<short%> and %<double%> in "
+                          "declaration specifiers"));
+             else if (specs->typespec_word == cts_dfloat32)
+                error_at (loc,
+                         ("both %<short%> and %<_Decimal32%> in "
+                          "declaration specifiers"));
+             else if (specs->typespec_word == cts_dfloat64)
+               error_at (loc,
+                         ("both %<short%> and %<_Decimal64%> in "
+                          "declaration specifiers"));
+             else if (specs->typespec_word == cts_dfloat128)
+               error_at (loc,
+                         ("both %<short%> and %<_Decimal128%> in "
+                          "declaration specifiers"));
+             else
+               {
+                 specs->short_p = true;
+                 specs->locations[cdw_short] = loc;
+               }
+             break;
+           case RID_SIGNED:
+             dupe = specs->signed_p;
+             if (specs->unsigned_p)
+               error_at (loc,
+                         ("both %<signed%> and %<unsigned%> in "
+                          "declaration specifiers"));
+             else if (specs->typespec_word == cts_void)
+               error_at (loc,
+                         ("both %<signed%> and %<void%> in "
+                          "declaration specifiers"));
+             else if (specs->typespec_word == cts_bool)
+               error_at (loc,
+                         ("both %<signed%> and %<_Bool%> in "
+                          "declaration specifiers"));
+             else if (specs->typespec_word == cts_float)
+               error_at (loc,
+                         ("both %<signed%> and %<float%> in "
+                          "declaration specifiers"));
+             else if (specs->typespec_word == cts_double)
+               error_at (loc,
+                         ("both %<signed%> and %<double%> in "
+                          "declaration specifiers"));
+             else if (specs->typespec_word == cts_dfloat32)
+               error_at (loc,
+                         ("both %<signed%> and %<_Decimal32%> in "
+                          "declaration specifiers"));
+             else if (specs->typespec_word == cts_dfloat64)
+               error_at (loc,
+                         ("both %<signed%> and %<_Decimal64%> in "
+                          "declaration specifiers"));
+             else if (specs->typespec_word == cts_dfloat128)
+               error_at (loc,
+                         ("both %<signed%> and %<_Decimal128%> in "
+                          "declaration specifiers"));
+             else
+               {
+                 specs->signed_p = true;
+                 specs->locations[cdw_signed] = loc;
+               }
+             break;
+           case RID_UNSIGNED:
+             dupe = specs->unsigned_p;
+             if (specs->signed_p)
+               error_at (loc,
+                         ("both %<signed%> and %<unsigned%> in "
+                          "declaration specifiers"));
+             else if (specs->typespec_word == cts_void)
+               error_at (loc,
+                         ("both %<unsigned%> and %<void%> in "
+                          "declaration specifiers"));
+             else if (specs->typespec_word == cts_bool)
+               error_at (loc,
+                         ("both %<unsigned%> and %<_Bool%> in "
+                          "declaration specifiers"));
+             else if (specs->typespec_word == cts_float)
+               error_at (loc,
+                         ("both %<unsigned%> and %<float%> in "
+                          "declaration specifiers"));
+             else if (specs->typespec_word == cts_double)
+               error_at (loc,
+                         ("both %<unsigned%> and %<double%> in "
+                          "declaration specifiers"));
+              else if (specs->typespec_word == cts_dfloat32)
+               error_at (loc,
+                         ("both %<unsigned%> and %<_Decimal32%> in "
+                          "declaration specifiers"));
+             else if (specs->typespec_word == cts_dfloat64)
+               error_at (loc,
+                         ("both %<unsigned%> and %<_Decimal64%> in "
+                          "declaration specifiers"));
+             else if (specs->typespec_word == cts_dfloat128)
+               error_at (loc,
+                         ("both %<unsigned%> and %<_Decimal128%> in "
+                          "declaration specifiers"));
+             else
+               {
+                 specs->unsigned_p = true;
+                 specs->locations[cdw_unsigned] = loc;
+               }
+             break;
+           case RID_COMPLEX:
+             dupe = specs->complex_p;
+             if (!flag_isoc99 && !in_system_header_at (loc))
+               pedwarn (loc, OPT_Wpedantic,
+                        "ISO C90 does not support complex types");
+             if (specs->typespec_word == cts_void)
+               error_at (loc,
+                         ("both %<complex%> and %<void%> in "
+                          "declaration specifiers"));
+             else if (specs->typespec_word == cts_bool)
+               error_at (loc,
+                         ("both %<complex%> and %<_Bool%> in "
+                          "declaration specifiers"));
+              else if (specs->typespec_word == cts_dfloat32)
+               error_at (loc,
+                         ("both %<complex%> and %<_Decimal32%> in "
+                          "declaration specifiers"));
+             else if (specs->typespec_word == cts_dfloat64)
+               error_at (loc,
+                         ("both %<complex%> and %<_Decimal64%> in "
+                          "declaration specifiers"));
+             else if (specs->typespec_word == cts_dfloat128)
+               error_at (loc,
+                         ("both %<complex%> and %<_Decimal128%> in "
+                          "declaration specifiers"));
+             else if (specs->typespec_word == cts_fract)
+               error_at (loc,
+                         ("both %<complex%> and %<_Fract%> in "
+                          "declaration specifiers"));
+             else if (specs->typespec_word == cts_accum)
+               error_at (loc,
+                         ("both %<complex%> and %<_Accum%> in "
+                          "declaration specifiers"));
+             else if (specs->saturating_p)
+               error_at (loc,
+                         ("both %<complex%> and %<_Sat%> in "
+                          "declaration specifiers"));
+             else
+               {
+                 specs->complex_p = true;
+                 specs->locations[cdw_complex] = loc;
+               }
+             break;
+           case RID_SAT:
+             dupe = specs->saturating_p;
+             pedwarn (loc, OPT_Wpedantic,
+                      "ISO C does not support saturating types");
+             if (specs->typespec_word == cts_int128)
+               {
+                 error_at (loc,
+                           ("both %<_Sat%> and %<__int128%> in "
+                            "declaration specifiers"));
+               }
+             else if (specs->typespec_word == cts_void)
+               error_at (loc,
+                         ("both %<_Sat%> and %<void%> in "
+                          "declaration specifiers"));
+             else if (specs->typespec_word == cts_bool)
+               error_at (loc,
+                         ("both %<_Sat%> and %<_Bool%> in "
+                          "declaration specifiers"));
+             else if (specs->typespec_word == cts_char)
+               error_at (loc,
+                         ("both %<_Sat%> and %<char%> in "
+                          "declaration specifiers"));
+             else if (specs->typespec_word == cts_int)
+               error_at (loc,
+                         ("both %<_Sat%> and %<int%> in "
+                          "declaration specifiers"));
+             else if (specs->typespec_word == cts_float)
+               error_at (loc,
+                         ("both %<_Sat%> and %<float%> in "
+                          "declaration specifiers"));
+             else if (specs->typespec_word == cts_double)
+               error_at (loc,
+                         ("both %<_Sat%> and %<double%> in "
+                          "declaration specifiers"));
+              else if (specs->typespec_word == cts_dfloat32)
+               error_at (loc,
+                         ("both %<_Sat%> and %<_Decimal32%> in "
+                          "declaration specifiers"));
+             else if (specs->typespec_word == cts_dfloat64)
+               error_at (loc,
+                         ("both %<_Sat%> and %<_Decimal64%> in "
+                          "declaration specifiers"));
+             else if (specs->typespec_word == cts_dfloat128)
+               error_at (loc,
+                         ("both %<_Sat%> and %<_Decimal128%> in "
+                          "declaration specifiers"));
+             else if (specs->complex_p)
+               error_at (loc,
+                         ("both %<_Sat%> and %<complex%> in "
+                          "declaration specifiers"));
+             else
+               {
+                 specs->saturating_p = true;
+                 specs->locations[cdw_saturating] = loc;
+               }
+             break;
+           default:
+             gcc_unreachable ();
+           }
+
+         if (dupe)
+           error_at (loc, "duplicate %qE", type);
+
+         return specs;
+       }
+      else
+       {
+         /* "void", "_Bool", "char", "int", "float", "double", "_Decimal32",
+            "__int128", "_Decimal64", "_Decimal128", "_Fract" or "_Accum".  */
+         if (specs->typespec_word != cts_none)
+           {
+             error_at (loc,
+                       "two or more data types in declaration specifiers");
+             return specs;
+           }
+         switch (i)
+           {
+           case RID_INT128:
+             if (int128_integer_type_node == NULL_TREE)
+               {
+                 error_at (loc, "%<__int128%> is not supported for this target");
+                 return specs;
+               }
+             if (!in_system_header)
+               pedwarn (loc, OPT_Wpedantic,
+                        "ISO C does not support %<__int128%> type");
+
+             if (specs->long_p)
+               error_at (loc,
+                         ("both %<__int128%> and %<long%> in "
+                          "declaration specifiers"));
+             else if (specs->saturating_p)
+               error_at (loc,
+                         ("both %<_Sat%> and %<__int128%> in "
+                          "declaration specifiers"));
+             else if (specs->short_p)
+               error_at (loc,
+                         ("both %<__int128%> and %<short%> in "
+                          "declaration specifiers"));
+             else
+               {
+                 specs->typespec_word = cts_int128;
+                 specs->locations[cdw_typespec] = loc;
+               }
+             return specs;
+           case RID_VOID:
+             if (specs->long_p)
+               error_at (loc,
+                         ("both %<long%> and %<void%> in "
+                          "declaration specifiers"));
+             else if (specs->short_p)
+               error_at (loc,
+                         ("both %<short%> and %<void%> in "
+                          "declaration specifiers"));
+             else if (specs->signed_p)
+               error_at (loc,
+                         ("both %<signed%> and %<void%> in "
+                          "declaration specifiers"));
+             else if (specs->unsigned_p)
+               error_at (loc,
+                         ("both %<unsigned%> and %<void%> in "
+                          "declaration specifiers"));
+             else if (specs->complex_p)
+               error_at (loc,
+                         ("both %<complex%> and %<void%> in "
+                          "declaration specifiers"));
+             else if (specs->saturating_p)
+               error_at (loc,
+                         ("both %<_Sat%> and %<void%> in "
+                          "declaration specifiers"));
+             else
+               {
+                 specs->typespec_word = cts_void;
+                 specs->locations[cdw_typespec] = loc;
+               }
+             return specs;
+           case RID_BOOL:
+             if (specs->long_p)
+               error_at (loc,
+                         ("both %<long%> and %<_Bool%> in "
+                          "declaration specifiers"));
+             else if (specs->short_p)
+               error_at (loc,
+                         ("both %<short%> and %<_Bool%> in "
+                          "declaration specifiers"));
+             else if (specs->signed_p)
+               error_at (loc,
+                         ("both %<signed%> and %<_Bool%> in "
+                          "declaration specifiers"));
+             else if (specs->unsigned_p)
+               error_at (loc,
+                         ("both %<unsigned%> and %<_Bool%> in "
+                          "declaration specifiers"));
+             else if (specs->complex_p)
+               error_at (loc,
+                         ("both %<complex%> and %<_Bool%> in "
+                          "declaration specifiers"));
+             else if (specs->saturating_p)
+               error_at (loc,
+                         ("both %<_Sat%> and %<_Bool%> in "
+                          "declaration specifiers"));
+             else
+               {
+                 specs->typespec_word = cts_bool;
+                 specs->locations[cdw_typespec] = loc;
+               }
+             return specs;
+           case RID_CHAR:
+             if (specs->long_p)
+               error_at (loc,
+                         ("both %<long%> and %<char%> in "
+                          "declaration specifiers"));
+             else if (specs->short_p)
+               error_at (loc,
+                         ("both %<short%> and %<char%> in "
+                          "declaration specifiers"));
+             else if (specs->saturating_p)
+               error_at (loc,
+                         ("both %<_Sat%> and %<char%> in "
+                          "declaration specifiers"));
+             else
+               {
+                 specs->typespec_word = cts_char;
+                 specs->locations[cdw_typespec] = loc;
+               }
+             return specs;
+           case RID_INT:
+             if (specs->saturating_p)
+               error_at (loc,
+                         ("both %<_Sat%> and %<int%> in "
+                          "declaration specifiers"));
+             else
+               {
+                 specs->typespec_word = cts_int;
+                 specs->locations[cdw_typespec] = loc;
+               }
+             return specs;
+           case RID_FLOAT:
+             if (specs->long_p)
+               error_at (loc,
+                         ("both %<long%> and %<float%> in "
+                          "declaration specifiers"));
+             else if (specs->short_p)
+               error_at (loc,
+                         ("both %<short%> and %<float%> in "
+                          "declaration specifiers"));
+             else if (specs->signed_p)
+               error_at (loc,
+                         ("both %<signed%> and %<float%> in "
+                          "declaration specifiers"));
+             else if (specs->unsigned_p)
+               error_at (loc,
+                         ("both %<unsigned%> and %<float%> in "
+                          "declaration specifiers"));
+             else if (specs->saturating_p)
+               error_at (loc,
+                         ("both %<_Sat%> and %<float%> in "
+                          "declaration specifiers"));
+             else
+               {
+                 specs->typespec_word = cts_float;
+                 specs->locations[cdw_typespec] = loc;
+               }
+             return specs;
+           case RID_DOUBLE:
+             if (specs->long_long_p)
+               error_at (loc,
+                         ("both %<long long%> and %<double%> in "
+                          "declaration specifiers"));
+             else if (specs->short_p)
+               error_at (loc,
+                         ("both %<short%> and %<double%> in "
+                          "declaration specifiers"));
+             else if (specs->signed_p)
+               error_at (loc,
+                         ("both %<signed%> and %<double%> in "
+                          "declaration specifiers"));
+             else if (specs->unsigned_p)
+               error_at (loc,
+                         ("both %<unsigned%> and %<double%> in "
+                          "declaration specifiers"));
+             else if (specs->saturating_p)
+               error_at (loc,
+                         ("both %<_Sat%> and %<double%> in "
+                          "declaration specifiers"));
+             else
+               {
+                 specs->typespec_word = cts_double;
+                 specs->locations[cdw_typespec] = loc;
+               }
+             return specs;
+           case RID_DFLOAT32:
+           case RID_DFLOAT64:
+           case RID_DFLOAT128:
+             {
+               const char *str;
+               if (i == RID_DFLOAT32)
+                 str = "_Decimal32";
+               else if (i == RID_DFLOAT64)
+                 str = "_Decimal64";
+               else
+                 str = "_Decimal128";
+               if (specs->long_long_p)
+                 error_at (loc,
+                           ("both %<long long%> and %<%s%> in "
+                            "declaration specifiers"),
+                           str);
+               if (specs->long_p)
+                 error_at (loc,
+                           ("both %<long%> and %<%s%> in "
+                            "declaration specifiers"),
+                           str);
+               else if (specs->short_p)
+                 error_at (loc,
+                           ("both %<short%> and %<%s%> in "
+                            "declaration specifiers"),
+                           str);
+               else if (specs->signed_p)
+                 error_at (loc,
+                           ("both %<signed%> and %<%s%> in "
+                            "declaration specifiers"),
+                           str);
+               else if (specs->unsigned_p)
+                 error_at (loc,
+                           ("both %<unsigned%> and %<%s%> in "
+                            "declaration specifiers"),
+                           str);
+                else if (specs->complex_p)
+                  error_at (loc,
+                           ("both %<complex%> and %<%s%> in "
+                            "declaration specifiers"),
+                           str);
+                else if (specs->saturating_p)
+                  error_at (loc,
+                           ("both %<_Sat%> and %<%s%> in "
+                            "declaration specifiers"),
+                           str);
+               else if (i == RID_DFLOAT32)
+                 specs->typespec_word = cts_dfloat32;
+               else if (i == RID_DFLOAT64)
+                 specs->typespec_word = cts_dfloat64;
+               else
+                 specs->typespec_word = cts_dfloat128;
+               specs->locations[cdw_typespec] = loc;
+             }
+             if (!targetm.decimal_float_supported_p ())
+               error_at (loc,
+                         ("decimal floating point not supported "
+                          "for this target"));
+             pedwarn (loc, OPT_Wpedantic,
+                      "ISO C does not support decimal floating point");
+             return specs;
+           case RID_FRACT:
+           case RID_ACCUM:
+             {
+               const char *str;
+               if (i == RID_FRACT)
+                 str = "_Fract";
+               else
+                 str = "_Accum";
+                if (specs->complex_p)
+                  error_at (loc,
+                           ("both %<complex%> and %<%s%> in "
+                            "declaration specifiers"),
+                           str);
+               else if (i == RID_FRACT)
+                   specs->typespec_word = cts_fract;
+               else
+                   specs->typespec_word = cts_accum;
+               specs->locations[cdw_typespec] = loc;
+             }
+             if (!targetm.fixed_point_supported_p ())
+               error_at (loc,
+                         "fixed-point types not supported for this target");
+             pedwarn (loc, OPT_Wpedantic,
+                      "ISO C does not support fixed-point types");
+             return specs;
+           default:
+             /* ObjC reserved word "id", handled below.  */
+             break;
+           }
+       }
+    }
+
+  /* Now we have a typedef (a TYPE_DECL node), an identifier (some
+     form of ObjC type, cases such as "int" and "long" being handled
+     above), a TYPE (struct, union, enum and typeof specifiers) or an
+     ERROR_MARK.  In none of these cases may there have previously
+     been any type specifiers.  */
+  if (specs->type || specs->typespec_word != cts_none
+      || specs->long_p || specs->short_p || specs->signed_p
+      || specs->unsigned_p || specs->complex_p)
+    error_at (loc, "two or more data types in declaration specifiers");
+  else if (TREE_CODE (type) == TYPE_DECL)
+    {
+      if (TREE_TYPE (type) == error_mark_node)
+       ; /* Allow the type to default to int to avoid cascading errors.  */
+      else
+       {
+         specs->type = TREE_TYPE (type);
+         specs->decl_attr = DECL_ATTRIBUTES (type);
+         specs->typedef_p = true;
+         specs->explicit_signed_p = C_TYPEDEF_EXPLICITLY_SIGNED (type);
+         specs->locations[cdw_typedef] = loc;
+
+         /* If this typedef name is defined in a struct, then a C++
+            lookup would return a different value.  */
+         if (warn_cxx_compat
+             && I_SYMBOL_BINDING (DECL_NAME (type))->in_struct)
+           warning_at (loc, OPT_Wc___compat,
+                       "C++ lookup of %qD would return a field, not a type",
+                       type);
+
+         /* If we are parsing a struct, record that a struct field
+            used a typedef.  */
+         if (warn_cxx_compat && struct_parse_info != NULL)
+           VEC_safe_push (tree, heap, struct_parse_info->typedefs_seen, type);
+       }
+    }
+  else if (TREE_CODE (type) == IDENTIFIER_NODE)
+    {
+      tree t = lookup_name (type);
+      if (!t || TREE_CODE (t) != TYPE_DECL)
+       error_at (loc, "%qE fails to be a typedef or built in type", type);
+      else if (TREE_TYPE (t) == error_mark_node)
+       ;
+      else
+       {
+         specs->type = TREE_TYPE (t);
+         specs->locations[cdw_typespec] = loc;
+       }
+    }
+  else
+    {
+      if (TREE_CODE (type) != ERROR_MARK && spec.kind == ctsk_typeof)
+       {
+         specs->typedef_p = true;
+         specs->locations[cdw_typedef] = loc;
+         if (spec.expr)
+           {
+             if (specs->expr)
+               specs->expr = build2 (COMPOUND_EXPR, TREE_TYPE (spec.expr),
+                                     specs->expr, spec.expr);
+             else
+               specs->expr = spec.expr;
+             specs->expr_const_operands &= spec.expr_const_operands;
+           }
+       }
+      specs->type = type;
+    }
+
+  return specs;
+}
+
+/* Add the storage class specifier or function specifier SCSPEC to the
+   declaration specifiers SPECS, returning SPECS.  */
+
+struct c_declspecs *
+declspecs_add_scspec (source_location loc,
+                     struct c_declspecs *specs,
+                     tree scspec)
+{
+  enum rid i;
+  enum c_storage_class n = csc_none;
+  bool dupe = false;
+  specs->declspecs_seen_p = true;
+  gcc_assert (TREE_CODE (scspec) == IDENTIFIER_NODE
+             && C_IS_RESERVED_WORD (scspec));
+  i = C_RID_CODE (scspec);
+  if (specs->non_sc_seen_p)
+    warning (OPT_Wold_style_declaration,
+             "%qE is not at beginning of declaration", scspec);
+  switch (i)
+    {
+    case RID_INLINE:
+      /* C99 permits duplicate inline.  Although of doubtful utility,
+        it seems simplest to permit it in gnu89 mode as well, as
+        there is also little utility in maintaining this as a
+        difference between gnu89 and C99 inline.  */
+      dupe = false;
+      specs->inline_p = true;
+      specs->locations[cdw_inline] = loc;
+      break;
+    case RID_NORETURN:
+      /* Duplicate _Noreturn is permitted.  */
+      dupe = false;
+      specs->noreturn_p = true;
+      specs->locations[cdw_noreturn] = loc;
+      break;
+    case RID_THREAD:
+      dupe = specs->thread_p;
+      if (specs->storage_class == csc_auto)
+       error ("%<__thread%> used with %<auto%>");
+      else if (specs->storage_class == csc_register)
+       error ("%<__thread%> used with %<register%>");
+      else if (specs->storage_class == csc_typedef)
+       error ("%<__thread%> used with %<typedef%>");
+      else
+       {
+         specs->thread_p = true;
+         specs->locations[cdw_thread] = loc;
+       }
+      break;
+    case RID_AUTO:
+      n = csc_auto;
+      break;
+    case RID_EXTERN:
+      n = csc_extern;
+      /* Diagnose "__thread extern".  */
+      if (specs->thread_p)
+       error ("%<__thread%> before %<extern%>");
+      break;
+    case RID_REGISTER:
+      n = csc_register;
+      break;
+    case RID_STATIC:
+      n = csc_static;
+      /* Diagnose "__thread static".  */
+      if (specs->thread_p)
+       error ("%<__thread%> before %<static%>");
+      break;
+    case RID_TYPEDEF:
+      n = csc_typedef;
+      break;
+    default:
+      gcc_unreachable ();
+    }
+  if (n != csc_none && n == specs->storage_class)
+    dupe = true;
+  if (dupe)
+    error ("duplicate %qE", scspec);
+  if (n != csc_none)
+    {
+      if (specs->storage_class != csc_none && n != specs->storage_class)
+       {
+         error ("multiple storage classes in declaration specifiers");
+       }
+      else
+       {
+         specs->storage_class = n;
+         specs->locations[cdw_storage_class] = loc;
+         if (n != csc_extern && n != csc_static && specs->thread_p)
+           {
+             error ("%<__thread%> used with %qE", scspec);
+             specs->thread_p = false;
+           }
+       }
+    }
+  return specs;
+}
+
+/* Add the attributes ATTRS to the declaration specifiers SPECS,
+   returning SPECS.  */
+
+struct c_declspecs *
+declspecs_add_attrs (source_location loc, struct c_declspecs *specs, tree attrs)
+{
+  specs->attrs = chainon (attrs, specs->attrs);
+  specs->locations[cdw_attributes] = loc;
+  specs->declspecs_seen_p = true;
+  return specs;
+}
+
+/* Add an _Alignas specifier (expression ALIGN, or type whose
+   alignment is ALIGN) to the declaration specifiers SPECS, returning
+   SPECS.  */
+struct c_declspecs *
+declspecs_add_alignas (source_location loc,
+                      struct c_declspecs *specs, tree align)
+{
+  int align_log;
+  specs->alignas_p = true;
+  specs->locations[cdw_alignas] = loc;
+  if (align == error_mark_node)
+    return specs;
+  align_log = check_user_alignment (align, true);
+  if (align_log > specs->align_log)
+    specs->align_log = align_log;
+  return specs;
+}
+
+/* Combine "long", "short", "signed", "unsigned" and "_Complex" type
+   specifiers with any other type specifier to determine the resulting
+   type.  This is where ISO C checks on complex types are made, since
+   "_Complex long" is a prefix of the valid ISO C type "_Complex long
+   double".  */
+
+struct c_declspecs *
+finish_declspecs (struct c_declspecs *specs)
+{
+  /* If a type was specified as a whole, we have no modifiers and are
+     done.  */
+  if (specs->type != NULL_TREE)
+    {
+      gcc_assert (!specs->long_p && !specs->long_long_p && !specs->short_p
+                 && !specs->signed_p && !specs->unsigned_p
+                 && !specs->complex_p);
+
+      /* Set a dummy type.  */
+      if (TREE_CODE (specs->type) == ERROR_MARK)
+        specs->type = integer_type_node;
+      return specs;
+    }
+
+  /* If none of "void", "_Bool", "char", "int", "float" or "double"
+     has been specified, treat it as "int" unless "_Complex" is
+     present and there are no other specifiers.  If we just have
+     "_Complex", it is equivalent to "_Complex double", but e.g.
+     "_Complex short" is equivalent to "_Complex short int".  */
+  if (specs->typespec_word == cts_none)
+    {
+      if (specs->saturating_p)
+       {
+         error_at (specs->locations[cdw_saturating],
+                   "%<_Sat%> is used without %<_Fract%> or %<_Accum%>");
+         if (!targetm.fixed_point_supported_p ())
+           error_at (specs->locations[cdw_saturating],
+                     "fixed-point types not supported for this target");
+         specs->typespec_word = cts_fract;
+       }
+      else if (specs->long_p || specs->short_p
+              || specs->signed_p || specs->unsigned_p)
+       {
+         specs->typespec_word = cts_int;
+       }
+      else if (specs->complex_p)
+       {
+         specs->typespec_word = cts_double;
+         pedwarn (specs->locations[cdw_complex], OPT_Wpedantic,
+                  "ISO C does not support plain %<complex%> meaning "
+                  "%<double complex%>");
+       }
+      else
+       {
+         specs->typespec_word = cts_int;
+         specs->default_int_p = true;
+         /* We don't diagnose this here because grokdeclarator will
+            give more specific diagnostics according to whether it is
+            a function definition.  */
+       }
+    }
+
+  /* If "signed" was specified, record this to distinguish "int" and
+     "signed int" in the case of a bit-field with
+     -funsigned-bitfields.  */
+  specs->explicit_signed_p = specs->signed_p;
+
+  /* Now compute the actual type.  */
+  switch (specs->typespec_word)
+    {
+    case cts_void:
+      gcc_assert (!specs->long_p && !specs->short_p
+                 && !specs->signed_p && !specs->unsigned_p
+                 && !specs->complex_p);
+      specs->type = void_type_node;
+      break;
+    case cts_bool:
+      gcc_assert (!specs->long_p && !specs->short_p
+                 && !specs->signed_p && !specs->unsigned_p
+                 && !specs->complex_p);
+      specs->type = boolean_type_node;
+      break;
+    case cts_char:
+      gcc_assert (!specs->long_p && !specs->short_p);
+      gcc_assert (!(specs->signed_p && specs->unsigned_p));
+      if (specs->signed_p)
+       specs->type = signed_char_type_node;
+      else if (specs->unsigned_p)
+       specs->type = unsigned_char_type_node;
+      else
+       specs->type = char_type_node;
+      if (specs->complex_p)
+       {
+         pedwarn (specs->locations[cdw_complex], OPT_Wpedantic,
+                  "ISO C does not support complex integer types");
+         specs->type = build_complex_type (specs->type);
+       }
+      break;
+    case cts_int128:
+      gcc_assert (!specs->long_p && !specs->short_p && !specs->long_long_p);
+      gcc_assert (!(specs->signed_p && specs->unsigned_p));
+      specs->type = (specs->unsigned_p
+                    ? int128_unsigned_type_node
+                    : int128_integer_type_node);
+      if (specs->complex_p)
+       {
+         pedwarn (specs->locations[cdw_complex], OPT_Wpedantic,
+                  "ISO C does not support complex integer types");
+         specs->type = build_complex_type (specs->type);
+       }
+      break;
+    case cts_int:
+      gcc_assert (!(specs->long_p && specs->short_p));
+      gcc_assert (!(specs->signed_p && specs->unsigned_p));
+      if (specs->long_long_p)
+       specs->type = (specs->unsigned_p
+                      ? long_long_unsigned_type_node
+                      : long_long_integer_type_node);
+      else if (specs->long_p)
+       specs->type = (specs->unsigned_p
+                      ? long_unsigned_type_node
+                      : long_integer_type_node);
+      else if (specs->short_p)
+       specs->type = (specs->unsigned_p
+                      ? short_unsigned_type_node
+                      : short_integer_type_node);
+      else
+       specs->type = (specs->unsigned_p
+                      ? unsigned_type_node
+                      : integer_type_node);
+      if (specs->complex_p)
+       {
+         pedwarn (specs->locations[cdw_complex], OPT_Wpedantic,
+                  "ISO C does not support complex integer types");
+         specs->type = build_complex_type (specs->type);
+       }
+      break;
+    case cts_float:
+      gcc_assert (!specs->long_p && !specs->short_p
+                 && !specs->signed_p && !specs->unsigned_p);
+      specs->type = (specs->complex_p
+                    ? complex_float_type_node
+                    : float_type_node);
+      break;
+    case cts_double:
+      gcc_assert (!specs->long_long_p && !specs->short_p
+                 && !specs->signed_p && !specs->unsigned_p);
+      if (specs->long_p)
+       {
+         specs->type = (specs->complex_p
+                        ? complex_long_double_type_node
+                        : long_double_type_node);
+       }
+      else
+       {
+         specs->type = (specs->complex_p
+                        ? complex_double_type_node
+                        : double_type_node);
+       }
+      break;
+    case cts_dfloat32:
+    case cts_dfloat64:
+    case cts_dfloat128:
+      gcc_assert (!specs->long_p && !specs->long_long_p && !specs->short_p
+                 && !specs->signed_p && !specs->unsigned_p && !specs->complex_p);
+      if (specs->typespec_word == cts_dfloat32)
+       specs->type = dfloat32_type_node;
+      else if (specs->typespec_word == cts_dfloat64)
+       specs->type = dfloat64_type_node;
+      else
+       specs->type = dfloat128_type_node;
+      break;
+    case cts_fract:
+      gcc_assert (!specs->complex_p);
+      if (!targetm.fixed_point_supported_p ())
+       specs->type = integer_type_node;
+      else if (specs->saturating_p)
+       {
+         if (specs->long_long_p)
+           specs->type = specs->unsigned_p
+                         ? sat_unsigned_long_long_fract_type_node
+                         : sat_long_long_fract_type_node;
+         else if (specs->long_p)
+           specs->type = specs->unsigned_p
+                         ? sat_unsigned_long_fract_type_node
+                         : sat_long_fract_type_node;
+         else if (specs->short_p)
+           specs->type = specs->unsigned_p
+                         ? sat_unsigned_short_fract_type_node
+                         : sat_short_fract_type_node;
+         else
+           specs->type = specs->unsigned_p
+                         ? sat_unsigned_fract_type_node
+                         : sat_fract_type_node;
+       }
+      else
+       {
+         if (specs->long_long_p)
+           specs->type = specs->unsigned_p
+                         ? unsigned_long_long_fract_type_node
+                         : long_long_fract_type_node;
+         else if (specs->long_p)
+           specs->type = specs->unsigned_p
+                         ? unsigned_long_fract_type_node
+                         : long_fract_type_node;
+         else if (specs->short_p)
+           specs->type = specs->unsigned_p
+                         ? unsigned_short_fract_type_node
+                         : short_fract_type_node;
+         else
+           specs->type = specs->unsigned_p
+                         ? unsigned_fract_type_node
+                         : fract_type_node;
+       }
+      break;
+    case cts_accum:
+      gcc_assert (!specs->complex_p);
+      if (!targetm.fixed_point_supported_p ())
+       specs->type = integer_type_node;
+      else if (specs->saturating_p)
+       {
+         if (specs->long_long_p)
+           specs->type = specs->unsigned_p
+                         ? sat_unsigned_long_long_accum_type_node
+                         : sat_long_long_accum_type_node;
+         else if (specs->long_p)
+           specs->type = specs->unsigned_p
+                         ? sat_unsigned_long_accum_type_node
+                         : sat_long_accum_type_node;
+         else if (specs->short_p)
+           specs->type = specs->unsigned_p
+                         ? sat_unsigned_short_accum_type_node
+                         : sat_short_accum_type_node;
+         else
+           specs->type = specs->unsigned_p
+                         ? sat_unsigned_accum_type_node
+                         : sat_accum_type_node;
+       }
+      else
+       {
+         if (specs->long_long_p)
+           specs->type = specs->unsigned_p
+                         ? unsigned_long_long_accum_type_node
+                         : long_long_accum_type_node;
+         else if (specs->long_p)
+           specs->type = specs->unsigned_p
+                         ? unsigned_long_accum_type_node
+                         : long_accum_type_node;
+         else if (specs->short_p)
+           specs->type = specs->unsigned_p
+                         ? unsigned_short_accum_type_node
+                         : short_accum_type_node;
+         else
+           specs->type = specs->unsigned_p
+                         ? unsigned_accum_type_node
+                         : accum_type_node;
+       }
+      break;
+    default:
+      gcc_unreachable ();
+    }
+
+  return specs;
+}
+
+/* A subroutine of c_write_global_declarations.  Perform final processing
+   on one file scope's declarations (or the external scope's declarations),
+   GLOBALS.  */
+
+static void
+c_write_global_declarations_1 (tree globals)
+{
+  tree decl;
+  bool reconsider;
+
+  /* Process the decls in the order they were written.  */
+  for (decl = globals; decl; decl = DECL_CHAIN (decl))
+    {
+      /* Check for used but undefined static functions using the C
+        standard's definition of "used", and set TREE_NO_WARNING so
+        that check_global_declarations doesn't repeat the check.  */
+      if (TREE_CODE (decl) == FUNCTION_DECL
+         && DECL_INITIAL (decl) == 0
+         && DECL_EXTERNAL (decl)
+         && !TREE_PUBLIC (decl)
+         && C_DECL_USED (decl))
+       {
+         pedwarn (input_location, 0, "%q+F used but never defined", decl);
+         TREE_NO_WARNING (decl) = 1;
+       }
+
+      wrapup_global_declaration_1 (decl);
+    }
+
+  do
+    {
+      reconsider = false;
+      for (decl = globals; decl; decl = DECL_CHAIN (decl))
+       reconsider |= wrapup_global_declaration_2 (decl);
+    }
+  while (reconsider);
+
+  for (decl = globals; decl; decl = DECL_CHAIN (decl))
+    check_global_declaration_1 (decl);
+}
+
+/* A subroutine of c_write_global_declarations Emit debug information for each
+   of the declarations in GLOBALS.  */
+
+static void
+c_write_global_declarations_2 (tree globals)
+{
+  tree decl;
+
+  for (decl = globals; decl ; decl = DECL_CHAIN (decl))
+    debug_hooks->global_decl (decl);
+}
+
+/* Callback to collect a source_ref from a DECL.  */
+
+static void
+collect_source_ref_cb (tree decl)
+{
+  if (!DECL_IS_BUILTIN (decl))
+    collect_source_ref (LOCATION_FILE (decl_sloc (decl, false)));
+}
+
+/* Preserve the external declarations scope across a garbage collect.  */
+static GTY(()) tree ext_block;
+
+/* Collect all references relevant to SOURCE_FILE.  */
+
+static void
+collect_all_refs (const char *source_file)
+{
+  tree t;
+  unsigned i;
+
+  FOR_EACH_VEC_ELT (tree, all_translation_units, i, t)
+    collect_ada_nodes (BLOCK_VARS (DECL_INITIAL (t)), source_file);
+
+  collect_ada_nodes (BLOCK_VARS (ext_block), source_file);
+}
+
+/* Iterate over all global declarations and call CALLBACK.  */
+
+static void
+for_each_global_decl (void (*callback) (tree decl))
+{
+  tree t;
+  tree decls;
+  tree decl;
+  unsigned i;
+
+  FOR_EACH_VEC_ELT (tree, all_translation_units, i, t)
+    { 
+      decls = DECL_INITIAL (t);
+      for (decl = BLOCK_VARS (decls); decl; decl = TREE_CHAIN (decl))
+       callback (decl);
+    }
+
+  for (decl = BLOCK_VARS (ext_block); decl; decl = TREE_CHAIN (decl))
+    callback (decl);
+}
+
+void
+c_write_global_declarations (void)
+{
+  tree t;
+  unsigned i;
+
+  /* We don't want to do this if generating a PCH.  */
+  if (pch_file)
+    return;
+
+  timevar_start (TV_PHASE_DEFERRED);
+
+  /* Do the Objective-C stuff.  This is where all the Objective-C
+     module stuff gets generated (symtab, class/protocol/selector
+     lists etc).  */
+  if (c_dialect_objc ())
+    objc_write_global_declarations ();
+
+  /* Close the external scope.  */
+  ext_block = pop_scope ();
+  external_scope = 0;
+  gcc_assert (!current_scope);
+
+  /* Handle -fdump-ada-spec[-slim]. */
+  if (dump_enabled_p (TDI_ada))
+    {
+      /* Build a table of files to generate specs for */
+      if (get_dump_file_info (TDI_ada)->flags & TDF_SLIM)
+       collect_source_ref (main_input_filename);
+      else
+       for_each_global_decl (collect_source_ref_cb);
+
+      dump_ada_specs (collect_all_refs, NULL);
+    }
+
+  if (ext_block)
+    {
+      tree tmp = BLOCK_VARS (ext_block);
+      int flags;
+      FILE * stream = dump_begin (TDI_tu, &flags);
+      if (stream && tmp)
+       {
+         dump_node (tmp, flags & ~TDF_SLIM, stream);
+         dump_end (TDI_tu, stream);
+       }
+    }
+
+  /* Process all file scopes in this compilation, and the external_scope,
+     through wrapup_global_declarations and check_global_declarations.  */
+  FOR_EACH_VEC_ELT (tree, all_translation_units, i, t)
+    c_write_global_declarations_1 (BLOCK_VARS (DECL_INITIAL (t)));
+  c_write_global_declarations_1 (BLOCK_VARS (ext_block));
+
+  timevar_stop (TV_PHASE_DEFERRED);
+  timevar_start (TV_PHASE_OPT_GEN);
+
+  /* We're done parsing; proceed to optimize and emit assembly.
+     FIXME: shouldn't be the front end's responsibility to call this.  */
+  finalize_compilation_unit ();
+
+  timevar_stop (TV_PHASE_OPT_GEN);
+  timevar_start (TV_PHASE_DBGINFO);
+
+  /* After cgraph has had a chance to emit everything that's going to
+     be emitted, output debug information for globals.  */
+  if (!seen_error ())
+    {
+      timevar_push (TV_SYMOUT);
+      FOR_EACH_VEC_ELT (tree, all_translation_units, i, t)
+       c_write_global_declarations_2 (BLOCK_VARS (DECL_INITIAL (t)));
+      c_write_global_declarations_2 (BLOCK_VARS (ext_block));
+      timevar_pop (TV_SYMOUT);
+    }
+
+  ext_block = NULL;
+  timevar_stop (TV_PHASE_DBGINFO);
+}
+
+/* Register reserved keyword WORD as qualifier for address space AS.  */
+
+void
+c_register_addr_space (const char *word, addr_space_t as)
+{
+  int rid = RID_FIRST_ADDR_SPACE + as;
+  tree id;
+
+  /* Address space qualifiers are only supported
+     in C with GNU extensions enabled.  */
+  if (c_dialect_objc () || flag_no_asm)
+    return;
+
+  id = get_identifier (word);
+  C_SET_RID_CODE (id, rid);
+  C_IS_RESERVED_WORD (id) = 1;
+  ridpointers [rid] = id;
+}
+
+#include "gt-c-c-decl.h"
diff --git a/gcc/c/c-errors.c b/gcc/c/c-errors.c
new file mode 100644 (file)
index 0000000..bee534c
--- /dev/null
@@ -0,0 +1,64 @@
+/* Various diagnostic subroutines for the GNU C language.
+   Copyright (C) 2000, 2001, 2003, 2007, 2008 Free Software Foundation, Inc.
+   Contributed by Gabriel Dos Reis <gdr@codesourcery.com>
+
+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/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "tree.h"
+#include "c-tree.h"
+#include "tm_p.h"
+#include "flags.h"
+#include "diagnostic.h"
+
+/* Issue an ISO C99 pedantic warning MSGID.  */
+
+void
+pedwarn_c99 (location_t location, int opt, const char *gmsgid, ...)
+{
+  diagnostic_info diagnostic;
+  va_list ap;
+
+  va_start (ap, gmsgid);
+  diagnostic_set_info (&diagnostic, gmsgid, &ap, location,
+                      flag_isoc99 ? DK_PEDWARN : DK_WARNING);
+  diagnostic.option_index = opt;
+  report_diagnostic (&diagnostic);
+  va_end (ap);
+}
+
+/* Issue an ISO C90 pedantic warning MSGID.  This function is supposed to
+   be used for matters that are allowed in ISO C99 but not supported in
+   ISO C90, thus we explicitly don't pedwarn when C99 is specified.
+   (There is no flag_c90.)  */
+
+void
+pedwarn_c90 (location_t location, int opt, const char *gmsgid, ...)
+{
+  diagnostic_info diagnostic;
+  va_list ap;
+
+  va_start (ap, gmsgid);
+  diagnostic_set_info (&diagnostic, gmsgid, &ap, location,
+                      flag_isoc99 ? DK_WARNING : DK_PEDWARN);
+  diagnostic.option_index = opt;
+  report_diagnostic (&diagnostic);
+  va_end (ap);
+}
diff --git a/gcc/c/c-lang.c b/gcc/c/c-lang.c
new file mode 100644 (file)
index 0000000..ae1b081
--- /dev/null
@@ -0,0 +1,52 @@
+/* Language-specific hook definitions for C front end.
+   Copyright (C) 1991, 1995, 1997, 1998,
+   1999, 2000, 2001, 2003, 2004, 2005, 2007, 2008, 2009, 2010
+   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/>.  */
+
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "tree.h"
+#include "c-tree.h"
+#include "c-family/c-common.h"
+#include "langhooks.h"
+#include "langhooks-def.h"
+#include "tree-inline.h"
+#include "diagnostic-core.h"
+#include "c-objc-common.h"
+#include "c-family/c-pragma.h"
+
+enum c_language_kind c_language = clk_c;
+
+/* Lang hooks common to C and ObjC are declared in c-objc-common.h;
+   consequently, there should be very few hooks below.  */
+
+#undef LANG_HOOKS_NAME
+#define LANG_HOOKS_NAME "GNU C"
+#undef LANG_HOOKS_INIT
+#define LANG_HOOKS_INIT c_objc_common_init
+#undef LANG_HOOKS_INIT_TS
+#define LANG_HOOKS_INIT_TS c_common_init_ts
+
+/* Each front end provides its own lang hook initializer.  */
+struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
+
+#include "gtype-c.h"
diff --git a/gcc/c/c-lang.h b/gcc/c/c-lang.h
new file mode 100644 (file)
index 0000000..256a269
--- /dev/null
@@ -0,0 +1,60 @@
+/* Definitions for C language specific types.
+   Copyright (C) 2009, 2010
+   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 GCC_C_LANG_H
+#define GCC_C_LANG_H
+
+#include "c-family/c-common.h"
+#include "ggc.h"
+
+struct GTY((variable_size)) lang_type {
+  /* In a RECORD_TYPE, a sorted array of the fields of the type.  */
+  struct sorted_fields_type * GTY ((reorder ("resort_sorted_fields"))) s;
+  /* In an ENUMERAL_TYPE, the min and max values.  */
+  tree enum_min;
+  tree enum_max;
+  /* In a RECORD_TYPE, information specific to Objective-C, such
+     as a list of adopted protocols or a pointer to a corresponding
+     @interface.  See objc/objc-act.h for details.  */
+  tree objc_info;
+};
+
+struct GTY(()) lang_decl {
+  char dummy;
+};
+
+/* Save and restore the variables in this file and elsewhere
+   that keep track of the progress of compilation of the current function.
+   Used for nested functions.  */
+
+struct GTY(()) language_function {
+  struct c_language_function base;
+  tree x_break_label;
+  tree x_cont_label;
+  struct c_switch * GTY((skip)) x_switch_stack;
+  struct c_arg_info * GTY((skip)) arg_info;
+  int returns_value;
+  int returns_null;
+  int returns_abnormally;
+  int warn_about_return_type;
+};
+
+
+#endif /* ! GCC_C_LANG_H */
diff --git a/gcc/c/c-objc-common.c b/gcc/c/c-objc-common.c
new file mode 100644 (file)
index 0000000..9351cd5
--- /dev/null
@@ -0,0 +1,214 @@
+/* Some code common to C and ObjC front ends.
+   Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007,
+   2009, 2010 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/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tree.h"
+#include "c-tree.h"
+#include "intl.h"
+#include "c-family/c-pretty-print.h"
+#include "flags.h"
+#include "diagnostic.h"
+#include "tree-pretty-print.h"
+#include "langhooks.h"
+#include "c-objc-common.h"
+
+static bool c_tree_printer (pretty_printer *, text_info *, const char *,
+                           int, bool, bool, bool);
+
+bool
+c_missing_noreturn_ok_p (tree decl)
+{
+  /* A missing noreturn is not ok for freestanding implementations and
+     ok for the `main' function in hosted implementations.  */
+  return flag_hosted && MAIN_NAME_P (DECL_ASSEMBLER_NAME (decl));
+}
+
+/* Called from check_global_declarations.  */
+
+bool
+c_warn_unused_global_decl (const_tree decl)
+{
+  if (TREE_CODE (decl) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (decl))
+    return false;
+  if (DECL_IN_SYSTEM_HEADER (decl))
+    return false;
+
+  return true;
+}
+
+/* Initialization common to C and Objective-C front ends.  */
+bool
+c_objc_common_init (void)
+{
+  c_init_decl_processing ();
+
+  if (c_common_init () == false)
+    return false;
+
+  /* These were not defined in the Objective-C front end, but I'm
+     putting them here anyway.  The diagnostic format decoder might
+     want an enhanced ObjC implementation.  */
+  diagnostic_format_decoder (global_dc) = &c_tree_printer;
+
+  return true;
+}
+
+/* Called during diagnostic message formatting process to print a
+   source-level entity onto BUFFER.  The meaning of the format specifiers
+   is as follows:
+   %D: a general decl,
+   %E: an identifier or expression,
+   %F: a function declaration,
+   %T: a type.
+   %V: a list of type qualifiers from a tree.
+   %v: an explicit list of type qualifiers
+   %#v: an explicit list of type qualifiers of a function type.
+
+   Please notice when called, the `%' part was already skipped by the
+   diagnostic machinery.  */
+static bool
+c_tree_printer (pretty_printer *pp, text_info *text, const char *spec,
+               int precision, bool wide, bool set_locus, bool hash)
+{
+  tree t = NULL_TREE;
+  tree name;
+  c_pretty_printer *cpp = (c_pretty_printer *) pp;
+  pp->padding = pp_none;
+
+  if (precision != 0 || wide)
+    return false;
+
+  if (*spec == 'K')
+    {
+      percent_K_format (text);
+      return true;
+    }
+
+  if (*spec != 'v')
+    {
+      t = va_arg (*text->args_ptr, tree);
+      if (set_locus && text->locus)
+       *text->locus = DECL_SOURCE_LOCATION (t);
+    }
+
+  switch (*spec)
+    {
+    case 'D':
+      if (DECL_DEBUG_EXPR_IS_FROM (t) && DECL_DEBUG_EXPR (t))
+       {
+         t = DECL_DEBUG_EXPR (t);
+         if (!DECL_P (t))
+           {
+             pp_c_expression (cpp, t);
+             return true;
+           }
+       }
+      /* FALLTHRU */
+
+    case 'F':
+      if (DECL_NAME (t))
+       {
+         pp_identifier (cpp, lang_hooks.decl_printable_name (t, 2));
+         return true;
+       }
+      break;
+
+    case 'T':
+      gcc_assert (TYPE_P (t));
+      name = TYPE_NAME (t);
+
+      if (name && TREE_CODE (name) == TYPE_DECL)
+       {
+         if (DECL_NAME (name))
+           pp_identifier (cpp, lang_hooks.decl_printable_name (name, 2));
+         else
+           pp_type_id (cpp, t);
+         return true;
+       }
+      else
+       {
+         pp_type_id (cpp, t);
+         return true;
+       }
+      break;
+
+    case 'E':
+      if (TREE_CODE (t) == IDENTIFIER_NODE)
+       pp_identifier (cpp, IDENTIFIER_POINTER (t));
+      else
+       pp_expression (cpp, t);
+      return true;
+
+    case 'V':
+      pp_c_type_qualifier_list (cpp, t);
+      return true;
+
+    case 'v':
+      pp_c_cv_qualifiers (cpp, va_arg (*text->args_ptr, int), hash);
+      return true;
+
+    default:
+      return false;
+    }
+
+  pp_string (cpp, _("({anonymous})"));
+  return true;
+}
+
+/* In C and ObjC, all decls have "C" linkage.  */
+bool
+has_c_linkage (const_tree decl ATTRIBUTE_UNUSED)
+{
+  return true;
+}
+
+void
+c_initialize_diagnostics (diagnostic_context *context)
+{
+  pretty_printer *base;
+  c_pretty_printer *pp;
+
+  c_common_initialize_diagnostics (context);
+
+  base = context->printer;
+  pp = XNEW (c_pretty_printer);
+  memcpy (pp_base (pp), base, sizeof (pretty_printer));
+  pp_c_pretty_printer_init (pp);
+  context->printer = (pretty_printer *) pp;
+
+  /* It is safe to free this object because it was previously XNEW()'d.  */
+  XDELETE (base);
+}
+
+int
+c_types_compatible_p (tree x, tree y)
+{
+  return comptypes (TYPE_MAIN_VARIANT (x), TYPE_MAIN_VARIANT (y));
+}
+
+/* Determine if the type is a vla type for the backend.  */
+
+bool
+c_vla_unspec_p (tree x, tree fn ATTRIBUTE_UNUSED)
+{
+  return c_vla_type_p (x);
+}
diff --git a/gcc/c/c-objc-common.h b/gcc/c/c-objc-common.h
new file mode 100644 (file)
index 0000000..dbbd50a
--- /dev/null
@@ -0,0 +1,109 @@
+/* Language hooks common to C and ObjC front ends.
+   Copyright (C) 2004, 2005, 2007, 2008, 2009, 2010
+   Free Software Foundation, Inc.
+   Contributed by Ziemowit Laski  <zlaski@apple.com>
+
+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 GCC_C_OBJC_COMMON
+#define GCC_C_OBJC_COMMON
+
+/* Lang hooks that are shared between C and ObjC are defined here.  Hooks
+   specific to C or ObjC go in c-lang.c and objc/objc-lang.c, respectively.  */
+
+#undef LANG_HOOKS_IDENTIFIER_SIZE
+#define LANG_HOOKS_IDENTIFIER_SIZE C_SIZEOF_STRUCT_LANG_IDENTIFIER
+#undef LANG_HOOKS_FINISH
+#define LANG_HOOKS_FINISH c_common_finish
+#undef LANG_HOOKS_OPTION_LANG_MASK
+#define LANG_HOOKS_OPTION_LANG_MASK c_common_option_lang_mask
+#undef LANG_HOOKS_COMPLAIN_WRONG_LANG_P
+#define LANG_HOOKS_COMPLAIN_WRONG_LANG_P c_common_complain_wrong_lang_p
+#undef LANG_HOOKS_INIT_OPTIONS_STRUCT
+#define LANG_HOOKS_INIT_OPTIONS_STRUCT c_common_init_options_struct
+#undef LANG_HOOKS_INIT_OPTIONS
+#define LANG_HOOKS_INIT_OPTIONS c_common_init_options
+#undef LANG_HOOKS_INITIALIZE_DIAGNOSTICS
+#define LANG_HOOKS_INITIALIZE_DIAGNOSTICS c_initialize_diagnostics
+#undef LANG_HOOKS_HANDLE_OPTION
+#define LANG_HOOKS_HANDLE_OPTION c_common_handle_option
+#undef LANG_HOOKS_POST_OPTIONS
+#define LANG_HOOKS_POST_OPTIONS c_common_post_options
+#undef LANG_HOOKS_GET_ALIAS_SET
+#define LANG_HOOKS_GET_ALIAS_SET c_common_get_alias_set
+#undef LANG_HOOKS_PARSE_FILE
+#define LANG_HOOKS_PARSE_FILE c_common_parse_file
+#undef LANG_HOOKS_FINISH_INCOMPLETE_DECL
+#define LANG_HOOKS_FINISH_INCOMPLETE_DECL c_finish_incomplete_decl
+#undef LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL
+#define LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL c_warn_unused_global_decl
+#undef LANG_HOOKS_PRINT_IDENTIFIER
+#define LANG_HOOKS_PRINT_IDENTIFIER c_print_identifier
+#undef LANG_HOOKS_TYPES_COMPATIBLE_P
+#define LANG_HOOKS_TYPES_COMPATIBLE_P c_types_compatible_p
+#undef LANG_HOOKS_MISSING_NORETURN_OK_P
+#define LANG_HOOKS_MISSING_NORETURN_OK_P c_missing_noreturn_ok_p
+#undef  LANG_HOOKS_BUILTIN_FUNCTION
+#define LANG_HOOKS_BUILTIN_FUNCTION c_builtin_function
+#undef  LANG_HOOKS_BUILTIN_FUNCTION_EXT_SCOPE
+#define LANG_HOOKS_BUILTIN_FUNCTION_EXT_SCOPE c_builtin_function_ext_scope
+
+/* Attribute hooks.  */
+#undef LANG_HOOKS_COMMON_ATTRIBUTE_TABLE
+#define LANG_HOOKS_COMMON_ATTRIBUTE_TABLE c_common_attribute_table
+#undef LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE
+#define LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE c_common_format_attribute_table
+
+#undef LANG_HOOKS_TREE_DUMP_DUMP_TREE_FN
+#define LANG_HOOKS_TREE_DUMP_DUMP_TREE_FN c_dump_tree
+
+#undef LANG_HOOKS_TYPE_FOR_MODE
+#define LANG_HOOKS_TYPE_FOR_MODE c_common_type_for_mode
+#undef LANG_HOOKS_TYPE_FOR_SIZE
+#define LANG_HOOKS_TYPE_FOR_SIZE c_common_type_for_size
+#undef LANG_HOOKS_INCOMPLETE_TYPE_ERROR
+#define LANG_HOOKS_INCOMPLETE_TYPE_ERROR c_incomplete_type_error
+#undef LANG_HOOKS_TYPE_PROMOTES_TO
+#define LANG_HOOKS_TYPE_PROMOTES_TO c_type_promotes_to
+#undef LANG_HOOKS_REGISTER_BUILTIN_TYPE
+#define LANG_HOOKS_REGISTER_BUILTIN_TYPE c_register_builtin_type
+#undef LANG_HOOKS_TO_TARGET_CHARSET
+#define LANG_HOOKS_TO_TARGET_CHARSET c_common_to_target_charset
+#undef LANG_HOOKS_EXPR_TO_DECL
+#define LANG_HOOKS_EXPR_TO_DECL c_expr_to_decl
+
+/* The C front end's scoping structure is very different from
+   that expected by the language-independent code; it is best
+   to disable getdecls.
+   This means it must also provide its own write_globals.  */
+
+#undef LANG_HOOKS_GETDECLS
+#define LANG_HOOKS_GETDECLS lhd_return_null_tree_v
+#undef LANG_HOOKS_WRITE_GLOBALS
+#define LANG_HOOKS_WRITE_GLOBALS c_write_global_declarations
+
+/* Hooks for tree gimplification.  */
+#undef LANG_HOOKS_GIMPLIFY_EXPR
+#define LANG_HOOKS_GIMPLIFY_EXPR c_gimplify_expr
+
+#undef LANG_HOOKS_OMP_PREDETERMINED_SHARING
+#define LANG_HOOKS_OMP_PREDETERMINED_SHARING c_omp_predetermined_sharing
+
+#undef LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P
+#define LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P c_vla_unspec_p
+
+#endif /* GCC_C_OBJC_COMMON */
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
new file mode 100644 (file)
index 0000000..2237749
--- /dev/null
@@ -0,0 +1,10840 @@
+/* Parser for C and Objective-C.
+   Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011,
+   2012 Free Software Foundation, Inc.
+
+   Parser actions based on the old Bison parser; structure somewhat
+   influenced by and fragments based on the C++ parser.
+
+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/>.  */
+
+/* TODO:
+
+   Make sure all relevant comments, and all relevant code from all
+   actions, brought over from old parser.  Verify exact correspondence
+   of syntax accepted.
+
+   Add testcases covering every input symbol in every state in old and
+   new parsers.
+
+   Include full syntax for GNU C, including erroneous cases accepted
+   with error messages, in syntax productions in comments.
+
+   Make more diagnostics in the front end generally take an explicit
+   location rather than implicitly using input_location.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"                        /* For rtl.h: needs enum reg_class.  */
+#include "tree.h"
+#include "langhooks.h"
+#include "input.h"
+#include "cpplib.h"
+#include "timevar.h"
+#include "c-family/c-pragma.h"
+#include "c-tree.h"
+#include "flags.h"
+#include "ggc.h"
+#include "c-family/c-common.h"
+#include "c-family/c-objc.h"
+#include "vec.h"
+#include "target.h"
+#include "cgraph.h"
+#include "plugin.h"
+
+\f
+/* Initialization routine for this file.  */
+
+void
+c_parse_init (void)
+{
+  /* The only initialization required is of the reserved word
+     identifiers.  */
+  unsigned int i;
+  tree id;
+  int mask = 0;
+
+  /* Make sure RID_MAX hasn't grown past the 8 bits used to hold the keyword in
+     the c_token structure.  */
+  gcc_assert (RID_MAX <= 255);
+
+  mask |= D_CXXONLY;
+  if (!flag_isoc99)
+    mask |= D_C99;
+  if (flag_no_asm)
+    {
+      mask |= D_ASM | D_EXT;
+      if (!flag_isoc99)
+       mask |= D_EXT89;
+    }
+  if (!c_dialect_objc ())
+    mask |= D_OBJC | D_CXX_OBJC;
+
+  ridpointers = ggc_alloc_cleared_vec_tree ((int) RID_MAX);
+  for (i = 0; i < num_c_common_reswords; i++)
+    {
+      /* If a keyword is disabled, do not enter it into the table
+        and so create a canonical spelling that isn't a keyword.  */
+      if (c_common_reswords[i].disable & mask)
+       {
+         if (warn_cxx_compat
+             && (c_common_reswords[i].disable & D_CXXWARN))
+           {
+             id = get_identifier (c_common_reswords[i].word);
+             C_SET_RID_CODE (id, RID_CXX_COMPAT_WARN);
+             C_IS_RESERVED_WORD (id) = 1;
+           }
+         continue;
+       }
+
+      id = get_identifier (c_common_reswords[i].word);
+      C_SET_RID_CODE (id, c_common_reswords[i].rid);
+      C_IS_RESERVED_WORD (id) = 1;
+      ridpointers [(int) c_common_reswords[i].rid] = id;
+    }
+}
+\f
+/* The C lexer intermediates between the lexer in cpplib and c-lex.c
+   and the C parser.  Unlike the C++ lexer, the parser structure
+   stores the lexer information instead of using a separate structure.
+   Identifiers are separated into ordinary identifiers, type names,
+   keywords and some other Objective-C types of identifiers, and some
+   look-ahead is maintained.
+
+   ??? It might be a good idea to lex the whole file up front (as for
+   C++).  It would then be possible to share more of the C and C++
+   lexer code, if desired.  */
+
+/* The following local token type is used.  */
+
+/* A keyword.  */
+#define CPP_KEYWORD ((enum cpp_ttype) (N_TTYPES + 1))
+
+/* More information about the type of a CPP_NAME token.  */
+typedef enum c_id_kind {
+  /* An ordinary identifier.  */
+  C_ID_ID,
+  /* An identifier declared as a typedef name.  */
+  C_ID_TYPENAME,
+  /* An identifier declared as an Objective-C class name.  */
+  C_ID_CLASSNAME,
+  /* An address space identifier.  */
+  C_ID_ADDRSPACE,
+  /* Not an identifier.  */
+  C_ID_NONE
+} c_id_kind;
+
+/* A single C token after string literal concatenation and conversion
+   of preprocessing tokens to tokens.  */
+typedef struct GTY (()) c_token {
+  /* The kind of token.  */
+  ENUM_BITFIELD (cpp_ttype) type : 8;
+  /* If this token is a CPP_NAME, this value indicates whether also
+     declared as some kind of type.  Otherwise, it is C_ID_NONE.  */
+  ENUM_BITFIELD (c_id_kind) id_kind : 8;
+  /* If this token is a keyword, this value indicates which keyword.
+     Otherwise, this value is RID_MAX.  */
+  ENUM_BITFIELD (rid) keyword : 8;
+  /* If this token is a CPP_PRAGMA, this indicates the pragma that
+     was seen.  Otherwise it is PRAGMA_NONE.  */
+  ENUM_BITFIELD (pragma_kind) pragma_kind : 8;
+  /* The location at which this token was found.  */
+  location_t location;
+  /* The value associated with this token, if any.  */
+  tree value;
+} c_token;
+
+/* A parser structure recording information about the state and
+   context of parsing.  Includes lexer information with up to two
+   tokens of look-ahead; more are not needed for C.  */
+typedef struct GTY(()) c_parser {
+  /* The look-ahead tokens.  */
+  c_token tokens[2];
+  /* How many look-ahead tokens are available (0, 1 or 2).  */
+  short tokens_avail;
+  /* True if a syntax error is being recovered from; false otherwise.
+     c_parser_error sets this flag.  It should clear this flag when
+     enough tokens have been consumed to recover from the error.  */
+  BOOL_BITFIELD error : 1;
+  /* True if we're processing a pragma, and shouldn't automatically
+     consume CPP_PRAGMA_EOL.  */
+  BOOL_BITFIELD in_pragma : 1;
+  /* True if we're parsing the outermost block of an if statement.  */
+  BOOL_BITFIELD in_if_block : 1;
+  /* True if we want to lex an untranslated string.  */
+  BOOL_BITFIELD lex_untranslated_string : 1;
+
+  /* Objective-C specific parser/lexer information.  */
+
+  /* True if we are in a context where the Objective-C "PQ" keywords
+     are considered keywords.  */
+  BOOL_BITFIELD objc_pq_context : 1;
+  /* True if we are parsing a (potential) Objective-C foreach
+     statement.  This is set to true after we parsed 'for (' and while
+     we wait for 'in' or ';' to decide if it's a standard C for loop or an
+     Objective-C foreach loop.  */
+  BOOL_BITFIELD objc_could_be_foreach_context : 1;
+  /* The following flag is needed to contextualize Objective-C lexical
+     analysis.  In some cases (e.g., 'int NSObject;'), it is
+     undesirable to bind an identifier to an Objective-C class, even
+     if a class with that name exists.  */
+  BOOL_BITFIELD objc_need_raw_identifier : 1;
+  /* Nonzero if we're processing a __transaction statement.  The value
+     is 1 | TM_STMT_ATTR_*.  */
+  unsigned int in_transaction : 4;
+  /* True if we are in a context where the Objective-C "Property attribute"
+     keywords are valid.  */
+  BOOL_BITFIELD objc_property_attr_context : 1;
+} c_parser;
+
+
+/* The actual parser and external interface.  ??? Does this need to be
+   garbage-collected?  */
+
+static GTY (()) c_parser *the_parser;
+
+/* Read in and lex a single token, storing it in *TOKEN.  */
+
+static void
+c_lex_one_token (c_parser *parser, c_token *token)
+{
+  timevar_push (TV_LEX);
+
+  token->type = c_lex_with_flags (&token->value, &token->location, NULL,
+                                 (parser->lex_untranslated_string
+                                  ? C_LEX_STRING_NO_TRANSLATE : 0));
+  token->id_kind = C_ID_NONE;
+  token->keyword = RID_MAX;
+  token->pragma_kind = PRAGMA_NONE;
+
+  switch (token->type)
+    {
+    case CPP_NAME:
+      {
+       tree decl;
+
+       bool objc_force_identifier = parser->objc_need_raw_identifier;
+       if (c_dialect_objc ())
+         parser->objc_need_raw_identifier = false;
+
+       if (C_IS_RESERVED_WORD (token->value))
+         {
+           enum rid rid_code = C_RID_CODE (token->value);
+
+           if (rid_code == RID_CXX_COMPAT_WARN)
+             {
+               warning_at (token->location,
+                           OPT_Wc___compat,
+                           "identifier %qE conflicts with C++ keyword",
+                           token->value);
+             }
+           else if (rid_code >= RID_FIRST_ADDR_SPACE
+                    && rid_code <= RID_LAST_ADDR_SPACE)
+             {
+               token->id_kind = C_ID_ADDRSPACE;
+               token->keyword = rid_code;
+               break;
+             }
+           else if (c_dialect_objc () && OBJC_IS_PQ_KEYWORD (rid_code))
+             {
+               /* We found an Objective-C "pq" keyword (in, out,
+                  inout, bycopy, byref, oneway).  They need special
+                  care because the interpretation depends on the
+                  context.  */
+               if (parser->objc_pq_context)
+                 {
+                   token->type = CPP_KEYWORD;
+                   token->keyword = rid_code;
+                   break;
+                 }
+               else if (parser->objc_could_be_foreach_context
+                        && rid_code == RID_IN)
+                 {
+                   /* We are in Objective-C, inside a (potential)
+                      foreach context (which means after having
+                      parsed 'for (', but before having parsed ';'),
+                      and we found 'in'.  We consider it the keyword
+                      which terminates the declaration at the
+                      beginning of a foreach-statement.  Note that
+                      this means you can't use 'in' for anything else
+                      in that context; in particular, in Objective-C
+                      you can't use 'in' as the name of the running
+                      variable in a C for loop.  We could potentially
+                      try to add code here to disambiguate, but it
+                      seems a reasonable limitation.  */
+                   token->type = CPP_KEYWORD;
+                   token->keyword = rid_code;
+                   break;
+                 }
+               /* Else, "pq" keywords outside of the "pq" context are
+                  not keywords, and we fall through to the code for
+                  normal tokens.  */
+             }
+           else if (c_dialect_objc () && OBJC_IS_PATTR_KEYWORD (rid_code))
+             {
+               /* We found an Objective-C "property attribute"
+                  keyword (getter, setter, readonly, etc). These are
+                  only valid in the property context.  */
+               if (parser->objc_property_attr_context)
+                 {
+                   token->type = CPP_KEYWORD;
+                   token->keyword = rid_code;
+                   break;
+                 }
+               /* Else they are not special keywords.
+               */
+             }
+           else if (c_dialect_objc () 
+                    && (OBJC_IS_AT_KEYWORD (rid_code)
+                        || OBJC_IS_CXX_KEYWORD (rid_code)))
+             {
+               /* We found one of the Objective-C "@" keywords (defs,
+                  selector, synchronized, etc) or one of the
+                  Objective-C "cxx" keywords (class, private,
+                  protected, public, try, catch, throw) without a
+                  preceding '@' sign.  Do nothing and fall through to
+                  the code for normal tokens (in C++ we would still
+                  consider the CXX ones keywords, but not in C).  */
+               ;
+             }
+           else
+             {
+               token->type = CPP_KEYWORD;
+               token->keyword = rid_code;
+               break;
+             }
+         }
+
+       decl = lookup_name (token->value);
+       if (decl)
+         {
+           if (TREE_CODE (decl) == TYPE_DECL)
+             {
+               token->id_kind = C_ID_TYPENAME;
+               break;
+             }
+         }
+       else if (c_dialect_objc ())
+         {
+           tree objc_interface_decl = objc_is_class_name (token->value);
+           /* Objective-C class names are in the same namespace as
+              variables and typedefs, and hence are shadowed by local
+              declarations.  */
+           if (objc_interface_decl
+                && (!objc_force_identifier || global_bindings_p ()))
+             {
+               token->value = objc_interface_decl;
+               token->id_kind = C_ID_CLASSNAME;
+               break;
+             }
+         }
+        token->id_kind = C_ID_ID;
+      }
+      break;
+    case CPP_AT_NAME:
+      /* This only happens in Objective-C; it must be a keyword.  */
+      token->type = CPP_KEYWORD;
+      switch (C_RID_CODE (token->value))
+       {
+         /* Replace 'class' with '@class', 'private' with '@private',
+            etc.  This prevents confusion with the C++ keyword
+            'class', and makes the tokens consistent with other
+            Objective-C 'AT' keywords.  For example '@class' is
+            reported as RID_AT_CLASS which is consistent with
+            '@synchronized', which is reported as
+            RID_AT_SYNCHRONIZED.
+         */
+       case RID_CLASS:     token->keyword = RID_AT_CLASS; break;
+       case RID_PRIVATE:   token->keyword = RID_AT_PRIVATE; break;
+       case RID_PROTECTED: token->keyword = RID_AT_PROTECTED; break;
+       case RID_PUBLIC:    token->keyword = RID_AT_PUBLIC; break;
+       case RID_THROW:     token->keyword = RID_AT_THROW; break;
+       case RID_TRY:       token->keyword = RID_AT_TRY; break;
+       case RID_CATCH:     token->keyword = RID_AT_CATCH; break;
+       default:            token->keyword = C_RID_CODE (token->value);
+       }
+      break;
+    case CPP_COLON:
+    case CPP_COMMA:
+    case CPP_CLOSE_PAREN:
+    case CPP_SEMICOLON:
+      /* These tokens may affect the interpretation of any identifiers
+        following, if doing Objective-C.  */
+      if (c_dialect_objc ())
+       parser->objc_need_raw_identifier = false;
+      break;
+    case CPP_PRAGMA:
+      /* We smuggled the cpp_token->u.pragma value in an INTEGER_CST.  */
+      token->pragma_kind = (enum pragma_kind) TREE_INT_CST_LOW (token->value);
+      token->value = NULL;
+      break;
+    default:
+      break;
+    }
+  timevar_pop (TV_LEX);
+}
+
+/* Return a pointer to the next token from PARSER, reading it in if
+   necessary.  */
+
+static inline c_token *
+c_parser_peek_token (c_parser *parser)
+{
+  if (parser->tokens_avail == 0)
+    {
+      c_lex_one_token (parser, &parser->tokens[0]);
+      parser->tokens_avail = 1;
+    }
+  return &parser->tokens[0];
+}
+
+/* Return true if the next token from PARSER has the indicated
+   TYPE.  */
+
+static inline bool
+c_parser_next_token_is (c_parser *parser, enum cpp_ttype type)
+{
+  return c_parser_peek_token (parser)->type == type;
+}
+
+/* Return true if the next token from PARSER does not have the
+   indicated TYPE.  */
+
+static inline bool
+c_parser_next_token_is_not (c_parser *parser, enum cpp_ttype type)
+{
+  return !c_parser_next_token_is (parser, type);
+}
+
+/* Return true if the next token from PARSER is the indicated
+   KEYWORD.  */
+
+static inline bool
+c_parser_next_token_is_keyword (c_parser *parser, enum rid keyword)
+{
+  return c_parser_peek_token (parser)->keyword == keyword;
+}
+
+/* Return a pointer to the next-but-one token from PARSER, reading it
+   in if necessary.  The next token is already read in.  */
+
+static c_token *
+c_parser_peek_2nd_token (c_parser *parser)
+{
+  if (parser->tokens_avail >= 2)
+    return &parser->tokens[1];
+  gcc_assert (parser->tokens_avail == 1);
+  gcc_assert (parser->tokens[0].type != CPP_EOF);
+  gcc_assert (parser->tokens[0].type != CPP_PRAGMA_EOL);
+  c_lex_one_token (parser, &parser->tokens[1]);
+  parser->tokens_avail = 2;
+  return &parser->tokens[1];
+}
+
+/* Return true if TOKEN can start a type name,
+   false otherwise.  */
+static bool
+c_token_starts_typename (c_token *token)
+{
+  switch (token->type)
+    {
+    case CPP_NAME:
+      switch (token->id_kind)
+       {
+       case C_ID_ID:
+         return false;
+       case C_ID_ADDRSPACE:
+         return true;
+       case C_ID_TYPENAME:
+         return true;
+       case C_ID_CLASSNAME:
+         gcc_assert (c_dialect_objc ());
+         return true;
+       default:
+         gcc_unreachable ();
+       }
+    case CPP_KEYWORD:
+      switch (token->keyword)
+       {
+       case RID_UNSIGNED:
+       case RID_LONG:
+       case RID_INT128:
+       case RID_SHORT:
+       case RID_SIGNED:
+       case RID_COMPLEX:
+       case RID_INT:
+       case RID_CHAR:
+       case RID_FLOAT:
+       case RID_DOUBLE:
+       case RID_VOID:
+       case RID_DFLOAT32:
+       case RID_DFLOAT64:
+       case RID_DFLOAT128:
+       case RID_BOOL:
+       case RID_ENUM:
+       case RID_STRUCT:
+       case RID_UNION:
+       case RID_TYPEOF:
+       case RID_CONST:
+       case RID_VOLATILE:
+       case RID_RESTRICT:
+       case RID_ATTRIBUTE:
+       case RID_FRACT:
+       case RID_ACCUM:
+       case RID_SAT:
+         return true;
+       default:
+         return false;
+       }
+    case CPP_LESS:
+      if (c_dialect_objc ())
+       return true;
+      return false;
+    default:
+      return false;
+    }
+}
+
+enum c_lookahead_kind {
+  /* Always treat unknown identifiers as typenames.  */
+  cla_prefer_type,
+
+  /* Could be parsing a nonabstract declarator.  Only treat an identifier
+     as a typename if followed by another identifier or a star.  */
+  cla_nonabstract_decl,
+
+  /* Never treat identifiers as typenames.  */
+  cla_prefer_id
+};
+
+/* Return true if the next token from PARSER can start a type name,
+   false otherwise.  LA specifies how to do lookahead in order to
+   detect unknown type names.  If unsure, pick CLA_PREFER_ID.  */
+
+static inline bool
+c_parser_next_tokens_start_typename (c_parser *parser, enum c_lookahead_kind la)
+{
+  c_token *token = c_parser_peek_token (parser);
+  if (c_token_starts_typename (token))
+    return true;
+
+  /* Try a bit harder to detect an unknown typename.  */
+  if (la != cla_prefer_id
+      && token->type == CPP_NAME
+      && token->id_kind == C_ID_ID
+
+      /* Do not try too hard when we could have "object in array".  */
+      && !parser->objc_could_be_foreach_context
+
+      && (la == cla_prefer_type
+         || c_parser_peek_2nd_token (parser)->type == CPP_NAME
+         || c_parser_peek_2nd_token (parser)->type == CPP_MULT)
+
+      /* Only unknown identifiers.  */
+      && !lookup_name (token->value))
+    return true;
+
+  return false;
+}
+
+/* Return true if TOKEN is a type qualifier, false otherwise.  */
+static bool
+c_token_is_qualifier (c_token *token)
+{
+  switch (token->type)
+    {
+    case CPP_NAME:
+      switch (token->id_kind)
+       {
+       case C_ID_ADDRSPACE:
+         return true;
+       default:
+         return false;
+       }
+    case CPP_KEYWORD:
+      switch (token->keyword)
+       {
+       case RID_CONST:
+       case RID_VOLATILE:
+       case RID_RESTRICT:
+       case RID_ATTRIBUTE:
+         return true;
+       default:
+         return false;
+       }
+    case CPP_LESS:
+      return false;
+    default:
+      gcc_unreachable ();
+    }
+}
+
+/* Return true if the next token from PARSER is a type qualifier,
+   false otherwise.  */
+static inline bool
+c_parser_next_token_is_qualifier (c_parser *parser)
+{
+  c_token *token = c_parser_peek_token (parser);
+  return c_token_is_qualifier (token);
+}
+
+/* Return true if TOKEN can start declaration specifiers, false
+   otherwise.  */
+static bool
+c_token_starts_declspecs (c_token *token)
+{
+  switch (token->type)
+    {
+    case CPP_NAME:
+      switch (token->id_kind)
+       {
+       case C_ID_ID:
+         return false;
+       case C_ID_ADDRSPACE:
+         return true;
+       case C_ID_TYPENAME:
+         return true;
+       case C_ID_CLASSNAME:
+         gcc_assert (c_dialect_objc ());
+         return true;
+       default:
+         gcc_unreachable ();
+       }
+    case CPP_KEYWORD:
+      switch (token->keyword)
+       {
+       case RID_STATIC:
+       case RID_EXTERN:
+       case RID_REGISTER:
+       case RID_TYPEDEF:
+       case RID_INLINE:
+       case RID_NORETURN:
+       case RID_AUTO:
+       case RID_THREAD:
+       case RID_UNSIGNED:
+       case RID_LONG:
+       case RID_INT128:
+       case RID_SHORT:
+       case RID_SIGNED:
+       case RID_COMPLEX:
+       case RID_INT:
+       case RID_CHAR:
+       case RID_FLOAT:
+       case RID_DOUBLE:
+       case RID_VOID:
+       case RID_DFLOAT32:
+       case RID_DFLOAT64:
+       case RID_DFLOAT128:
+       case RID_BOOL:
+       case RID_ENUM:
+       case RID_STRUCT:
+       case RID_UNION:
+       case RID_TYPEOF:
+       case RID_CONST:
+       case RID_VOLATILE:
+       case RID_RESTRICT:
+       case RID_ATTRIBUTE:
+       case RID_FRACT:
+       case RID_ACCUM:
+       case RID_SAT:
+       case RID_ALIGNAS:
+         return true;
+       default:
+         return false;
+       }
+    case CPP_LESS:
+      if (c_dialect_objc ())
+       return true;
+      return false;
+    default:
+      return false;
+    }
+}
+
+
+/* Return true if TOKEN can start declaration specifiers or a static
+   assertion, false otherwise.  */
+static bool
+c_token_starts_declaration (c_token *token)
+{
+  if (c_token_starts_declspecs (token)
+      || token->keyword == RID_STATIC_ASSERT)
+    return true;
+  else
+    return false;
+}
+
+/* Return true if the next token from PARSER can start declaration
+   specifiers, false otherwise.  */
+static inline bool
+c_parser_next_token_starts_declspecs (c_parser *parser)
+{
+  c_token *token = c_parser_peek_token (parser);
+
+  /* In Objective-C, a classname normally starts a declspecs unless it
+     is immediately followed by a dot.  In that case, it is the
+     Objective-C 2.0 "dot-syntax" for class objects, ie, calls the
+     setter/getter on the class.  c_token_starts_declspecs() can't
+     differentiate between the two cases because it only checks the
+     current token, so we have a special check here.  */
+  if (c_dialect_objc () 
+      && token->type == CPP_NAME
+      && token->id_kind == C_ID_CLASSNAME 
+      && c_parser_peek_2nd_token (parser)->type == CPP_DOT)
+    return false;
+
+  return c_token_starts_declspecs (token);
+}
+
+/* Return true if the next tokens from PARSER can start declaration
+   specifiers or a static assertion, false otherwise.  */
+static inline bool
+c_parser_next_tokens_start_declaration (c_parser *parser)
+{
+  c_token *token = c_parser_peek_token (parser);
+
+  /* Same as above.  */
+  if (c_dialect_objc () 
+      && token->type == CPP_NAME
+      && token->id_kind == C_ID_CLASSNAME 
+      && c_parser_peek_2nd_token (parser)->type == CPP_DOT)
+    return false;
+
+  /* Labels do not start declarations.  */
+  if (token->type == CPP_NAME
+      && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
+    return false;
+
+  if (c_token_starts_declaration (token))
+    return true;
+
+  if (c_parser_next_tokens_start_typename (parser, cla_nonabstract_decl))
+    return true;
+
+  return false;
+}
+
+/* Consume the next token from PARSER.  */
+
+static void
+c_parser_consume_token (c_parser *parser)
+{
+  gcc_assert (parser->tokens_avail >= 1);
+  gcc_assert (parser->tokens[0].type != CPP_EOF);
+  gcc_assert (!parser->in_pragma || parser->tokens[0].type != CPP_PRAGMA_EOL);
+  gcc_assert (parser->error || parser->tokens[0].type != CPP_PRAGMA);
+  if (parser->tokens_avail == 2)
+    parser->tokens[0] = parser->tokens[1];
+  parser->tokens_avail--;
+}
+
+/* Expect the current token to be a #pragma.  Consume it and remember
+   that we've begun parsing a pragma.  */
+
+static void
+c_parser_consume_pragma (c_parser *parser)
+{
+  gcc_assert (!parser->in_pragma);
+  gcc_assert (parser->tokens_avail >= 1);
+  gcc_assert (parser->tokens[0].type == CPP_PRAGMA);
+  if (parser->tokens_avail == 2)
+    parser->tokens[0] = parser->tokens[1];
+  parser->tokens_avail--;
+  parser->in_pragma = true;
+}
+
+/* Update the globals input_location and in_system_header from
+   TOKEN.  */
+static inline void
+c_parser_set_source_position_from_token (c_token *token)
+{
+  if (token->type != CPP_EOF)
+    {
+      input_location = token->location;
+    }
+}
+
+/* Issue a diagnostic of the form
+      FILE:LINE: MESSAGE before TOKEN
+   where TOKEN is the next token in the input stream of PARSER.
+   MESSAGE (specified by the caller) is usually of the form "expected
+   OTHER-TOKEN".
+
+   Do not issue a diagnostic if still recovering from an error.
+
+   ??? This is taken from the C++ parser, but building up messages in
+   this way is not i18n-friendly and some other approach should be
+   used.  */
+
+static void
+c_parser_error (c_parser *parser, const char *gmsgid)
+{
+  c_token *token = c_parser_peek_token (parser);
+  if (parser->error)
+    return;
+  parser->error = true;
+  if (!gmsgid)
+    return;
+  /* This diagnostic makes more sense if it is tagged to the line of
+     the token we just peeked at.  */
+  c_parser_set_source_position_from_token (token);
+  c_parse_error (gmsgid,
+                /* Because c_parse_error does not understand
+                   CPP_KEYWORD, keywords are treated like
+                   identifiers.  */
+                (token->type == CPP_KEYWORD ? CPP_NAME : token->type),
+                /* ??? The C parser does not save the cpp flags of a
+                   token, we need to pass 0 here and we will not get
+                   the source spelling of some tokens but rather the
+                   canonical spelling.  */
+                token->value, /*flags=*/0);
+}
+
+/* If the next token is of the indicated TYPE, consume it.  Otherwise,
+   issue the error MSGID.  If MSGID is NULL then a message has already
+   been produced and no message will be produced this time.  Returns
+   true if found, false otherwise.  */
+
+static bool
+c_parser_require (c_parser *parser,
+                 enum cpp_ttype type,
+                 const char *msgid)
+{
+  if (c_parser_next_token_is (parser, type))
+    {
+      c_parser_consume_token (parser);
+      return true;
+    }
+  else
+    {
+      c_parser_error (parser, msgid);
+      return false;
+    }
+}
+
+/* If the next token is the indicated keyword, consume it.  Otherwise,
+   issue the error MSGID.  Returns true if found, false otherwise.  */
+
+static bool
+c_parser_require_keyword (c_parser *parser,
+                         enum rid keyword,
+                         const char *msgid)
+{
+  if (c_parser_next_token_is_keyword (parser, keyword))
+    {
+      c_parser_consume_token (parser);
+      return true;
+    }
+  else
+    {
+      c_parser_error (parser, msgid);
+      return false;
+    }
+}
+
+/* Like c_parser_require, except that tokens will be skipped until the
+   desired token is found.  An error message is still produced if the
+   next token is not as expected.  If MSGID is NULL then a message has
+   already been produced and no message will be produced this
+   time.  */
+
+static void
+c_parser_skip_until_found (c_parser *parser,
+                          enum cpp_ttype type,
+                          const char *msgid)
+{
+  unsigned nesting_depth = 0;
+
+  if (c_parser_require (parser, type, msgid))
+    return;
+
+  /* Skip tokens until the desired token is found.  */
+  while (true)
+    {
+      /* Peek at the next token.  */
+      c_token *token = c_parser_peek_token (parser);
+      /* If we've reached the token we want, consume it and stop.  */
+      if (token->type == type && !nesting_depth)
+       {
+         c_parser_consume_token (parser);
+         break;
+       }
+
+      /* If we've run out of tokens, stop.  */
+      if (token->type == CPP_EOF)
+       return;
+      if (token->type == CPP_PRAGMA_EOL && parser->in_pragma)
+       return;
+      if (token->type == CPP_OPEN_BRACE
+         || token->type == CPP_OPEN_PAREN
+         || token->type == CPP_OPEN_SQUARE)
+       ++nesting_depth;
+      else if (token->type == CPP_CLOSE_BRACE
+              || token->type == CPP_CLOSE_PAREN
+              || token->type == CPP_CLOSE_SQUARE)
+       {
+         if (nesting_depth-- == 0)
+           break;
+       }
+      /* Consume this token.  */
+      c_parser_consume_token (parser);
+    }
+  parser->error = false;
+}
+
+/* Skip tokens until the end of a parameter is found, but do not
+   consume the comma, semicolon or closing delimiter.  */
+
+static void
+c_parser_skip_to_end_of_parameter (c_parser *parser)
+{
+  unsigned nesting_depth = 0;
+
+  while (true)
+    {
+      c_token *token = c_parser_peek_token (parser);
+      if ((token->type == CPP_COMMA || token->type == CPP_SEMICOLON)
+         && !nesting_depth)
+       break;
+      /* If we've run out of tokens, stop.  */
+      if (token->type == CPP_EOF)
+       return;
+      if (token->type == CPP_PRAGMA_EOL && parser->in_pragma)
+       return;
+      if (token->type == CPP_OPEN_BRACE
+         || token->type == CPP_OPEN_PAREN
+         || token->type == CPP_OPEN_SQUARE)
+       ++nesting_depth;
+      else if (token->type == CPP_CLOSE_BRACE
+              || token->type == CPP_CLOSE_PAREN
+              || token->type == CPP_CLOSE_SQUARE)
+       {
+         if (nesting_depth-- == 0)
+           break;
+       }
+      /* Consume this token.  */
+      c_parser_consume_token (parser);
+    }
+  parser->error = false;
+}
+
+/* Expect to be at the end of the pragma directive and consume an
+   end of line marker.  */
+
+static void
+c_parser_skip_to_pragma_eol (c_parser *parser)
+{
+  gcc_assert (parser->in_pragma);
+  parser->in_pragma = false;
+
+  if (!c_parser_require (parser, CPP_PRAGMA_EOL, "expected end of line"))
+    while (true)
+      {
+       c_token *token = c_parser_peek_token (parser);
+       if (token->type == CPP_EOF)
+         break;
+       if (token->type == CPP_PRAGMA_EOL)
+         {
+           c_parser_consume_token (parser);
+           break;
+         }
+       c_parser_consume_token (parser);
+      }
+
+  parser->error = false;
+}
+
+/* Skip tokens until we have consumed an entire block, or until we
+   have consumed a non-nested ';'.  */
+
+static void
+c_parser_skip_to_end_of_block_or_statement (c_parser *parser)
+{
+  unsigned nesting_depth = 0;
+  bool save_error = parser->error;
+
+  while (true)
+    {
+      c_token *token;
+
+      /* Peek at the next token.  */
+      token = c_parser_peek_token (parser);
+
+      switch (token->type)
+       {
+       case CPP_EOF:
+         return;
+
+       case CPP_PRAGMA_EOL:
+         if (parser->in_pragma)
+           return;
+         break;
+
+       case CPP_SEMICOLON:
+         /* If the next token is a ';', we have reached the
+            end of the statement.  */
+         if (!nesting_depth)
+           {
+             /* Consume the ';'.  */
+             c_parser_consume_token (parser);
+             goto finished;
+           }
+         break;
+
+       case CPP_CLOSE_BRACE:
+         /* If the next token is a non-nested '}', then we have
+            reached the end of the current block.  */
+         if (nesting_depth == 0 || --nesting_depth == 0)
+           {
+             c_parser_consume_token (parser);
+             goto finished;
+           }
+         break;
+
+       case CPP_OPEN_BRACE:
+         /* If it the next token is a '{', then we are entering a new
+            block.  Consume the entire block.  */
+         ++nesting_depth;
+         break;
+
+       case CPP_PRAGMA:
+         /* If we see a pragma, consume the whole thing at once.  We
+            have some safeguards against consuming pragmas willy-nilly.
+            Normally, we'd expect to be here with parser->error set,
+            which disables these safeguards.  But it's possible to get
+            here for secondary error recovery, after parser->error has
+            been cleared.  */
+         c_parser_consume_pragma (parser);
+         c_parser_skip_to_pragma_eol (parser);
+         parser->error = save_error;
+         continue;
+
+       default:
+         break;
+       }
+
+      c_parser_consume_token (parser);
+    }
+
+ finished:
+  parser->error = false;
+}
+
+/* CPP's options (initialized by c-opts.c).  */
+extern cpp_options *cpp_opts;
+
+/* Save the warning flags which are controlled by __extension__.  */
+
+static inline int
+disable_extension_diagnostics (void)
+{
+  int ret = (pedantic
+            | (warn_pointer_arith << 1)
+            | (warn_traditional << 2)
+            | (flag_iso << 3)
+            | (warn_long_long << 4)
+            | (warn_cxx_compat << 5)
+            | (warn_overlength_strings << 6));
+  cpp_opts->cpp_pedantic = pedantic = 0;
+  warn_pointer_arith = 0;
+  cpp_opts->cpp_warn_traditional = warn_traditional = 0;
+  flag_iso = 0;
+  cpp_opts->cpp_warn_long_long = warn_long_long = 0;
+  warn_cxx_compat = 0;
+  warn_overlength_strings = 0;
+  return ret;
+}
+
+/* Restore the warning flags which are controlled by __extension__.
+   FLAGS is the return value from disable_extension_diagnostics.  */
+
+static inline void
+restore_extension_diagnostics (int flags)
+{
+  cpp_opts->cpp_pedantic = pedantic = flags & 1;
+  warn_pointer_arith = (flags >> 1) & 1;
+  cpp_opts->cpp_warn_traditional = warn_traditional = (flags >> 2) & 1;
+  flag_iso = (flags >> 3) & 1;
+  cpp_opts->cpp_warn_long_long = warn_long_long = (flags >> 4) & 1;
+  warn_cxx_compat = (flags >> 5) & 1;
+  warn_overlength_strings = (flags >> 6) & 1;
+}
+
+/* Possibly kinds of declarator to parse.  */
+typedef enum c_dtr_syn {
+  /* A normal declarator with an identifier.  */
+  C_DTR_NORMAL,
+  /* An abstract declarator (maybe empty).  */
+  C_DTR_ABSTRACT,
+  /* A parameter declarator: may be either, but after a type name does
+     not redeclare a typedef name as an identifier if it can
+     alternatively be interpreted as a typedef name; see DR#009,
+     applied in C90 TC1, omitted from C99 and reapplied in C99 TC2
+     following DR#249.  For example, given a typedef T, "int T" and
+     "int *T" are valid parameter declarations redeclaring T, while
+     "int (T)" and "int * (T)" and "int (T[])" and "int (T (int))" are
+     abstract declarators rather than involving redundant parentheses;
+     the same applies with attributes inside the parentheses before
+     "T".  */
+  C_DTR_PARM
+} c_dtr_syn;
+
+/* The binary operation precedence levels, where 0 is a dummy lowest level
+   used for the bottom of the stack.  */
+enum c_parser_prec {
+  PREC_NONE,
+  PREC_LOGOR,
+  PREC_LOGAND,
+  PREC_BITOR,
+  PREC_BITXOR,
+  PREC_BITAND,
+  PREC_EQ,
+  PREC_REL,
+  PREC_SHIFT,
+  PREC_ADD,
+  PREC_MULT,
+  NUM_PRECS
+};
+
+static void c_parser_external_declaration (c_parser *);
+static void c_parser_asm_definition (c_parser *);
+static void c_parser_declaration_or_fndef (c_parser *, bool, bool, bool,
+                                          bool, bool, tree *);
+static void c_parser_static_assert_declaration_no_semi (c_parser *);
+static void c_parser_static_assert_declaration (c_parser *);
+static void c_parser_declspecs (c_parser *, struct c_declspecs *, bool, bool,
+                               bool, enum c_lookahead_kind);
+static struct c_typespec c_parser_enum_specifier (c_parser *);
+static struct c_typespec c_parser_struct_or_union_specifier (c_parser *);
+static tree c_parser_struct_declaration (c_parser *);
+static struct c_typespec c_parser_typeof_specifier (c_parser *);
+static tree c_parser_alignas_specifier (c_parser *);
+static struct c_declarator *c_parser_declarator (c_parser *, bool, c_dtr_syn,
+                                                bool *);
+static struct c_declarator *c_parser_direct_declarator (c_parser *, bool,
+                                                       c_dtr_syn, bool *);
+static struct c_declarator *c_parser_direct_declarator_inner (c_parser *,
+                                                             bool,
+                                                             struct c_declarator *);
+static struct c_arg_info *c_parser_parms_declarator (c_parser *, bool, tree);
+static struct c_arg_info *c_parser_parms_list_declarator (c_parser *, tree,
+                                                         tree);
+static struct c_parm *c_parser_parameter_declaration (c_parser *, tree);
+static tree c_parser_simple_asm_expr (c_parser *);
+static tree c_parser_attributes (c_parser *);
+static struct c_type_name *c_parser_type_name (c_parser *);
+static struct c_expr c_parser_initializer (c_parser *);
+static struct c_expr c_parser_braced_init (c_parser *, tree, bool);
+static void c_parser_initelt (c_parser *, struct obstack *);
+static void c_parser_initval (c_parser *, struct c_expr *,
+                             struct obstack *);
+static tree c_parser_compound_statement (c_parser *);
+static void c_parser_compound_statement_nostart (c_parser *);
+static void c_parser_label (c_parser *);
+static void c_parser_statement (c_parser *);
+static void c_parser_statement_after_labels (c_parser *);
+static void c_parser_if_statement (c_parser *);
+static void c_parser_switch_statement (c_parser *);
+static void c_parser_while_statement (c_parser *);
+static void c_parser_do_statement (c_parser *);
+static void c_parser_for_statement (c_parser *);
+static tree c_parser_asm_statement (c_parser *);
+static tree c_parser_asm_operands (c_parser *, bool);
+static tree c_parser_asm_goto_operands (c_parser *);
+static tree c_parser_asm_clobbers (c_parser *);
+static struct c_expr c_parser_expr_no_commas (c_parser *, struct c_expr *);
+static struct c_expr c_parser_conditional_expression (c_parser *,
+                                                     struct c_expr *);
+static struct c_expr c_parser_binary_expression (c_parser *, struct c_expr *,
+                                                enum c_parser_prec);
+static struct c_expr c_parser_cast_expression (c_parser *, struct c_expr *);
+static struct c_expr c_parser_unary_expression (c_parser *);
+static struct c_expr c_parser_sizeof_expression (c_parser *);
+static struct c_expr c_parser_alignof_expression (c_parser *);
+static struct c_expr c_parser_postfix_expression (c_parser *);
+static struct c_expr c_parser_postfix_expression_after_paren_type (c_parser *,
+                                                                  struct c_type_name *,
+                                                                  location_t);
+static struct c_expr c_parser_postfix_expression_after_primary (c_parser *,
+                                                               location_t loc,
+                                                               struct c_expr);
+static tree c_parser_transaction (c_parser *, enum rid);
+static struct c_expr c_parser_transaction_expression (c_parser *, enum rid);
+static tree c_parser_transaction_cancel (c_parser *);
+static struct c_expr c_parser_expression (c_parser *);
+static struct c_expr c_parser_expression_conv (c_parser *);
+static VEC(tree,gc) *c_parser_expr_list (c_parser *, bool, bool,
+                                        VEC(tree,gc) **);
+static void c_parser_omp_construct (c_parser *);
+static void c_parser_omp_threadprivate (c_parser *);
+static void c_parser_omp_barrier (c_parser *);
+static void c_parser_omp_flush (c_parser *);
+static void c_parser_omp_taskwait (c_parser *);
+static void c_parser_omp_taskyield (c_parser *);
+
+enum pragma_context { pragma_external, pragma_stmt, pragma_compound };
+static bool c_parser_pragma (c_parser *, enum pragma_context);
+
+/* These Objective-C parser functions are only ever called when
+   compiling Objective-C.  */
+static void c_parser_objc_class_definition (c_parser *, tree);
+static void c_parser_objc_class_instance_variables (c_parser *);
+static void c_parser_objc_class_declaration (c_parser *);
+static void c_parser_objc_alias_declaration (c_parser *);
+static void c_parser_objc_protocol_definition (c_parser *, tree);
+static bool c_parser_objc_method_type (c_parser *);
+static void c_parser_objc_method_definition (c_parser *);
+static void c_parser_objc_methodprotolist (c_parser *);
+static void c_parser_objc_methodproto (c_parser *);
+static tree c_parser_objc_method_decl (c_parser *, bool, tree *, tree *);
+static tree c_parser_objc_type_name (c_parser *);
+static tree c_parser_objc_protocol_refs (c_parser *);
+static void c_parser_objc_try_catch_finally_statement (c_parser *);
+static void c_parser_objc_synchronized_statement (c_parser *);
+static tree c_parser_objc_selector (c_parser *);
+static tree c_parser_objc_selector_arg (c_parser *);
+static tree c_parser_objc_receiver (c_parser *);
+static tree c_parser_objc_message_args (c_parser *);
+static tree c_parser_objc_keywordexpr (c_parser *);
+static void c_parser_objc_at_property_declaration (c_parser *);
+static void c_parser_objc_at_synthesize_declaration (c_parser *);
+static void c_parser_objc_at_dynamic_declaration (c_parser *);
+static bool c_parser_objc_diagnose_bad_element_prefix
+  (c_parser *, struct c_declspecs *);
+
+/* Parse a translation unit (C90 6.7, C99 6.9).
+
+   translation-unit:
+     external-declarations
+
+   external-declarations:
+     external-declaration
+     external-declarations external-declaration
+
+   GNU extensions:
+
+   translation-unit:
+     empty
+*/
+
+static void
+c_parser_translation_unit (c_parser *parser)
+{
+  if (c_parser_next_token_is (parser, CPP_EOF))
+    {
+      pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic,
+              "ISO C forbids an empty translation unit");
+    }
+  else
+    {
+      void *obstack_position = obstack_alloc (&parser_obstack, 0);
+      mark_valid_location_for_stdc_pragma (false);
+      do
+       {
+         ggc_collect ();
+         c_parser_external_declaration (parser);
+         obstack_free (&parser_obstack, obstack_position);
+       }
+      while (c_parser_next_token_is_not (parser, CPP_EOF));
+    }
+}
+
+/* Parse an external declaration (C90 6.7, C99 6.9).
+
+   external-declaration:
+     function-definition
+     declaration
+
+   GNU extensions:
+
+   external-declaration:
+     asm-definition
+     ;
+     __extension__ external-declaration
+
+   Objective-C:
+
+   external-declaration:
+     objc-class-definition
+     objc-class-declaration
+     objc-alias-declaration
+     objc-protocol-definition
+     objc-method-definition
+     @end
+*/
+
+static void
+c_parser_external_declaration (c_parser *parser)
+{
+  int ext;
+  switch (c_parser_peek_token (parser)->type)
+    {
+    case CPP_KEYWORD:
+      switch (c_parser_peek_token (parser)->keyword)
+       {
+       case RID_EXTENSION:
+         ext = disable_extension_diagnostics ();
+         c_parser_consume_token (parser);
+         c_parser_external_declaration (parser);
+         restore_extension_diagnostics (ext);
+         break;
+       case RID_ASM:
+         c_parser_asm_definition (parser);
+         break;
+       case RID_AT_INTERFACE:
+       case RID_AT_IMPLEMENTATION:
+         gcc_assert (c_dialect_objc ());
+         c_parser_objc_class_definition (parser, NULL_TREE);
+         break;
+       case RID_AT_CLASS:
+         gcc_assert (c_dialect_objc ());
+         c_parser_objc_class_declaration (parser);
+         break;
+       case RID_AT_ALIAS:
+         gcc_assert (c_dialect_objc ());
+         c_parser_objc_alias_declaration (parser);
+         break;
+       case RID_AT_PROTOCOL:
+         gcc_assert (c_dialect_objc ());
+         c_parser_objc_protocol_definition (parser, NULL_TREE);
+         break;
+       case RID_AT_PROPERTY:
+         gcc_assert (c_dialect_objc ());
+         c_parser_objc_at_property_declaration (parser);
+         break;
+       case RID_AT_SYNTHESIZE:
+         gcc_assert (c_dialect_objc ());
+         c_parser_objc_at_synthesize_declaration (parser);
+         break;
+       case RID_AT_DYNAMIC:
+         gcc_assert (c_dialect_objc ());
+         c_parser_objc_at_dynamic_declaration (parser);
+         break;
+       case RID_AT_END:
+         gcc_assert (c_dialect_objc ());
+         c_parser_consume_token (parser);
+         objc_finish_implementation ();
+         break;
+       default:
+         goto decl_or_fndef;
+       }
+      break;
+    case CPP_SEMICOLON:
+      pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic,
+              "ISO C does not allow extra %<;%> outside of a function");
+      c_parser_consume_token (parser);
+      break;
+    case CPP_PRAGMA:
+      mark_valid_location_for_stdc_pragma (true);
+      c_parser_pragma (parser, pragma_external);
+      mark_valid_location_for_stdc_pragma (false);
+      break;
+    case CPP_PLUS:
+    case CPP_MINUS:
+      if (c_dialect_objc ())
+       {
+         c_parser_objc_method_definition (parser);
+         break;
+       }
+      /* Else fall through, and yield a syntax error trying to parse
+        as a declaration or function definition.  */
+    default:
+    decl_or_fndef:
+      /* A declaration or a function definition (or, in Objective-C,
+        an @interface or @protocol with prefix attributes).  We can
+        only tell which after parsing the declaration specifiers, if
+        any, and the first declarator.  */
+      c_parser_declaration_or_fndef (parser, true, true, true, false, true, NULL);
+      break;
+    }
+}
+
+/* Parse a declaration or function definition (C90 6.5, 6.7.1, C99
+   6.7, 6.9.1).  If FNDEF_OK is true, a function definition is
+   accepted; otherwise (old-style parameter declarations) only other
+   declarations are accepted.  If STATIC_ASSERT_OK is true, a static
+   assertion is accepted; otherwise (old-style parameter declarations)
+   it is not.  If NESTED is true, we are inside a function or parsing
+   old-style parameter declarations; any functions encountered are
+   nested functions and declaration specifiers are required; otherwise
+   we are at top level and functions are normal functions and
+   declaration specifiers may be optional.  If EMPTY_OK is true, empty
+   declarations are OK (subject to all other constraints); otherwise
+   (old-style parameter declarations) they are diagnosed.  If
+   START_ATTR_OK is true, the declaration specifiers may start with
+   attributes; otherwise they may not.
+   OBJC_FOREACH_OBJECT_DECLARATION can be used to get back the parsed
+   declaration when parsing an Objective-C foreach statement.
+
+   declaration:
+     declaration-specifiers init-declarator-list[opt] ;
+     static_assert-declaration
+
+   function-definition:
+     declaration-specifiers[opt] declarator declaration-list[opt]
+       compound-statement
+
+   declaration-list:
+     declaration
+     declaration-list declaration
+
+   init-declarator-list:
+     init-declarator
+     init-declarator-list , init-declarator
+
+   init-declarator:
+     declarator simple-asm-expr[opt] attributes[opt]
+     declarator simple-asm-expr[opt] attributes[opt] = initializer
+
+   GNU extensions:
+
+   nested-function-definition:
+     declaration-specifiers declarator declaration-list[opt]
+       compound-statement
+
+   Objective-C:
+     attributes objc-class-definition
+     attributes objc-category-definition
+     attributes objc-protocol-definition
+
+   The simple-asm-expr and attributes are GNU extensions.
+
+   This function does not handle __extension__; that is handled in its
+   callers.  ??? Following the old parser, __extension__ may start
+   external declarations, declarations in functions and declarations
+   at the start of "for" loops, but not old-style parameter
+   declarations.
+
+   C99 requires declaration specifiers in a function definition; the
+   absence is diagnosed through the diagnosis of implicit int.  In GNU
+   C we also allow but diagnose declarations without declaration
+   specifiers, but only at top level (elsewhere they conflict with
+   other syntax).
+
+   In Objective-C, declarations of the looping variable in a foreach
+   statement are exceptionally terminated by 'in' (for example, 'for
+   (NSObject *object in array) { ... }').
+
+   OpenMP:
+
+   declaration:
+     threadprivate-directive  */
+
+static void
+c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
+                              bool static_assert_ok, bool empty_ok,
+                              bool nested, bool start_attr_ok,
+                              tree *objc_foreach_object_declaration)
+{
+  struct c_declspecs *specs;
+  tree prefix_attrs;
+  tree all_prefix_attrs;
+  bool diagnosed_no_specs = false;
+  location_t here = c_parser_peek_token (parser)->location;
+
+  if (static_assert_ok
+      && c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT))
+    {
+      c_parser_static_assert_declaration (parser);
+      return;
+    }
+  specs = build_null_declspecs ();
+
+  /* Try to detect an unknown type name when we have "A B" or "A *B".  */
+  if (c_parser_peek_token (parser)->type == CPP_NAME
+      && c_parser_peek_token (parser)->id_kind == C_ID_ID
+      && (c_parser_peek_2nd_token (parser)->type == CPP_NAME
+          || c_parser_peek_2nd_token (parser)->type == CPP_MULT)
+      && (!nested || !lookup_name (c_parser_peek_token (parser)->value)))
+    {
+      error_at (here, "unknown type name %qE",
+                c_parser_peek_token (parser)->value);
+
+      /* Parse declspecs normally to get a correct pointer type, but avoid
+         a further "fails to be a type name" error.  Refuse nested functions
+         since it is not how the user likely wants us to recover.  */
+      c_parser_peek_token (parser)->type = CPP_KEYWORD;
+      c_parser_peek_token (parser)->keyword = RID_VOID;
+      c_parser_peek_token (parser)->value = error_mark_node;
+      fndef_ok = !nested;
+    }
+
+  c_parser_declspecs (parser, specs, true, true, start_attr_ok, cla_nonabstract_decl);
+  if (parser->error)
+    {
+      c_parser_skip_to_end_of_block_or_statement (parser);
+      return;
+    }
+  if (nested && !specs->declspecs_seen_p)
+    {
+      c_parser_error (parser, "expected declaration specifiers");
+      c_parser_skip_to_end_of_block_or_statement (parser);
+      return;
+    }
+  finish_declspecs (specs);
+  if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+    {
+      if (empty_ok)
+       shadow_tag (specs);
+      else
+       {
+         shadow_tag_warned (specs, 1);
+         pedwarn (here, 0, "empty declaration");
+       }
+      c_parser_consume_token (parser);
+      return;
+    }
+
+  /* Provide better error recovery.  Note that a type name here is usually
+     better diagnosed as a redeclaration.  */
+  if (empty_ok
+      && specs->typespec_kind == ctsk_tagdef
+      && c_parser_next_token_starts_declspecs (parser)
+      && !c_parser_next_token_is (parser, CPP_NAME))
+    {
+      c_parser_error (parser, "expected %<;%>, identifier or %<(%>");
+      parser->error = false;
+      shadow_tag_warned (specs, 1);
+      return;
+    }
+  else if (c_dialect_objc ())
+    {
+      /* Prefix attributes are an error on method decls.  */
+      switch (c_parser_peek_token (parser)->type)
+       {
+         case CPP_PLUS:
+         case CPP_MINUS:
+           if (c_parser_objc_diagnose_bad_element_prefix (parser, specs))
+             return;
+           if (specs->attrs)
+             {
+               warning_at (c_parser_peek_token (parser)->location, 
+                           OPT_Wattributes,
+                           "prefix attributes are ignored for methods");
+               specs->attrs = NULL_TREE;
+             }
+           if (fndef_ok)
+             c_parser_objc_method_definition (parser);
+           else
+             c_parser_objc_methodproto (parser);
+           return;
+           break;
+         default:
+           break;
+       }
+      /* This is where we parse 'attributes @interface ...',
+        'attributes @implementation ...', 'attributes @protocol ...'
+        (where attributes could be, for example, __attribute__
+        ((deprecated)).
+      */
+      switch (c_parser_peek_token (parser)->keyword)
+       {
+       case RID_AT_INTERFACE:
+         {
+           if (c_parser_objc_diagnose_bad_element_prefix (parser, specs))
+             return;
+           c_parser_objc_class_definition (parser, specs->attrs);
+           return;
+         }
+         break;
+       case RID_AT_IMPLEMENTATION:
+         {
+           if (c_parser_objc_diagnose_bad_element_prefix (parser, specs))
+             return;
+           if (specs->attrs)
+             {
+               warning_at (c_parser_peek_token (parser)->location, 
+                       OPT_Wattributes,
+                       "prefix attributes are ignored for implementations");
+               specs->attrs = NULL_TREE;
+             }
+           c_parser_objc_class_definition (parser, NULL_TREE);     
+           return;
+         }
+         break;
+       case RID_AT_PROTOCOL:
+         {
+           if (c_parser_objc_diagnose_bad_element_prefix (parser, specs))
+             return;
+           c_parser_objc_protocol_definition (parser, specs->attrs);
+           return;
+         }
+         break;
+       case RID_AT_ALIAS:
+       case RID_AT_CLASS:
+       case RID_AT_END:
+       case RID_AT_PROPERTY:
+         if (specs->attrs)
+           {
+             c_parser_error (parser, "unexpected attribute");
+             specs->attrs = NULL;
+           }
+         break;
+       default:
+         break;
+       }
+    }
+  
+  pending_xref_error ();
+  prefix_attrs = specs->attrs;
+  all_prefix_attrs = prefix_attrs;
+  specs->attrs = NULL_TREE;
+  while (true)
+    {
+      struct c_declarator *declarator;
+      bool dummy = false;
+      timevar_id_t tv;
+      tree fnbody;
+      /* Declaring either one or more declarators (in which case we
+        should diagnose if there were no declaration specifiers) or a
+        function definition (in which case the diagnostic for
+        implicit int suffices).  */
+      declarator = c_parser_declarator (parser, 
+                                       specs->typespec_kind != ctsk_none,
+                                       C_DTR_NORMAL, &dummy);
+      if (declarator == NULL)
+       {
+         c_parser_skip_to_end_of_block_or_statement (parser);
+         return;
+       }
+      if (c_parser_next_token_is (parser, CPP_EQ)
+         || c_parser_next_token_is (parser, CPP_COMMA)
+         || c_parser_next_token_is (parser, CPP_SEMICOLON)
+         || c_parser_next_token_is_keyword (parser, RID_ASM)
+         || c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE)
+         || c_parser_next_token_is_keyword (parser, RID_IN))
+       {
+         tree asm_name = NULL_TREE;
+         tree postfix_attrs = NULL_TREE;
+         if (!diagnosed_no_specs && !specs->declspecs_seen_p)
+           {
+             diagnosed_no_specs = true;
+             pedwarn (here, 0, "data definition has no type or storage class");
+           }
+         /* Having seen a data definition, there cannot now be a
+            function definition.  */
+         fndef_ok = false;
+         if (c_parser_next_token_is_keyword (parser, RID_ASM))
+           asm_name = c_parser_simple_asm_expr (parser);
+         if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
+           postfix_attrs = c_parser_attributes (parser);
+         if (c_parser_next_token_is (parser, CPP_EQ))
+           {
+             tree d;
+             struct c_expr init;
+             location_t init_loc;
+             c_parser_consume_token (parser);
+             /* The declaration of the variable is in effect while
+                its initializer is parsed.  */
+             d = start_decl (declarator, specs, true,
+                             chainon (postfix_attrs, all_prefix_attrs));
+             if (!d)
+               d = error_mark_node;
+             start_init (d, asm_name, global_bindings_p ());
+             init_loc = c_parser_peek_token (parser)->location;
+             init = c_parser_initializer (parser);
+             finish_init ();
+             if (d != error_mark_node)
+               {
+                 maybe_warn_string_init (TREE_TYPE (d), init);
+                 finish_decl (d, init_loc, init.value,
+                              init.original_type, asm_name);
+               }
+           }
+         else
+           {
+             tree d = start_decl (declarator, specs, false,
+                                  chainon (postfix_attrs,
+                                           all_prefix_attrs));
+             if (d)
+               finish_decl (d, UNKNOWN_LOCATION, NULL_TREE,
+                            NULL_TREE, asm_name);
+             
+             if (c_parser_next_token_is_keyword (parser, RID_IN))
+               {
+                 if (d)
+                   *objc_foreach_object_declaration = d;
+                 else
+                   *objc_foreach_object_declaration = error_mark_node;             
+               }
+           }
+         if (c_parser_next_token_is (parser, CPP_COMMA))
+           {
+             c_parser_consume_token (parser);
+             if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
+               all_prefix_attrs = chainon (c_parser_attributes (parser),
+                                           prefix_attrs);
+             else
+               all_prefix_attrs = prefix_attrs;
+             continue;
+           }
+         else if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+           {
+             c_parser_consume_token (parser);
+             return;
+           }
+         else if (c_parser_next_token_is_keyword (parser, RID_IN))
+           {
+             /* This can only happen in Objective-C: we found the
+                'in' that terminates the declaration inside an
+                Objective-C foreach statement.  Do not consume the
+                token, so that the caller can use it to determine
+                that this indeed is a foreach context.  */
+             return;
+           }
+         else
+           {
+             c_parser_error (parser, "expected %<,%> or %<;%>");
+             c_parser_skip_to_end_of_block_or_statement (parser);
+             return;
+           }
+       }
+      else if (!fndef_ok)
+       {
+         c_parser_error (parser, "expected %<=%>, %<,%>, %<;%>, "
+                         "%<asm%> or %<__attribute__%>");
+         c_parser_skip_to_end_of_block_or_statement (parser);
+         return;
+       }
+      /* Function definition (nested or otherwise).  */
+      if (nested)
+       {
+         pedwarn (here, OPT_Wpedantic, "ISO C forbids nested functions");
+         c_push_function_context ();
+       }
+      if (!start_function (specs, declarator, all_prefix_attrs))
+       {
+         /* This can appear in many cases looking nothing like a
+            function definition, so we don't give a more specific
+            error suggesting there was one.  */
+         c_parser_error (parser, "expected %<=%>, %<,%>, %<;%>, %<asm%> "
+                         "or %<__attribute__%>");
+         if (nested)
+           c_pop_function_context ();
+         break;
+       }
+
+      if (DECL_DECLARED_INLINE_P (current_function_decl))
+        tv = TV_PARSE_INLINE;
+      else
+        tv = TV_PARSE_FUNC;
+      timevar_push (tv);
+
+      /* Parse old-style parameter declarations.  ??? Attributes are
+        not allowed to start declaration specifiers here because of a
+        syntax conflict between a function declaration with attribute
+        suffix and a function definition with an attribute prefix on
+        first old-style parameter declaration.  Following the old
+        parser, they are not accepted on subsequent old-style
+        parameter declarations either.  However, there is no
+        ambiguity after the first declaration, nor indeed on the
+        first as long as we don't allow postfix attributes after a
+        declarator with a nonempty identifier list in a definition;
+        and postfix attributes have never been accepted here in
+        function definitions either.  */
+      while (c_parser_next_token_is_not (parser, CPP_EOF)
+            && c_parser_next_token_is_not (parser, CPP_OPEN_BRACE))
+       c_parser_declaration_or_fndef (parser, false, false, false,
+                                      true, false, NULL);
+      store_parm_decls ();
+      DECL_STRUCT_FUNCTION (current_function_decl)->function_start_locus
+       = c_parser_peek_token (parser)->location;
+      fnbody = c_parser_compound_statement (parser);
+      if (nested)
+       {
+         tree decl = current_function_decl;
+         /* Mark nested functions as needing static-chain initially.
+            lower_nested_functions will recompute it but the
+            DECL_STATIC_CHAIN flag is also used before that happens,
+            by initializer_constant_valid_p.  See gcc.dg/nested-fn-2.c.  */
+         DECL_STATIC_CHAIN (decl) = 1;
+         add_stmt (fnbody);
+         finish_function ();
+         c_pop_function_context ();
+         add_stmt (build_stmt (DECL_SOURCE_LOCATION (decl), DECL_EXPR, decl));
+       }
+      else
+       {
+         add_stmt (fnbody);
+         finish_function ();
+       }
+
+      timevar_pop (tv);
+      break;
+    }
+}
+
+/* Parse an asm-definition (asm() outside a function body).  This is a
+   GNU extension.
+
+   asm-definition:
+     simple-asm-expr ;
+*/
+
+static void
+c_parser_asm_definition (c_parser *parser)
+{
+  tree asm_str = c_parser_simple_asm_expr (parser);
+  if (asm_str)
+    add_asm_node (asm_str);
+  c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+}
+
+/* Parse a static assertion (C11 6.7.10).
+
+   static_assert-declaration:
+     static_assert-declaration-no-semi ;
+*/
+
+static void
+c_parser_static_assert_declaration (c_parser *parser)
+{
+  c_parser_static_assert_declaration_no_semi (parser);
+  if (parser->error
+      || !c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
+    c_parser_skip_to_end_of_block_or_statement (parser);
+}
+
+/* Parse a static assertion (C11 6.7.10), without the trailing
+   semicolon.
+
+   static_assert-declaration-no-semi:
+     _Static_assert ( constant-expression , string-literal )
+*/
+
+static void
+c_parser_static_assert_declaration_no_semi (c_parser *parser)
+{
+  location_t assert_loc, value_loc;
+  tree value;
+  tree string;
+
+  gcc_assert (c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT));
+  assert_loc = c_parser_peek_token (parser)->location;
+  if (!flag_isoc11)
+    {
+      if (flag_isoc99)
+       pedwarn (assert_loc, OPT_Wpedantic,
+                "ISO C99 does not support %<_Static_assert%>");
+      else
+       pedwarn (assert_loc, OPT_Wpedantic,
+                "ISO C90 does not support %<_Static_assert%>");
+    }
+  c_parser_consume_token (parser);
+  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+    return;
+  value_loc = c_parser_peek_token (parser)->location;
+  value = c_parser_expr_no_commas (parser, NULL).value;
+  parser->lex_untranslated_string = true;
+  if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
+    {
+      parser->lex_untranslated_string = false;
+      return;
+    }
+  switch (c_parser_peek_token (parser)->type)
+    {
+    case CPP_STRING:
+    case CPP_STRING16:
+    case CPP_STRING32:
+    case CPP_WSTRING:
+    case CPP_UTF8STRING:
+      string = c_parser_peek_token (parser)->value;
+      c_parser_consume_token (parser);
+      parser->lex_untranslated_string = false;
+      break;
+    default:
+      c_parser_error (parser, "expected string literal");
+      parser->lex_untranslated_string = false;
+      return;
+    }
+  c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+
+  if (!INTEGRAL_TYPE_P (TREE_TYPE (value)))
+    {
+      error_at (value_loc, "expression in static assertion is not an integer");
+      return;
+    }
+  if (TREE_CODE (value) != INTEGER_CST)
+    {
+      value = c_fully_fold (value, false, NULL);
+      if (TREE_CODE (value) == INTEGER_CST)
+       pedwarn (value_loc, OPT_Wpedantic, "expression in static assertion "
+                "is not an integer constant expression");
+    }
+  if (TREE_CODE (value) != INTEGER_CST)
+    {
+      error_at (value_loc, "expression in static assertion is not constant");
+      return;
+    }
+  constant_expression_warning (value);
+  if (integer_zerop (value))
+    error_at (assert_loc, "static assertion failed: %E", string);
+}
+
+/* Parse some declaration specifiers (possibly none) (C90 6.5, C99
+   6.7), adding them to SPECS (which may already include some).
+   Storage class specifiers are accepted iff SCSPEC_OK; type
+   specifiers are accepted iff TYPESPEC_OK; attributes are accepted at
+   the start iff START_ATTR_OK.
+
+   declaration-specifiers:
+     storage-class-specifier declaration-specifiers[opt]
+     type-specifier declaration-specifiers[opt]
+     type-qualifier declaration-specifiers[opt]
+     function-specifier declaration-specifiers[opt]
+     alignment-specifier declaration-specifiers[opt]
+
+   Function specifiers (inline) are from C99, and are currently
+   handled as storage class specifiers, as is __thread.  Alignment
+   specifiers are from C11.
+
+   C90 6.5.1, C99 6.7.1:
+   storage-class-specifier:
+     typedef
+     extern
+     static
+     auto
+     register
+
+   C99 6.7.4:
+   function-specifier:
+     inline
+     _Noreturn
+
+   (_Noreturn is new in C11.)
+
+   C90 6.5.2, C99 6.7.2:
+   type-specifier:
+     void
+     char
+     short
+     int
+     long
+     float
+     double
+     signed
+     unsigned
+     _Bool
+     _Complex
+     [_Imaginary removed in C99 TC2]
+     struct-or-union-specifier
+     enum-specifier
+     typedef-name
+
+   (_Bool and _Complex are new in C99.)
+
+   C90 6.5.3, C99 6.7.3:
+
+   type-qualifier:
+     const
+     restrict
+     volatile
+     address-space-qualifier
+
+   (restrict is new in C99.)
+
+   GNU extensions:
+
+   declaration-specifiers:
+     attributes declaration-specifiers[opt]
+
+   type-qualifier:
+     address-space
+
+   address-space:
+     identifier recognized by the target
+
+   storage-class-specifier:
+     __thread
+
+   type-specifier:
+     typeof-specifier
+     __int128
+     _Decimal32
+     _Decimal64
+     _Decimal128
+     _Fract
+     _Accum
+     _Sat
+
+  (_Fract, _Accum, and _Sat are new from ISO/IEC DTR 18037:
+   http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1169.pdf)
+
+   Objective-C:
+
+   type-specifier:
+     class-name objc-protocol-refs[opt]
+     typedef-name objc-protocol-refs
+     objc-protocol-refs
+*/
+
+static void
+c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
+                   bool scspec_ok, bool typespec_ok, bool start_attr_ok,
+                   enum c_lookahead_kind la)
+{
+  bool attrs_ok = start_attr_ok;
+  bool seen_type = specs->typespec_kind != ctsk_none;
+
+  if (!typespec_ok)
+    gcc_assert (la == cla_prefer_id);
+
+  while (c_parser_next_token_is (parser, CPP_NAME)
+        || c_parser_next_token_is (parser, CPP_KEYWORD)
+        || (c_dialect_objc () && c_parser_next_token_is (parser, CPP_LESS)))
+    {
+      struct c_typespec t;
+      tree attrs;
+      tree align;
+      location_t loc = c_parser_peek_token (parser)->location;
+
+      /* If we cannot accept a type, exit if the next token must start
+        one.  Also, if we already have seen a tagged definition,
+        a typename would be an error anyway and likely the user
+        has simply forgotten a semicolon, so we exit.  */
+      if ((!typespec_ok || specs->typespec_kind == ctsk_tagdef)
+         && c_parser_next_tokens_start_typename (parser, la)
+         && !c_parser_next_token_is_qualifier (parser))
+       break;
+
+      if (c_parser_next_token_is (parser, CPP_NAME))
+       {
+         c_token *name_token = c_parser_peek_token (parser);
+         tree value = name_token->value;
+         c_id_kind kind = name_token->id_kind;
+
+         if (kind == C_ID_ADDRSPACE)
+           {
+             addr_space_t as
+               = name_token->keyword - RID_FIRST_ADDR_SPACE;
+             declspecs_add_addrspace (name_token->location, specs, as);
+             c_parser_consume_token (parser);
+             attrs_ok = true;
+             continue;
+           }
+
+         gcc_assert (!c_parser_next_token_is_qualifier (parser));
+
+         /* If we cannot accept a type, and the next token must start one,
+            exit.  Do the same if we already have seen a tagged definition,
+            since it would be an error anyway and likely the user has simply
+            forgotten a semicolon.  */
+         if (seen_type || !c_parser_next_tokens_start_typename (parser, la))
+           break;
+
+         /* Now at an unknown typename (C_ID_ID), a C_ID_TYPENAME or
+            a C_ID_CLASSNAME.  */
+         c_parser_consume_token (parser);
+         seen_type = true;
+         attrs_ok = true;
+         if (kind == C_ID_ID)
+           {
+             error ("unknown type name %qE", value);
+             t.kind = ctsk_typedef;
+             t.spec = error_mark_node;
+           }
+         else if (kind == C_ID_TYPENAME
+                  && (!c_dialect_objc ()
+                      || c_parser_next_token_is_not (parser, CPP_LESS)))
+           {
+             t.kind = ctsk_typedef;
+             /* For a typedef name, record the meaning, not the name.
+                In case of 'foo foo, bar;'.  */
+             t.spec = lookup_name (value);
+           }
+         else
+           {
+             tree proto = NULL_TREE;
+             gcc_assert (c_dialect_objc ());
+             t.kind = ctsk_objc;
+             if (c_parser_next_token_is (parser, CPP_LESS))
+               proto = c_parser_objc_protocol_refs (parser);
+             t.spec = objc_get_protocol_qualified_type (value, proto);
+           }
+         t.expr = NULL_TREE;
+         t.expr_const_operands = true;
+         declspecs_add_type (name_token->location, specs, t);
+         continue;
+       }
+      if (c_parser_next_token_is (parser, CPP_LESS))
+       {
+         /* Make "<SomeProtocol>" equivalent to "id <SomeProtocol>" -
+            nisse@lysator.liu.se.  */
+         tree proto;
+         gcc_assert (c_dialect_objc ());
+         if (!typespec_ok || seen_type)
+           break;
+         proto = c_parser_objc_protocol_refs (parser);
+         t.kind = ctsk_objc;
+         t.spec = objc_get_protocol_qualified_type (NULL_TREE, proto);
+         t.expr = NULL_TREE;
+         t.expr_const_operands = true;
+         declspecs_add_type (loc, specs, t);
+         continue;
+       }
+      gcc_assert (c_parser_next_token_is (parser, CPP_KEYWORD));
+      switch (c_parser_peek_token (parser)->keyword)
+       {
+       case RID_STATIC:
+       case RID_EXTERN:
+       case RID_REGISTER:
+       case RID_TYPEDEF:
+       case RID_INLINE:
+       case RID_NORETURN:
+       case RID_AUTO:
+       case RID_THREAD:
+         if (!scspec_ok)
+           goto out;
+         attrs_ok = true;
+         /* TODO: Distinguish between function specifiers (inline, noreturn)
+            and storage class specifiers, either here or in
+            declspecs_add_scspec.  */
+         declspecs_add_scspec (loc, specs,
+                               c_parser_peek_token (parser)->value);
+         c_parser_consume_token (parser);
+         break;
+       case RID_UNSIGNED:
+       case RID_LONG:
+       case RID_INT128:
+       case RID_SHORT:
+       case RID_SIGNED:
+       case RID_COMPLEX:
+       case RID_INT:
+       case RID_CHAR:
+       case RID_FLOAT:
+       case RID_DOUBLE:
+       case RID_VOID:
+       case RID_DFLOAT32:
+       case RID_DFLOAT64:
+       case RID_DFLOAT128:
+       case RID_BOOL:
+       case RID_FRACT:
+       case RID_ACCUM:
+       case RID_SAT:
+         if (!typespec_ok)
+           goto out;
+         attrs_ok = true;
+         seen_type = true;
+         if (c_dialect_objc ())
+           parser->objc_need_raw_identifier = true;
+         t.kind = ctsk_resword;
+         t.spec = c_parser_peek_token (parser)->value;
+         t.expr = NULL_TREE;
+         t.expr_const_operands = true;
+         declspecs_add_type (loc, specs, t);
+         c_parser_consume_token (parser);
+         break;
+       case RID_ENUM:
+         if (!typespec_ok)
+           goto out;
+         attrs_ok = true;
+         seen_type = true;
+         t = c_parser_enum_specifier (parser);
+         declspecs_add_type (loc, specs, t);
+         break;
+       case RID_STRUCT:
+       case RID_UNION:
+         if (!typespec_ok)
+           goto out;
+         attrs_ok = true;
+         seen_type = true;
+         t = c_parser_struct_or_union_specifier (parser);
+          invoke_plugin_callbacks (PLUGIN_FINISH_TYPE, t.spec);
+         declspecs_add_type (loc, specs, t);
+         break;
+       case RID_TYPEOF:
+         /* ??? The old parser rejected typeof after other type
+            specifiers, but is a syntax error the best way of
+            handling this?  */
+         if (!typespec_ok || seen_type)
+           goto out;
+         attrs_ok = true;
+         seen_type = true;
+         t = c_parser_typeof_specifier (parser);
+         declspecs_add_type (loc, specs, t);
+         break;
+       case RID_CONST:
+       case RID_VOLATILE:
+       case RID_RESTRICT:
+         attrs_ok = true;
+         declspecs_add_qual (loc, specs, c_parser_peek_token (parser)->value);
+         c_parser_consume_token (parser);
+         break;
+       case RID_ATTRIBUTE:
+         if (!attrs_ok)
+           goto out;
+         attrs = c_parser_attributes (parser);
+         declspecs_add_attrs (loc, specs, attrs);
+         break;
+       case RID_ALIGNAS:
+         align = c_parser_alignas_specifier (parser);
+         declspecs_add_alignas (loc, specs, align);
+         break;
+       default:
+         goto out;
+       }
+    }
+ out: ;
+}
+
+/* Parse an enum specifier (C90 6.5.2.2, C99 6.7.2.2).
+
+   enum-specifier:
+     enum attributes[opt] identifier[opt] { enumerator-list } attributes[opt]
+     enum attributes[opt] identifier[opt] { enumerator-list , } attributes[opt]
+     enum attributes[opt] identifier
+
+   The form with trailing comma is new in C99.  The forms with
+   attributes are GNU extensions.  In GNU C, we accept any expression
+   without commas in the syntax (assignment expressions, not just
+   conditional expressions); assignment expressions will be diagnosed
+   as non-constant.
+
+   enumerator-list:
+     enumerator
+     enumerator-list , enumerator
+
+   enumerator:
+     enumeration-constant
+     enumeration-constant = constant-expression
+*/
+
+static struct c_typespec
+c_parser_enum_specifier (c_parser *parser)
+{
+  struct c_typespec ret;
+  tree attrs;
+  tree ident = NULL_TREE;
+  location_t enum_loc;
+  location_t ident_loc = UNKNOWN_LOCATION;  /* Quiet warning.  */
+  gcc_assert (c_parser_next_token_is_keyword (parser, RID_ENUM));
+  enum_loc = c_parser_peek_token (parser)->location;
+  c_parser_consume_token (parser);
+  attrs = c_parser_attributes (parser);
+  enum_loc = c_parser_peek_token (parser)->location;
+  /* Set the location in case we create a decl now.  */
+  c_parser_set_source_position_from_token (c_parser_peek_token (parser));
+  if (c_parser_next_token_is (parser, CPP_NAME))
+    {
+      ident = c_parser_peek_token (parser)->value;
+      ident_loc = c_parser_peek_token (parser)->location;
+      enum_loc = ident_loc;
+      c_parser_consume_token (parser);
+    }
+  if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
+    {
+      /* Parse an enum definition.  */
+      struct c_enum_contents the_enum;
+      tree type;
+      tree postfix_attrs;
+      /* We chain the enumerators in reverse order, then put them in
+        forward order at the end.  */
+      tree values;
+      timevar_push (TV_PARSE_ENUM);
+      type = start_enum (enum_loc, &the_enum, ident);
+      values = NULL_TREE;
+      c_parser_consume_token (parser);
+      while (true)
+       {
+         tree enum_id;
+         tree enum_value;
+         tree enum_decl;
+         bool seen_comma;
+         c_token *token;
+         location_t comma_loc = UNKNOWN_LOCATION;  /* Quiet warning.  */
+         location_t decl_loc, value_loc;
+         if (c_parser_next_token_is_not (parser, CPP_NAME))
+           {
+             c_parser_error (parser, "expected identifier");
+             c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
+             values = error_mark_node;
+             break;
+           }
+         token = c_parser_peek_token (parser);
+         enum_id = token->value;
+         /* Set the location in case we create a decl now.  */
+         c_parser_set_source_position_from_token (token);
+         decl_loc = value_loc = token->location;
+         c_parser_consume_token (parser);
+         if (c_parser_next_token_is (parser, CPP_EQ))
+           {
+             c_parser_consume_token (parser);
+             value_loc = c_parser_peek_token (parser)->location;
+             enum_value = c_parser_expr_no_commas (parser, NULL).value;
+           }
+         else
+           enum_value = NULL_TREE;
+         enum_decl = build_enumerator (decl_loc, value_loc,
+                                       &the_enum, enum_id, enum_value);
+         TREE_CHAIN (enum_decl) = values;
+         values = enum_decl;
+         seen_comma = false;
+         if (c_parser_next_token_is (parser, CPP_COMMA))
+           {
+             comma_loc = c_parser_peek_token (parser)->location;
+             seen_comma = true;
+             c_parser_consume_token (parser);
+           }
+         if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
+           {
+             if (seen_comma && !flag_isoc99)
+               pedwarn (comma_loc, OPT_Wpedantic, "comma at end of enumerator list");
+             c_parser_consume_token (parser);
+             break;
+           }
+         if (!seen_comma)
+           {
+             c_parser_error (parser, "expected %<,%> or %<}%>");
+             c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
+             values = error_mark_node;
+             break;
+           }
+       }
+      postfix_attrs = c_parser_attributes (parser);
+      ret.spec = finish_enum (type, nreverse (values),
+                             chainon (attrs, postfix_attrs));
+      ret.kind = ctsk_tagdef;
+      ret.expr = NULL_TREE;
+      ret.expr_const_operands = true;
+      timevar_pop (TV_PARSE_ENUM);
+      return ret;
+    }
+  else if (!ident)
+    {
+      c_parser_error (parser, "expected %<{%>");
+      ret.spec = error_mark_node;
+      ret.kind = ctsk_tagref;
+      ret.expr = NULL_TREE;
+      ret.expr_const_operands = true;
+      return ret;
+    }
+  ret = parser_xref_tag (ident_loc, ENUMERAL_TYPE, ident);
+  /* In ISO C, enumerated types can be referred to only if already
+     defined.  */
+  if (pedantic && !COMPLETE_TYPE_P (ret.spec))
+    {
+      gcc_assert (ident);
+      pedwarn (enum_loc, OPT_Wpedantic,
+              "ISO C forbids forward references to %<enum%> types");
+    }
+  return ret;
+}
+
+/* Parse a struct or union specifier (C90 6.5.2.1, C99 6.7.2.1).
+
+   struct-or-union-specifier:
+     struct-or-union attributes[opt] identifier[opt]
+       { struct-contents } attributes[opt]
+     struct-or-union attributes[opt] identifier
+
+   struct-contents:
+     struct-declaration-list
+
+   struct-declaration-list:
+     struct-declaration ;
+     struct-declaration-list struct-declaration ;
+
+   GNU extensions:
+
+   struct-contents:
+     empty
+     struct-declaration
+     struct-declaration-list struct-declaration
+
+   struct-declaration-list:
+     struct-declaration-list ;
+     ;
+
+   (Note that in the syntax here, unlike that in ISO C, the semicolons
+   are included here rather than in struct-declaration, in order to
+   describe the syntax with extra semicolons and missing semicolon at
+   end.)
+
+   Objective-C:
+
+   struct-declaration-list:
+     @defs ( class-name )
+
+   (Note this does not include a trailing semicolon, but can be
+   followed by further declarations, and gets a pedwarn-if-pedantic
+   when followed by a semicolon.)  */
+
+static struct c_typespec
+c_parser_struct_or_union_specifier (c_parser *parser)
+{
+  struct c_typespec ret;
+  tree attrs;
+  tree ident = NULL_TREE;
+  location_t struct_loc;
+  location_t ident_loc = UNKNOWN_LOCATION;
+  enum tree_code code;
+  switch (c_parser_peek_token (parser)->keyword)
+    {
+    case RID_STRUCT:
+      code = RECORD_TYPE;
+      break;
+    case RID_UNION:
+      code = UNION_TYPE;
+      break;
+    default:
+      gcc_unreachable ();
+    }
+  struct_loc = c_parser_peek_token (parser)->location;
+  c_parser_consume_token (parser);
+  attrs = c_parser_attributes (parser);
+
+  /* Set the location in case we create a decl now.  */
+  c_parser_set_source_position_from_token (c_parser_peek_token (parser));
+
+  if (c_parser_next_token_is (parser, CPP_NAME))
+    {
+      ident = c_parser_peek_token (parser)->value;
+      ident_loc = c_parser_peek_token (parser)->location;
+      struct_loc = ident_loc;
+      c_parser_consume_token (parser);
+    }
+  if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
+    {
+      /* Parse a struct or union definition.  Start the scope of the
+        tag before parsing components.  */
+      struct c_struct_parse_info *struct_info;
+      tree type = start_struct (struct_loc, code, ident, &struct_info);
+      tree postfix_attrs;
+      /* We chain the components in reverse order, then put them in
+        forward order at the end.  Each struct-declaration may
+        declare multiple components (comma-separated), so we must use
+        chainon to join them, although when parsing each
+        struct-declaration we can use TREE_CHAIN directly.
+
+        The theory behind all this is that there will be more
+        semicolon separated fields than comma separated fields, and
+        so we'll be minimizing the number of node traversals required
+        by chainon.  */
+      tree contents;
+      timevar_push (TV_PARSE_STRUCT);
+      contents = NULL_TREE;
+      c_parser_consume_token (parser);
+      /* Handle the Objective-C @defs construct,
+        e.g. foo(sizeof(struct{ @defs(ClassName) }));.  */
+      if (c_parser_next_token_is_keyword (parser, RID_AT_DEFS))
+       {
+         tree name;
+         gcc_assert (c_dialect_objc ());
+         c_parser_consume_token (parser);
+         if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+           goto end_at_defs;
+         if (c_parser_next_token_is (parser, CPP_NAME)
+             && c_parser_peek_token (parser)->id_kind == C_ID_CLASSNAME)
+           {
+             name = c_parser_peek_token (parser)->value;
+             c_parser_consume_token (parser);
+           }
+         else
+           {
+             c_parser_error (parser, "expected class name");
+             c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+             goto end_at_defs;
+           }
+         c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+                                    "expected %<)%>");
+         contents = nreverse (objc_get_class_ivars (name));
+       }
+    end_at_defs:
+      /* Parse the struct-declarations and semicolons.  Problems with
+        semicolons are diagnosed here; empty structures are diagnosed
+        elsewhere.  */
+      while (true)
+       {
+         tree decls;
+         /* Parse any stray semicolon.  */
+         if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+           {
+             pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic,
+                      "extra semicolon in struct or union specified");
+             c_parser_consume_token (parser);
+             continue;
+           }
+         /* Stop if at the end of the struct or union contents.  */
+         if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
+           {
+             c_parser_consume_token (parser);
+             break;
+           }
+         /* Accept #pragmas at struct scope.  */
+         if (c_parser_next_token_is (parser, CPP_PRAGMA))
+           {
+             c_parser_pragma (parser, pragma_external);
+             continue;
+           }
+         /* Parse some comma-separated declarations, but not the
+            trailing semicolon if any.  */
+         decls = c_parser_struct_declaration (parser);
+         contents = chainon (decls, contents);
+         /* If no semicolon follows, either we have a parse error or
+            are at the end of the struct or union and should
+            pedwarn.  */
+         if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+           c_parser_consume_token (parser);
+         else
+           {
+             if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
+               pedwarn (c_parser_peek_token (parser)->location, 0,
+                        "no semicolon at end of struct or union");
+             else if (parser->error
+                      || !c_parser_next_token_starts_declspecs (parser))
+               {
+                 c_parser_error (parser, "expected %<;%>");
+                 c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
+                 break;
+               }
+
+             /* If we come here, we have already emitted an error
+                for an expected `;', identifier or `(', and we also
+                recovered already.  Go on with the next field. */
+           }
+       }
+      postfix_attrs = c_parser_attributes (parser);
+      ret.spec = finish_struct (struct_loc, type, nreverse (contents),
+                               chainon (attrs, postfix_attrs), struct_info);
+      ret.kind = ctsk_tagdef;
+      ret.expr = NULL_TREE;
+      ret.expr_const_operands = true;
+      timevar_pop (TV_PARSE_STRUCT);
+      return ret;
+    }
+  else if (!ident)
+    {
+      c_parser_error (parser, "expected %<{%>");
+      ret.spec = error_mark_node;
+      ret.kind = ctsk_tagref;
+      ret.expr = NULL_TREE;
+      ret.expr_const_operands = true;
+      return ret;
+    }
+  ret = parser_xref_tag (ident_loc, code, ident);
+  return ret;
+}
+
+/* Parse a struct-declaration (C90 6.5.2.1, C99 6.7.2.1), *without*
+   the trailing semicolon.
+
+   struct-declaration:
+     specifier-qualifier-list struct-declarator-list
+     static_assert-declaration-no-semi
+
+   specifier-qualifier-list:
+     type-specifier specifier-qualifier-list[opt]
+     type-qualifier specifier-qualifier-list[opt]
+     attributes specifier-qualifier-list[opt]
+
+   struct-declarator-list:
+     struct-declarator
+     struct-declarator-list , attributes[opt] struct-declarator
+
+   struct-declarator:
+     declarator attributes[opt]
+     declarator[opt] : constant-expression attributes[opt]
+
+   GNU extensions:
+
+   struct-declaration:
+     __extension__ struct-declaration
+     specifier-qualifier-list
+
+   Unlike the ISO C syntax, semicolons are handled elsewhere.  The use
+   of attributes where shown is a GNU extension.  In GNU C, we accept
+   any expression without commas in the syntax (assignment
+   expressions, not just conditional expressions); assignment
+   expressions will be diagnosed as non-constant.  */
+
+static tree
+c_parser_struct_declaration (c_parser *parser)
+{
+  struct c_declspecs *specs;
+  tree prefix_attrs;
+  tree all_prefix_attrs;
+  tree decls;
+  location_t decl_loc;
+  if (c_parser_next_token_is_keyword (parser, RID_EXTENSION))
+    {
+      int ext;
+      tree decl;
+      ext = disable_extension_diagnostics ();
+      c_parser_consume_token (parser);
+      decl = c_parser_struct_declaration (parser);
+      restore_extension_diagnostics (ext);
+      return decl;
+    }
+  if (c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT))
+    {
+      c_parser_static_assert_declaration_no_semi (parser);
+      return NULL_TREE;
+    }
+  specs = build_null_declspecs ();
+  decl_loc = c_parser_peek_token (parser)->location;
+  c_parser_declspecs (parser, specs, false, true, true, cla_nonabstract_decl);
+  if (parser->error)
+    return NULL_TREE;
+  if (!specs->declspecs_seen_p)
+    {
+      c_parser_error (parser, "expected specifier-qualifier-list");
+      return NULL_TREE;
+    }
+  finish_declspecs (specs);
+  if (c_parser_next_token_is (parser, CPP_SEMICOLON)
+      || c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
+    {
+      tree ret;
+      if (specs->typespec_kind == ctsk_none)
+       {
+         pedwarn (decl_loc, OPT_Wpedantic,
+                  "ISO C forbids member declarations with no members");
+         shadow_tag_warned (specs, pedantic);
+         ret = NULL_TREE;
+       }
+      else
+       {
+         /* Support for unnamed structs or unions as members of
+            structs or unions (which is [a] useful and [b] supports
+            MS P-SDK).  */
+         tree attrs = NULL;
+
+         ret = grokfield (c_parser_peek_token (parser)->location,
+                          build_id_declarator (NULL_TREE), specs,
+                          NULL_TREE, &attrs);
+         if (ret)
+           decl_attributes (&ret, attrs, 0);
+       }
+      return ret;
+    }
+
+  /* Provide better error recovery.  Note that a type name here is valid,
+     and will be treated as a field name.  */
+  if (specs->typespec_kind == ctsk_tagdef
+      && TREE_CODE (specs->type) != ENUMERAL_TYPE
+      && c_parser_next_token_starts_declspecs (parser)
+      && !c_parser_next_token_is (parser, CPP_NAME))
+    {
+      c_parser_error (parser, "expected %<;%>, identifier or %<(%>");
+      parser->error = false;
+      return NULL_TREE;
+    }
+
+  pending_xref_error ();
+  prefix_attrs = specs->attrs;
+  all_prefix_attrs = prefix_attrs;
+  specs->attrs = NULL_TREE;
+  decls = NULL_TREE;
+  while (true)
+    {
+      /* Declaring one or more declarators or un-named bit-fields.  */
+      struct c_declarator *declarator;
+      bool dummy = false;
+      if (c_parser_next_token_is (parser, CPP_COLON))
+       declarator = build_id_declarator (NULL_TREE);
+      else
+       declarator = c_parser_declarator (parser,
+                                         specs->typespec_kind != ctsk_none,
+                                         C_DTR_NORMAL, &dummy);
+      if (declarator == NULL)
+       {
+         c_parser_skip_to_end_of_block_or_statement (parser);
+         break;
+       }
+      if (c_parser_next_token_is (parser, CPP_COLON)
+         || c_parser_next_token_is (parser, CPP_COMMA)
+         || c_parser_next_token_is (parser, CPP_SEMICOLON)
+         || c_parser_next_token_is (parser, CPP_CLOSE_BRACE)
+         || c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
+       {
+         tree postfix_attrs = NULL_TREE;
+         tree width = NULL_TREE;
+         tree d;
+         if (c_parser_next_token_is (parser, CPP_COLON))
+           {
+             c_parser_consume_token (parser);
+             width = c_parser_expr_no_commas (parser, NULL).value;
+           }
+         if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
+           postfix_attrs = c_parser_attributes (parser);
+         d = grokfield (c_parser_peek_token (parser)->location,
+                        declarator, specs, width, &all_prefix_attrs);
+         decl_attributes (&d, chainon (postfix_attrs,
+                                       all_prefix_attrs), 0);
+         DECL_CHAIN (d) = decls;
+         decls = d;
+         if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
+           all_prefix_attrs = chainon (c_parser_attributes (parser),
+                                       prefix_attrs);
+         else
+           all_prefix_attrs = prefix_attrs;
+         if (c_parser_next_token_is (parser, CPP_COMMA))
+           c_parser_consume_token (parser);
+         else if (c_parser_next_token_is (parser, CPP_SEMICOLON)
+                  || c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
+           {
+             /* Semicolon consumed in caller.  */
+             break;
+           }
+         else
+           {
+             c_parser_error (parser, "expected %<,%>, %<;%> or %<}%>");
+             break;
+           }
+       }
+      else
+       {
+         c_parser_error (parser,
+                         "expected %<:%>, %<,%>, %<;%>, %<}%> or "
+                         "%<__attribute__%>");
+         break;
+       }
+    }
+  return decls;
+}
+
+/* Parse a typeof specifier (a GNU extension).
+
+   typeof-specifier:
+     typeof ( expression )
+     typeof ( type-name )
+*/
+
+static struct c_typespec
+c_parser_typeof_specifier (c_parser *parser)
+{
+  struct c_typespec ret;
+  ret.kind = ctsk_typeof;
+  ret.spec = error_mark_node;
+  ret.expr = NULL_TREE;
+  ret.expr_const_operands = true;
+  gcc_assert (c_parser_next_token_is_keyword (parser, RID_TYPEOF));
+  c_parser_consume_token (parser);
+  c_inhibit_evaluation_warnings++;
+  in_typeof++;
+  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+    {
+      c_inhibit_evaluation_warnings--;
+      in_typeof--;
+      return ret;
+    }
+  if (c_parser_next_tokens_start_typename (parser, cla_prefer_id))
+    {
+      struct c_type_name *type = c_parser_type_name (parser);
+      c_inhibit_evaluation_warnings--;
+      in_typeof--;
+      if (type != NULL)
+       {
+         ret.spec = groktypename (type, &ret.expr, &ret.expr_const_operands);
+         pop_maybe_used (variably_modified_type_p (ret.spec, NULL_TREE));
+       }
+    }
+  else
+    {
+      bool was_vm;
+      location_t here = c_parser_peek_token (parser)->location;
+      struct c_expr expr = c_parser_expression (parser);
+      c_inhibit_evaluation_warnings--;
+      in_typeof--;
+      if (TREE_CODE (expr.value) == COMPONENT_REF
+         && DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1)))
+       error_at (here, "%<typeof%> applied to a bit-field");
+      mark_exp_read (expr.value);
+      ret.spec = TREE_TYPE (expr.value);
+      was_vm = variably_modified_type_p (ret.spec, NULL_TREE);
+      /* This is returned with the type so that when the type is
+        evaluated, this can be evaluated.  */
+      if (was_vm)
+       ret.expr = c_fully_fold (expr.value, false, &ret.expr_const_operands);
+      pop_maybe_used (was_vm);
+    }
+  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+  return ret;
+}
+
+/* Parse an alignment-specifier.
+
+   C11 6.7.5:
+
+   alignment-specifier:
+     _Alignas ( type-name )
+     _Alignas ( constant-expression )
+*/
+
+static tree
+c_parser_alignas_specifier (c_parser * parser)
+{
+  tree ret = error_mark_node;
+  location_t loc = c_parser_peek_token (parser)->location;
+  gcc_assert (c_parser_next_token_is_keyword (parser, RID_ALIGNAS));
+  c_parser_consume_token (parser);
+  if (!flag_isoc11)
+    {
+      if (flag_isoc99)
+       pedwarn (loc, OPT_Wpedantic,
+                "ISO C99 does not support %<_Alignas%>");
+      else
+       pedwarn (loc, OPT_Wpedantic,
+                "ISO C90 does not support %<_Alignas%>");
+    }
+  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+    return ret;
+  if (c_parser_next_tokens_start_typename (parser, cla_prefer_id))
+    {
+      struct c_type_name *type = c_parser_type_name (parser);
+      if (type != NULL)
+       ret = c_alignof (loc, groktypename (type, NULL, NULL));
+    }
+  else
+    ret = c_parser_expr_no_commas (parser, NULL).value;
+  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+  return ret;
+}
+
+/* Parse a declarator, possibly an abstract declarator (C90 6.5.4,
+   6.5.5, C99 6.7.5, 6.7.6).  If TYPE_SEEN_P then a typedef name may
+   be redeclared; otherwise it may not.  KIND indicates which kind of
+   declarator is wanted.  Returns a valid declarator except in the
+   case of a syntax error in which case NULL is returned.  *SEEN_ID is
+   set to true if an identifier being declared is seen; this is used
+   to diagnose bad forms of abstract array declarators and to
+   determine whether an identifier list is syntactically permitted.
+
+   declarator:
+     pointer[opt] direct-declarator
+
+   direct-declarator:
+     identifier
+     ( attributes[opt] declarator )
+     direct-declarator array-declarator
+     direct-declarator ( parameter-type-list )
+     direct-declarator ( identifier-list[opt] )
+
+   pointer:
+     * type-qualifier-list[opt]
+     * type-qualifier-list[opt] pointer
+
+   type-qualifier-list:
+     type-qualifier
+     attributes
+     type-qualifier-list type-qualifier
+     type-qualifier-list attributes
+
+   parameter-type-list:
+     parameter-list
+     parameter-list , ...
+
+   parameter-list:
+     parameter-declaration
+     parameter-list , parameter-declaration
+
+   parameter-declaration:
+     declaration-specifiers declarator attributes[opt]
+     declaration-specifiers abstract-declarator[opt] attributes[opt]
+
+   identifier-list:
+     identifier
+     identifier-list , identifier
+
+   abstract-declarator:
+     pointer
+     pointer[opt] direct-abstract-declarator
+
+   direct-abstract-declarator:
+     ( attributes[opt] abstract-declarator )
+     direct-abstract-declarator[opt] array-declarator
+     direct-abstract-declarator[opt] ( parameter-type-list[opt] )
+
+   GNU extensions:
+
+   direct-declarator:
+     direct-declarator ( parameter-forward-declarations
+                        parameter-type-list[opt] )
+
+   direct-abstract-declarator:
+     direct-abstract-declarator[opt] ( parameter-forward-declarations
+                                      parameter-type-list[opt] )
+
+   parameter-forward-declarations:
+     parameter-list ;
+     parameter-forward-declarations parameter-list ;
+
+   The uses of attributes shown above are GNU extensions.
+
+   Some forms of array declarator are not included in C99 in the
+   syntax for abstract declarators; these are disallowed elsewhere.
+   This may be a defect (DR#289).
+
+   This function also accepts an omitted abstract declarator as being
+   an abstract declarator, although not part of the formal syntax.  */
+
+static struct c_declarator *
+c_parser_declarator (c_parser *parser, bool type_seen_p, c_dtr_syn kind,
+                    bool *seen_id)
+{
+  /* Parse any initial pointer part.  */
+  if (c_parser_next_token_is (parser, CPP_MULT))
+    {
+      struct c_declspecs *quals_attrs = build_null_declspecs ();
+      struct c_declarator *inner;
+      c_parser_consume_token (parser);
+      c_parser_declspecs (parser, quals_attrs, false, false, true, cla_prefer_id);
+      inner = c_parser_declarator (parser, type_seen_p, kind, seen_id);
+      if (inner == NULL)
+       return NULL;
+      else
+       return make_pointer_declarator (quals_attrs, inner);
+    }
+  /* Now we have a direct declarator, direct abstract declarator or
+     nothing (which counts as a direct abstract declarator here).  */
+  return c_parser_direct_declarator (parser, type_seen_p, kind, seen_id);
+}
+
+/* Parse a direct declarator or direct abstract declarator; arguments
+   as c_parser_declarator.  */
+
+static struct c_declarator *
+c_parser_direct_declarator (c_parser *parser, bool type_seen_p, c_dtr_syn kind,
+                           bool *seen_id)
+{
+  /* The direct declarator must start with an identifier (possibly
+     omitted) or a parenthesized declarator (possibly abstract).  In
+     an ordinary declarator, initial parentheses must start a
+     parenthesized declarator.  In an abstract declarator or parameter
+     declarator, they could start a parenthesized declarator or a
+     parameter list.  To tell which, the open parenthesis and any
+     following attributes must be read.  If a declaration specifier
+     follows, then it is a parameter list; if the specifier is a
+     typedef name, there might be an ambiguity about redeclaring it,
+     which is resolved in the direction of treating it as a typedef
+     name.  If a close parenthesis follows, it is also an empty
+     parameter list, as the syntax does not permit empty abstract
+     declarators.  Otherwise, it is a parenthesized declarator (in
+     which case the analysis may be repeated inside it, recursively).
+
+     ??? There is an ambiguity in a parameter declaration "int
+     (__attribute__((foo)) x)", where x is not a typedef name: it
+     could be an abstract declarator for a function, or declare x with
+     parentheses.  The proper resolution of this ambiguity needs
+     documenting.  At present we follow an accident of the old
+     parser's implementation, whereby the first parameter must have
+     some declaration specifiers other than just attributes.  Thus as
+     a parameter declaration it is treated as a parenthesized
+     parameter named x, and as an abstract declarator it is
+     rejected.
+
+     ??? Also following the old parser, attributes inside an empty
+     parameter list are ignored, making it a list not yielding a
+     prototype, rather than giving an error or making it have one
+     parameter with implicit type int.
+
+     ??? Also following the old parser, typedef names may be
+     redeclared in declarators, but not Objective-C class names.  */
+
+  if (kind != C_DTR_ABSTRACT
+      && c_parser_next_token_is (parser, CPP_NAME)
+      && ((type_seen_p
+          && (c_parser_peek_token (parser)->id_kind == C_ID_TYPENAME
+              || c_parser_peek_token (parser)->id_kind == C_ID_CLASSNAME))
+         || c_parser_peek_token (parser)->id_kind == C_ID_ID))
+    {
+      struct c_declarator *inner
+       = build_id_declarator (c_parser_peek_token (parser)->value);
+      *seen_id = true;
+      inner->id_loc = c_parser_peek_token (parser)->location;
+      c_parser_consume_token (parser);
+      return c_parser_direct_declarator_inner (parser, *seen_id, inner);
+    }
+
+  if (kind != C_DTR_NORMAL
+      && c_parser_next_token_is (parser, CPP_OPEN_SQUARE))
+    {
+      struct c_declarator *inner = build_id_declarator (NULL_TREE);
+      return c_parser_direct_declarator_inner (parser, *seen_id, inner);
+    }
+
+  /* Either we are at the end of an abstract declarator, or we have
+     parentheses.  */
+
+  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+    {
+      tree attrs;
+      struct c_declarator *inner;
+      c_parser_consume_token (parser);
+      attrs = c_parser_attributes (parser);
+      if (kind != C_DTR_NORMAL
+         && (c_parser_next_token_starts_declspecs (parser)
+             || c_parser_next_token_is (parser, CPP_CLOSE_PAREN)))
+       {
+         struct c_arg_info *args
+           = c_parser_parms_declarator (parser, kind == C_DTR_NORMAL,
+                                        attrs);
+         if (args == NULL)
+           return NULL;
+         else
+           {
+             inner
+               = build_function_declarator (args,
+                                            build_id_declarator (NULL_TREE));
+             return c_parser_direct_declarator_inner (parser, *seen_id,
+                                                      inner);
+           }
+       }
+      /* A parenthesized declarator.  */
+      inner = c_parser_declarator (parser, type_seen_p, kind, seen_id);
+      if (inner != NULL && attrs != NULL)
+       inner = build_attrs_declarator (attrs, inner);
+      if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+       {
+         c_parser_consume_token (parser);
+         if (inner == NULL)
+           return NULL;
+         else
+           return c_parser_direct_declarator_inner (parser, *seen_id, inner);
+       }
+      else
+       {
+         c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+                                    "expected %<)%>");
+         return NULL;
+       }
+    }
+  else
+    {
+      if (kind == C_DTR_NORMAL)
+       {
+         c_parser_error (parser, "expected identifier or %<(%>");
+         return NULL;
+       }
+      else
+       return build_id_declarator (NULL_TREE);
+    }
+}
+
+/* Parse part of a direct declarator or direct abstract declarator,
+   given that some (in INNER) has already been parsed; ID_PRESENT is
+   true if an identifier is present, false for an abstract
+   declarator.  */
+
+static struct c_declarator *
+c_parser_direct_declarator_inner (c_parser *parser, bool id_present,
+                                 struct c_declarator *inner)
+{
+  /* Parse a sequence of array declarators and parameter lists.  */
+  if (c_parser_next_token_is (parser, CPP_OPEN_SQUARE))
+    {
+      location_t brace_loc = c_parser_peek_token (parser)->location;
+      struct c_declarator *declarator;
+      struct c_declspecs *quals_attrs = build_null_declspecs ();
+      bool static_seen;
+      bool star_seen;
+      tree dimen;
+      c_parser_consume_token (parser);
+      c_parser_declspecs (parser, quals_attrs, false, false, true, cla_prefer_id);
+      static_seen = c_parser_next_token_is_keyword (parser, RID_STATIC);
+      if (static_seen)
+       c_parser_consume_token (parser);
+      if (static_seen && !quals_attrs->declspecs_seen_p)
+       c_parser_declspecs (parser, quals_attrs, false, false, true, cla_prefer_id);
+      if (!quals_attrs->declspecs_seen_p)
+       quals_attrs = NULL;
+      /* If "static" is present, there must be an array dimension.
+        Otherwise, there may be a dimension, "*", or no
+        dimension.  */
+      if (static_seen)
+       {
+         star_seen = false;
+         dimen = c_parser_expr_no_commas (parser, NULL).value;
+       }
+      else
+       {
+         if (c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
+           {
+             dimen = NULL_TREE;
+             star_seen = false;
+           }
+         else if (c_parser_next_token_is (parser, CPP_MULT))
+           {
+             if (c_parser_peek_2nd_token (parser)->type == CPP_CLOSE_SQUARE)
+               {
+                 dimen = NULL_TREE;
+                 star_seen = true;
+                 c_parser_consume_token (parser);
+               }
+             else
+               {
+                 star_seen = false;
+                 dimen = c_parser_expr_no_commas (parser, NULL).value;
+               }
+           }
+         else
+           {
+             star_seen = false;
+             dimen = c_parser_expr_no_commas (parser, NULL).value;
+           }
+       }
+      if (c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
+       c_parser_consume_token (parser);
+      else
+       {
+         c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
+                                    "expected %<]%>");
+         return NULL;
+       }
+      if (dimen)
+       mark_exp_read (dimen);
+      declarator = build_array_declarator (brace_loc, dimen, quals_attrs,
+                                          static_seen, star_seen);
+      if (declarator == NULL)
+       return NULL;
+      inner = set_array_declarator_inner (declarator, inner);
+      return c_parser_direct_declarator_inner (parser, id_present, inner);
+    }
+  else if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+    {
+      tree attrs;
+      struct c_arg_info *args;
+      c_parser_consume_token (parser);
+      attrs = c_parser_attributes (parser);
+      args = c_parser_parms_declarator (parser, id_present, attrs);
+      if (args == NULL)
+       return NULL;
+      else
+       {
+         inner = build_function_declarator (args, inner);
+         return c_parser_direct_declarator_inner (parser, id_present, inner);
+       }
+    }
+  return inner;
+}
+
+/* Parse a parameter list or identifier list, including the closing
+   parenthesis but not the opening one.  ATTRS are the attributes at
+   the start of the list.  ID_LIST_OK is true if an identifier list is
+   acceptable; such a list must not have attributes at the start.  */
+
+static struct c_arg_info *
+c_parser_parms_declarator (c_parser *parser, bool id_list_ok, tree attrs)
+{
+  push_scope ();
+  declare_parm_level ();
+  /* If the list starts with an identifier, it is an identifier list.
+     Otherwise, it is either a prototype list or an empty list.  */
+  if (id_list_ok
+      && !attrs
+      && c_parser_next_token_is (parser, CPP_NAME)
+      && c_parser_peek_token (parser)->id_kind == C_ID_ID
+      
+      /* Look ahead to detect typos in type names.  */
+      && c_parser_peek_2nd_token (parser)->type != CPP_NAME
+      && c_parser_peek_2nd_token (parser)->type != CPP_MULT
+      && c_parser_peek_2nd_token (parser)->type != CPP_OPEN_PAREN
+      && c_parser_peek_2nd_token (parser)->type != CPP_OPEN_SQUARE)
+    {
+      tree list = NULL_TREE, *nextp = &list;
+      while (c_parser_next_token_is (parser, CPP_NAME)
+            && c_parser_peek_token (parser)->id_kind == C_ID_ID)
+       {
+         *nextp = build_tree_list (NULL_TREE,
+                                   c_parser_peek_token (parser)->value);
+         nextp = & TREE_CHAIN (*nextp);
+         c_parser_consume_token (parser);
+         if (c_parser_next_token_is_not (parser, CPP_COMMA))
+           break;
+         c_parser_consume_token (parser);
+         if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+           {
+             c_parser_error (parser, "expected identifier");
+             break;
+           }
+       }
+      if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+       {
+         struct c_arg_info *ret = build_arg_info ();
+         ret->types = list;
+         c_parser_consume_token (parser);
+         pop_scope ();
+         return ret;
+       }
+      else
+       {
+         c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+                                    "expected %<)%>");
+         pop_scope ();
+         return NULL;
+       }
+    }
+  else
+    {
+      struct c_arg_info *ret = c_parser_parms_list_declarator (parser, attrs,
+                                                              NULL);
+      pop_scope ();
+      return ret;
+    }
+}
+
+/* Parse a parameter list (possibly empty), including the closing
+   parenthesis but not the opening one.  ATTRS are the attributes at
+   the start of the list.  EXPR is NULL or an expression that needs to
+   be evaluated for the side effects of array size expressions in the
+   parameters.  */
+
+static struct c_arg_info *
+c_parser_parms_list_declarator (c_parser *parser, tree attrs, tree expr)
+{
+  bool bad_parm = false;
+
+  /* ??? Following the old parser, forward parameter declarations may
+     use abstract declarators, and if no real parameter declarations
+     follow the forward declarations then this is not diagnosed.  Also
+     note as above that attributes are ignored as the only contents of
+     the parentheses, or as the only contents after forward
+     declarations.  */
+  if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+    {
+      struct c_arg_info *ret = build_arg_info ();
+      c_parser_consume_token (parser);
+      return ret;
+    }
+  if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
+    {
+      struct c_arg_info *ret = build_arg_info ();
+
+      if (flag_allow_parameterless_variadic_functions)
+        {
+          /* F (...) is allowed.  */
+          ret->types = NULL_TREE;
+        }
+      else
+        {
+          /* Suppress -Wold-style-definition for this case.  */
+          ret->types = error_mark_node;
+          error_at (c_parser_peek_token (parser)->location,
+                    "ISO C requires a named argument before %<...%>");
+        }
+      c_parser_consume_token (parser);
+      if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+       {
+         c_parser_consume_token (parser);
+         return ret;
+       }
+      else
+       {
+         c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+                                    "expected %<)%>");
+         return NULL;
+       }
+    }
+  /* Nonempty list of parameters, either terminated with semicolon
+     (forward declarations; recurse) or with close parenthesis (normal
+     function) or with ", ... )" (variadic function).  */
+  while (true)
+    {
+      /* Parse a parameter.  */
+      struct c_parm *parm = c_parser_parameter_declaration (parser, attrs);
+      attrs = NULL_TREE;
+      if (parm == NULL)
+       bad_parm = true;
+      else
+       push_parm_decl (parm, &expr);
+      if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+       {
+         tree new_attrs;
+         c_parser_consume_token (parser);
+         mark_forward_parm_decls ();
+         new_attrs = c_parser_attributes (parser);
+         return c_parser_parms_list_declarator (parser, new_attrs, expr);
+       }
+      if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+       {
+         c_parser_consume_token (parser);
+         if (bad_parm)
+           return NULL;
+         else
+           return get_parm_info (false, expr);
+       }
+      if (!c_parser_require (parser, CPP_COMMA,
+                            "expected %<;%>, %<,%> or %<)%>"))
+       {
+         c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+         return NULL;
+       }
+      if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
+       {
+         c_parser_consume_token (parser);
+         if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+           {
+             c_parser_consume_token (parser);
+             if (bad_parm)
+               return NULL;
+             else
+               return get_parm_info (true, expr);
+           }
+         else
+           {
+             c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+                                        "expected %<)%>");
+             return NULL;
+           }
+       }
+    }
+}
+
+/* Parse a parameter declaration.  ATTRS are the attributes at the
+   start of the declaration if it is the first parameter.  */
+
+static struct c_parm *
+c_parser_parameter_declaration (c_parser *parser, tree attrs)
+{
+  struct c_declspecs *specs;
+  struct c_declarator *declarator;
+  tree prefix_attrs;
+  tree postfix_attrs = NULL_TREE;
+  bool dummy = false;
+
+  /* Accept #pragmas between parameter declarations.  */
+  while (c_parser_next_token_is (parser, CPP_PRAGMA))
+    c_parser_pragma (parser, pragma_external);
+
+  if (!c_parser_next_token_starts_declspecs (parser))
+    {
+      c_token *token = c_parser_peek_token (parser);
+      if (parser->error)
+       return NULL;
+      c_parser_set_source_position_from_token (token);
+      if (c_parser_next_tokens_start_typename (parser, cla_prefer_type))
+       {
+         error ("unknown type name %qE", token->value);
+         parser->error = true;
+       }
+      /* ??? In some Objective-C cases '...' isn't applicable so there
+        should be a different message.  */
+      else
+       c_parser_error (parser,
+                       "expected declaration specifiers or %<...%>");
+      c_parser_skip_to_end_of_parameter (parser);
+      return NULL;
+    }
+  specs = build_null_declspecs ();
+  if (attrs)
+    {
+      declspecs_add_attrs (input_location, specs, attrs);
+      attrs = NULL_TREE;
+    }
+  c_parser_declspecs (parser, specs, true, true, true, cla_nonabstract_decl);
+  finish_declspecs (specs);
+  pending_xref_error ();
+  prefix_attrs = specs->attrs;
+  specs->attrs = NULL_TREE;
+  declarator = c_parser_declarator (parser,
+                                   specs->typespec_kind != ctsk_none,
+                                   C_DTR_PARM, &dummy);
+  if (declarator == NULL)
+    {
+      c_parser_skip_until_found (parser, CPP_COMMA, NULL);
+      return NULL;
+    }
+  if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
+    postfix_attrs = c_parser_attributes (parser);
+  return build_c_parm (specs, chainon (postfix_attrs, prefix_attrs),
+                      declarator);
+}
+
+/* Parse a string literal in an asm expression.  It should not be
+   translated, and wide string literals are an error although
+   permitted by the syntax.  This is a GNU extension.
+
+   asm-string-literal:
+     string-literal
+
+   ??? At present, following the old parser, the caller needs to have
+   set lex_untranslated_string to 1.  It would be better to follow the
+   C++ parser rather than using this kludge.  */
+
+static tree
+c_parser_asm_string_literal (c_parser *parser)
+{
+  tree str;
+  int save_flag = warn_overlength_strings;
+  warn_overlength_strings = 0;
+  if (c_parser_next_token_is (parser, CPP_STRING))
+    {
+      str = c_parser_peek_token (parser)->value;
+      c_parser_consume_token (parser);
+    }
+  else if (c_parser_next_token_is (parser, CPP_WSTRING))
+    {
+      error_at (c_parser_peek_token (parser)->location,
+               "wide string literal in %<asm%>");
+      str = build_string (1, "");
+      c_parser_consume_token (parser);
+    }
+  else
+    {
+      c_parser_error (parser, "expected string literal");
+      str = NULL_TREE;
+    }
+  warn_overlength_strings = save_flag;
+  return str;
+}
+
+/* Parse a simple asm expression.  This is used in restricted
+   contexts, where a full expression with inputs and outputs does not
+   make sense.  This is a GNU extension.
+
+   simple-asm-expr:
+     asm ( asm-string-literal )
+*/
+
+static tree
+c_parser_simple_asm_expr (c_parser *parser)
+{
+  tree str;
+  gcc_assert (c_parser_next_token_is_keyword (parser, RID_ASM));
+  /* ??? Follow the C++ parser rather than using the
+     lex_untranslated_string kludge.  */
+  parser->lex_untranslated_string = true;
+  c_parser_consume_token (parser);
+  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+    {
+      parser->lex_untranslated_string = false;
+      return NULL_TREE;
+    }
+  str = c_parser_asm_string_literal (parser);
+  parser->lex_untranslated_string = false;
+  if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+    {
+      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+      return NULL_TREE;
+    }
+  return str;
+}
+
+static tree
+c_parser_attribute_any_word (c_parser *parser)
+{
+  tree attr_name = NULL_TREE;
+
+  if (c_parser_next_token_is (parser, CPP_KEYWORD))
+    {
+      /* ??? See comment above about what keywords are accepted here.  */
+      bool ok;
+      switch (c_parser_peek_token (parser)->keyword)
+       {
+       case RID_STATIC:
+       case RID_UNSIGNED:
+       case RID_LONG:
+       case RID_INT128:
+       case RID_CONST:
+       case RID_EXTERN:
+       case RID_REGISTER:
+       case RID_TYPEDEF:
+       case RID_SHORT:
+       case RID_INLINE:
+       case RID_NORETURN:
+       case RID_VOLATILE:
+       case RID_SIGNED:
+       case RID_AUTO:
+       case RID_RESTRICT:
+       case RID_COMPLEX:
+       case RID_THREAD:
+       case RID_INT:
+       case RID_CHAR:
+       case RID_FLOAT:
+       case RID_DOUBLE:
+       case RID_VOID:
+       case RID_DFLOAT32:
+       case RID_DFLOAT64:
+       case RID_DFLOAT128:
+       case RID_BOOL:
+       case RID_FRACT:
+       case RID_ACCUM:
+       case RID_SAT:
+       case RID_TRANSACTION_ATOMIC:
+       case RID_TRANSACTION_CANCEL:
+         ok = true;
+         break;
+       default:
+         ok = false;
+         break;
+       }
+      if (!ok)
+       return NULL_TREE;
+
+      /* Accept __attribute__((__const)) as __attribute__((const)) etc.  */
+      attr_name = ridpointers[(int) c_parser_peek_token (parser)->keyword];
+    }
+  else if (c_parser_next_token_is (parser, CPP_NAME))
+    attr_name = c_parser_peek_token (parser)->value;
+
+  return attr_name;
+}
+
+/* Parse (possibly empty) attributes.  This is a GNU extension.
+
+   attributes:
+     empty
+     attributes attribute
+
+   attribute:
+     __attribute__ ( ( attribute-list ) )
+
+   attribute-list:
+     attrib
+     attribute_list , attrib
+
+   attrib:
+     empty
+     any-word
+     any-word ( identifier )
+     any-word ( identifier , nonempty-expr-list )
+     any-word ( expr-list )
+
+   where the "identifier" must not be declared as a type, and
+   "any-word" may be any identifier (including one declared as a
+   type), a reserved word storage class specifier, type specifier or
+   type qualifier.  ??? This still leaves out most reserved keywords
+   (following the old parser), shouldn't we include them, and why not
+   allow identifiers declared as types to start the arguments?  */
+
+static tree
+c_parser_attributes (c_parser *parser)
+{
+  tree attrs = NULL_TREE;
+  while (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
+    {
+      /* ??? Follow the C++ parser rather than using the
+        lex_untranslated_string kludge.  */
+      parser->lex_untranslated_string = true;
+      c_parser_consume_token (parser);
+      if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+       {
+         parser->lex_untranslated_string = false;
+         return attrs;
+       }
+      if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+       {
+         parser->lex_untranslated_string = false;
+         c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+         return attrs;
+       }
+      /* Parse the attribute list.  */
+      while (c_parser_next_token_is (parser, CPP_COMMA)
+            || c_parser_next_token_is (parser, CPP_NAME)
+            || c_parser_next_token_is (parser, CPP_KEYWORD))
+       {
+         tree attr, attr_name, attr_args;
+         VEC(tree,gc) *expr_list;
+         if (c_parser_next_token_is (parser, CPP_COMMA))
+           {
+             c_parser_consume_token (parser);
+             continue;
+           }
+
+         attr_name = c_parser_attribute_any_word (parser);
+         if (attr_name == NULL)
+           break;
+         c_parser_consume_token (parser);
+         if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN))
+           {
+             attr = build_tree_list (attr_name, NULL_TREE);
+             attrs = chainon (attrs, attr);
+             continue;
+           }
+         c_parser_consume_token (parser);
+         /* Parse the attribute contents.  If they start with an
+            identifier which is followed by a comma or close
+            parenthesis, then the arguments start with that
+            identifier; otherwise they are an expression list.  
+            In objective-c the identifier may be a classname.  */
+         if (c_parser_next_token_is (parser, CPP_NAME)
+             && (c_parser_peek_token (parser)->id_kind == C_ID_ID
+                 || (c_dialect_objc () 
+                     && c_parser_peek_token (parser)->id_kind == C_ID_CLASSNAME))
+             && ((c_parser_peek_2nd_token (parser)->type == CPP_COMMA)
+                 || (c_parser_peek_2nd_token (parser)->type
+                     == CPP_CLOSE_PAREN)))
+           {
+             tree arg1 = c_parser_peek_token (parser)->value;
+             c_parser_consume_token (parser);
+             if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+               attr_args = build_tree_list (NULL_TREE, arg1);
+             else
+               {
+                 tree tree_list;
+                 c_parser_consume_token (parser);
+                 expr_list = c_parser_expr_list (parser, false, true, NULL);
+                 tree_list = build_tree_list_vec (expr_list);
+                 attr_args = tree_cons (NULL_TREE, arg1, tree_list);
+                 release_tree_vector (expr_list);
+               }
+           }
+         else
+           {
+             if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+               attr_args = NULL_TREE;
+             else
+               {
+                 expr_list = c_parser_expr_list (parser, false, true, NULL);
+                 attr_args = build_tree_list_vec (expr_list);
+                 release_tree_vector (expr_list);
+               }
+           }
+         attr = build_tree_list (attr_name, attr_args);
+         if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+           c_parser_consume_token (parser);
+         else
+           {
+             parser->lex_untranslated_string = false;
+             c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+                                        "expected %<)%>");
+             return attrs;
+           }
+         attrs = chainon (attrs, attr);
+       }
+      if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+       c_parser_consume_token (parser);
+      else
+       {
+         parser->lex_untranslated_string = false;
+         c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+                                    "expected %<)%>");
+         return attrs;
+       }
+      if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+       c_parser_consume_token (parser);
+      else
+       {
+         parser->lex_untranslated_string = false;
+         c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+                                    "expected %<)%>");
+         return attrs;
+       }
+      parser->lex_untranslated_string = false;
+    }
+  return attrs;
+}
+
+/* Parse a type name (C90 6.5.5, C99 6.7.6).
+
+   type-name:
+     specifier-qualifier-list abstract-declarator[opt]
+*/
+
+static struct c_type_name *
+c_parser_type_name (c_parser *parser)
+{
+  struct c_declspecs *specs = build_null_declspecs ();
+  struct c_declarator *declarator;
+  struct c_type_name *ret;
+  bool dummy = false;
+  c_parser_declspecs (parser, specs, false, true, true, cla_prefer_type);
+  if (!specs->declspecs_seen_p)
+    {
+      c_parser_error (parser, "expected specifier-qualifier-list");
+      return NULL;
+    }
+  if (specs->type != error_mark_node)
+    {
+      pending_xref_error ();
+      finish_declspecs (specs);
+    }
+  declarator = c_parser_declarator (parser,
+                                   specs->typespec_kind != ctsk_none,
+                                   C_DTR_ABSTRACT, &dummy);
+  if (declarator == NULL)
+    return NULL;
+  ret = XOBNEW (&parser_obstack, struct c_type_name);
+  ret->specs = specs;
+  ret->declarator = declarator;
+  return ret;
+}
+
+/* Parse an initializer (C90 6.5.7, C99 6.7.8).
+
+   initializer:
+     assignment-expression
+     { initializer-list }
+     { initializer-list , }
+
+   initializer-list:
+     designation[opt] initializer
+     initializer-list , designation[opt] initializer
+
+   designation:
+     designator-list =
+
+   designator-list:
+     designator
+     designator-list designator
+
+   designator:
+     array-designator
+     . identifier
+
+   array-designator:
+     [ constant-expression ]
+
+   GNU extensions:
+
+   initializer:
+     { }
+
+   designation:
+     array-designator
+     identifier :
+
+   array-designator:
+     [ constant-expression ... constant-expression ]
+
+   Any expression without commas is accepted in the syntax for the
+   constant-expressions, with non-constant expressions rejected later.
+
+   This function is only used for top-level initializers; for nested
+   ones, see c_parser_initval.  */
+
+static struct c_expr
+c_parser_initializer (c_parser *parser)
+{
+  if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
+    return c_parser_braced_init (parser, NULL_TREE, false);
+  else
+    {
+      struct c_expr ret;
+      location_t loc = c_parser_peek_token (parser)->location;
+      ret = c_parser_expr_no_commas (parser, NULL);
+      if (TREE_CODE (ret.value) != STRING_CST
+         && TREE_CODE (ret.value) != COMPOUND_LITERAL_EXPR)
+       ret = default_function_array_read_conversion (loc, ret);
+      return ret;
+    }
+}
+
+/* Parse a braced initializer list.  TYPE is the type specified for a
+   compound literal, and NULL_TREE for other initializers and for
+   nested braced lists.  NESTED_P is true for nested braced lists,
+   false for the list of a compound literal or the list that is the
+   top-level initializer in a declaration.  */
+
+static struct c_expr
+c_parser_braced_init (c_parser *parser, tree type, bool nested_p)
+{
+  struct c_expr ret;
+  struct obstack braced_init_obstack;
+  location_t brace_loc = c_parser_peek_token (parser)->location;
+  gcc_obstack_init (&braced_init_obstack);
+  gcc_assert (c_parser_next_token_is (parser, CPP_OPEN_BRACE));
+  c_parser_consume_token (parser);
+  if (nested_p)
+    push_init_level (0, &braced_init_obstack);
+  else
+    really_start_incremental_init (type);
+  if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
+    {
+      pedwarn (brace_loc, OPT_Wpedantic, "ISO C forbids empty initializer braces");
+    }
+  else
+    {
+      /* Parse a non-empty initializer list, possibly with a trailing
+        comma.  */
+      while (true)
+       {
+         c_parser_initelt (parser, &braced_init_obstack);
+         if (parser->error)
+           break;
+         if (c_parser_next_token_is (parser, CPP_COMMA))
+           c_parser_consume_token (parser);
+         else
+           break;
+         if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
+           break;
+       }
+    }
+  if (c_parser_next_token_is_not (parser, CPP_CLOSE_BRACE))
+    {
+      ret.value = error_mark_node;
+      ret.original_code = ERROR_MARK;
+      ret.original_type = NULL;
+      c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, "expected %<}%>");
+      pop_init_level (0, &braced_init_obstack);
+      obstack_free (&braced_init_obstack, NULL);
+      return ret;
+    }
+  c_parser_consume_token (parser);
+  ret = pop_init_level (0, &braced_init_obstack);
+  obstack_free (&braced_init_obstack, NULL);
+  return ret;
+}
+
+/* Parse a nested initializer, including designators.  */
+
+static void
+c_parser_initelt (c_parser *parser, struct obstack * braced_init_obstack)
+{
+  /* Parse any designator or designator list.  A single array
+     designator may have the subsequent "=" omitted in GNU C, but a
+     longer list or a structure member designator may not.  */
+  if (c_parser_next_token_is (parser, CPP_NAME)
+      && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
+    {
+      /* Old-style structure member designator.  */
+      set_init_label (c_parser_peek_token (parser)->value,
+                     braced_init_obstack);
+      /* Use the colon as the error location.  */
+      pedwarn (c_parser_peek_2nd_token (parser)->location, OPT_Wpedantic,
+              "obsolete use of designated initializer with %<:%>");
+      c_parser_consume_token (parser);
+      c_parser_consume_token (parser);
+    }
+  else
+    {
+      /* des_seen is 0 if there have been no designators, 1 if there
+        has been a single array designator and 2 otherwise.  */
+      int des_seen = 0;
+      /* Location of a designator.  */
+      location_t des_loc = UNKNOWN_LOCATION;  /* Quiet warning.  */
+      while (c_parser_next_token_is (parser, CPP_OPEN_SQUARE)
+            || c_parser_next_token_is (parser, CPP_DOT))
+       {
+         int des_prev = des_seen;
+         if (!des_seen)
+           des_loc = c_parser_peek_token (parser)->location;
+         if (des_seen < 2)
+           des_seen++;
+         if (c_parser_next_token_is (parser, CPP_DOT))
+           {
+             des_seen = 2;
+             c_parser_consume_token (parser);
+             if (c_parser_next_token_is (parser, CPP_NAME))
+               {
+                 set_init_label (c_parser_peek_token (parser)->value,
+                                 braced_init_obstack);
+                 c_parser_consume_token (parser);
+               }
+             else
+               {
+                 struct c_expr init;
+                 init.value = error_mark_node;
+                 init.original_code = ERROR_MARK;
+                 init.original_type = NULL;
+                 c_parser_error (parser, "expected identifier");
+                 c_parser_skip_until_found (parser, CPP_COMMA, NULL);
+                 process_init_element (init, false, braced_init_obstack);
+                 return;
+               }
+           }
+         else
+           {
+             tree first, second;
+             location_t ellipsis_loc = UNKNOWN_LOCATION;  /* Quiet warning.  */
+             /* ??? Following the old parser, [ objc-receiver
+                objc-message-args ] is accepted as an initializer,
+                being distinguished from a designator by what follows
+                the first assignment expression inside the square
+                brackets, but after a first array designator a
+                subsequent square bracket is for Objective-C taken to
+                start an expression, using the obsolete form of
+                designated initializer without '=', rather than
+                possibly being a second level of designation: in LALR
+                terms, the '[' is shifted rather than reducing
+                designator to designator-list.  */
+             if (des_prev == 1 && c_dialect_objc ())
+               {
+                 des_seen = des_prev;
+                 break;
+               }
+             if (des_prev == 0 && c_dialect_objc ())
+               {
+                 /* This might be an array designator or an
+                    Objective-C message expression.  If the former,
+                    continue parsing here; if the latter, parse the
+                    remainder of the initializer given the starting
+                    primary-expression.  ??? It might make sense to
+                    distinguish when des_prev == 1 as well; see
+                    previous comment.  */
+                 tree rec, args;
+                 struct c_expr mexpr;
+                 c_parser_consume_token (parser);
+                 if (c_parser_peek_token (parser)->type == CPP_NAME
+                     && ((c_parser_peek_token (parser)->id_kind
+                          == C_ID_TYPENAME)
+                         || (c_parser_peek_token (parser)->id_kind
+                             == C_ID_CLASSNAME)))
+                   {
+                     /* Type name receiver.  */
+                     tree id = c_parser_peek_token (parser)->value;
+                     c_parser_consume_token (parser);
+                     rec = objc_get_class_reference (id);
+                     goto parse_message_args;
+                   }
+                 first = c_parser_expr_no_commas (parser, NULL).value;
+                 mark_exp_read (first);
+                 if (c_parser_next_token_is (parser, CPP_ELLIPSIS)
+                     || c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
+                   goto array_desig_after_first;
+                 /* Expression receiver.  So far only one part
+                    without commas has been parsed; there might be
+                    more of the expression.  */
+                 rec = first;
+                 while (c_parser_next_token_is (parser, CPP_COMMA))
+                   {
+                     struct c_expr next;
+                     location_t comma_loc, exp_loc;
+                     comma_loc = c_parser_peek_token (parser)->location;
+                     c_parser_consume_token (parser);
+                     exp_loc = c_parser_peek_token (parser)->location;
+                     next = c_parser_expr_no_commas (parser, NULL);
+                     next = default_function_array_read_conversion (exp_loc,
+                                                                    next);
+                     rec = build_compound_expr (comma_loc, rec, next.value);
+                   }
+               parse_message_args:
+                 /* Now parse the objc-message-args.  */
+                 args = c_parser_objc_message_args (parser);
+                 c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
+                                            "expected %<]%>");
+                 mexpr.value
+                   = objc_build_message_expr (rec, args);
+                 mexpr.original_code = ERROR_MARK;
+                 mexpr.original_type = NULL;
+                 /* Now parse and process the remainder of the
+                    initializer, starting with this message
+                    expression as a primary-expression.  */
+                 c_parser_initval (parser, &mexpr, braced_init_obstack);
+                 return;
+               }
+             c_parser_consume_token (parser);
+             first = c_parser_expr_no_commas (parser, NULL).value;
+             mark_exp_read (first);
+           array_desig_after_first:
+             if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
+               {
+                 ellipsis_loc = c_parser_peek_token (parser)->location;
+                 c_parser_consume_token (parser);
+                 second = c_parser_expr_no_commas (parser, NULL).value;
+                 mark_exp_read (second);
+               }
+             else
+               second = NULL_TREE;
+             if (c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
+               {
+                 c_parser_consume_token (parser);
+                 set_init_index (first, second, braced_init_obstack);
+                 if (second)
+                   pedwarn (ellipsis_loc, OPT_Wpedantic,
+                            "ISO C forbids specifying range of elements to initialize");
+               }
+             else
+               c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
+                                          "expected %<]%>");
+           }
+       }
+      if (des_seen >= 1)
+       {
+         if (c_parser_next_token_is (parser, CPP_EQ))
+           {
+             if (!flag_isoc99)
+               pedwarn (des_loc, OPT_Wpedantic,
+                        "ISO C90 forbids specifying subobject to initialize");
+             c_parser_consume_token (parser);
+           }
+         else
+           {
+             if (des_seen == 1)
+               pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic,
+                        "obsolete use of designated initializer without %<=%>");
+             else
+               {
+                 struct c_expr init;
+                 init.value = error_mark_node;
+                 init.original_code = ERROR_MARK;
+                 init.original_type = NULL;
+                 c_parser_error (parser, "expected %<=%>");
+                 c_parser_skip_until_found (parser, CPP_COMMA, NULL);
+                 process_init_element (init, false, braced_init_obstack);
+                 return;
+               }
+           }
+       }
+    }
+  c_parser_initval (parser, NULL, braced_init_obstack);
+}
+
+/* Parse a nested initializer; as c_parser_initializer but parses
+   initializers within braced lists, after any designators have been
+   applied.  If AFTER is not NULL then it is an Objective-C message
+   expression which is the primary-expression starting the
+   initializer.  */
+
+static void
+c_parser_initval (c_parser *parser, struct c_expr *after,
+                 struct obstack * braced_init_obstack)
+{
+  struct c_expr init;
+  gcc_assert (!after || c_dialect_objc ());
+  if (c_parser_next_token_is (parser, CPP_OPEN_BRACE) && !after)
+    init = c_parser_braced_init (parser, NULL_TREE, true);
+  else
+    {
+      location_t loc = c_parser_peek_token (parser)->location;
+      init = c_parser_expr_no_commas (parser, after);
+      if (init.value != NULL_TREE
+         && TREE_CODE (init.value) != STRING_CST
+         && TREE_CODE (init.value) != COMPOUND_LITERAL_EXPR)
+       init = default_function_array_read_conversion (loc, init);
+    }
+  process_init_element (init, false, braced_init_obstack);
+}
+
+/* Parse a compound statement (possibly a function body) (C90 6.6.2,
+   C99 6.8.2).
+
+   compound-statement:
+     { block-item-list[opt] }
+     { label-declarations block-item-list }
+
+   block-item-list:
+     block-item
+     block-item-list block-item
+
+   block-item:
+     nested-declaration
+     statement
+
+   nested-declaration:
+     declaration
+
+   GNU extensions:
+
+   compound-statement:
+     { label-declarations block-item-list }
+
+   nested-declaration:
+     __extension__ nested-declaration
+     nested-function-definition
+
+   label-declarations:
+     label-declaration
+     label-declarations label-declaration
+
+   label-declaration:
+     __label__ identifier-list ;
+
+   Allowing the mixing of declarations and code is new in C99.  The
+   GNU syntax also permits (not shown above) labels at the end of
+   compound statements, which yield an error.  We don't allow labels
+   on declarations; this might seem like a natural extension, but
+   there would be a conflict between attributes on the label and
+   prefix attributes on the declaration.  ??? The syntax follows the
+   old parser in requiring something after label declarations.
+   Although they are erroneous if the labels declared aren't defined,
+   is it useful for the syntax to be this way?
+
+   OpenMP:
+
+   block-item:
+     openmp-directive
+
+   openmp-directive:
+     barrier-directive
+     flush-directive  */
+
+static tree
+c_parser_compound_statement (c_parser *parser)
+{
+  tree stmt;
+  location_t brace_loc;
+  brace_loc = c_parser_peek_token (parser)->location;
+  if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
+    {
+      /* Ensure a scope is entered and left anyway to avoid confusion
+        if we have just prepared to enter a function body.  */
+      stmt = c_begin_compound_stmt (true);
+      c_end_compound_stmt (brace_loc, stmt, true);
+      return error_mark_node;
+    }
+  stmt = c_begin_compound_stmt (true);
+  c_parser_compound_statement_nostart (parser);
+  return c_end_compound_stmt (brace_loc, stmt, true);
+}
+
+/* Parse a compound statement except for the opening brace.  This is
+   used for parsing both compound statements and statement expressions
+   (which follow different paths to handling the opening).  */
+
+static void
+c_parser_compound_statement_nostart (c_parser *parser)
+{
+  bool last_stmt = false;
+  bool last_label = false;
+  bool save_valid_for_pragma = valid_location_for_stdc_pragma_p ();
+  location_t label_loc = UNKNOWN_LOCATION;  /* Quiet warning.  */
+  if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
+    {
+      c_parser_consume_token (parser);
+      return;
+    }
+  mark_valid_location_for_stdc_pragma (true);
+  if (c_parser_next_token_is_keyword (parser, RID_LABEL))
+    {
+      /* Read zero or more forward-declarations for labels that nested
+        functions can jump to.  */
+      mark_valid_location_for_stdc_pragma (false);
+      while (c_parser_next_token_is_keyword (parser, RID_LABEL))
+       {
+         label_loc = c_parser_peek_token (parser)->location;
+         c_parser_consume_token (parser);
+         /* Any identifiers, including those declared as type names,
+            are OK here.  */
+         while (true)
+           {
+             tree label;
+             if (c_parser_next_token_is_not (parser, CPP_NAME))
+               {
+                 c_parser_error (parser, "expected identifier");
+                 break;
+               }
+             label
+               = declare_label (c_parser_peek_token (parser)->value);
+             C_DECLARED_LABEL_FLAG (label) = 1;
+             add_stmt (build_stmt (label_loc, DECL_EXPR, label));
+             c_parser_consume_token (parser);
+             if (c_parser_next_token_is (parser, CPP_COMMA))
+               c_parser_consume_token (parser);
+             else
+               break;
+           }
+         c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+       }
+      pedwarn (label_loc, OPT_Wpedantic, "ISO C forbids label declarations");
+    }
+  /* We must now have at least one statement, label or declaration.  */
+  if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
+    {
+      mark_valid_location_for_stdc_pragma (save_valid_for_pragma);
+      c_parser_error (parser, "expected declaration or statement");
+      c_parser_consume_token (parser);
+      return;
+    }
+  while (c_parser_next_token_is_not (parser, CPP_CLOSE_BRACE))
+    {
+      location_t loc = c_parser_peek_token (parser)->location;
+      if (c_parser_next_token_is_keyword (parser, RID_CASE)
+         || c_parser_next_token_is_keyword (parser, RID_DEFAULT)
+         || (c_parser_next_token_is (parser, CPP_NAME)
+             && c_parser_peek_2nd_token (parser)->type == CPP_COLON))
+       {
+         if (c_parser_next_token_is_keyword (parser, RID_CASE))
+           label_loc = c_parser_peek_2nd_token (parser)->location;
+         else
+           label_loc = c_parser_peek_token (parser)->location;
+         last_label = true;
+         last_stmt = false;
+         mark_valid_location_for_stdc_pragma (false);
+         c_parser_label (parser);
+       }
+      else if (!last_label
+              && c_parser_next_tokens_start_declaration (parser))
+       {
+         last_label = false;
+         mark_valid_location_for_stdc_pragma (false);
+         c_parser_declaration_or_fndef (parser, true, true, true, true, true, NULL);
+         if (last_stmt)
+           pedwarn_c90 (loc,
+                        (pedantic && !flag_isoc99)
+                        ? OPT_Wpedantic
+                        : OPT_Wdeclaration_after_statement,
+                        "ISO C90 forbids mixed declarations and code");
+         last_stmt = false;
+       }
+      else if (!last_label
+              && c_parser_next_token_is_keyword (parser, RID_EXTENSION))
+       {
+         /* __extension__ can start a declaration, but is also an
+            unary operator that can start an expression.  Consume all
+            but the last of a possible series of __extension__ to
+            determine which.  */
+         while (c_parser_peek_2nd_token (parser)->type == CPP_KEYWORD
+                && (c_parser_peek_2nd_token (parser)->keyword
+                    == RID_EXTENSION))
+           c_parser_consume_token (parser);
+         if (c_token_starts_declaration (c_parser_peek_2nd_token (parser)))
+           {
+             int ext;
+             ext = disable_extension_diagnostics ();
+             c_parser_consume_token (parser);
+             last_label = false;
+             mark_valid_location_for_stdc_pragma (false);
+             c_parser_declaration_or_fndef (parser, true, true, true, true,
+                                            true, NULL);
+             /* Following the old parser, __extension__ does not
+                disable this diagnostic.  */
+             restore_extension_diagnostics (ext);
+             if (last_stmt)
+               pedwarn_c90 (loc, (pedantic && !flag_isoc99)
+                            ? OPT_Wpedantic
+                            : OPT_Wdeclaration_after_statement,
+                            "ISO C90 forbids mixed declarations and code");
+             last_stmt = false;
+           }
+         else
+           goto statement;
+       }
+      else if (c_parser_next_token_is (parser, CPP_PRAGMA))
+       {
+         /* External pragmas, and some omp pragmas, are not associated
+            with regular c code, and so are not to be considered statements
+            syntactically.  This ensures that the user doesn't put them
+            places that would turn into syntax errors if the directive
+            were ignored.  */
+         if (c_parser_pragma (parser, pragma_compound))
+           last_label = false, last_stmt = true;
+       }
+      else if (c_parser_next_token_is (parser, CPP_EOF))
+       {
+         mark_valid_location_for_stdc_pragma (save_valid_for_pragma);
+         c_parser_error (parser, "expected declaration or statement");
+         return;
+       }
+      else if (c_parser_next_token_is_keyword (parser, RID_ELSE))
+        {
+          if (parser->in_if_block)
+            {
+             mark_valid_location_for_stdc_pragma (save_valid_for_pragma);
+              error_at (loc, """expected %<}%> before %<else%>");
+              return;
+            }
+          else
+            {
+              error_at (loc, "%<else%> without a previous %<if%>");
+              c_parser_consume_token (parser);
+              continue;
+            }
+        }
+      else
+       {
+       statement:
+         last_label = false;
+         last_stmt = true;
+         mark_valid_location_for_stdc_pragma (false);
+         c_parser_statement_after_labels (parser);
+       }
+
+      parser->error = false;
+    }
+  if (last_label)
+    error_at (label_loc, "label at end of compound statement");
+  c_parser_consume_token (parser);
+  /* Restore the value we started with.  */
+  mark_valid_location_for_stdc_pragma (save_valid_for_pragma);
+}
+
+/* Parse a label (C90 6.6.1, C99 6.8.1).
+
+   label:
+     identifier : attributes[opt]
+     case constant-expression :
+     default :
+
+   GNU extensions:
+
+   label:
+     case constant-expression ... constant-expression :
+
+   The use of attributes on labels is a GNU extension.  The syntax in
+   GNU C accepts any expressions without commas, non-constant
+   expressions being rejected later.  */
+
+static void
+c_parser_label (c_parser *parser)
+{
+  location_t loc1 = c_parser_peek_token (parser)->location;
+  tree label = NULL_TREE;
+  if (c_parser_next_token_is_keyword (parser, RID_CASE))
+    {
+      tree exp1, exp2;
+      c_parser_consume_token (parser);
+      exp1 = c_parser_expr_no_commas (parser, NULL).value;
+      if (c_parser_next_token_is (parser, CPP_COLON))
+       {
+         c_parser_consume_token (parser);
+         label = do_case (loc1, exp1, NULL_TREE);
+       }
+      else if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
+       {
+         c_parser_consume_token (parser);
+         exp2 = c_parser_expr_no_commas (parser, NULL).value;
+         if (c_parser_require (parser, CPP_COLON, "expected %<:%>"))
+           label = do_case (loc1, exp1, exp2);
+       }
+      else
+       c_parser_error (parser, "expected %<:%> or %<...%>");
+    }
+  else if (c_parser_next_token_is_keyword (parser, RID_DEFAULT))
+    {
+      c_parser_consume_token (parser);
+      if (c_parser_require (parser, CPP_COLON, "expected %<:%>"))
+       label = do_case (loc1, NULL_TREE, NULL_TREE);
+    }
+  else
+    {
+      tree name = c_parser_peek_token (parser)->value;
+      tree tlab;
+      tree attrs;
+      location_t loc2 = c_parser_peek_token (parser)->location;
+      gcc_assert (c_parser_next_token_is (parser, CPP_NAME));
+      c_parser_consume_token (parser);
+      gcc_assert (c_parser_next_token_is (parser, CPP_COLON));
+      c_parser_consume_token (parser);
+      attrs = c_parser_attributes (parser);
+      tlab = define_label (loc2, name);
+      if (tlab)
+       {
+         decl_attributes (&tlab, attrs, 0);
+         label = add_stmt (build_stmt (loc1, LABEL_EXPR, tlab));
+       }
+    }
+  if (label)
+    {
+      if (c_parser_next_tokens_start_declaration (parser))
+       {
+         error_at (c_parser_peek_token (parser)->location,
+                   "a label can only be part of a statement and "
+                   "a declaration is not a statement");
+         c_parser_declaration_or_fndef (parser, /*fndef_ok*/ false,
+                                        /*static_assert_ok*/ true,
+                                        /*nested*/ true, /*empty_ok*/ false,
+                                        /*start_attr_ok*/ true, NULL);
+       }
+    }
+}
+
+/* Parse a statement (C90 6.6, C99 6.8).
+
+   statement:
+     labeled-statement
+     compound-statement
+     expression-statement
+     selection-statement
+     iteration-statement
+     jump-statement
+
+   labeled-statement:
+     label statement
+
+   expression-statement:
+     expression[opt] ;
+
+   selection-statement:
+     if-statement
+     switch-statement
+
+   iteration-statement:
+     while-statement
+     do-statement
+     for-statement
+
+   jump-statement:
+     goto identifier ;
+     continue ;
+     break ;
+     return expression[opt] ;
+
+   GNU extensions:
+
+   statement:
+     asm-statement
+
+   jump-statement:
+     goto * expression ;
+
+   Objective-C:
+
+   statement:
+     objc-throw-statement
+     objc-try-catch-statement
+     objc-synchronized-statement
+
+   objc-throw-statement:
+     @throw expression ;
+     @throw ;
+
+   OpenMP:
+
+   statement:
+     openmp-construct
+
+   openmp-construct:
+     parallel-construct
+     for-construct
+     sections-construct
+     single-construct
+     parallel-for-construct
+     parallel-sections-construct
+     master-construct
+     critical-construct
+     atomic-construct
+     ordered-construct
+
+   parallel-construct:
+     parallel-directive structured-block
+
+   for-construct:
+     for-directive iteration-statement
+
+   sections-construct:
+     sections-directive section-scope
+
+   single-construct:
+     single-directive structured-block
+
+   parallel-for-construct:
+     parallel-for-directive iteration-statement
+
+   parallel-sections-construct:
+     parallel-sections-directive section-scope
+
+   master-construct:
+     master-directive structured-block
+
+   critical-construct:
+     critical-directive structured-block
+
+   atomic-construct:
+     atomic-directive expression-statement
+
+   ordered-construct:
+     ordered-directive structured-block
+
+   Transactional Memory:
+
+   statement:
+     transaction-statement
+     transaction-cancel-statement
+*/
+
+static void
+c_parser_statement (c_parser *parser)
+{
+  while (c_parser_next_token_is_keyword (parser, RID_CASE)
+        || c_parser_next_token_is_keyword (parser, RID_DEFAULT)
+        || (c_parser_next_token_is (parser, CPP_NAME)
+            && c_parser_peek_2nd_token (parser)->type == CPP_COLON))
+    c_parser_label (parser);
+  c_parser_statement_after_labels (parser);
+}
+
+/* Parse a statement, other than a labeled statement.  */
+
+static void
+c_parser_statement_after_labels (c_parser *parser)
+{
+  location_t loc = c_parser_peek_token (parser)->location;
+  tree stmt = NULL_TREE;
+  bool in_if_block = parser->in_if_block;
+  parser->in_if_block = false;
+  switch (c_parser_peek_token (parser)->type)
+    {
+    case CPP_OPEN_BRACE:
+      add_stmt (c_parser_compound_statement (parser));
+      break;
+    case CPP_KEYWORD:
+      switch (c_parser_peek_token (parser)->keyword)
+       {
+       case RID_IF:
+         c_parser_if_statement (parser);
+         break;
+       case RID_SWITCH:
+         c_parser_switch_statement (parser);
+         break;
+       case RID_WHILE:
+         c_parser_while_statement (parser);
+         break;
+       case RID_DO:
+         c_parser_do_statement (parser);
+         break;
+       case RID_FOR:
+         c_parser_for_statement (parser);
+         break;
+       case RID_GOTO:
+         c_parser_consume_token (parser);
+         if (c_parser_next_token_is (parser, CPP_NAME))
+           {
+             stmt = c_finish_goto_label (loc,
+                                         c_parser_peek_token (parser)->value);
+             c_parser_consume_token (parser);
+           }
+         else if (c_parser_next_token_is (parser, CPP_MULT))
+           {
+             tree val;
+
+             c_parser_consume_token (parser);
+             val = c_parser_expression (parser).value;
+             mark_exp_read (val);
+             stmt = c_finish_goto_ptr (loc, val);
+           }
+         else
+           c_parser_error (parser, "expected identifier or %<*%>");
+         goto expect_semicolon;
+       case RID_CONTINUE:
+         c_parser_consume_token (parser);
+         stmt = c_finish_bc_stmt (loc, &c_cont_label, false);
+         goto expect_semicolon;
+       case RID_BREAK:
+         c_parser_consume_token (parser);
+         stmt = c_finish_bc_stmt (loc, &c_break_label, true);
+         goto expect_semicolon;
+       case RID_RETURN:
+         c_parser_consume_token (parser);
+         if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+           {
+             stmt = c_finish_return (loc, NULL_TREE, NULL_TREE);
+             c_parser_consume_token (parser);
+           }
+         else
+           {
+             struct c_expr expr = c_parser_expression_conv (parser);
+             mark_exp_read (expr.value);
+             stmt = c_finish_return (loc, expr.value, expr.original_type);
+             goto expect_semicolon;
+           }
+         break;
+       case RID_ASM:
+         stmt = c_parser_asm_statement (parser);
+         break;
+       case RID_TRANSACTION_ATOMIC:
+       case RID_TRANSACTION_RELAXED:
+         stmt = c_parser_transaction (parser,
+             c_parser_peek_token (parser)->keyword);
+         break;
+       case RID_TRANSACTION_CANCEL:
+         stmt = c_parser_transaction_cancel (parser);
+         goto expect_semicolon;
+       case RID_AT_THROW:
+         gcc_assert (c_dialect_objc ());
+         c_parser_consume_token (parser);
+         if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+           {
+             stmt = objc_build_throw_stmt (loc, NULL_TREE);
+             c_parser_consume_token (parser);
+           }
+         else
+           {
+             tree expr = c_parser_expression (parser).value;
+             expr = c_fully_fold (expr, false, NULL);
+             stmt = objc_build_throw_stmt (loc, expr);
+             goto expect_semicolon;
+           }
+         break;
+       case RID_AT_TRY:
+         gcc_assert (c_dialect_objc ());
+         c_parser_objc_try_catch_finally_statement (parser);
+         break;
+       case RID_AT_SYNCHRONIZED:
+         gcc_assert (c_dialect_objc ());
+         c_parser_objc_synchronized_statement (parser);
+         break;
+       default:
+         goto expr_stmt;
+       }
+      break;
+    case CPP_SEMICOLON:
+      c_parser_consume_token (parser);
+      break;
+    case CPP_CLOSE_PAREN:
+    case CPP_CLOSE_SQUARE:
+      /* Avoid infinite loop in error recovery:
+        c_parser_skip_until_found stops at a closing nesting
+        delimiter without consuming it, but here we need to consume
+        it to proceed further.  */
+      c_parser_error (parser, "expected statement");
+      c_parser_consume_token (parser);
+      break;
+    case CPP_PRAGMA:
+      c_parser_pragma (parser, pragma_stmt);
+      break;
+    default:
+    expr_stmt:
+      stmt = c_finish_expr_stmt (loc, c_parser_expression_conv (parser).value);
+    expect_semicolon:
+      c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+      break;
+    }
+  /* Two cases cannot and do not have line numbers associated: If stmt
+     is degenerate, such as "2;", then stmt is an INTEGER_CST, which
+     cannot hold line numbers.  But that's OK because the statement
+     will either be changed to a MODIFY_EXPR during gimplification of
+     the statement expr, or discarded.  If stmt was compound, but
+     without new variables, we will have skipped the creation of a
+     BIND and will have a bare STATEMENT_LIST.  But that's OK because
+     (recursively) all of the component statements should already have
+     line numbers assigned.  ??? Can we discard no-op statements
+     earlier?  */
+  if (CAN_HAVE_LOCATION_P (stmt)
+      && EXPR_LOCATION (stmt) == UNKNOWN_LOCATION)
+    SET_EXPR_LOCATION (stmt, loc);
+
+  parser->in_if_block = in_if_block;
+}
+
+/* Parse the condition from an if, do, while or for statements.  */
+
+static tree
+c_parser_condition (c_parser *parser)
+{
+  location_t loc = c_parser_peek_token (parser)->location;
+  tree cond;
+  cond = c_parser_expression_conv (parser).value;
+  cond = c_objc_common_truthvalue_conversion (loc, cond);
+  cond = c_fully_fold (cond, false, NULL);
+  if (warn_sequence_point)
+    verify_sequence_points (cond);
+  return cond;
+}
+
+/* Parse a parenthesized condition from an if, do or while statement.
+
+   condition:
+     ( expression )
+*/
+static tree
+c_parser_paren_condition (c_parser *parser)
+{
+  tree cond;
+  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+    return error_mark_node;
+  cond = c_parser_condition (parser);
+  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+  return cond;
+}
+
+/* Parse a statement which is a block in C99.  */
+
+static tree
+c_parser_c99_block_statement (c_parser *parser)
+{
+  tree block = c_begin_compound_stmt (flag_isoc99);
+  location_t loc = c_parser_peek_token (parser)->location;
+  c_parser_statement (parser);
+  return c_end_compound_stmt (loc, block, flag_isoc99);
+}
+
+/* Parse the body of an if statement.  This is just parsing a
+   statement but (a) it is a block in C99, (b) we track whether the
+   body is an if statement for the sake of -Wparentheses warnings, (c)
+   we handle an empty body specially for the sake of -Wempty-body
+   warnings, and (d) we call parser_compound_statement directly
+   because c_parser_statement_after_labels resets
+   parser->in_if_block.  */
+
+static tree
+c_parser_if_body (c_parser *parser, bool *if_p)
+{
+  tree block = c_begin_compound_stmt (flag_isoc99);
+  location_t body_loc = c_parser_peek_token (parser)->location;
+  while (c_parser_next_token_is_keyword (parser, RID_CASE)
+        || c_parser_next_token_is_keyword (parser, RID_DEFAULT)
+        || (c_parser_next_token_is (parser, CPP_NAME)
+            && c_parser_peek_2nd_token (parser)->type == CPP_COLON))
+    c_parser_label (parser);
+  *if_p = c_parser_next_token_is_keyword (parser, RID_IF);
+  if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+    {
+      location_t loc = c_parser_peek_token (parser)->location;
+      add_stmt (build_empty_stmt (loc));
+      c_parser_consume_token (parser);
+      if (!c_parser_next_token_is_keyword (parser, RID_ELSE))
+       warning_at (loc, OPT_Wempty_body,
+                   "suggest braces around empty body in an %<if%> statement");
+    }
+  else if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
+    add_stmt (c_parser_compound_statement (parser));
+  else
+    c_parser_statement_after_labels (parser);
+  return c_end_compound_stmt (body_loc, block, flag_isoc99);
+}
+
+/* Parse the else body of an if statement.  This is just parsing a
+   statement but (a) it is a block in C99, (b) we handle an empty body
+   specially for the sake of -Wempty-body warnings.  */
+
+static tree
+c_parser_else_body (c_parser *parser)
+{
+  location_t else_loc = c_parser_peek_token (parser)->location;
+  tree block = c_begin_compound_stmt (flag_isoc99);
+  while (c_parser_next_token_is_keyword (parser, RID_CASE)
+        || c_parser_next_token_is_keyword (parser, RID_DEFAULT)
+        || (c_parser_next_token_is (parser, CPP_NAME)
+            && c_parser_peek_2nd_token (parser)->type == CPP_COLON))
+    c_parser_label (parser);
+  if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+    {
+      location_t loc = c_parser_peek_token (parser)->location;
+      warning_at (loc,
+                 OPT_Wempty_body,
+                "suggest braces around empty body in an %<else%> statement");
+      add_stmt (build_empty_stmt (loc));
+      c_parser_consume_token (parser);
+    }
+  else
+    c_parser_statement_after_labels (parser);
+  return c_end_compound_stmt (else_loc, block, flag_isoc99);
+}
+
+/* Parse an if statement (C90 6.6.4, C99 6.8.4).
+
+   if-statement:
+     if ( expression ) statement
+     if ( expression ) statement else statement
+*/
+
+static void
+c_parser_if_statement (c_parser *parser)
+{
+  tree block;
+  location_t loc;
+  tree cond;
+  bool first_if = false;
+  tree first_body, second_body;
+  bool in_if_block;
+
+  gcc_assert (c_parser_next_token_is_keyword (parser, RID_IF));
+  c_parser_consume_token (parser);
+  block = c_begin_compound_stmt (flag_isoc99);
+  loc = c_parser_peek_token (parser)->location;
+  cond = c_parser_paren_condition (parser);
+  in_if_block = parser->in_if_block;
+  parser->in_if_block = true;
+  first_body = c_parser_if_body (parser, &first_if);
+  parser->in_if_block = in_if_block;
+  if (c_parser_next_token_is_keyword (parser, RID_ELSE))
+    {
+      c_parser_consume_token (parser);
+      second_body = c_parser_else_body (parser);
+    }
+  else
+    second_body = NULL_TREE;
+  c_finish_if_stmt (loc, cond, first_body, second_body, first_if);
+  add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
+}
+
+/* Parse a switch statement (C90 6.6.4, C99 6.8.4).
+
+   switch-statement:
+     switch (expression) statement
+*/
+
+static void
+c_parser_switch_statement (c_parser *parser)
+{
+  tree block, expr, body, save_break;
+  location_t switch_loc = c_parser_peek_token (parser)->location;
+  location_t switch_cond_loc;
+  gcc_assert (c_parser_next_token_is_keyword (parser, RID_SWITCH));
+  c_parser_consume_token (parser);
+  block = c_begin_compound_stmt (flag_isoc99);
+  if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+    {
+      switch_cond_loc = c_parser_peek_token (parser)->location;
+      expr = c_parser_expression (parser).value;
+      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+    }
+  else
+    {
+      switch_cond_loc = UNKNOWN_LOCATION;
+      expr = error_mark_node;
+    }
+  c_start_case (switch_loc, switch_cond_loc, expr);
+  save_break = c_break_label;
+  c_break_label = NULL_TREE;
+  body = c_parser_c99_block_statement (parser);
+  c_finish_case (body);
+  if (c_break_label)
+    {
+      location_t here = c_parser_peek_token (parser)->location;
+      tree t = build1 (LABEL_EXPR, void_type_node, c_break_label);
+      SET_EXPR_LOCATION (t, here);
+      add_stmt (t);
+    }
+  c_break_label = save_break;
+  add_stmt (c_end_compound_stmt (switch_loc, block, flag_isoc99));
+}
+
+/* Parse a while statement (C90 6.6.5, C99 6.8.5).
+
+   while-statement:
+      while (expression) statement
+*/
+
+static void
+c_parser_while_statement (c_parser *parser)
+{
+  tree block, cond, body, save_break, save_cont;
+  location_t loc;
+  gcc_assert (c_parser_next_token_is_keyword (parser, RID_WHILE));
+  c_parser_consume_token (parser);
+  block = c_begin_compound_stmt (flag_isoc99);
+  loc = c_parser_peek_token (parser)->location;
+  cond = c_parser_paren_condition (parser);
+  save_break = c_break_label;
+  c_break_label = NULL_TREE;
+  save_cont = c_cont_label;
+  c_cont_label = NULL_TREE;
+  body = c_parser_c99_block_statement (parser);
+  c_finish_loop (loc, cond, NULL, body, c_break_label, c_cont_label, true);
+  add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
+  c_break_label = save_break;
+  c_cont_label = save_cont;
+}
+
+/* Parse a do statement (C90 6.6.5, C99 6.8.5).
+
+   do-statement:
+     do statement while ( expression ) ;
+*/
+
+static void
+c_parser_do_statement (c_parser *parser)
+{
+  tree block, cond, body, save_break, save_cont, new_break, new_cont;
+  location_t loc;
+  gcc_assert (c_parser_next_token_is_keyword (parser, RID_DO));
+  c_parser_consume_token (parser);
+  if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+    warning_at (c_parser_peek_token (parser)->location,
+               OPT_Wempty_body,
+               "suggest braces around empty body in %<do%> statement");
+  block = c_begin_compound_stmt (flag_isoc99);
+  loc = c_parser_peek_token (parser)->location;
+  save_break = c_break_label;
+  c_break_label = NULL_TREE;
+  save_cont = c_cont_label;
+  c_cont_label = NULL_TREE;
+  body = c_parser_c99_block_statement (parser);
+  c_parser_require_keyword (parser, RID_WHILE, "expected %<while%>");
+  new_break = c_break_label;
+  c_break_label = save_break;
+  new_cont = c_cont_label;
+  c_cont_label = save_cont;
+  cond = c_parser_paren_condition (parser);
+  if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
+    c_parser_skip_to_end_of_block_or_statement (parser);
+  c_finish_loop (loc, cond, NULL, body, new_break, new_cont, false);
+  add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
+}
+
+/* Parse a for statement (C90 6.6.5, C99 6.8.5).
+
+   for-statement:
+     for ( expression[opt] ; expression[opt] ; expression[opt] ) statement
+     for ( nested-declaration expression[opt] ; expression[opt] ) statement
+
+   The form with a declaration is new in C99.
+
+   ??? In accordance with the old parser, the declaration may be a
+   nested function, which is then rejected in check_for_loop_decls,
+   but does it make any sense for this to be included in the grammar?
+   Note in particular that the nested function does not include a
+   trailing ';', whereas the "declaration" production includes one.
+   Also, can we reject bad declarations earlier and cheaper than
+   check_for_loop_decls?
+
+   In Objective-C, there are two additional variants:
+
+   foreach-statement:
+     for ( expression in expresssion ) statement
+     for ( declaration in expression ) statement
+
+   This is inconsistent with C, because the second variant is allowed
+   even if c99 is not enabled.
+
+   The rest of the comment documents these Objective-C foreach-statement.
+
+   Here is the canonical example of the first variant:
+    for (object in array)    { do something with object }
+   we call the first expression ("object") the "object_expression" and 
+   the second expression ("array") the "collection_expression".
+   object_expression must be an lvalue of type "id" (a generic Objective-C
+   object) because the loop works by assigning to object_expression the
+   various objects from the collection_expression.  collection_expression
+   must evaluate to something of type "id" which responds to the method
+   countByEnumeratingWithState:objects:count:.
+
+   The canonical example of the second variant is:
+    for (id object in array)    { do something with object }
+   which is completely equivalent to
+    {
+      id object;
+      for (object in array) { do something with object }
+    }
+   Note that initizializing 'object' in some way (eg, "for ((object =
+   xxx) in array) { do something with object }") is possibly
+   technically valid, but completely pointless as 'object' will be
+   assigned to something else as soon as the loop starts.  We should
+   most likely reject it (TODO).
+
+   The beginning of the Objective-C foreach-statement looks exactly
+   like the beginning of the for-statement, and we can tell it is a
+   foreach-statement only because the initial declaration or
+   expression is terminated by 'in' instead of ';'.
+*/
+
+static void
+c_parser_for_statement (c_parser *parser)
+{
+  tree block, cond, incr, save_break, save_cont, body;
+  /* The following are only used when parsing an ObjC foreach statement.  */
+  tree object_expression;
+  /* Silence the bogus uninitialized warning.  */
+  tree collection_expression = NULL;
+  location_t loc = c_parser_peek_token (parser)->location;
+  location_t for_loc = c_parser_peek_token (parser)->location;
+  bool is_foreach_statement = false;
+  gcc_assert (c_parser_next_token_is_keyword (parser, RID_FOR));
+  c_parser_consume_token (parser);
+  /* Open a compound statement in Objective-C as well, just in case this is
+     as foreach expression.  */
+  block = c_begin_compound_stmt (flag_isoc99 || c_dialect_objc ());
+  cond = error_mark_node;
+  incr = error_mark_node;
+  if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+    {
+      /* Parse the initialization declaration or expression.  */
+      object_expression = error_mark_node;
+      parser->objc_could_be_foreach_context = c_dialect_objc ();
+      if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+       {
+         parser->objc_could_be_foreach_context = false;
+         c_parser_consume_token (parser);
+         c_finish_expr_stmt (loc, NULL_TREE);
+       }
+      else if (c_parser_next_tokens_start_declaration (parser))
+       {
+         c_parser_declaration_or_fndef (parser, true, true, true, true, true, 
+                                        &object_expression);
+         parser->objc_could_be_foreach_context = false;
+         
+         if (c_parser_next_token_is_keyword (parser, RID_IN))
+           {
+             c_parser_consume_token (parser);
+             is_foreach_statement = true;
+             if (check_for_loop_decls (for_loc, true) == NULL_TREE)
+               c_parser_error (parser, "multiple iterating variables in fast enumeration");
+           }
+         else
+           check_for_loop_decls (for_loc, flag_isoc99);
+       }
+      else if (c_parser_next_token_is_keyword (parser, RID_EXTENSION))
+       {
+         /* __extension__ can start a declaration, but is also an
+            unary operator that can start an expression.  Consume all
+            but the last of a possible series of __extension__ to
+            determine which.  */
+         while (c_parser_peek_2nd_token (parser)->type == CPP_KEYWORD
+                && (c_parser_peek_2nd_token (parser)->keyword
+                    == RID_EXTENSION))
+           c_parser_consume_token (parser);
+         if (c_token_starts_declaration (c_parser_peek_2nd_token (parser)))
+           {
+             int ext;
+             ext = disable_extension_diagnostics ();
+             c_parser_consume_token (parser);
+             c_parser_declaration_or_fndef (parser, true, true, true, true,
+                                            true, &object_expression);
+             parser->objc_could_be_foreach_context = false;
+             
+             restore_extension_diagnostics (ext);
+             if (c_parser_next_token_is_keyword (parser, RID_IN))
+               {
+                 c_parser_consume_token (parser);
+                 is_foreach_statement = true;
+                 if (check_for_loop_decls (for_loc, true) == NULL_TREE)
+                   c_parser_error (parser, "multiple iterating variables in fast enumeration");
+               }
+             else
+               check_for_loop_decls (for_loc, flag_isoc99);
+           }
+         else
+           goto init_expr;
+       }
+      else
+       {
+       init_expr:
+         {
+           tree init_expression;
+           init_expression = c_parser_expression (parser).value;
+           parser->objc_could_be_foreach_context = false;
+           if (c_parser_next_token_is_keyword (parser, RID_IN))
+             {
+               c_parser_consume_token (parser);
+               is_foreach_statement = true;
+               if (! lvalue_p (init_expression))
+                 c_parser_error (parser, "invalid iterating variable in fast enumeration");
+               object_expression = c_fully_fold (init_expression, false, NULL);
+             }
+           else
+             {
+               c_finish_expr_stmt (loc, init_expression);
+               c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+             }
+         }
+       }
+      /* Parse the loop condition.  In the case of a foreach
+        statement, there is no loop condition.  */
+      gcc_assert (!parser->objc_could_be_foreach_context);
+      if (!is_foreach_statement)
+       {
+         if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+           {
+             c_parser_consume_token (parser);
+             cond = NULL_TREE;
+           }
+         else
+           {
+             cond = c_parser_condition (parser);
+             c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+           }
+       }
+      /* Parse the increment expression (the third expression in a
+        for-statement).  In the case of a foreach-statement, this is
+        the expression that follows the 'in'.  */
+      if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+       {
+         if (is_foreach_statement)
+           {
+             c_parser_error (parser, "missing collection in fast enumeration");
+             collection_expression = error_mark_node;
+           }
+         else
+           incr = c_process_expr_stmt (loc, NULL_TREE);
+       }
+      else
+       {
+         if (is_foreach_statement)
+           collection_expression = c_fully_fold (c_parser_expression (parser).value,
+                                                 false, NULL);
+         else
+           incr = c_process_expr_stmt (loc, c_parser_expression (parser).value);
+       }
+      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+    }
+  save_break = c_break_label;
+  c_break_label = NULL_TREE;
+  save_cont = c_cont_label;
+  c_cont_label = NULL_TREE;
+  body = c_parser_c99_block_statement (parser);
+  if (is_foreach_statement)
+    objc_finish_foreach_loop (loc, object_expression, collection_expression, body, c_break_label, c_cont_label);
+  else
+    c_finish_loop (loc, cond, incr, body, c_break_label, c_cont_label, true);
+  add_stmt (c_end_compound_stmt (loc, block, flag_isoc99 || c_dialect_objc ()));
+  c_break_label = save_break;
+  c_cont_label = save_cont;
+}
+
+/* Parse an asm statement, a GNU extension.  This is a full-blown asm
+   statement with inputs, outputs, clobbers, and volatile tag
+   allowed.
+
+   asm-statement:
+     asm type-qualifier[opt] ( asm-argument ) ;
+     asm type-qualifier[opt] goto ( asm-goto-argument ) ;
+
+   asm-argument:
+     asm-string-literal
+     asm-string-literal : asm-operands[opt]
+     asm-string-literal : asm-operands[opt] : asm-operands[opt]
+     asm-string-literal : asm-operands[opt] : asm-operands[opt] : asm-clobbers[opt]
+
+   asm-goto-argument:
+     asm-string-literal : : asm-operands[opt] : asm-clobbers[opt] \
+       : asm-goto-operands
+
+   Qualifiers other than volatile are accepted in the syntax but
+   warned for.  */
+
+static tree
+c_parser_asm_statement (c_parser *parser)
+{
+  tree quals, str, outputs, inputs, clobbers, labels, ret;
+  bool simple, is_goto;
+  location_t asm_loc = c_parser_peek_token (parser)->location;
+  int section, nsections;
+
+  gcc_assert (c_parser_next_token_is_keyword (parser, RID_ASM));
+  c_parser_consume_token (parser);
+  if (c_parser_next_token_is_keyword (parser, RID_VOLATILE))
+    {
+      quals = c_parser_peek_token (parser)->value;
+      c_parser_consume_token (parser);
+    }
+  else if (c_parser_next_token_is_keyword (parser, RID_CONST)
+          || c_parser_next_token_is_keyword (parser, RID_RESTRICT))
+    {
+      warning_at (c_parser_peek_token (parser)->location,
+                 0,
+                 "%E qualifier ignored on asm",
+                 c_parser_peek_token (parser)->value);
+      quals = NULL_TREE;
+      c_parser_consume_token (parser);
+    }
+  else
+    quals = NULL_TREE;
+
+  is_goto = false;
+  if (c_parser_next_token_is_keyword (parser, RID_GOTO))
+    {
+      c_parser_consume_token (parser);
+      is_goto = true;
+    }
+
+  /* ??? Follow the C++ parser rather than using the
+     lex_untranslated_string kludge.  */
+  parser->lex_untranslated_string = true;
+  ret = NULL;
+
+  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+    goto error;
+
+  str = c_parser_asm_string_literal (parser);
+  if (str == NULL_TREE)
+    goto error_close_paren;
+
+  simple = true;
+  outputs = NULL_TREE;
+  inputs = NULL_TREE;
+  clobbers = NULL_TREE;
+  labels = NULL_TREE;
+
+  if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN) && !is_goto)
+    goto done_asm;
+
+  /* Parse each colon-delimited section of operands.  */
+  nsections = 3 + is_goto;
+  for (section = 0; section < nsections; ++section)
+    {
+      if (!c_parser_require (parser, CPP_COLON,
+                            is_goto
+                            ? "expected %<:%>"
+                            : "expected %<:%> or %<)%>"))
+       goto error_close_paren;
+
+      /* Once past any colon, we're no longer a simple asm.  */
+      simple = false;
+
+      if ((!c_parser_next_token_is (parser, CPP_COLON)
+          && !c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+         || section == 3)
+       switch (section)
+         {
+         case 0:
+           /* For asm goto, we don't allow output operands, but reserve
+              the slot for a future extension that does allow them.  */
+           if (!is_goto)
+             outputs = c_parser_asm_operands (parser, false);
+           break;
+         case 1:
+           inputs = c_parser_asm_operands (parser, true);
+           break;
+         case 2:
+           clobbers = c_parser_asm_clobbers (parser);
+           break;
+         case 3:
+           labels = c_parser_asm_goto_operands (parser);
+           break;
+         default:
+           gcc_unreachable ();
+         }
+
+      if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN) && !is_goto)
+       goto done_asm;
+    }
+
+ done_asm:
+  if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+    {
+      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+      goto error;
+    }
+
+  if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
+    c_parser_skip_to_end_of_block_or_statement (parser);
+
+  ret = build_asm_stmt (quals, build_asm_expr (asm_loc, str, outputs, inputs,
+                                              clobbers, labels, simple));
+
+ error:
+  parser->lex_untranslated_string = false;
+  return ret;
+
+ error_close_paren:
+  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+  goto error;
+}
+
+/* Parse asm operands, a GNU extension.  If CONVERT_P (for inputs but
+   not outputs), apply the default conversion of functions and arrays
+   to pointers.
+
+   asm-operands:
+     asm-operand
+     asm-operands , asm-operand
+
+   asm-operand:
+     asm-string-literal ( expression )
+     [ identifier ] asm-string-literal ( expression )
+*/
+
+static tree
+c_parser_asm_operands (c_parser *parser, bool convert_p)
+{
+  tree list = NULL_TREE;
+  location_t loc;
+  while (true)
+    {
+      tree name, str;
+      struct c_expr expr;
+      if (c_parser_next_token_is (parser, CPP_OPEN_SQUARE))
+       {
+         c_parser_consume_token (parser);
+         if (c_parser_next_token_is (parser, CPP_NAME))
+           {
+             tree id = c_parser_peek_token (parser)->value;
+             c_parser_consume_token (parser);
+             name = build_string (IDENTIFIER_LENGTH (id),
+                                  IDENTIFIER_POINTER (id));
+           }
+         else
+           {
+             c_parser_error (parser, "expected identifier");
+             c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL);
+             return NULL_TREE;
+           }
+         c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
+                                    "expected %<]%>");
+       }
+      else
+       name = NULL_TREE;
+      str = c_parser_asm_string_literal (parser);
+      if (str == NULL_TREE)
+       return NULL_TREE;
+      parser->lex_untranslated_string = false;
+      if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+       {
+         parser->lex_untranslated_string = true;
+         return NULL_TREE;
+       }
+      loc = c_parser_peek_token (parser)->location;
+      expr = c_parser_expression (parser);
+      mark_exp_read (expr.value);
+      if (convert_p)
+       expr = default_function_array_conversion (loc, expr);
+      expr.value = c_fully_fold (expr.value, false, NULL);
+      parser->lex_untranslated_string = true;
+      if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+       {
+         c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+         return NULL_TREE;
+       }
+      list = chainon (list, build_tree_list (build_tree_list (name, str),
+                                            expr.value));
+      if (c_parser_next_token_is (parser, CPP_COMMA))
+       c_parser_consume_token (parser);
+      else
+       break;
+    }
+  return list;
+}
+
+/* Parse asm clobbers, a GNU extension.
+
+   asm-clobbers:
+     asm-string-literal
+     asm-clobbers , asm-string-literal
+*/
+
+static tree
+c_parser_asm_clobbers (c_parser *parser)
+{
+  tree list = NULL_TREE;
+  while (true)
+    {
+      tree str = c_parser_asm_string_literal (parser);
+      if (str)
+       list = tree_cons (NULL_TREE, str, list);
+      else
+       return NULL_TREE;
+      if (c_parser_next_token_is (parser, CPP_COMMA))
+       c_parser_consume_token (parser);
+      else
+       break;
+    }
+  return list;
+}
+
+/* Parse asm goto labels, a GNU extension.
+
+   asm-goto-operands:
+     identifier
+     asm-goto-operands , identifier
+*/
+
+static tree
+c_parser_asm_goto_operands (c_parser *parser)
+{
+  tree list = NULL_TREE;
+  while (true)
+    {
+      tree name, label;
+
+      if (c_parser_next_token_is (parser, CPP_NAME))
+       {
+         c_token *tok = c_parser_peek_token (parser);
+         name = tok->value;
+         label = lookup_label_for_goto (tok->location, name);
+         c_parser_consume_token (parser);
+         TREE_USED (label) = 1;
+       }
+      else
+       {
+         c_parser_error (parser, "expected identifier");
+         return NULL_TREE;
+       }
+
+      name = build_string (IDENTIFIER_LENGTH (name),
+                          IDENTIFIER_POINTER (name));
+      list = tree_cons (name, label, list);
+      if (c_parser_next_token_is (parser, CPP_COMMA))
+       c_parser_consume_token (parser);
+      else
+       return nreverse (list);
+    }
+}
+
+/* Parse an expression other than a compound expression; that is, an
+   assignment expression (C90 6.3.16, C99 6.5.16).  If AFTER is not
+   NULL then it is an Objective-C message expression which is the
+   primary-expression starting the expression as an initializer.
+
+   assignment-expression:
+     conditional-expression
+     unary-expression assignment-operator assignment-expression
+
+   assignment-operator: one of
+     = *= /= %= += -= <<= >>= &= ^= |=
+
+   In GNU C we accept any conditional expression on the LHS and
+   diagnose the invalid lvalue rather than producing a syntax
+   error.  */
+
+static struct c_expr
+c_parser_expr_no_commas (c_parser *parser, struct c_expr *after)
+{
+  struct c_expr lhs, rhs, ret;
+  enum tree_code code;
+  location_t op_location, exp_location;
+  gcc_assert (!after || c_dialect_objc ());
+  lhs = c_parser_conditional_expression (parser, after);
+  op_location = c_parser_peek_token (parser)->location;
+  switch (c_parser_peek_token (parser)->type)
+    {
+    case CPP_EQ:
+      code = NOP_EXPR;
+      break;
+    case CPP_MULT_EQ:
+      code = MULT_EXPR;
+      break;
+    case CPP_DIV_EQ:
+      code = TRUNC_DIV_EXPR;
+      break;
+    case CPP_MOD_EQ:
+      code = TRUNC_MOD_EXPR;
+      break;
+    case CPP_PLUS_EQ:
+      code = PLUS_EXPR;
+      break;
+    case CPP_MINUS_EQ:
+      code = MINUS_EXPR;
+      break;
+    case CPP_LSHIFT_EQ:
+      code = LSHIFT_EXPR;
+      break;
+    case CPP_RSHIFT_EQ:
+      code = RSHIFT_EXPR;
+      break;
+    case CPP_AND_EQ:
+      code = BIT_AND_EXPR;
+      break;
+    case CPP_XOR_EQ:
+      code = BIT_XOR_EXPR;
+      break;
+    case CPP_OR_EQ:
+      code = BIT_IOR_EXPR;
+      break;
+    default:
+      return lhs;
+    }
+  c_parser_consume_token (parser);
+  exp_location = c_parser_peek_token (parser)->location;
+  rhs = c_parser_expr_no_commas (parser, NULL);
+  rhs = default_function_array_read_conversion (exp_location, rhs);
+  ret.value = build_modify_expr (op_location, lhs.value, lhs.original_type,
+                                code, exp_location, rhs.value,
+                                rhs.original_type);
+  if (code == NOP_EXPR)
+    ret.original_code = MODIFY_EXPR;
+  else
+    {
+      TREE_NO_WARNING (ret.value) = 1;
+      ret.original_code = ERROR_MARK;
+    }
+  ret.original_type = NULL;
+  return ret;
+}
+
+/* Parse a conditional expression (C90 6.3.15, C99 6.5.15).  If AFTER
+   is not NULL then it is an Objective-C message expression which is
+   the primary-expression starting the expression as an initializer.
+
+   conditional-expression:
+     logical-OR-expression
+     logical-OR-expression ? expression : conditional-expression
+
+   GNU extensions:
+
+   conditional-expression:
+     logical-OR-expression ? : conditional-expression
+*/
+
+static struct c_expr
+c_parser_conditional_expression (c_parser *parser, struct c_expr *after)
+{
+  struct c_expr cond, exp1, exp2, ret;
+  location_t cond_loc, colon_loc, middle_loc;
+
+  gcc_assert (!after || c_dialect_objc ());
+
+  cond = c_parser_binary_expression (parser, after, PREC_NONE);
+
+  if (c_parser_next_token_is_not (parser, CPP_QUERY))
+    return cond;
+  cond_loc = c_parser_peek_token (parser)->location;
+  cond = default_function_array_read_conversion (cond_loc, cond);
+  c_parser_consume_token (parser);
+  if (c_parser_next_token_is (parser, CPP_COLON))
+    {
+      tree eptype = NULL_TREE;
+
+      middle_loc = c_parser_peek_token (parser)->location;
+      pedwarn (middle_loc, OPT_Wpedantic, 
+              "ISO C forbids omitting the middle term of a ?: expression");
+      warn_for_omitted_condop (middle_loc, cond.value);
+      if (TREE_CODE (cond.value) == EXCESS_PRECISION_EXPR)
+       {
+         eptype = TREE_TYPE (cond.value);
+         cond.value = TREE_OPERAND (cond.value, 0);
+       }
+      /* Make sure first operand is calculated only once.  */
+      exp1.value = c_save_expr (default_conversion (cond.value));
+      if (eptype)
+       exp1.value = build1 (EXCESS_PRECISION_EXPR, eptype, exp1.value);
+      exp1.original_type = NULL;
+      cond.value = c_objc_common_truthvalue_conversion (cond_loc, exp1.value);
+      c_inhibit_evaluation_warnings += cond.value == truthvalue_true_node;
+    }
+  else
+    {
+      cond.value
+       = c_objc_common_truthvalue_conversion
+       (cond_loc, default_conversion (cond.value));
+      c_inhibit_evaluation_warnings += cond.value == truthvalue_false_node;
+      exp1 = c_parser_expression_conv (parser);
+      mark_exp_read (exp1.value);
+      c_inhibit_evaluation_warnings +=
+       ((cond.value == truthvalue_true_node)
+        - (cond.value == truthvalue_false_node));
+    }
+
+  colon_loc = c_parser_peek_token (parser)->location;
+  if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
+    {
+      c_inhibit_evaluation_warnings -= cond.value == truthvalue_true_node;
+      ret.value = error_mark_node;
+      ret.original_code = ERROR_MARK;
+      ret.original_type = NULL;
+      return ret;
+    }
+  {
+    location_t exp2_loc = c_parser_peek_token (parser)->location;
+    exp2 = c_parser_conditional_expression (parser, NULL);
+    exp2 = default_function_array_read_conversion (exp2_loc, exp2);
+  }
+  c_inhibit_evaluation_warnings -= cond.value == truthvalue_true_node;
+  ret.value = build_conditional_expr (colon_loc, cond.value,
+                                     cond.original_code == C_MAYBE_CONST_EXPR,
+                                     exp1.value, exp1.original_type,
+                                     exp2.value, exp2.original_type);
+  ret.original_code = ERROR_MARK;
+  if (exp1.value == error_mark_node || exp2.value == error_mark_node)
+    ret.original_type = NULL;
+  else
+    {
+      tree t1, t2;
+
+      /* If both sides are enum type, the default conversion will have
+        made the type of the result be an integer type.  We want to
+        remember the enum types we started with.  */
+      t1 = exp1.original_type ? exp1.original_type : TREE_TYPE (exp1.value);
+      t2 = exp2.original_type ? exp2.original_type : TREE_TYPE (exp2.value);
+      ret.original_type = ((t1 != error_mark_node
+                           && t2 != error_mark_node
+                           && (TYPE_MAIN_VARIANT (t1)
+                               == TYPE_MAIN_VARIANT (t2)))
+                          ? t1
+                          : NULL);
+    }
+  return ret;
+}
+
+/* Parse a binary expression; that is, a logical-OR-expression (C90
+   6.3.5-6.3.14, C99 6.5.5-6.5.14).  If AFTER is not NULL then it is
+   an Objective-C message expression which is the primary-expression
+   starting the expression as an initializer.  PREC is the starting
+   precedence, usually PREC_NONE.
+
+   multiplicative-expression:
+     cast-expression
+     multiplicative-expression * cast-expression
+     multiplicative-expression / cast-expression
+     multiplicative-expression % cast-expression
+
+   additive-expression:
+     multiplicative-expression
+     additive-expression + multiplicative-expression
+     additive-expression - multiplicative-expression
+
+   shift-expression:
+     additive-expression
+     shift-expression << additive-expression
+     shift-expression >> additive-expression
+
+   relational-expression:
+     shift-expression
+     relational-expression < shift-expression
+     relational-expression > shift-expression
+     relational-expression <= shift-expression
+     relational-expression >= shift-expression
+
+   equality-expression:
+     relational-expression
+     equality-expression == relational-expression
+     equality-expression != relational-expression
+
+   AND-expression:
+     equality-expression
+     AND-expression & equality-expression
+
+   exclusive-OR-expression:
+     AND-expression
+     exclusive-OR-expression ^ AND-expression
+
+   inclusive-OR-expression:
+     exclusive-OR-expression
+     inclusive-OR-expression | exclusive-OR-expression
+
+   logical-AND-expression:
+     inclusive-OR-expression
+     logical-AND-expression && inclusive-OR-expression
+
+   logical-OR-expression:
+     logical-AND-expression
+     logical-OR-expression || logical-AND-expression
+*/
+
+static struct c_expr
+c_parser_binary_expression (c_parser *parser, struct c_expr *after,
+                           enum c_parser_prec prec)
+{
+  /* A binary expression is parsed using operator-precedence parsing,
+     with the operands being cast expressions.  All the binary
+     operators are left-associative.  Thus a binary expression is of
+     form:
+
+     E0 op1 E1 op2 E2 ...
+
+     which we represent on a stack.  On the stack, the precedence
+     levels are strictly increasing.  When a new operator is
+     encountered of higher precedence than that at the top of the
+     stack, it is pushed; its LHS is the top expression, and its RHS
+     is everything parsed until it is popped.  When a new operator is
+     encountered with precedence less than or equal to that at the top
+     of the stack, triples E[i-1] op[i] E[i] are popped and replaced
+     by the result of the operation until the operator at the top of
+     the stack has lower precedence than the new operator or there is
+     only one element on the stack; then the top expression is the LHS
+     of the new operator.  In the case of logical AND and OR
+     expressions, we also need to adjust c_inhibit_evaluation_warnings
+     as appropriate when the operators are pushed and popped.  */
+
+  struct {
+    /* The expression at this stack level.  */
+    struct c_expr expr;
+    /* The precedence of the operator on its left, PREC_NONE at the
+       bottom of the stack.  */
+    enum c_parser_prec prec;
+    /* The operation on its left.  */
+    enum tree_code op;
+    /* The source location of this operation.  */
+    location_t loc;
+  } stack[NUM_PRECS];
+  int sp;
+  /* Location of the binary operator.  */
+  location_t binary_loc = UNKNOWN_LOCATION;  /* Quiet warning.  */
+#define POP                                                                  \
+  do {                                                                       \
+    switch (stack[sp].op)                                                    \
+      {                                                                              \
+      case TRUTH_ANDIF_EXPR:                                                 \
+       c_inhibit_evaluation_warnings -= (stack[sp - 1].expr.value            \
+                                         == truthvalue_false_node);          \
+       break;                                                                \
+      case TRUTH_ORIF_EXPR:                                                  \
+       c_inhibit_evaluation_warnings -= (stack[sp - 1].expr.value            \
+                                         == truthvalue_true_node);           \
+       break;                                                                \
+      default:                                                               \
+       break;                                                                \
+      }                                                                              \
+    stack[sp - 1].expr                                                       \
+      = default_function_array_read_conversion (stack[sp - 1].loc,           \
+                                               stack[sp - 1].expr);          \
+    stack[sp].expr                                                           \
+      = default_function_array_read_conversion (stack[sp].loc,               \
+                                               stack[sp].expr);              \
+    stack[sp - 1].expr = parser_build_binary_op (stack[sp].loc,                      \
+                                                stack[sp].op,                \
+                                                stack[sp - 1].expr,          \
+                                                stack[sp].expr);             \
+    sp--;                                                                    \
+  } while (0)
+  gcc_assert (!after || c_dialect_objc ());
+  stack[0].loc = c_parser_peek_token (parser)->location;
+  stack[0].expr = c_parser_cast_expression (parser, after);
+  stack[0].prec = prec;
+  sp = 0;
+  while (true)
+    {
+      enum c_parser_prec oprec;
+      enum tree_code ocode;
+      if (parser->error)
+       goto out;
+      switch (c_parser_peek_token (parser)->type)
+       {
+       case CPP_MULT:
+         oprec = PREC_MULT;
+         ocode = MULT_EXPR;
+         break;
+       case CPP_DIV:
+         oprec = PREC_MULT;
+         ocode = TRUNC_DIV_EXPR;
+         break;
+       case CPP_MOD:
+         oprec = PREC_MULT;
+         ocode = TRUNC_MOD_EXPR;
+         break;
+       case CPP_PLUS:
+         oprec = PREC_ADD;
+         ocode = PLUS_EXPR;
+         break;
+       case CPP_MINUS:
+         oprec = PREC_ADD;
+         ocode = MINUS_EXPR;
+         break;
+       case CPP_LSHIFT:
+         oprec = PREC_SHIFT;
+         ocode = LSHIFT_EXPR;
+         break;
+       case CPP_RSHIFT:
+         oprec = PREC_SHIFT;
+         ocode = RSHIFT_EXPR;
+         break;
+       case CPP_LESS:
+         oprec = PREC_REL;
+         ocode = LT_EXPR;
+         break;
+       case CPP_GREATER:
+         oprec = PREC_REL;
+         ocode = GT_EXPR;
+         break;
+       case CPP_LESS_EQ:
+         oprec = PREC_REL;
+         ocode = LE_EXPR;
+         break;
+       case CPP_GREATER_EQ:
+         oprec = PREC_REL;
+         ocode = GE_EXPR;
+         break;
+       case CPP_EQ_EQ:
+         oprec = PREC_EQ;
+         ocode = EQ_EXPR;
+         break;
+       case CPP_NOT_EQ:
+         oprec = PREC_EQ;
+         ocode = NE_EXPR;
+         break;
+       case CPP_AND:
+         oprec = PREC_BITAND;
+         ocode = BIT_AND_EXPR;
+         break;
+       case CPP_XOR:
+         oprec = PREC_BITXOR;
+         ocode = BIT_XOR_EXPR;
+         break;
+       case CPP_OR:
+         oprec = PREC_BITOR;
+         ocode = BIT_IOR_EXPR;
+         break;
+       case CPP_AND_AND:
+         oprec = PREC_LOGAND;
+         ocode = TRUTH_ANDIF_EXPR;
+         break;
+       case CPP_OR_OR:
+         oprec = PREC_LOGOR;
+         ocode = TRUTH_ORIF_EXPR;
+         break;
+       default:
+         /* Not a binary operator, so end of the binary
+            expression.  */
+         goto out;
+       }
+      binary_loc = c_parser_peek_token (parser)->location;
+      while (oprec <= stack[sp].prec)
+       {
+         if (sp == 0)
+           goto out;
+         POP;
+       }
+      c_parser_consume_token (parser);
+      switch (ocode)
+       {
+       case TRUTH_ANDIF_EXPR:
+         stack[sp].expr
+           = default_function_array_read_conversion (stack[sp].loc,
+                                                     stack[sp].expr);
+         stack[sp].expr.value = c_objc_common_truthvalue_conversion
+           (stack[sp].loc, default_conversion (stack[sp].expr.value));
+         c_inhibit_evaluation_warnings += (stack[sp].expr.value
+                                           == truthvalue_false_node);
+         break;
+       case TRUTH_ORIF_EXPR:
+         stack[sp].expr
+           = default_function_array_read_conversion (stack[sp].loc,
+                                                     stack[sp].expr);
+         stack[sp].expr.value = c_objc_common_truthvalue_conversion
+           (stack[sp].loc, default_conversion (stack[sp].expr.value));
+         c_inhibit_evaluation_warnings += (stack[sp].expr.value
+                                           == truthvalue_true_node);
+         break;
+       default:
+         break;
+       }
+      sp++;
+      stack[sp].loc = binary_loc;
+      stack[sp].expr = c_parser_cast_expression (parser, NULL);
+      stack[sp].prec = oprec;
+      stack[sp].op = ocode;
+      stack[sp].loc = binary_loc;
+    }
+ out:
+  while (sp > 0)
+    POP;
+  return stack[0].expr;
+#undef POP
+}
+
+/* Parse a cast expression (C90 6.3.4, C99 6.5.4).  If AFTER is not
+   NULL then it is an Objective-C message expression which is the
+   primary-expression starting the expression as an initializer.
+
+   cast-expression:
+     unary-expression
+     ( type-name ) unary-expression
+*/
+
+static struct c_expr
+c_parser_cast_expression (c_parser *parser, struct c_expr *after)
+{
+  location_t cast_loc = c_parser_peek_token (parser)->location;
+  gcc_assert (!after || c_dialect_objc ());
+  if (after)
+    return c_parser_postfix_expression_after_primary (parser,
+                                                     cast_loc, *after);
+  /* If the expression begins with a parenthesized type name, it may
+     be either a cast or a compound literal; we need to see whether
+     the next character is '{' to tell the difference.  If not, it is
+     an unary expression.  Full detection of unknown typenames here
+     would require a 3-token lookahead.  */
+  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
+      && c_token_starts_typename (c_parser_peek_2nd_token (parser)))
+    {
+      struct c_type_name *type_name;
+      struct c_expr ret;
+      struct c_expr expr;
+      c_parser_consume_token (parser);
+      type_name = c_parser_type_name (parser);
+      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+      if (type_name == NULL)
+       {
+         ret.value = error_mark_node;
+         ret.original_code = ERROR_MARK;
+         ret.original_type = NULL;
+         return ret;
+       }
+
+      /* Save casted types in the function's used types hash table.  */
+      used_types_insert (type_name->specs->type);
+
+      if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
+       return c_parser_postfix_expression_after_paren_type (parser, type_name,
+                                                            cast_loc);
+      {
+       location_t expr_loc = c_parser_peek_token (parser)->location;
+       expr = c_parser_cast_expression (parser, NULL);
+       expr = default_function_array_read_conversion (expr_loc, expr);
+      }
+      ret.value = c_cast_expr (cast_loc, type_name, expr.value);
+      ret.original_code = ERROR_MARK;
+      ret.original_type = NULL;
+      return ret;
+    }
+  else
+    return c_parser_unary_expression (parser);
+}
+
+/* Parse an unary expression (C90 6.3.3, C99 6.5.3).
+
+   unary-expression:
+     postfix-expression
+     ++ unary-expression
+     -- unary-expression
+     unary-operator cast-expression
+     sizeof unary-expression
+     sizeof ( type-name )
+
+   unary-operator: one of
+     & * + - ~ !
+
+   GNU extensions:
+
+   unary-expression:
+     __alignof__ unary-expression
+     __alignof__ ( type-name )
+     && identifier
+
+   (C11 permits _Alignof with type names only.)
+
+   unary-operator: one of
+     __extension__ __real__ __imag__
+
+   Transactional Memory:
+
+   unary-expression:
+     transaction-expression
+
+   In addition, the GNU syntax treats ++ and -- as unary operators, so
+   they may be applied to cast expressions with errors for non-lvalues
+   given later.  */
+
+static struct c_expr
+c_parser_unary_expression (c_parser *parser)
+{
+  int ext;
+  struct c_expr ret, op;
+  location_t op_loc = c_parser_peek_token (parser)->location;
+  location_t exp_loc;
+  ret.original_code = ERROR_MARK;
+  ret.original_type = NULL;
+  switch (c_parser_peek_token (parser)->type)
+    {
+    case CPP_PLUS_PLUS:
+      c_parser_consume_token (parser);
+      exp_loc = c_parser_peek_token (parser)->location;
+      op = c_parser_cast_expression (parser, NULL);
+      op = default_function_array_read_conversion (exp_loc, op);
+      return parser_build_unary_op (op_loc, PREINCREMENT_EXPR, op);
+    case CPP_MINUS_MINUS:
+      c_parser_consume_token (parser);
+      exp_loc = c_parser_peek_token (parser)->location;
+      op = c_parser_cast_expression (parser, NULL);
+      op = default_function_array_read_conversion (exp_loc, op);
+      return parser_build_unary_op (op_loc, PREDECREMENT_EXPR, op);
+    case CPP_AND:
+      c_parser_consume_token (parser);
+      op = c_parser_cast_expression (parser, NULL);
+      mark_exp_read (op.value);
+      return parser_build_unary_op (op_loc, ADDR_EXPR, op);
+    case CPP_MULT:
+      c_parser_consume_token (parser);
+      exp_loc = c_parser_peek_token (parser)->location;
+      op = c_parser_cast_expression (parser, NULL);
+      op = default_function_array_read_conversion (exp_loc, op);
+      ret.value = build_indirect_ref (op_loc, op.value, RO_UNARY_STAR);
+      return ret;
+    case CPP_PLUS:
+      if (!c_dialect_objc () && !in_system_header)
+       warning_at (op_loc,
+                   OPT_Wtraditional,
+                   "traditional C rejects the unary plus operator");
+      c_parser_consume_token (parser);
+      exp_loc = c_parser_peek_token (parser)->location;
+      op = c_parser_cast_expression (parser, NULL);
+      op = default_function_array_read_conversion (exp_loc, op);
+      return parser_build_unary_op (op_loc, CONVERT_EXPR, op);
+    case CPP_MINUS:
+      c_parser_consume_token (parser);
+      exp_loc = c_parser_peek_token (parser)->location;
+      op = c_parser_cast_expression (parser, NULL);
+      op = default_function_array_read_conversion (exp_loc, op);
+      return parser_build_unary_op (op_loc, NEGATE_EXPR, op);
+    case CPP_COMPL:
+      c_parser_consume_token (parser);
+      exp_loc = c_parser_peek_token (parser)->location;
+      op = c_parser_cast_expression (parser, NULL);
+      op = default_function_array_read_conversion (exp_loc, op);
+      return parser_build_unary_op (op_loc, BIT_NOT_EXPR, op);
+    case CPP_NOT:
+      c_parser_consume_token (parser);
+      exp_loc = c_parser_peek_token (parser)->location;
+      op = c_parser_cast_expression (parser, NULL);
+      op = default_function_array_read_conversion (exp_loc, op);
+      return parser_build_unary_op (op_loc, TRUTH_NOT_EXPR, op);
+    case CPP_AND_AND:
+      /* Refer to the address of a label as a pointer.  */
+      c_parser_consume_token (parser);
+      if (c_parser_next_token_is (parser, CPP_NAME))
+       {
+         ret.value = finish_label_address_expr
+           (c_parser_peek_token (parser)->value, op_loc);
+         c_parser_consume_token (parser);
+       }
+      else
+       {
+         c_parser_error (parser, "expected identifier");
+         ret.value = error_mark_node;
+       }
+       return ret;
+    case CPP_KEYWORD:
+      switch (c_parser_peek_token (parser)->keyword)
+       {
+       case RID_SIZEOF:
+         return c_parser_sizeof_expression (parser);
+       case RID_ALIGNOF:
+         return c_parser_alignof_expression (parser);
+       case RID_EXTENSION:
+         c_parser_consume_token (parser);
+         ext = disable_extension_diagnostics ();
+         ret = c_parser_cast_expression (parser, NULL);
+         restore_extension_diagnostics (ext);
+         return ret;
+       case RID_REALPART:
+         c_parser_consume_token (parser);
+         exp_loc = c_parser_peek_token (parser)->location;
+         op = c_parser_cast_expression (parser, NULL);
+         op = default_function_array_conversion (exp_loc, op);
+         return parser_build_unary_op (op_loc, REALPART_EXPR, op);
+       case RID_IMAGPART:
+         c_parser_consume_token (parser);
+         exp_loc = c_parser_peek_token (parser)->location;
+         op = c_parser_cast_expression (parser, NULL);
+         op = default_function_array_conversion (exp_loc, op);
+         return parser_build_unary_op (op_loc, IMAGPART_EXPR, op);
+       case RID_TRANSACTION_ATOMIC:
+       case RID_TRANSACTION_RELAXED:
+         return c_parser_transaction_expression (parser,
+             c_parser_peek_token (parser)->keyword);
+       default:
+         return c_parser_postfix_expression (parser);
+       }
+    default:
+      return c_parser_postfix_expression (parser);
+    }
+}
+
+/* Parse a sizeof expression.  */
+
+static struct c_expr
+c_parser_sizeof_expression (c_parser *parser)
+{
+  struct c_expr expr;
+  location_t expr_loc;
+  gcc_assert (c_parser_next_token_is_keyword (parser, RID_SIZEOF));
+  c_parser_consume_token (parser);
+  c_inhibit_evaluation_warnings++;
+  in_sizeof++;
+  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
+      && c_token_starts_typename (c_parser_peek_2nd_token (parser)))
+    {
+      /* Either sizeof ( type-name ) or sizeof unary-expression
+        starting with a compound literal.  */
+      struct c_type_name *type_name;
+      c_parser_consume_token (parser);
+      expr_loc = c_parser_peek_token (parser)->location;
+      type_name = c_parser_type_name (parser);
+      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+      if (type_name == NULL)
+       {
+         struct c_expr ret;
+         c_inhibit_evaluation_warnings--;
+         in_sizeof--;
+         ret.value = error_mark_node;
+         ret.original_code = ERROR_MARK;
+         ret.original_type = NULL;
+         return ret;
+       }
+      if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
+       {
+         expr = c_parser_postfix_expression_after_paren_type (parser,
+                                                              type_name,
+                                                              expr_loc);
+         goto sizeof_expr;
+       }
+      /* sizeof ( type-name ).  */
+      c_inhibit_evaluation_warnings--;
+      in_sizeof--;
+      return c_expr_sizeof_type (expr_loc, type_name);
+    }
+  else
+    {
+      expr_loc = c_parser_peek_token (parser)->location;
+      expr = c_parser_unary_expression (parser);
+    sizeof_expr:
+      c_inhibit_evaluation_warnings--;
+      in_sizeof--;
+      mark_exp_read (expr.value);
+      if (TREE_CODE (expr.value) == COMPONENT_REF
+         && DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1)))
+       error_at (expr_loc, "%<sizeof%> applied to a bit-field");
+      return c_expr_sizeof_expr (expr_loc, expr);
+    }
+}
+
+/* Parse an alignof expression.  */
+
+static struct c_expr
+c_parser_alignof_expression (c_parser *parser)
+{
+  struct c_expr expr;
+  location_t loc = c_parser_peek_token (parser)->location;
+  tree alignof_spelling = c_parser_peek_token (parser)->value;
+  gcc_assert (c_parser_next_token_is_keyword (parser, RID_ALIGNOF));
+  /* A diagnostic is not required for the use of this identifier in
+     the implementation namespace; only diagnose it for the C11
+     spelling because of existing code using the other spellings.  */
+  if (!flag_isoc11
+      && strcmp (IDENTIFIER_POINTER (alignof_spelling), "_Alignof") == 0)
+    {
+      if (flag_isoc99)
+       pedwarn (loc, OPT_Wpedantic, "ISO C99 does not support %qE",
+                alignof_spelling);
+      else
+       pedwarn (loc, OPT_Wpedantic, "ISO C90 does not support %qE",
+                alignof_spelling);
+    }
+  c_parser_consume_token (parser);
+  c_inhibit_evaluation_warnings++;
+  in_alignof++;
+  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
+      && c_token_starts_typename (c_parser_peek_2nd_token (parser)))
+    {
+      /* Either __alignof__ ( type-name ) or __alignof__
+        unary-expression starting with a compound literal.  */
+      location_t loc;
+      struct c_type_name *type_name;
+      struct c_expr ret;
+      c_parser_consume_token (parser);
+      loc = c_parser_peek_token (parser)->location;
+      type_name = c_parser_type_name (parser);
+      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+      if (type_name == NULL)
+       {
+         struct c_expr ret;
+         c_inhibit_evaluation_warnings--;
+         in_alignof--;
+         ret.value = error_mark_node;
+         ret.original_code = ERROR_MARK;
+         ret.original_type = NULL;
+         return ret;
+       }
+      if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
+       {
+         expr = c_parser_postfix_expression_after_paren_type (parser,
+                                                              type_name,
+                                                              loc);
+         goto alignof_expr;
+       }
+      /* alignof ( type-name ).  */
+      c_inhibit_evaluation_warnings--;
+      in_alignof--;
+      ret.value = c_alignof (loc, groktypename (type_name, NULL, NULL));
+      ret.original_code = ERROR_MARK;
+      ret.original_type = NULL;
+      return ret;
+    }
+  else
+    {
+      struct c_expr ret;
+      expr = c_parser_unary_expression (parser);
+    alignof_expr:
+      mark_exp_read (expr.value);
+      c_inhibit_evaluation_warnings--;
+      in_alignof--;
+      pedwarn (loc, OPT_Wpedantic, "ISO C does not allow %<%E (expression)%>",
+              alignof_spelling);
+      ret.value = c_alignof_expr (loc, expr.value);
+      ret.original_code = ERROR_MARK;
+      ret.original_type = NULL;
+      return ret;
+    }
+}
+
+/* Helper function to read arguments of builtins which are interfaces
+   for the middle-end nodes like COMPLEX_EXPR, VEC_PERM_EXPR and
+   others.  The name of the builtin is passed using BNAME parameter.
+   Function returns true if there were no errors while parsing and
+   stores the arguments in CEXPR_LIST.  */
+static bool
+c_parser_get_builtin_args (c_parser *parser, const char *bname,
+                          VEC(c_expr_t,gc) **ret_cexpr_list)
+{
+  location_t loc = c_parser_peek_token (parser)->location;
+  VEC (c_expr_t,gc) *cexpr_list;
+  c_expr_t expr;
+
+  *ret_cexpr_list = NULL;
+  if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN))
+    {
+      error_at (loc, "cannot take address of %qs", bname);
+      return false;
+    }
+
+  c_parser_consume_token (parser);
+
+  if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+    {
+      c_parser_consume_token (parser);
+      return true;
+    }
+
+  expr = c_parser_expr_no_commas (parser, NULL);
+  cexpr_list = VEC_alloc (c_expr_t, gc, 1);
+  C_EXPR_APPEND (cexpr_list, expr);
+  while (c_parser_next_token_is (parser, CPP_COMMA))
+    {
+      c_parser_consume_token (parser);
+      expr = c_parser_expr_no_commas (parser, NULL);
+      C_EXPR_APPEND (cexpr_list, expr);
+    }
+
+  if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+    return false;
+
+  *ret_cexpr_list = cexpr_list;
+  return true;
+}
+
+
+/* Parse a postfix expression (C90 6.3.1-6.3.2, C99 6.5.1-6.5.2).
+
+   postfix-expression:
+     primary-expression
+     postfix-expression [ expression ]
+     postfix-expression ( argument-expression-list[opt] )
+     postfix-expression . identifier
+     postfix-expression -> identifier
+     postfix-expression ++
+     postfix-expression --
+     ( type-name ) { initializer-list }
+     ( type-name ) { initializer-list , }
+
+   argument-expression-list:
+     argument-expression
+     argument-expression-list , argument-expression
+
+   primary-expression:
+     identifier
+     constant
+     string-literal
+     ( expression )
+
+   GNU extensions:
+
+   primary-expression:
+     __func__
+       (treated as a keyword in GNU C)
+     __FUNCTION__
+     __PRETTY_FUNCTION__
+     ( compound-statement )
+     __builtin_va_arg ( assignment-expression , type-name )
+     __builtin_offsetof ( type-name , offsetof-member-designator )
+     __builtin_choose_expr ( assignment-expression ,
+                            assignment-expression ,
+                            assignment-expression )
+     __builtin_types_compatible_p ( type-name , type-name )
+     __builtin_complex ( assignment-expression , assignment-expression )
+     __builtin_shuffle ( assignment-expression , assignment-expression )
+     __builtin_shuffle ( assignment-expression , 
+                        assignment-expression ,
+                        assignment-expression, )
+
+   offsetof-member-designator:
+     identifier
+     offsetof-member-designator . identifier
+     offsetof-member-designator [ expression ]
+
+   Objective-C:
+
+   primary-expression:
+     [ objc-receiver objc-message-args ]
+     @selector ( objc-selector-arg )
+     @protocol ( identifier )
+     @encode ( type-name )
+     objc-string-literal
+     Classname . identifier
+*/
+
+static struct c_expr
+c_parser_postfix_expression (c_parser *parser)
+{
+  struct c_expr expr, e1;
+  struct c_type_name *t1, *t2;
+  location_t loc = c_parser_peek_token (parser)->location;;
+  expr.original_code = ERROR_MARK;
+  expr.original_type = NULL;
+  switch (c_parser_peek_token (parser)->type)
+    {
+    case CPP_NUMBER:
+      expr.value = c_parser_peek_token (parser)->value;
+      loc = c_parser_peek_token (parser)->location;
+      c_parser_consume_token (parser);
+      if (TREE_CODE (expr.value) == FIXED_CST
+         && !targetm.fixed_point_supported_p ())
+       {
+         error_at (loc, "fixed-point types not supported for this target");
+         expr.value = error_mark_node;
+       }
+      break;
+    case CPP_CHAR:
+    case CPP_CHAR16:
+    case CPP_CHAR32:
+    case CPP_WCHAR:
+      expr.value = c_parser_peek_token (parser)->value;
+      c_parser_consume_token (parser);
+      break;
+    case CPP_STRING:
+    case CPP_STRING16:
+    case CPP_STRING32:
+    case CPP_WSTRING:
+    case CPP_UTF8STRING:
+      expr.value = c_parser_peek_token (parser)->value;
+      expr.original_code = STRING_CST;
+      c_parser_consume_token (parser);
+      break;
+    case CPP_OBJC_STRING:
+      gcc_assert (c_dialect_objc ());
+      expr.value
+       = objc_build_string_object (c_parser_peek_token (parser)->value);
+      c_parser_consume_token (parser);
+      break;
+    case CPP_NAME:
+      switch (c_parser_peek_token (parser)->id_kind)
+       {
+       case C_ID_ID:
+         {
+           tree id = c_parser_peek_token (parser)->value;
+           c_parser_consume_token (parser);
+           expr.value = build_external_ref (loc, id,
+                                            (c_parser_peek_token (parser)->type
+                                             == CPP_OPEN_PAREN),
+                                            &expr.original_type);
+           break;
+         }
+       case C_ID_CLASSNAME:
+         {
+           /* Here we parse the Objective-C 2.0 Class.name dot
+              syntax.  */
+           tree class_name = c_parser_peek_token (parser)->value;
+           tree component;
+           c_parser_consume_token (parser);
+           gcc_assert (c_dialect_objc ());
+           if (!c_parser_require (parser, CPP_DOT, "expected %<.%>"))
+             {
+               expr.value = error_mark_node;
+               break;
+             }
+           if (c_parser_next_token_is_not (parser, CPP_NAME))
+             {
+               c_parser_error (parser, "expected identifier");
+               expr.value = error_mark_node;
+               break;
+             }
+           component = c_parser_peek_token (parser)->value;
+           c_parser_consume_token (parser);
+           expr.value = objc_build_class_component_ref (class_name, 
+                                                        component);
+           break;
+         }
+       default:
+         c_parser_error (parser, "expected expression");
+         expr.value = error_mark_node;
+         break;
+       }
+      break;
+    case CPP_OPEN_PAREN:
+      /* A parenthesized expression, statement expression or compound
+        literal.  */
+      if (c_parser_peek_2nd_token (parser)->type == CPP_OPEN_BRACE)
+       {
+         /* A statement expression.  */
+         tree stmt;
+         location_t brace_loc;
+         c_parser_consume_token (parser);
+         brace_loc = c_parser_peek_token (parser)->location;
+         c_parser_consume_token (parser);
+         if (!building_stmt_list_p ())
+           {
+             error_at (loc, "braced-group within expression allowed "
+                       "only inside a function");
+             parser->error = true;
+             c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
+             c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+             expr.value = error_mark_node;
+             break;
+           }
+         stmt = c_begin_stmt_expr ();
+         c_parser_compound_statement_nostart (parser);
+         c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+                                    "expected %<)%>");
+         pedwarn (loc, OPT_Wpedantic,
+                  "ISO C forbids braced-groups within expressions");
+         expr.value = c_finish_stmt_expr (brace_loc, stmt);
+         mark_exp_read (expr.value);
+       }
+      else if (c_token_starts_typename (c_parser_peek_2nd_token (parser)))
+       {
+         /* A compound literal.  ??? Can we actually get here rather
+            than going directly to
+            c_parser_postfix_expression_after_paren_type from
+            elsewhere?  */
+         location_t loc;
+         struct c_type_name *type_name;
+         c_parser_consume_token (parser);
+         loc = c_parser_peek_token (parser)->location;
+         type_name = c_parser_type_name (parser);
+         c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+                                    "expected %<)%>");
+         if (type_name == NULL)
+           {
+             expr.value = error_mark_node;
+           }
+         else
+           expr = c_parser_postfix_expression_after_paren_type (parser,
+                                                                type_name,
+                                                                loc);
+       }
+      else
+       {
+         /* A parenthesized expression.  */
+         c_parser_consume_token (parser);
+         expr = c_parser_expression (parser);
+         if (TREE_CODE (expr.value) == MODIFY_EXPR)
+           TREE_NO_WARNING (expr.value) = 1;
+         if (expr.original_code != C_MAYBE_CONST_EXPR)
+           expr.original_code = ERROR_MARK;
+         /* Don't change EXPR.ORIGINAL_TYPE.  */
+         c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+                                    "expected %<)%>");
+       }
+      break;
+    case CPP_KEYWORD:
+      switch (c_parser_peek_token (parser)->keyword)
+       {
+       case RID_FUNCTION_NAME:
+       case RID_PRETTY_FUNCTION_NAME:
+       case RID_C99_FUNCTION_NAME:
+         expr.value = fname_decl (loc,
+                                  c_parser_peek_token (parser)->keyword,
+                                  c_parser_peek_token (parser)->value);
+         c_parser_consume_token (parser);
+         break;
+       case RID_VA_ARG:
+         c_parser_consume_token (parser);
+         if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+           {
+             expr.value = error_mark_node;
+             break;
+           }
+         e1 = c_parser_expr_no_commas (parser, NULL);
+         mark_exp_read (e1.value);
+         e1.value = c_fully_fold (e1.value, false, NULL);
+         if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
+           {
+             c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+             expr.value = error_mark_node;
+             break;
+           }
+         loc = c_parser_peek_token (parser)->location;
+         t1 = c_parser_type_name (parser);
+         c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+                                    "expected %<)%>");
+         if (t1 == NULL)
+           {
+             expr.value = error_mark_node;
+           }
+         else
+           {
+             tree type_expr = NULL_TREE;
+             expr.value = c_build_va_arg (loc, e1.value,
+                                          groktypename (t1, &type_expr, NULL));
+             if (type_expr)
+               {
+                 expr.value = build2 (C_MAYBE_CONST_EXPR,
+                                      TREE_TYPE (expr.value), type_expr,
+                                      expr.value);
+                 C_MAYBE_CONST_EXPR_NON_CONST (expr.value) = true;
+               }
+           }
+         break;
+       case RID_OFFSETOF:
+         c_parser_consume_token (parser);
+         if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+           {
+             expr.value = error_mark_node;
+             break;
+           }
+         t1 = c_parser_type_name (parser);
+         if (t1 == NULL)
+           parser->error = true;
+         if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
+            gcc_assert (parser->error);
+         if (parser->error)
+           {
+             c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+             expr.value = error_mark_node;
+             break;
+           }
+
+         {
+           tree type = groktypename (t1, NULL, NULL);
+           tree offsetof_ref;
+           if (type == error_mark_node)
+             offsetof_ref = error_mark_node;
+           else
+             {
+               offsetof_ref = build1 (INDIRECT_REF, type, null_pointer_node);
+               SET_EXPR_LOCATION (offsetof_ref, loc);
+             }
+           /* Parse the second argument to __builtin_offsetof.  We
+              must have one identifier, and beyond that we want to
+              accept sub structure and sub array references.  */
+           if (c_parser_next_token_is (parser, CPP_NAME))
+             {
+               offsetof_ref = build_component_ref
+                 (loc, offsetof_ref, c_parser_peek_token (parser)->value);
+               c_parser_consume_token (parser);
+               while (c_parser_next_token_is (parser, CPP_DOT)
+                      || c_parser_next_token_is (parser,
+                                                 CPP_OPEN_SQUARE)
+                      || c_parser_next_token_is (parser,
+                                                 CPP_DEREF))
+                 {
+                   if (c_parser_next_token_is (parser, CPP_DEREF))
+                     {
+                       loc = c_parser_peek_token (parser)->location;
+                       offsetof_ref = build_array_ref (loc,
+                                                       offsetof_ref,
+                                                       integer_zero_node);
+                       goto do_dot;
+                     }
+                   else if (c_parser_next_token_is (parser, CPP_DOT))
+                     {
+                     do_dot:
+                       c_parser_consume_token (parser);
+                       if (c_parser_next_token_is_not (parser,
+                                                       CPP_NAME))
+                         {
+                           c_parser_error (parser, "expected identifier");
+                           break;
+                         }
+                       offsetof_ref = build_component_ref
+                         (loc, offsetof_ref,
+                          c_parser_peek_token (parser)->value);
+                       c_parser_consume_token (parser);
+                     }
+                   else
+                     {
+                       tree idx;
+                       loc = c_parser_peek_token (parser)->location;
+                       c_parser_consume_token (parser);
+                       idx = c_parser_expression (parser).value;
+                       idx = c_fully_fold (idx, false, NULL);
+                       c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
+                                                  "expected %<]%>");
+                       offsetof_ref = build_array_ref (loc, offsetof_ref, idx);
+                     }
+                 }
+             }
+           else
+             c_parser_error (parser, "expected identifier");
+           c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+                                      "expected %<)%>");
+           expr.value = fold_offsetof (offsetof_ref);
+         }
+         break;
+       case RID_CHOOSE_EXPR:
+         {
+           VEC (c_expr_t, gc) *cexpr_list;
+           c_expr_t *e1_p, *e2_p, *e3_p;
+           tree c;
+
+           c_parser_consume_token (parser);
+           if (!c_parser_get_builtin_args (parser,
+                                           "__builtin_choose_expr",
+                                           &cexpr_list))
+             {
+               expr.value = error_mark_node;
+               break;
+             }
+
+           if (VEC_length (c_expr_t, cexpr_list) != 3)
+             {
+               error_at (loc, "wrong number of arguments to "
+                              "%<__builtin_choose_expr%>");
+               expr.value = error_mark_node;
+               break;
+             }
+
+           e1_p = VEC_index (c_expr_t, cexpr_list, 0);
+           e2_p = VEC_index (c_expr_t, cexpr_list, 1);
+           e3_p = VEC_index (c_expr_t, cexpr_list, 2);
+
+           c = e1_p->value;
+           mark_exp_read (e2_p->value);
+           mark_exp_read (e3_p->value);
+           if (TREE_CODE (c) != INTEGER_CST
+               || !INTEGRAL_TYPE_P (TREE_TYPE (c)))
+             error_at (loc,
+                       "first argument to %<__builtin_choose_expr%> not"
+                       " a constant");
+           constant_expression_warning (c);
+           expr = integer_zerop (c) ? *e3_p : *e2_p;
+           break;
+         }
+       case RID_TYPES_COMPATIBLE_P:
+         c_parser_consume_token (parser);
+         if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+           {
+             expr.value = error_mark_node;
+             break;
+           }
+         t1 = c_parser_type_name (parser);
+         if (t1 == NULL)
+           {
+             expr.value = error_mark_node;
+             break;
+           }
+         if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
+           {
+             c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+             expr.value = error_mark_node;
+             break;
+           }
+         t2 = c_parser_type_name (parser);
+         if (t2 == NULL)
+           {
+             expr.value = error_mark_node;
+             break;
+           }
+         c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+                                    "expected %<)%>");
+         {
+           tree e1, e2;
+           e1 = groktypename (t1, NULL, NULL);
+           e2 = groktypename (t2, NULL, NULL);
+           if (e1 == error_mark_node || e2 == error_mark_node)
+             {
+               expr.value = error_mark_node;
+               break;
+             }
+
+           e1 = TYPE_MAIN_VARIANT (e1);
+           e2 = TYPE_MAIN_VARIANT (e2);
+
+           expr.value
+             = comptypes (e1, e2) ? integer_one_node : integer_zero_node;
+         }
+         break;
+       case RID_BUILTIN_COMPLEX:
+         {
+           VEC(c_expr_t, gc) *cexpr_list;
+           c_expr_t *e1_p, *e2_p;
+
+           c_parser_consume_token (parser);
+           if (!c_parser_get_builtin_args (parser,
+                                           "__builtin_complex",
+                                           &cexpr_list))
+             {
+               expr.value = error_mark_node;
+               break;
+             }
+
+           if (VEC_length (c_expr_t, cexpr_list) != 2)
+             {
+               error_at (loc, "wrong number of arguments to "
+                              "%<__builtin_complex%>");
+               expr.value = error_mark_node;
+               break;
+             }
+
+           e1_p = VEC_index (c_expr_t, cexpr_list, 0);
+           e2_p = VEC_index (c_expr_t, cexpr_list, 1);
+
+           mark_exp_read (e1_p->value);
+           if (TREE_CODE (e1_p->value) == EXCESS_PRECISION_EXPR)
+             e1_p->value = convert (TREE_TYPE (e1_p->value),
+                                    TREE_OPERAND (e1_p->value, 0));
+           mark_exp_read (e2_p->value);
+           if (TREE_CODE (e2_p->value) == EXCESS_PRECISION_EXPR)
+             e2_p->value = convert (TREE_TYPE (e2_p->value),
+                                    TREE_OPERAND (e2_p->value, 0));
+           if (!SCALAR_FLOAT_TYPE_P (TREE_TYPE (e1_p->value))
+               || DECIMAL_FLOAT_TYPE_P (TREE_TYPE (e1_p->value))
+               || !SCALAR_FLOAT_TYPE_P (TREE_TYPE (e2_p->value))
+               || DECIMAL_FLOAT_TYPE_P (TREE_TYPE (e2_p->value)))
+             {
+               error_at (loc, "%<__builtin_complex%> operand "
+                         "not of real binary floating-point type");
+               expr.value = error_mark_node;
+               break;
+             }
+           if (TYPE_MAIN_VARIANT (TREE_TYPE (e1_p->value))
+               != TYPE_MAIN_VARIANT (TREE_TYPE (e2_p->value)))
+             {
+               error_at (loc,
+                         "%<__builtin_complex%> operands of different types");
+               expr.value = error_mark_node;
+               break;
+             }
+           if (!flag_isoc99)
+             pedwarn (loc, OPT_Wpedantic,
+                      "ISO C90 does not support complex types");
+           expr.value = build2 (COMPLEX_EXPR,
+                                build_complex_type
+                                  (TYPE_MAIN_VARIANT
+                                    (TREE_TYPE (e1_p->value))),
+                                e1_p->value, e2_p->value);
+           break;
+         }
+       case RID_BUILTIN_SHUFFLE:
+         {
+           VEC(c_expr_t,gc) *cexpr_list;
+           unsigned int i;
+           c_expr_t *p;
+
+           c_parser_consume_token (parser);
+           if (!c_parser_get_builtin_args (parser,
+                                           "__builtin_shuffle",
+                                           &cexpr_list))
+             {
+               expr.value = error_mark_node;
+               break;
+             }
+
+           FOR_EACH_VEC_ELT (c_expr_t, cexpr_list, i, p)
+             mark_exp_read (p->value);
+
+           if (VEC_length (c_expr_t, cexpr_list) == 2)
+             expr.value =
+               c_build_vec_perm_expr
+                 (loc, VEC_index (c_expr_t, cexpr_list, 0)->value,
+                  NULL_TREE, VEC_index (c_expr_t, cexpr_list, 1)->value);
+
+           else if (VEC_length (c_expr_t, cexpr_list) == 3)
+             expr.value =
+               c_build_vec_perm_expr
+                 (loc, VEC_index (c_expr_t, cexpr_list, 0)->value,
+                  VEC_index (c_expr_t, cexpr_list, 1)->value,
+                  VEC_index (c_expr_t, cexpr_list, 2)->value);
+           else
+             {
+               error_at (loc, "wrong number of arguments to "
+                              "%<__builtin_shuffle%>");
+               expr.value = error_mark_node;
+             }
+           break;
+         }
+       case RID_AT_SELECTOR:
+         gcc_assert (c_dialect_objc ());
+         c_parser_consume_token (parser);
+         if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+           {
+             expr.value = error_mark_node;
+             break;
+           }
+         {
+           tree sel = c_parser_objc_selector_arg (parser);
+           c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+                                      "expected %<)%>");
+           expr.value = objc_build_selector_expr (loc, sel);
+         }
+         break;
+       case RID_AT_PROTOCOL:
+         gcc_assert (c_dialect_objc ());
+         c_parser_consume_token (parser);
+         if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+           {
+             expr.value = error_mark_node;
+             break;
+           }
+         if (c_parser_next_token_is_not (parser, CPP_NAME))
+           {
+             c_parser_error (parser, "expected identifier");
+             c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+             expr.value = error_mark_node;
+             break;
+           }
+         {
+           tree id = c_parser_peek_token (parser)->value;
+           c_parser_consume_token (parser);
+           c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+                                      "expected %<)%>");
+           expr.value = objc_build_protocol_expr (id);
+         }
+         break;
+       case RID_AT_ENCODE:
+         /* Extension to support C-structures in the archiver.  */
+         gcc_assert (c_dialect_objc ());
+         c_parser_consume_token (parser);
+         if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+           {
+             expr.value = error_mark_node;
+             break;
+           }
+         t1 = c_parser_type_name (parser);
+         if (t1 == NULL)
+           {
+             expr.value = error_mark_node;
+             c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+             break;
+           }
+         c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+                                    "expected %<)%>");
+         {
+           tree type = groktypename (t1, NULL, NULL);
+           expr.value = objc_build_encode_expr (type);
+         }
+         break;
+       default:
+         c_parser_error (parser, "expected expression");
+         expr.value = error_mark_node;
+         break;
+       }
+      break;
+    case CPP_OPEN_SQUARE:
+      if (c_dialect_objc ())
+       {
+         tree receiver, args;
+         c_parser_consume_token (parser);
+         receiver = c_parser_objc_receiver (parser);
+         args = c_parser_objc_message_args (parser);
+         c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
+                                    "expected %<]%>");
+         expr.value = objc_build_message_expr (receiver, args);
+         break;
+       }
+      /* Else fall through to report error.  */
+    default:
+      c_parser_error (parser, "expected expression");
+      expr.value = error_mark_node;
+      break;
+    }
+  return c_parser_postfix_expression_after_primary (parser, loc, expr);
+}
+
+/* Parse a postfix expression after a parenthesized type name: the
+   brace-enclosed initializer of a compound literal, possibly followed
+   by some postfix operators.  This is separate because it is not
+   possible to tell until after the type name whether a cast
+   expression has a cast or a compound literal, or whether the operand
+   of sizeof is a parenthesized type name or starts with a compound
+   literal.  TYPE_LOC is the location where TYPE_NAME starts--the
+   location of the first token after the parentheses around the type
+   name.  */
+
+static struct c_expr
+c_parser_postfix_expression_after_paren_type (c_parser *parser,
+                                             struct c_type_name *type_name,
+                                             location_t type_loc)
+{
+  tree type;
+  struct c_expr init;
+  bool non_const;
+  struct c_expr expr;
+  location_t start_loc;
+  tree type_expr = NULL_TREE;
+  bool type_expr_const = true;
+  check_compound_literal_type (type_loc, type_name);
+  start_init (NULL_TREE, NULL, 0);
+  type = groktypename (type_name, &type_expr, &type_expr_const);
+  start_loc = c_parser_peek_token (parser)->location;
+  if (type != error_mark_node && C_TYPE_VARIABLE_SIZE (type))
+    {
+      error_at (type_loc, "compound literal has variable size");
+      type = error_mark_node;
+    }
+  init = c_parser_braced_init (parser, type, false);
+  finish_init ();
+  maybe_warn_string_init (type, init);
+
+  if (type != error_mark_node
+      && !ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (type))
+      && current_function_decl)
+    {
+      error ("compound literal qualified by address-space qualifier");
+      type = error_mark_node;
+    }
+
+  if (!flag_isoc99)
+    pedwarn (start_loc, OPT_Wpedantic, "ISO C90 forbids compound literals");
+  non_const = ((init.value && TREE_CODE (init.value) == CONSTRUCTOR)
+              ? CONSTRUCTOR_NON_CONST (init.value)
+              : init.original_code == C_MAYBE_CONST_EXPR);
+  non_const |= !type_expr_const;
+  expr.value = build_compound_literal (start_loc, type, init.value, non_const);
+  expr.original_code = ERROR_MARK;
+  expr.original_type = NULL;
+  if (type_expr)
+    {
+      if (TREE_CODE (expr.value) == C_MAYBE_CONST_EXPR)
+       {
+         gcc_assert (C_MAYBE_CONST_EXPR_PRE (expr.value) == NULL_TREE);
+         C_MAYBE_CONST_EXPR_PRE (expr.value) = type_expr;
+       }
+      else
+       {
+         gcc_assert (!non_const);
+         expr.value = build2 (C_MAYBE_CONST_EXPR, type,
+                              type_expr, expr.value);
+       }
+    }
+  return c_parser_postfix_expression_after_primary (parser, start_loc, expr);
+}
+
+/* Parse a postfix expression after the initial primary or compound
+   literal; that is, parse a series of postfix operators.
+
+   EXPR_LOC is the location of the primary expression.  */
+
+static struct c_expr
+c_parser_postfix_expression_after_primary (c_parser *parser,
+                                          location_t expr_loc,
+                                          struct c_expr expr)
+{
+  struct c_expr orig_expr;
+  tree ident, idx;
+  VEC(tree,gc) *exprlist;
+  VEC(tree,gc) *origtypes;
+  while (true)
+    {
+      location_t op_loc = c_parser_peek_token (parser)->location;
+      switch (c_parser_peek_token (parser)->type)
+       {
+       case CPP_OPEN_SQUARE:
+         /* Array reference.  */
+         c_parser_consume_token (parser);
+         idx = c_parser_expression (parser).value;
+         c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
+                                    "expected %<]%>");
+         expr.value = build_array_ref (op_loc, expr.value, idx);
+         expr.original_code = ERROR_MARK;
+         expr.original_type = NULL;
+         break;
+       case CPP_OPEN_PAREN:
+         /* Function call.  */
+         c_parser_consume_token (parser);
+         if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+           exprlist = NULL;
+         else
+           exprlist = c_parser_expr_list (parser, true, false, &origtypes);
+         c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+                                    "expected %<)%>");
+         orig_expr = expr;
+         mark_exp_read (expr.value);
+         /* FIXME diagnostics: Ideally we want the FUNCNAME, not the
+            "(" after the FUNCNAME, which is what we have now.    */
+         expr.value = build_function_call_vec (op_loc, expr.value, exprlist,
+                                               origtypes);
+         expr.original_code = ERROR_MARK;
+         if (TREE_CODE (expr.value) == INTEGER_CST
+             && TREE_CODE (orig_expr.value) == FUNCTION_DECL
+             && DECL_BUILT_IN_CLASS (orig_expr.value) == BUILT_IN_NORMAL
+             && DECL_FUNCTION_CODE (orig_expr.value) == BUILT_IN_CONSTANT_P)
+           expr.original_code = C_MAYBE_CONST_EXPR;
+         expr.original_type = NULL;
+         if (exprlist != NULL)
+           {
+             release_tree_vector (exprlist);
+             release_tree_vector (origtypes);
+           }
+         break;
+       case CPP_DOT:
+         /* Structure element reference.  */
+         c_parser_consume_token (parser);
+         expr = default_function_array_conversion (expr_loc, expr);
+         if (c_parser_next_token_is (parser, CPP_NAME))
+           ident = c_parser_peek_token (parser)->value;
+         else
+           {
+             c_parser_error (parser, "expected identifier");
+             expr.value = error_mark_node;
+             expr.original_code = ERROR_MARK;
+              expr.original_type = NULL;
+             return expr;
+           }
+         c_parser_consume_token (parser);
+         expr.value = build_component_ref (op_loc, expr.value, ident);
+         expr.original_code = ERROR_MARK;
+         if (TREE_CODE (expr.value) != COMPONENT_REF)
+           expr.original_type = NULL;
+         else
+           {
+             /* Remember the original type of a bitfield.  */
+             tree field = TREE_OPERAND (expr.value, 1);
+             if (TREE_CODE (field) != FIELD_DECL)
+               expr.original_type = NULL;
+             else
+               expr.original_type = DECL_BIT_FIELD_TYPE (field);
+           }
+         break;
+       case CPP_DEREF:
+         /* Structure element reference.  */
+         c_parser_consume_token (parser);
+         expr = default_function_array_conversion (expr_loc, expr);
+         if (c_parser_next_token_is (parser, CPP_NAME))
+           ident = c_parser_peek_token (parser)->value;
+         else
+           {
+             c_parser_error (parser, "expected identifier");
+             expr.value = error_mark_node;
+             expr.original_code = ERROR_MARK;
+             expr.original_type = NULL;
+             return expr;
+           }
+         c_parser_consume_token (parser);
+         expr.value = build_component_ref (op_loc,
+                                           build_indirect_ref (op_loc,
+                                                               expr.value,
+                                                               RO_ARROW),
+                                           ident);
+         expr.original_code = ERROR_MARK;
+         if (TREE_CODE (expr.value) != COMPONENT_REF)
+           expr.original_type = NULL;
+         else
+           {
+             /* Remember the original type of a bitfield.  */
+             tree field = TREE_OPERAND (expr.value, 1);
+             if (TREE_CODE (field) != FIELD_DECL)
+               expr.original_type = NULL;
+             else
+               expr.original_type = DECL_BIT_FIELD_TYPE (field);
+           }
+         break;
+       case CPP_PLUS_PLUS:
+         /* Postincrement.  */
+         c_parser_consume_token (parser);
+         expr = default_function_array_read_conversion (expr_loc, expr);
+         expr.value = build_unary_op (op_loc,
+                                      POSTINCREMENT_EXPR, expr.value, 0);
+         expr.original_code = ERROR_MARK;
+         expr.original_type = NULL;
+         break;
+       case CPP_MINUS_MINUS:
+         /* Postdecrement.  */
+         c_parser_consume_token (parser);
+         expr = default_function_array_read_conversion (expr_loc, expr);
+         expr.value = build_unary_op (op_loc,
+                                      POSTDECREMENT_EXPR, expr.value, 0);
+         expr.original_code = ERROR_MARK;
+         expr.original_type = NULL;
+         break;
+       default:
+         return expr;
+       }
+    }
+}
+
+/* Parse an expression (C90 6.3.17, C99 6.5.17).
+
+   expression:
+     assignment-expression
+     expression , assignment-expression
+*/
+
+static struct c_expr
+c_parser_expression (c_parser *parser)
+{
+  struct c_expr expr;
+  expr = c_parser_expr_no_commas (parser, NULL);
+  while (c_parser_next_token_is (parser, CPP_COMMA))
+    {
+      struct c_expr next;
+      tree lhsval;
+      location_t loc = c_parser_peek_token (parser)->location;
+      location_t expr_loc;
+      c_parser_consume_token (parser);
+      expr_loc = c_parser_peek_token (parser)->location;
+      lhsval = expr.value;
+      while (TREE_CODE (lhsval) == COMPOUND_EXPR)
+       lhsval = TREE_OPERAND (lhsval, 1);
+      if (DECL_P (lhsval) || handled_component_p (lhsval))
+       mark_exp_read (lhsval);
+      next = c_parser_expr_no_commas (parser, NULL);
+      next = default_function_array_conversion (expr_loc, next);
+      expr.value = build_compound_expr (loc, expr.value, next.value);
+      expr.original_code = COMPOUND_EXPR;
+      expr.original_type = next.original_type;
+    }
+  return expr;
+}
+
+/* Parse an expression and convert functions or arrays to
+   pointers.  */
+
+static struct c_expr
+c_parser_expression_conv (c_parser *parser)
+{
+  struct c_expr expr;
+  location_t loc = c_parser_peek_token (parser)->location;
+  expr = c_parser_expression (parser);
+  expr = default_function_array_conversion (loc, expr);
+  return expr;
+}
+
+/* Parse a non-empty list of expressions.  If CONVERT_P, convert
+   functions and arrays to pointers.  If FOLD_P, fold the expressions.
+
+   nonempty-expr-list:
+     assignment-expression
+     nonempty-expr-list , assignment-expression
+*/
+
+static VEC(tree,gc) *
+c_parser_expr_list (c_parser *parser, bool convert_p, bool fold_p,
+                   VEC(tree,gc) **p_orig_types)
+{
+  VEC(tree,gc) *ret;
+  VEC(tree,gc) *orig_types;
+  struct c_expr expr;
+  location_t loc = c_parser_peek_token (parser)->location;
+
+  ret = make_tree_vector ();
+  if (p_orig_types == NULL)
+    orig_types = NULL;
+  else
+    orig_types = make_tree_vector ();
+
+  expr = c_parser_expr_no_commas (parser, NULL);
+  if (convert_p)
+    expr = default_function_array_read_conversion (loc, expr);
+  if (fold_p)
+    expr.value = c_fully_fold (expr.value, false, NULL);
+  VEC_quick_push (tree, ret, expr.value);
+  if (orig_types != NULL)
+    VEC_quick_push (tree, orig_types, expr.original_type);
+  while (c_parser_next_token_is (parser, CPP_COMMA))
+    {
+      c_parser_consume_token (parser);
+      loc = c_parser_peek_token (parser)->location;
+      expr = c_parser_expr_no_commas (parser, NULL);
+      if (convert_p)
+       expr = default_function_array_read_conversion (loc, expr);
+      if (fold_p)
+       expr.value = c_fully_fold (expr.value, false, NULL);
+      VEC_safe_push (tree, gc, ret, expr.value);
+      if (orig_types != NULL)
+       VEC_safe_push (tree, gc, orig_types, expr.original_type);
+    }
+  if (orig_types != NULL)
+    *p_orig_types = orig_types;
+  return ret;
+}
+\f
+/* Parse Objective-C-specific constructs.  */
+
+/* Parse an objc-class-definition.
+
+   objc-class-definition:
+     @interface identifier objc-superclass[opt] objc-protocol-refs[opt]
+       objc-class-instance-variables[opt] objc-methodprotolist @end
+     @implementation identifier objc-superclass[opt]
+       objc-class-instance-variables[opt]
+     @interface identifier ( identifier ) objc-protocol-refs[opt]
+       objc-methodprotolist @end
+     @interface identifier ( ) objc-protocol-refs[opt]
+       objc-methodprotolist @end
+     @implementation identifier ( identifier )
+
+   objc-superclass:
+     : identifier
+
+   "@interface identifier (" must start "@interface identifier (
+   identifier ) ...": objc-methodprotolist in the first production may
+   not start with a parenthesized identifier as a declarator of a data
+   definition with no declaration specifiers if the objc-superclass,
+   objc-protocol-refs and objc-class-instance-variables are omitted.  */
+
+static void
+c_parser_objc_class_definition (c_parser *parser, tree attributes)
+{
+  bool iface_p;
+  tree id1;
+  tree superclass;
+  if (c_parser_next_token_is_keyword (parser, RID_AT_INTERFACE))
+    iface_p = true;
+  else if (c_parser_next_token_is_keyword (parser, RID_AT_IMPLEMENTATION))
+    iface_p = false;
+  else
+    gcc_unreachable ();
+
+  c_parser_consume_token (parser);
+  if (c_parser_next_token_is_not (parser, CPP_NAME))
+    {
+      c_parser_error (parser, "expected identifier");
+      return;
+    }
+  id1 = c_parser_peek_token (parser)->value;
+  c_parser_consume_token (parser);
+  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+    {
+      /* We have a category or class extension.  */
+      tree id2;
+      tree proto = NULL_TREE;
+      c_parser_consume_token (parser);
+      if (c_parser_next_token_is_not (parser, CPP_NAME))
+       {
+         if (iface_p && c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+           {
+             /* We have a class extension.  */
+             id2 = NULL_TREE;
+           }
+         else
+           {
+             c_parser_error (parser, "expected identifier or %<)%>");
+             c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+             return;
+           }
+       }
+      else
+       {
+         id2 = c_parser_peek_token (parser)->value;
+         c_parser_consume_token (parser);
+       }
+      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+      if (!iface_p)
+       {
+         objc_start_category_implementation (id1, id2);
+         return;
+       }
+      if (c_parser_next_token_is (parser, CPP_LESS))
+       proto = c_parser_objc_protocol_refs (parser);
+      objc_start_category_interface (id1, id2, proto, attributes);
+      c_parser_objc_methodprotolist (parser);
+      c_parser_require_keyword (parser, RID_AT_END, "expected %<@end%>");
+      objc_finish_interface ();
+      return;
+    }
+  if (c_parser_next_token_is (parser, CPP_COLON))
+    {
+      c_parser_consume_token (parser);
+      if (c_parser_next_token_is_not (parser, CPP_NAME))
+       {
+         c_parser_error (parser, "expected identifier");
+         return;
+       }
+      superclass = c_parser_peek_token (parser)->value;
+      c_parser_consume_token (parser);
+    }
+  else
+    superclass = NULL_TREE;
+  if (iface_p)
+    {
+      tree proto = NULL_TREE;
+      if (c_parser_next_token_is (parser, CPP_LESS))
+       proto = c_parser_objc_protocol_refs (parser);
+      objc_start_class_interface (id1, superclass, proto, attributes);
+    }
+  else
+    objc_start_class_implementation (id1, superclass);
+  if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
+    c_parser_objc_class_instance_variables (parser);
+  if (iface_p)
+    {
+      objc_continue_interface ();
+      c_parser_objc_methodprotolist (parser);
+      c_parser_require_keyword (parser, RID_AT_END, "expected %<@end%>");
+      objc_finish_interface ();
+    }
+  else
+    {
+      objc_continue_implementation ();
+      return;
+    }
+}
+
+/* Parse objc-class-instance-variables.
+
+   objc-class-instance-variables:
+     { objc-instance-variable-decl-list[opt] }
+
+   objc-instance-variable-decl-list:
+     objc-visibility-spec
+     objc-instance-variable-decl ;
+     ;
+     objc-instance-variable-decl-list objc-visibility-spec
+     objc-instance-variable-decl-list objc-instance-variable-decl ;
+     objc-instance-variable-decl-list ;
+
+   objc-visibility-spec:
+     @private
+     @protected
+     @public
+
+   objc-instance-variable-decl:
+     struct-declaration
+*/
+
+static void
+c_parser_objc_class_instance_variables (c_parser *parser)
+{
+  gcc_assert (c_parser_next_token_is (parser, CPP_OPEN_BRACE));
+  c_parser_consume_token (parser);
+  while (c_parser_next_token_is_not (parser, CPP_EOF))
+    {
+      tree decls;
+      /* Parse any stray semicolon.  */
+      if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+       {
+         pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic,
+                  "extra semicolon");
+         c_parser_consume_token (parser);
+         continue;
+       }
+      /* Stop if at the end of the instance variables.  */
+      if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
+       {
+         c_parser_consume_token (parser);
+         break;
+       }
+      /* Parse any objc-visibility-spec.  */
+      if (c_parser_next_token_is_keyword (parser, RID_AT_PRIVATE))
+       {
+         c_parser_consume_token (parser);
+         objc_set_visibility (OBJC_IVAR_VIS_PRIVATE);
+         continue;
+       }
+      else if (c_parser_next_token_is_keyword (parser, RID_AT_PROTECTED))
+       {
+         c_parser_consume_token (parser);
+         objc_set_visibility (OBJC_IVAR_VIS_PROTECTED);
+         continue;
+       }
+      else if (c_parser_next_token_is_keyword (parser, RID_AT_PUBLIC))
+       {
+         c_parser_consume_token (parser);
+         objc_set_visibility (OBJC_IVAR_VIS_PUBLIC);
+         continue;
+       }
+      else if (c_parser_next_token_is_keyword (parser, RID_AT_PACKAGE))
+       {
+         c_parser_consume_token (parser);
+         objc_set_visibility (OBJC_IVAR_VIS_PACKAGE);
+         continue;
+       }
+      else if (c_parser_next_token_is (parser, CPP_PRAGMA))
+       {
+         c_parser_pragma (parser, pragma_external);
+         continue;
+       }
+
+      /* Parse some comma-separated declarations.  */
+      decls = c_parser_struct_declaration (parser);
+      if (decls == NULL)
+       {
+         /* There is a syntax error.  We want to skip the offending
+            tokens up to the next ';' (included) or '}'
+            (excluded).  */
+         
+         /* First, skip manually a ')' or ']'.  This is because they
+            reduce the nesting level, so c_parser_skip_until_found()
+            wouldn't be able to skip past them.  */
+         c_token *token = c_parser_peek_token (parser);
+         if (token->type == CPP_CLOSE_PAREN || token->type == CPP_CLOSE_SQUARE)
+           c_parser_consume_token (parser);
+
+         /* Then, do the standard skipping.  */
+         c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
+
+         /* We hopefully recovered.  Start normal parsing again.  */
+         parser->error = false;
+         continue;
+       }
+      else
+       {
+         /* Comma-separated instance variables are chained together
+            in reverse order; add them one by one.  */
+         tree ivar = nreverse (decls);
+         for (; ivar; ivar = DECL_CHAIN (ivar))
+           objc_add_instance_variable (copy_node (ivar));
+       }
+      c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+    }
+}
+
+/* Parse an objc-class-declaration.
+
+   objc-class-declaration:
+     @class identifier-list ;
+*/
+
+static void
+c_parser_objc_class_declaration (c_parser *parser)
+{
+  gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_CLASS));
+  c_parser_consume_token (parser);
+  /* Any identifiers, including those declared as type names, are OK
+     here.  */
+  while (true)
+    {
+      tree id;
+      if (c_parser_next_token_is_not (parser, CPP_NAME))
+       {
+         c_parser_error (parser, "expected identifier");
+         c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
+         parser->error = false;
+         return;
+       }
+      id = c_parser_peek_token (parser)->value;
+      objc_declare_class (id);
+      c_parser_consume_token (parser);
+      if (c_parser_next_token_is (parser, CPP_COMMA))
+       c_parser_consume_token (parser);
+      else
+       break;
+    }
+  c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+}
+
+/* Parse an objc-alias-declaration.
+
+   objc-alias-declaration:
+     @compatibility_alias identifier identifier ;
+*/
+
+static void
+c_parser_objc_alias_declaration (c_parser *parser)
+{
+  tree id1, id2;
+  gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_ALIAS));
+  c_parser_consume_token (parser);
+  if (c_parser_next_token_is_not (parser, CPP_NAME))
+    {
+      c_parser_error (parser, "expected identifier");
+      c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
+      return;
+    }
+  id1 = c_parser_peek_token (parser)->value;
+  c_parser_consume_token (parser);
+  if (c_parser_next_token_is_not (parser, CPP_NAME))
+    {
+      c_parser_error (parser, "expected identifier");
+      c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
+      return;
+    }
+  id2 = c_parser_peek_token (parser)->value;
+  c_parser_consume_token (parser);
+  c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+  objc_declare_alias (id1, id2);
+}
+
+/* Parse an objc-protocol-definition.
+
+   objc-protocol-definition:
+     @protocol identifier objc-protocol-refs[opt] objc-methodprotolist @end
+     @protocol identifier-list ;
+
+   "@protocol identifier ;" should be resolved as "@protocol
+   identifier-list ;": objc-methodprotolist may not start with a
+   semicolon in the first alternative if objc-protocol-refs are
+   omitted.  */
+
+static void
+c_parser_objc_protocol_definition (c_parser *parser, tree attributes)
+{
+  gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_PROTOCOL));
+
+  c_parser_consume_token (parser);
+  if (c_parser_next_token_is_not (parser, CPP_NAME))
+    {
+      c_parser_error (parser, "expected identifier");
+      return;
+    }
+  if (c_parser_peek_2nd_token (parser)->type == CPP_COMMA
+      || c_parser_peek_2nd_token (parser)->type == CPP_SEMICOLON)
+    {
+      /* Any identifiers, including those declared as type names, are
+        OK here.  */
+      while (true)
+       {
+         tree id;
+         if (c_parser_next_token_is_not (parser, CPP_NAME))
+           {
+             c_parser_error (parser, "expected identifier");
+             break;
+           }
+         id = c_parser_peek_token (parser)->value;
+         objc_declare_protocol (id, attributes);
+         c_parser_consume_token (parser);
+         if (c_parser_next_token_is (parser, CPP_COMMA))
+           c_parser_consume_token (parser);
+         else
+           break;
+       }
+      c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+    }
+  else
+    {
+      tree id = c_parser_peek_token (parser)->value;
+      tree proto = NULL_TREE;
+      c_parser_consume_token (parser);
+      if (c_parser_next_token_is (parser, CPP_LESS))
+       proto = c_parser_objc_protocol_refs (parser);
+      parser->objc_pq_context = true;
+      objc_start_protocol (id, proto, attributes);
+      c_parser_objc_methodprotolist (parser);
+      c_parser_require_keyword (parser, RID_AT_END, "expected %<@end%>");
+      parser->objc_pq_context = false;
+      objc_finish_interface ();
+    }
+}
+
+/* Parse an objc-method-type.
+
+   objc-method-type:
+     +
+     -
+
+   Return true if it is a class method (+) and false if it is
+   an instance method (-).
+*/
+static inline bool
+c_parser_objc_method_type (c_parser *parser)
+{
+  switch (c_parser_peek_token (parser)->type)
+    {
+    case CPP_PLUS:
+      c_parser_consume_token (parser);
+      return true;
+    case CPP_MINUS:
+      c_parser_consume_token (parser);
+      return false;
+    default:
+      gcc_unreachable ();
+    }
+}
+
+/* Parse an objc-method-definition.
+
+   objc-method-definition:
+     objc-method-type objc-method-decl ;[opt] compound-statement
+*/
+
+static void
+c_parser_objc_method_definition (c_parser *parser)
+{
+  bool is_class_method = c_parser_objc_method_type (parser);
+  tree decl, attributes = NULL_TREE, expr = NULL_TREE;
+  parser->objc_pq_context = true;
+  decl = c_parser_objc_method_decl (parser, is_class_method, &attributes,
+                                   &expr);
+  if (decl == error_mark_node)
+    return;  /* Bail here. */
+
+  if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+    {
+      c_parser_consume_token (parser);
+      pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic,
+              "extra semicolon in method definition specified");
+    }
+
+  if (!c_parser_next_token_is (parser, CPP_OPEN_BRACE))
+    {
+      c_parser_error (parser, "expected %<{%>");
+      return;
+    }
+
+  parser->objc_pq_context = false;
+  if (objc_start_method_definition (is_class_method, decl, attributes, expr))
+    {
+      add_stmt (c_parser_compound_statement (parser));
+      objc_finish_method_definition (current_function_decl);
+    }
+  else
+    {
+      /* This code is executed when we find a method definition
+        outside of an @implementation context (or invalid for other
+        reasons).  Parse the method (to keep going) but do not emit
+        any code.
+      */
+      c_parser_compound_statement (parser);
+    }
+}
+
+/* Parse an objc-methodprotolist.
+
+   objc-methodprotolist:
+     empty
+     objc-methodprotolist objc-methodproto
+     objc-methodprotolist declaration
+     objc-methodprotolist ;
+     @optional
+     @required
+
+   The declaration is a data definition, which may be missing
+   declaration specifiers under the same rules and diagnostics as
+   other data definitions outside functions, and the stray semicolon
+   is diagnosed the same way as a stray semicolon outside a
+   function.  */
+
+static void
+c_parser_objc_methodprotolist (c_parser *parser)
+{
+  while (true)
+    {
+      /* The list is terminated by @end.  */
+      switch (c_parser_peek_token (parser)->type)
+       {
+       case CPP_SEMICOLON:
+         pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic,
+                  "ISO C does not allow extra %<;%> outside of a function");
+         c_parser_consume_token (parser);
+         break;
+       case CPP_PLUS:
+       case CPP_MINUS:
+         c_parser_objc_methodproto (parser);
+         break;
+       case CPP_PRAGMA:
+         c_parser_pragma (parser, pragma_external);
+         break;
+       case CPP_EOF:
+         return;
+       default:
+         if (c_parser_next_token_is_keyword (parser, RID_AT_END))
+           return;
+         else if (c_parser_next_token_is_keyword (parser, RID_AT_PROPERTY))
+           c_parser_objc_at_property_declaration (parser);
+         else if (c_parser_next_token_is_keyword (parser, RID_AT_OPTIONAL))
+           {
+             objc_set_method_opt (true);
+             c_parser_consume_token (parser);
+           }
+         else if (c_parser_next_token_is_keyword (parser, RID_AT_REQUIRED))
+           {
+             objc_set_method_opt (false);
+             c_parser_consume_token (parser);
+           }
+         else
+           c_parser_declaration_or_fndef (parser, false, false, true,
+                                          false, true, NULL);
+         break;
+       }
+    }
+}
+
+/* Parse an objc-methodproto.
+
+   objc-methodproto:
+     objc-method-type objc-method-decl ;
+*/
+
+static void
+c_parser_objc_methodproto (c_parser *parser)
+{
+  bool is_class_method = c_parser_objc_method_type (parser);
+  tree decl, attributes = NULL_TREE;
+
+  /* Remember protocol qualifiers in prototypes.  */
+  parser->objc_pq_context = true;
+  decl = c_parser_objc_method_decl (parser, is_class_method, &attributes,
+                                   NULL);
+  /* Forget protocol qualifiers now.  */
+  parser->objc_pq_context = false;
+
+  /* Do not allow the presence of attributes to hide an erroneous 
+     method implementation in the interface section.  */
+  if (!c_parser_next_token_is (parser, CPP_SEMICOLON))
+    {
+      c_parser_error (parser, "expected %<;%>");
+      return;
+    }
+  
+  if (decl != error_mark_node)
+    objc_add_method_declaration (is_class_method, decl, attributes);
+
+  c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+}
+
+/* If we are at a position that method attributes may be present, check that 
+   there are not any parsed already (a syntax error) and then collect any 
+   specified at the current location.  Finally, if new attributes were present,
+   check that the next token is legal ( ';' for decls and '{' for defs).  */
+   
+static bool 
+c_parser_objc_maybe_method_attributes (c_parser* parser, tree* attributes)
+{
+  bool bad = false;
+  if (*attributes)
+    {
+      c_parser_error (parser, 
+                   "method attributes must be specified at the end only");
+      *attributes = NULL_TREE;
+      bad = true;
+    }
+
+  if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
+    *attributes = c_parser_attributes (parser);
+
+  /* If there were no attributes here, just report any earlier error.  */
+  if (*attributes == NULL_TREE || bad)
+    return bad;
+
+  /* If the attributes are followed by a ; or {, then just report any earlier
+     error.  */
+  if (c_parser_next_token_is (parser, CPP_SEMICOLON)
+      || c_parser_next_token_is (parser, CPP_OPEN_BRACE))
+    return bad;
+
+  /* We've got attributes, but not at the end.  */
+  c_parser_error (parser, 
+                 "expected %<;%> or %<{%> after method attribute definition");
+  return true;
+}
+
+/* Parse an objc-method-decl.
+
+   objc-method-decl:
+     ( objc-type-name ) objc-selector
+     objc-selector
+     ( objc-type-name ) objc-keyword-selector objc-optparmlist
+     objc-keyword-selector objc-optparmlist
+     attributes
+
+   objc-keyword-selector:
+     objc-keyword-decl
+     objc-keyword-selector objc-keyword-decl
+
+   objc-keyword-decl:
+     objc-selector : ( objc-type-name ) identifier
+     objc-selector : identifier
+     : ( objc-type-name ) identifier
+     : identifier
+
+   objc-optparmlist:
+     objc-optparms objc-optellipsis
+
+   objc-optparms:
+     empty
+     objc-opt-parms , parameter-declaration
+
+   objc-optellipsis:
+     empty
+     , ...
+*/
+
+static tree
+c_parser_objc_method_decl (c_parser *parser, bool is_class_method,
+                          tree *attributes, tree *expr)
+{
+  tree type = NULL_TREE;
+  tree sel;
+  tree parms = NULL_TREE;
+  bool ellipsis = false;
+  bool attr_err = false;
+
+  *attributes = NULL_TREE;
+  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+    {
+      c_parser_consume_token (parser);
+      type = c_parser_objc_type_name (parser);
+      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+    }
+  sel = c_parser_objc_selector (parser);
+  /* If there is no selector, or a colon follows, we have an
+     objc-keyword-selector.  If there is a selector, and a colon does
+     not follow, that selector ends the objc-method-decl.  */
+  if (!sel || c_parser_next_token_is (parser, CPP_COLON))
+    {
+      tree tsel = sel;
+      tree list = NULL_TREE;
+      while (true)
+       {
+         tree atype = NULL_TREE, id, keyworddecl;
+         tree param_attr = NULL_TREE;
+         if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
+           break;
+         if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+           {
+             c_parser_consume_token (parser);
+             atype = c_parser_objc_type_name (parser);
+             c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+                                        "expected %<)%>");
+           }
+         /* New ObjC allows attributes on method parameters.  */
+         if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
+           param_attr = c_parser_attributes (parser);
+         if (c_parser_next_token_is_not (parser, CPP_NAME))
+           {
+             c_parser_error (parser, "expected identifier");
+             return error_mark_node;
+           }
+         id = c_parser_peek_token (parser)->value;
+         c_parser_consume_token (parser);
+         keyworddecl = objc_build_keyword_decl (tsel, atype, id, param_attr);
+         list = chainon (list, keyworddecl);
+         tsel = c_parser_objc_selector (parser);
+         if (!tsel && c_parser_next_token_is_not (parser, CPP_COLON))
+           break;
+       }
+
+      attr_err |= c_parser_objc_maybe_method_attributes (parser, attributes) ;
+
+      /* Parse the optional parameter list.  Optional Objective-C
+        method parameters follow the C syntax, and may include '...'
+        to denote a variable number of arguments.  */
+      parms = make_node (TREE_LIST);
+      while (c_parser_next_token_is (parser, CPP_COMMA))
+       {
+         struct c_parm *parm;
+         c_parser_consume_token (parser);
+         if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
+           {
+             ellipsis = true;
+             c_parser_consume_token (parser);
+             attr_err |= c_parser_objc_maybe_method_attributes 
+                                               (parser, attributes) ;
+             break;
+           }
+         parm = c_parser_parameter_declaration (parser, NULL_TREE);
+         if (parm == NULL)
+           break;
+         parms = chainon (parms,
+                          build_tree_list (NULL_TREE, grokparm (parm, expr)));
+       }
+      sel = list;
+    }
+  else
+    attr_err |= c_parser_objc_maybe_method_attributes (parser, attributes) ;
+
+  if (sel == NULL)
+    {
+      c_parser_error (parser, "objective-c method declaration is expected");
+      return error_mark_node;
+    }
+
+  if (attr_err)
+    return error_mark_node;
+
+  return objc_build_method_signature (is_class_method, type, sel, parms, ellipsis);
+}
+
+/* Parse an objc-type-name.
+
+   objc-type-name:
+     objc-type-qualifiers[opt] type-name
+     objc-type-qualifiers[opt]
+
+   objc-type-qualifiers:
+     objc-type-qualifier
+     objc-type-qualifiers objc-type-qualifier
+
+   objc-type-qualifier: one of
+     in out inout bycopy byref oneway
+*/
+
+static tree
+c_parser_objc_type_name (c_parser *parser)
+{
+  tree quals = NULL_TREE;
+  struct c_type_name *type_name = NULL;
+  tree type = NULL_TREE;
+  while (true)
+    {
+      c_token *token = c_parser_peek_token (parser);
+      if (token->type == CPP_KEYWORD
+         && (token->keyword == RID_IN
+             || token->keyword == RID_OUT
+             || token->keyword == RID_INOUT
+             || token->keyword == RID_BYCOPY
+             || token->keyword == RID_BYREF
+             || token->keyword == RID_ONEWAY))
+       {
+         quals = chainon (build_tree_list (NULL_TREE, token->value), quals);
+         c_parser_consume_token (parser);
+       }
+      else
+       break;
+    }
+  if (c_parser_next_tokens_start_typename (parser, cla_prefer_type))
+    type_name = c_parser_type_name (parser);
+  if (type_name)
+    type = groktypename (type_name, NULL, NULL);
+
+  /* If the type is unknown, and error has already been produced and
+     we need to recover from the error.  In that case, use NULL_TREE
+     for the type, as if no type had been specified; this will use the
+     default type ('id') which is good for error recovery.  */
+  if (type == error_mark_node)
+    type = NULL_TREE;
+
+  return build_tree_list (quals, type);
+}
+
+/* Parse objc-protocol-refs.
+
+   objc-protocol-refs:
+     < identifier-list >
+*/
+
+static tree
+c_parser_objc_protocol_refs (c_parser *parser)
+{
+  tree list = NULL_TREE;
+  gcc_assert (c_parser_next_token_is (parser, CPP_LESS));
+  c_parser_consume_token (parser);
+  /* Any identifiers, including those declared as type names, are OK
+     here.  */
+  while (true)
+    {
+      tree id;
+      if (c_parser_next_token_is_not (parser, CPP_NAME))
+       {
+         c_parser_error (parser, "expected identifier");
+         break;
+       }
+      id = c_parser_peek_token (parser)->value;
+      list = chainon (list, build_tree_list (NULL_TREE, id));
+      c_parser_consume_token (parser);
+      if (c_parser_next_token_is (parser, CPP_COMMA))
+       c_parser_consume_token (parser);
+      else
+       break;
+    }
+  c_parser_require (parser, CPP_GREATER, "expected %<>%>");
+  return list;
+}
+
+/* Parse an objc-try-catch-finally-statement.
+
+   objc-try-catch-finally-statement:
+     @try compound-statement objc-catch-list[opt]
+     @try compound-statement objc-catch-list[opt] @finally compound-statement
+
+   objc-catch-list:
+     @catch ( objc-catch-parameter-declaration ) compound-statement
+     objc-catch-list @catch ( objc-catch-parameter-declaration ) compound-statement
+
+   objc-catch-parameter-declaration:
+     parameter-declaration
+     '...'
+
+   where '...' is to be interpreted literally, that is, it means CPP_ELLIPSIS.
+
+   PS: This function is identical to cp_parser_objc_try_catch_finally_statement
+   for C++.  Keep them in sync.  */   
+
+static void
+c_parser_objc_try_catch_finally_statement (c_parser *parser)
+{
+  location_t location;
+  tree stmt;
+
+  gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_TRY));
+  c_parser_consume_token (parser);
+  location = c_parser_peek_token (parser)->location;
+  objc_maybe_warn_exceptions (location);
+  stmt = c_parser_compound_statement (parser);
+  objc_begin_try_stmt (location, stmt);
+
+  while (c_parser_next_token_is_keyword (parser, RID_AT_CATCH))
+    {
+      struct c_parm *parm;
+      tree parameter_declaration = error_mark_node;
+      bool seen_open_paren = false;
+
+      c_parser_consume_token (parser);
+      if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+       seen_open_paren = true;
+      if (c_parser_next_token_is (parser, 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
+            '...'.  */
+         c_parser_consume_token (parser);
+         parameter_declaration = NULL_TREE;
+       }
+      else
+       {
+         /* We have "@catch (NSException *exception)" or something
+            like that.  Parse the parameter declaration.  */
+         parm = c_parser_parameter_declaration (parser, NULL_TREE);
+         if (parm == NULL)
+           parameter_declaration = error_mark_node;
+         else
+           parameter_declaration = grokparm (parm, NULL);
+       }
+      if (seen_open_paren)
+       c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+      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 (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+           c_parser_consume_token (parser);
+         
+         /* 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);
+      if (c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
+       c_parser_compound_statement_nostart (parser);
+      objc_finish_catch_clause ();
+    }
+  if (c_parser_next_token_is_keyword (parser, RID_AT_FINALLY))
+    {
+      c_parser_consume_token (parser);
+      location = c_parser_peek_token (parser)->location;
+      stmt = c_parser_compound_statement (parser);
+      objc_build_finally_clause (location, stmt);
+    }
+  objc_finish_try_stmt ();
+}
+
+/* Parse an objc-synchronized-statement.
+
+   objc-synchronized-statement:
+     @synchronized ( expression ) compound-statement
+*/
+
+static void
+c_parser_objc_synchronized_statement (c_parser *parser)
+{
+  location_t loc;
+  tree expr, stmt;
+  gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_SYNCHRONIZED));
+  c_parser_consume_token (parser);
+  loc = c_parser_peek_token (parser)->location;
+  objc_maybe_warn_exceptions (loc);
+  if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+    {
+      expr = c_parser_expression (parser).value;
+      expr = c_fully_fold (expr, false, NULL);
+      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+    }
+  else
+    expr = error_mark_node;
+  stmt = c_parser_compound_statement (parser);
+  objc_build_synchronized (loc, expr, stmt);
+}
+
+/* Parse an objc-selector; return NULL_TREE without an error if the
+   next token is not an objc-selector.
+
+   objc-selector:
+     identifier
+     one of
+       enum struct union if else while do for switch case default
+       break continue return goto asm sizeof typeof __alignof
+       unsigned long const short volatile signed restrict _Complex
+       in out inout bycopy byref oneway int char float double void _Bool
+
+   ??? Why this selection of keywords but not, for example, storage
+   class specifiers?  */
+
+static tree
+c_parser_objc_selector (c_parser *parser)
+{
+  c_token *token = c_parser_peek_token (parser);
+  tree value = token->value;
+  if (token->type == CPP_NAME)
+    {
+      c_parser_consume_token (parser);
+      return value;
+    }
+  if (token->type != CPP_KEYWORD)
+    return NULL_TREE;
+  switch (token->keyword)
+    {
+    case RID_ENUM:
+    case RID_STRUCT:
+    case RID_UNION:
+    case RID_IF:
+    case RID_ELSE:
+    case RID_WHILE:
+    case RID_DO:
+    case RID_FOR:
+    case RID_SWITCH:
+    case RID_CASE:
+    case RID_DEFAULT:
+    case RID_BREAK:
+    case RID_CONTINUE:
+    case RID_RETURN:
+    case RID_GOTO:
+    case RID_ASM:
+    case RID_SIZEOF:
+    case RID_TYPEOF:
+    case RID_ALIGNOF:
+    case RID_UNSIGNED:
+    case RID_LONG:
+    case RID_INT128:
+    case RID_CONST:
+    case RID_SHORT:
+    case RID_VOLATILE:
+    case RID_SIGNED:
+    case RID_RESTRICT:
+    case RID_COMPLEX:
+    case RID_IN:
+    case RID_OUT:
+    case RID_INOUT:
+    case RID_BYCOPY:
+    case RID_BYREF:
+    case RID_ONEWAY:
+    case RID_INT:
+    case RID_CHAR:
+    case RID_FLOAT:
+    case RID_DOUBLE:
+    case RID_VOID:
+    case RID_BOOL:
+      c_parser_consume_token (parser);
+      return value;
+    default:
+      return NULL_TREE;
+    }
+}
+
+/* Parse an objc-selector-arg.
+
+   objc-selector-arg:
+     objc-selector
+     objc-keywordname-list
+
+   objc-keywordname-list:
+     objc-keywordname
+     objc-keywordname-list objc-keywordname
+
+   objc-keywordname:
+     objc-selector :
+     :
+*/
+
+static tree
+c_parser_objc_selector_arg (c_parser *parser)
+{
+  tree sel = c_parser_objc_selector (parser);
+  tree list = NULL_TREE;
+  if (sel && c_parser_next_token_is_not (parser, CPP_COLON))
+    return sel;
+  while (true)
+    {
+      if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
+       return list;
+      list = chainon (list, build_tree_list (sel, NULL_TREE));
+      sel = c_parser_objc_selector (parser);
+      if (!sel && c_parser_next_token_is_not (parser, CPP_COLON))
+       break;
+    }
+  return list;
+}
+
+/* Parse an objc-receiver.
+
+   objc-receiver:
+     expression
+     class-name
+     type-name
+*/
+
+static tree
+c_parser_objc_receiver (c_parser *parser)
+{
+  if (c_parser_peek_token (parser)->type == CPP_NAME
+      && (c_parser_peek_token (parser)->id_kind == C_ID_TYPENAME
+         || c_parser_peek_token (parser)->id_kind == C_ID_CLASSNAME))
+    {
+      tree id = c_parser_peek_token (parser)->value;
+      c_parser_consume_token (parser);
+      return objc_get_class_reference (id);
+    }
+  return c_fully_fold (c_parser_expression (parser).value, false, NULL);
+}
+
+/* Parse objc-message-args.
+
+   objc-message-args:
+     objc-selector
+     objc-keywordarg-list
+
+   objc-keywordarg-list:
+     objc-keywordarg
+     objc-keywordarg-list objc-keywordarg
+
+   objc-keywordarg:
+     objc-selector : objc-keywordexpr
+     : objc-keywordexpr
+*/
+
+static tree
+c_parser_objc_message_args (c_parser *parser)
+{
+  tree sel = c_parser_objc_selector (parser);
+  tree list = NULL_TREE;
+  if (sel && c_parser_next_token_is_not (parser, CPP_COLON))
+    return sel;
+  while (true)
+    {
+      tree keywordexpr;
+      if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
+       return error_mark_node;
+      keywordexpr = c_parser_objc_keywordexpr (parser);
+      list = chainon (list, build_tree_list (sel, keywordexpr));
+      sel = c_parser_objc_selector (parser);
+      if (!sel && c_parser_next_token_is_not (parser, CPP_COLON))
+       break;
+    }
+  return list;
+}
+
+/* Parse an objc-keywordexpr.
+
+   objc-keywordexpr:
+     nonempty-expr-list
+*/
+
+static tree
+c_parser_objc_keywordexpr (c_parser *parser)
+{
+  tree ret;
+  VEC(tree,gc) *expr_list = c_parser_expr_list (parser, true, true, NULL);
+  if (VEC_length (tree, expr_list) == 1)
+    {
+      /* Just return the expression, remove a level of
+        indirection.  */
+      ret = VEC_index (tree, expr_list, 0);
+    }
+  else
+    {
+      /* We have a comma expression, we will collapse later.  */
+      ret = build_tree_list_vec (expr_list);
+    }
+  release_tree_vector (expr_list);
+  return ret;
+}
+
+/* A check, needed in several places, that ObjC interface, implementation or
+   method definitions are not prefixed by incorrect items.  */
+static bool
+c_parser_objc_diagnose_bad_element_prefix (c_parser *parser, 
+                                          struct c_declspecs *specs)
+{
+  if (!specs->declspecs_seen_p || specs->non_sc_seen_p
+      || specs->typespec_kind != ctsk_none)
+    {
+      c_parser_error (parser, 
+                     "no type or storage class may be specified here,");
+      c_parser_skip_to_end_of_block_or_statement (parser);
+      return true;
+    }
+  return false;
+}
+
+/* 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 cp_parser_objc_at_propery_declaration
+  for C++.  Keep them in sync.  */
+static void
+c_parser_objc_at_property_declaration (c_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 = c_parser_peek_token (parser)->location;
+  gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_PROPERTY));
+
+  c_parser_consume_token (parser);  /* Eat '@property'.  */
+
+  /* Parse the optional attribute list...  */
+  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+    {
+      /* Eat the '(' */
+      c_parser_consume_token (parser);
+      
+      /* Property attribute keywords are valid now.  */
+      parser->objc_property_attr_context = true;
+
+      while (true)
+       {
+         bool syntax_error = false;
+         c_token *token = c_parser_peek_token (parser);
+         enum rid keyword;
+
+         if (token->type != CPP_KEYWORD)
+           {
+             if (token->type == CPP_CLOSE_PAREN)
+               c_parser_error (parser, "expected identifier");
+             else
+               {
+                 c_parser_consume_token (parser);
+                 c_parser_error (parser, "unknown property attribute");
+               }
+             break;
+           }
+         keyword = token->keyword;
+         c_parser_consume_token (parser);
+         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 (c_parser_next_token_is_not (parser, CPP_EQ))
+               {
+                 if (keyword == RID_GETTER)
+                   c_parser_error (parser,
+                                   "missing %<=%> (after %<getter%> attribute)");
+                 else
+                   c_parser_error (parser,
+                                   "missing %<=%> (after %<setter%> attribute)");
+                 syntax_error = true;
+                 break;
+               }
+             c_parser_consume_token (parser); /* eat the = */
+             if (c_parser_next_token_is_not (parser, CPP_NAME))
+               {
+                 c_parser_error (parser, "expected identifier");
+                 syntax_error = true;
+                 break;
+               }
+             if (keyword == RID_SETTER)
+               {
+                 if (property_setter_ident != NULL_TREE)
+                   c_parser_error (parser, "the %<setter%> attribute may only be specified once");
+                 else
+                   property_setter_ident = c_parser_peek_token (parser)->value;
+                 c_parser_consume_token (parser);
+                 if (c_parser_next_token_is_not (parser, CPP_COLON))
+                   c_parser_error (parser, "setter name must terminate with %<:%>");
+                 else
+                   c_parser_consume_token (parser);
+               }
+             else
+               {
+                 if (property_getter_ident != NULL_TREE)
+                   c_parser_error (parser, "the %<getter%> attribute may only be specified once");
+                 else
+                   property_getter_ident = c_parser_peek_token (parser)->value;
+                 c_parser_consume_token (parser);
+               }
+             break;
+           default:
+             c_parser_error (parser, "unknown property attribute");
+             syntax_error = true;
+             break;
+           }
+
+         if (syntax_error)
+           break;
+         
+         if (c_parser_next_token_is (parser, CPP_COMMA))
+           c_parser_consume_token (parser);
+         else
+           break;
+       }
+      parser->objc_property_attr_context = false;
+      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+    }
+  /* ... and the property declaration(s).  */
+  properties = c_parser_struct_declaration (parser);
+
+  if (properties == error_mark_node)
+    {
+      c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
+      parser->error = false;
+      return;
+    }
+
+  if (properties == NULL_TREE)
+    c_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);
+    }
+
+  c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+  parser->error = false;
+}
+
+/* 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 cp_parser_objc_at_synthesize_declaration
+  for C++.  Keep them in sync.
+*/
+static void
+c_parser_objc_at_synthesize_declaration (c_parser *parser)
+{
+  tree list = NULL_TREE;
+  location_t loc;
+  gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_SYNTHESIZE));
+  loc = c_parser_peek_token (parser)->location;
+
+  c_parser_consume_token (parser);
+  while (true)
+    {
+      tree property, ivar;
+      if (c_parser_next_token_is_not (parser, CPP_NAME))
+       {
+         c_parser_error (parser, "expected identifier");
+         c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
+         /* Once we find the semicolon, we can resume normal parsing.
+            We have to reset parser->error manually because
+            c_parser_skip_until_found() won't reset it for us if the
+            next token is precisely a semicolon.  */
+         parser->error = false;
+         return;
+       }
+      property = c_parser_peek_token (parser)->value;
+      c_parser_consume_token (parser);
+      if (c_parser_next_token_is (parser, CPP_EQ))
+       {
+         c_parser_consume_token (parser);
+         if (c_parser_next_token_is_not (parser, CPP_NAME))
+           {
+             c_parser_error (parser, "expected identifier");
+             c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
+             parser->error = false;
+             return;
+           }
+         ivar = c_parser_peek_token (parser)->value;
+         c_parser_consume_token (parser);
+       }
+      else
+       ivar = NULL_TREE;
+      list = chainon (list, build_tree_list (ivar, property));
+      if (c_parser_next_token_is (parser, CPP_COMMA))
+       c_parser_consume_token (parser);
+      else
+       break;
+    }
+  c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+  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 cp_parser_objc_at_dynamic_declaration
+  for C++.  Keep them in sync.
+*/
+static void
+c_parser_objc_at_dynamic_declaration (c_parser *parser)
+{
+  tree list = NULL_TREE;
+  location_t loc;
+  gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_DYNAMIC));
+  loc = c_parser_peek_token (parser)->location;
+
+  c_parser_consume_token (parser);
+  while (true)
+    {
+      tree property;
+      if (c_parser_next_token_is_not (parser, CPP_NAME))
+       {
+         c_parser_error (parser, "expected identifier");
+         c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
+         parser->error = false;
+         return;
+       }
+      property = c_parser_peek_token (parser)->value;
+      list = chainon (list, build_tree_list (NULL_TREE, property));
+      c_parser_consume_token (parser);
+      if (c_parser_next_token_is (parser, CPP_COMMA))
+       c_parser_consume_token (parser);
+      else
+       break;
+    }
+  c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+  objc_add_dynamic_declaration (loc, list);
+}
+
+\f
+/* Handle pragmas.  Some OpenMP pragmas are associated with, and therefore
+   should be considered, statements.  ALLOW_STMT is true if we're within
+   the context of a function and such pragmas are to be allowed.  Returns
+   true if we actually parsed such a pragma.  */
+
+static bool
+c_parser_pragma (c_parser *parser, enum pragma_context context)
+{
+  unsigned int id;
+
+  id = c_parser_peek_token (parser)->pragma_kind;
+  gcc_assert (id != PRAGMA_NONE);
+
+  switch (id)
+    {
+    case PRAGMA_OMP_BARRIER:
+      if (context != pragma_compound)
+       {
+         if (context == pragma_stmt)
+           c_parser_error (parser, "%<#pragma omp barrier%> may only be "
+                           "used in compound statements");
+         goto bad_stmt;
+       }
+      c_parser_omp_barrier (parser);
+      return false;
+
+    case PRAGMA_OMP_FLUSH:
+      if (context != pragma_compound)
+       {
+         if (context == pragma_stmt)
+           c_parser_error (parser, "%<#pragma omp flush%> may only be "
+                           "used in compound statements");
+         goto bad_stmt;
+       }
+      c_parser_omp_flush (parser);
+      return false;
+
+    case PRAGMA_OMP_TASKWAIT:
+      if (context != pragma_compound)
+       {
+         if (context == pragma_stmt)
+           c_parser_error (parser, "%<#pragma omp taskwait%> may only be "
+                           "used in compound statements");
+         goto bad_stmt;
+       }
+      c_parser_omp_taskwait (parser);
+      return false;
+
+    case PRAGMA_OMP_TASKYIELD:
+      if (context != pragma_compound)
+       {
+         if (context == pragma_stmt)
+           c_parser_error (parser, "%<#pragma omp taskyield%> may only be "
+                           "used in compound statements");
+         goto bad_stmt;
+       }
+      c_parser_omp_taskyield (parser);
+      return false;
+
+    case PRAGMA_OMP_THREADPRIVATE:
+      c_parser_omp_threadprivate (parser);
+      return false;
+
+    case PRAGMA_OMP_SECTION:
+      error_at (c_parser_peek_token (parser)->location,
+               "%<#pragma omp section%> may only be used in "
+               "%<#pragma omp sections%> construct");
+      c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
+      return false;
+
+    case PRAGMA_GCC_PCH_PREPROCESS:
+      c_parser_error (parser, "%<#pragma GCC pch_preprocess%> must be first");
+      c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
+      return false;
+
+    default:
+      if (id < PRAGMA_FIRST_EXTERNAL)
+       {
+         if (context == pragma_external)
+           {
+           bad_stmt:
+             c_parser_error (parser, "expected declaration specifiers");
+             c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
+             return false;
+           }
+         c_parser_omp_construct (parser);
+         return true;
+       }
+      break;
+    }
+
+  c_parser_consume_pragma (parser);
+  c_invoke_pragma_handler (id);
+
+  /* Skip to EOL, but suppress any error message.  Those will have been
+     generated by the handler routine through calling error, as opposed
+     to calling c_parser_error.  */
+  parser->error = true;
+  c_parser_skip_to_pragma_eol (parser);
+
+  return false;
+}
+
+/* The interface the pragma parsers have to the lexer.  */
+
+enum cpp_ttype
+pragma_lex (tree *value)
+{
+  c_token *tok = c_parser_peek_token (the_parser);
+  enum cpp_ttype ret = tok->type;
+
+  *value = tok->value;
+  if (ret == CPP_PRAGMA_EOL || ret == CPP_EOF)
+    ret = CPP_EOF;
+  else
+    {
+      if (ret == CPP_KEYWORD)
+       ret = CPP_NAME;
+      c_parser_consume_token (the_parser);
+    }
+
+  return ret;
+}
+
+static void
+c_parser_pragma_pch_preprocess (c_parser *parser)
+{
+  tree name = NULL;
+
+  c_parser_consume_pragma (parser);
+  if (c_parser_next_token_is (parser, CPP_STRING))
+    {
+      name = c_parser_peek_token (parser)->value;
+      c_parser_consume_token (parser);
+    }
+  else
+    c_parser_error (parser, "expected string literal");
+  c_parser_skip_to_pragma_eol (parser);
+
+  if (name)
+    c_common_pch_pragma (parse_in, TREE_STRING_POINTER (name));
+}
+\f
+/* OpenMP 2.5 parsing routines.  */
+
+/* Returns name of the next clause.
+   If the clause is not recognized PRAGMA_OMP_CLAUSE_NONE is returned and
+   the token is not consumed.  Otherwise appropriate pragma_omp_clause is
+   returned and the token is consumed.  */
+
+static pragma_omp_clause
+c_parser_omp_clause_name (c_parser *parser)
+{
+  pragma_omp_clause result = PRAGMA_OMP_CLAUSE_NONE;
+
+  if (c_parser_next_token_is_keyword (parser, RID_IF))
+    result = PRAGMA_OMP_CLAUSE_IF;
+  else if (c_parser_next_token_is_keyword (parser, RID_DEFAULT))
+    result = PRAGMA_OMP_CLAUSE_DEFAULT;
+  else if (c_parser_next_token_is (parser, CPP_NAME))
+    {
+      const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+
+      switch (p[0])
+       {
+       case 'c':
+         if (!strcmp ("collapse", p))
+           result = PRAGMA_OMP_CLAUSE_COLLAPSE;
+         else if (!strcmp ("copyin", p))
+           result = PRAGMA_OMP_CLAUSE_COPYIN;
+          else if (!strcmp ("copyprivate", p))
+           result = PRAGMA_OMP_CLAUSE_COPYPRIVATE;
+         break;
+       case 'f':
+         if (!strcmp ("final", p))
+           result = PRAGMA_OMP_CLAUSE_FINAL;
+         else if (!strcmp ("firstprivate", p))
+           result = PRAGMA_OMP_CLAUSE_FIRSTPRIVATE;
+         break;
+       case 'l':
+         if (!strcmp ("lastprivate", p))
+           result = PRAGMA_OMP_CLAUSE_LASTPRIVATE;
+         break;
+       case 'm':
+         if (!strcmp ("mergeable", p))
+           result = PRAGMA_OMP_CLAUSE_MERGEABLE;
+         break;
+       case 'n':
+         if (!strcmp ("nowait", p))
+           result = PRAGMA_OMP_CLAUSE_NOWAIT;
+         else if (!strcmp ("num_threads", p))
+           result = PRAGMA_OMP_CLAUSE_NUM_THREADS;
+         break;
+       case 'o':
+         if (!strcmp ("ordered", p))
+           result = PRAGMA_OMP_CLAUSE_ORDERED;
+         break;
+       case 'p':
+         if (!strcmp ("private", p))
+           result = PRAGMA_OMP_CLAUSE_PRIVATE;
+         break;
+       case 'r':
+         if (!strcmp ("reduction", p))
+           result = PRAGMA_OMP_CLAUSE_REDUCTION;
+         break;
+       case 's':
+         if (!strcmp ("schedule", p))
+           result = PRAGMA_OMP_CLAUSE_SCHEDULE;
+         else if (!strcmp ("shared", p))
+           result = PRAGMA_OMP_CLAUSE_SHARED;
+         break;
+       case 'u':
+         if (!strcmp ("untied", p))
+           result = PRAGMA_OMP_CLAUSE_UNTIED;
+         break;
+       }
+    }
+
+  if (result != PRAGMA_OMP_CLAUSE_NONE)
+    c_parser_consume_token (parser);
+
+  return result;
+}
+
+/* Validate that a clause of the given type does not already exist.  */
+
+static void
+check_no_duplicate_clause (tree clauses, enum omp_clause_code code,
+                          const char *name)
+{
+  tree c;
+
+  for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
+    if (OMP_CLAUSE_CODE (c) == code)
+      {
+       location_t loc = OMP_CLAUSE_LOCATION (c);
+       error_at (loc, "too many %qs clauses", name);
+       break;
+      }
+}
+
+/* OpenMP 2.5:
+   variable-list:
+     identifier
+     variable-list , identifier
+
+   If KIND is nonzero, create the appropriate node and install the
+   decl in OMP_CLAUSE_DECL and add the node to the head of the list.
+   If KIND is nonzero, CLAUSE_LOC is the location of the clause.
+
+   If KIND is zero, create a TREE_LIST with the decl in TREE_PURPOSE;
+   return the list created.  */
+
+static tree
+c_parser_omp_variable_list (c_parser *parser,
+                           location_t clause_loc,
+                           enum omp_clause_code kind,
+                            tree list)
+{
+  if (c_parser_next_token_is_not (parser, CPP_NAME)
+      || c_parser_peek_token (parser)->id_kind != C_ID_ID)
+    c_parser_error (parser, "expected identifier");
+
+  while (c_parser_next_token_is (parser, CPP_NAME)
+        && c_parser_peek_token (parser)->id_kind == C_ID_ID)
+    {
+      tree t = lookup_name (c_parser_peek_token (parser)->value);
+
+      if (t == NULL_TREE)
+       undeclared_variable (c_parser_peek_token (parser)->location,
+                            c_parser_peek_token (parser)->value);
+      else if (t == error_mark_node)
+       ;
+      else if (kind != 0)
+       {
+         tree u = build_omp_clause (clause_loc, kind);
+         OMP_CLAUSE_DECL (u) = t;
+         OMP_CLAUSE_CHAIN (u) = list;
+         list = u;
+       }
+      else
+       list = tree_cons (t, NULL_TREE, list);
+
+      c_parser_consume_token (parser);
+
+      if (c_parser_next_token_is_not (parser, CPP_COMMA))
+       break;
+
+      c_parser_consume_token (parser);
+    }
+
+  return list;
+}
+
+/* Similarly, but expect leading and trailing parenthesis.  This is a very
+   common case for omp clauses.  */
+
+static tree
+c_parser_omp_var_list_parens (c_parser *parser, enum omp_clause_code kind,
+                             tree list)
+{
+  /* The clauses location.  */
+  location_t loc = c_parser_peek_token (parser)->location;
+
+  if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+    {
+      list = c_parser_omp_variable_list (parser, loc, kind, list);
+      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+    }
+  return list;
+}
+
+/* OpenMP 3.0:
+   collapse ( constant-expression ) */
+
+static tree
+c_parser_omp_clause_collapse (c_parser *parser, tree list)
+{
+  tree c, num = error_mark_node;
+  HOST_WIDE_INT n;
+  location_t loc;
+
+  check_no_duplicate_clause (list, OMP_CLAUSE_COLLAPSE, "collapse");
+
+  loc = c_parser_peek_token (parser)->location;
+  if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+    {
+      num = c_parser_expr_no_commas (parser, NULL).value;
+      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+    }
+  if (num == error_mark_node)
+    return list;
+  if (!INTEGRAL_TYPE_P (TREE_TYPE (num))
+      || !host_integerp (num, 0)
+      || (n = tree_low_cst (num, 0)) <= 0
+      || (int) n != n)
+    {
+      error_at (loc,
+               "collapse argument needs positive constant integer expression");
+      return list;
+    }
+  c = build_omp_clause (loc, OMP_CLAUSE_COLLAPSE);
+  OMP_CLAUSE_COLLAPSE_EXPR (c) = num;
+  OMP_CLAUSE_CHAIN (c) = list;
+  return c;
+}
+
+/* OpenMP 2.5:
+   copyin ( variable-list ) */
+
+static tree
+c_parser_omp_clause_copyin (c_parser *parser, tree list)
+{
+  return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_COPYIN, list);
+}
+
+/* OpenMP 2.5:
+   copyprivate ( variable-list ) */
+
+static tree
+c_parser_omp_clause_copyprivate (c_parser *parser, tree list)
+{
+  return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_COPYPRIVATE, list);
+}
+
+/* OpenMP 2.5:
+   default ( shared | none ) */
+
+static tree
+c_parser_omp_clause_default (c_parser *parser, tree list)
+{
+  enum omp_clause_default_kind kind = OMP_CLAUSE_DEFAULT_UNSPECIFIED;
+  location_t loc = c_parser_peek_token (parser)->location;
+  tree c;
+
+  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+    return list;
+  if (c_parser_next_token_is (parser, CPP_NAME))
+    {
+      const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+
+      switch (p[0])
+       {
+       case 'n':
+         if (strcmp ("none", p) != 0)
+           goto invalid_kind;
+         kind = OMP_CLAUSE_DEFAULT_NONE;
+         break;
+
+       case 's':
+         if (strcmp ("shared", p) != 0)
+           goto invalid_kind;
+         kind = OMP_CLAUSE_DEFAULT_SHARED;
+         break;
+
+       default:
+         goto invalid_kind;
+       }
+
+      c_parser_consume_token (parser);
+    }
+  else
+    {
+    invalid_kind:
+      c_parser_error (parser, "expected %<none%> or %<shared%>");
+    }
+  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+
+  if (kind == OMP_CLAUSE_DEFAULT_UNSPECIFIED)
+    return list;
+
+  check_no_duplicate_clause (list, OMP_CLAUSE_DEFAULT, "default");
+  c = build_omp_clause (loc, OMP_CLAUSE_DEFAULT);
+  OMP_CLAUSE_CHAIN (c) = list;
+  OMP_CLAUSE_DEFAULT_KIND (c) = kind;
+
+  return c;
+}
+
+/* OpenMP 2.5:
+   firstprivate ( variable-list ) */
+
+static tree
+c_parser_omp_clause_firstprivate (c_parser *parser, tree list)
+{
+  return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_FIRSTPRIVATE, list);
+}
+
+/* OpenMP 3.1:
+   final ( expression ) */
+
+static tree
+c_parser_omp_clause_final (c_parser *parser, tree list)
+{
+  location_t loc = c_parser_peek_token (parser)->location;
+  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+    {
+      tree t = c_parser_paren_condition (parser);
+      tree c;
+
+      check_no_duplicate_clause (list, OMP_CLAUSE_FINAL, "final");
+
+      c = build_omp_clause (loc, OMP_CLAUSE_FINAL);
+      OMP_CLAUSE_FINAL_EXPR (c) = t;
+      OMP_CLAUSE_CHAIN (c) = list;
+      list = c;
+    }
+  else
+    c_parser_error (parser, "expected %<(%>");
+
+  return list;
+}
+
+/* OpenMP 2.5:
+   if ( expression ) */
+
+static tree
+c_parser_omp_clause_if (c_parser *parser, tree list)
+{
+  location_t loc = c_parser_peek_token (parser)->location;
+  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+    {
+      tree t = c_parser_paren_condition (parser);
+      tree c;
+
+      check_no_duplicate_clause (list, OMP_CLAUSE_IF, "if");
+
+      c = build_omp_clause (loc, OMP_CLAUSE_IF);
+      OMP_CLAUSE_IF_EXPR (c) = t;
+      OMP_CLAUSE_CHAIN (c) = list;
+      list = c;
+    }
+  else
+    c_parser_error (parser, "expected %<(%>");
+
+  return list;
+}
+
+/* OpenMP 2.5:
+   lastprivate ( variable-list ) */
+
+static tree
+c_parser_omp_clause_lastprivate (c_parser *parser, tree list)
+{
+  return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_LASTPRIVATE, list);
+}
+
+/* OpenMP 3.1:
+   mergeable */
+
+static tree
+c_parser_omp_clause_mergeable (c_parser *parser ATTRIBUTE_UNUSED, tree list)
+{
+  tree c;
+
+  /* FIXME: Should we allow duplicates?  */
+  check_no_duplicate_clause (list, OMP_CLAUSE_MERGEABLE, "mergeable");
+
+  c = build_omp_clause (c_parser_peek_token (parser)->location,
+                       OMP_CLAUSE_MERGEABLE);
+  OMP_CLAUSE_CHAIN (c) = list;
+
+  return c;
+}
+
+/* OpenMP 2.5:
+   nowait */
+
+static tree
+c_parser_omp_clause_nowait (c_parser *parser ATTRIBUTE_UNUSED, tree list)
+{
+  tree c;
+  location_t loc = c_parser_peek_token (parser)->location;
+
+  check_no_duplicate_clause (list, OMP_CLAUSE_NOWAIT, "nowait");
+
+  c = build_omp_clause (loc, OMP_CLAUSE_NOWAIT);
+  OMP_CLAUSE_CHAIN (c) = list;
+  return c;
+}
+
+/* OpenMP 2.5:
+   num_threads ( expression ) */
+
+static tree
+c_parser_omp_clause_num_threads (c_parser *parser, tree list)
+{
+  location_t num_threads_loc = c_parser_peek_token (parser)->location;
+  if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+    {
+      location_t expr_loc = c_parser_peek_token (parser)->location;
+      tree c, t = c_parser_expression (parser).value;
+      mark_exp_read (t);
+      t = c_fully_fold (t, false, NULL);
+
+      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+
+      if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
+       {
+         c_parser_error (parser, "expected integer expression");
+         return list;
+       }
+
+      /* Attempt to statically determine when the number isn't positive.  */
+      c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, t,
+                      build_int_cst (TREE_TYPE (t), 0));
+      if (CAN_HAVE_LOCATION_P (c))
+       SET_EXPR_LOCATION (c, expr_loc);
+      if (c == boolean_true_node)
+       {
+         warning_at (expr_loc, 0,
+                     "%<num_threads%> value must be positive");
+         t = integer_one_node;
+       }
+
+      check_no_duplicate_clause (list, OMP_CLAUSE_NUM_THREADS, "num_threads");
+
+      c = build_omp_clause (num_threads_loc, OMP_CLAUSE_NUM_THREADS);
+      OMP_CLAUSE_NUM_THREADS_EXPR (c) = t;
+      OMP_CLAUSE_CHAIN (c) = list;
+      list = c;
+    }
+
+  return list;
+}
+
+/* OpenMP 2.5:
+   ordered */
+
+static tree
+c_parser_omp_clause_ordered (c_parser *parser, tree list)
+{
+  tree c;
+
+  check_no_duplicate_clause (list, OMP_CLAUSE_ORDERED, "ordered");
+
+  c = build_omp_clause (c_parser_peek_token (parser)->location,
+                       OMP_CLAUSE_ORDERED);
+  OMP_CLAUSE_CHAIN (c) = list;
+
+  return c;
+}
+
+/* OpenMP 2.5:
+   private ( variable-list ) */
+
+static tree
+c_parser_omp_clause_private (c_parser *parser, tree list)
+{
+  return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_PRIVATE, list);
+}
+
+/* OpenMP 2.5:
+   reduction ( reduction-operator : variable-list )
+
+   reduction-operator:
+     One of: + * - & ^ | && ||
+     
+   OpenMP 3.1:
+   
+   reduction-operator:
+     One of: + * - & ^ | && || max min  */
+
+static tree
+c_parser_omp_clause_reduction (c_parser *parser, tree list)
+{
+  location_t clause_loc = c_parser_peek_token (parser)->location;
+  if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+    {
+      enum tree_code code;
+
+      switch (c_parser_peek_token (parser)->type)
+       {
+       case CPP_PLUS:
+         code = PLUS_EXPR;
+         break;
+       case CPP_MULT:
+         code = MULT_EXPR;
+         break;
+       case CPP_MINUS:
+         code = MINUS_EXPR;
+         break;
+       case CPP_AND:
+         code = BIT_AND_EXPR;
+         break;
+       case CPP_XOR:
+         code = BIT_XOR_EXPR;
+         break;
+       case CPP_OR:
+         code = BIT_IOR_EXPR;
+         break;
+       case CPP_AND_AND:
+         code = TRUTH_ANDIF_EXPR;
+         break;
+       case CPP_OR_OR:
+         code = TRUTH_ORIF_EXPR;
+         break;
+        case CPP_NAME:
+         {
+           const char *p
+             = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+           if (strcmp (p, "min") == 0)
+             {
+               code = MIN_EXPR;
+               break;
+             }
+           if (strcmp (p, "max") == 0)
+             {
+               code = MAX_EXPR;
+               break;
+             }
+         }
+         /* FALLTHRU */
+       default:
+         c_parser_error (parser,
+                         "expected %<+%>, %<*%>, %<-%>, %<&%>, "
+                         "%<^%>, %<|%>, %<&&%>, %<||%>, %<min%> or %<max%>");
+         c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, 0);
+         return list;
+       }
+      c_parser_consume_token (parser);
+      if (c_parser_require (parser, CPP_COLON, "expected %<:%>"))
+       {
+         tree nl, c;
+
+         nl = c_parser_omp_variable_list (parser, clause_loc,
+                                          OMP_CLAUSE_REDUCTION, list);
+         for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
+           OMP_CLAUSE_REDUCTION_CODE (c) = code;
+
+         list = nl;
+       }
+      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+    }
+  return list;
+}
+
+/* OpenMP 2.5:
+   schedule ( schedule-kind )
+   schedule ( schedule-kind , expression )
+
+   schedule-kind:
+     static | dynamic | guided | runtime | auto
+*/
+
+static tree
+c_parser_omp_clause_schedule (c_parser *parser, tree list)
+{
+  tree c, t;
+  location_t loc = c_parser_peek_token (parser)->location;
+
+  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+    return list;
+
+  c = build_omp_clause (loc, OMP_CLAUSE_SCHEDULE);
+
+  if (c_parser_next_token_is (parser, CPP_NAME))
+    {
+      tree kind = c_parser_peek_token (parser)->value;
+      const char *p = IDENTIFIER_POINTER (kind);
+
+      switch (p[0])
+       {
+       case 'd':
+         if (strcmp ("dynamic", p) != 0)
+           goto invalid_kind;
+         OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_DYNAMIC;
+         break;
+
+        case 'g':
+         if (strcmp ("guided", p) != 0)
+           goto invalid_kind;
+         OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_GUIDED;
+         break;
+
+       case 'r':
+         if (strcmp ("runtime", p) != 0)
+           goto invalid_kind;
+         OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_RUNTIME;
+         break;
+
+       default:
+         goto invalid_kind;
+       }
+    }
+  else if (c_parser_next_token_is_keyword (parser, RID_STATIC))
+    OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_STATIC;
+  else if (c_parser_next_token_is_keyword (parser, RID_AUTO))
+    OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_AUTO;
+  else
+    goto invalid_kind;
+
+  c_parser_consume_token (parser);
+  if (c_parser_next_token_is (parser, CPP_COMMA))
+    {
+      location_t here;
+      c_parser_consume_token (parser);
+
+      here = c_parser_peek_token (parser)->location;
+      t = c_parser_expr_no_commas (parser, NULL).value;
+      mark_exp_read (t);
+      t = c_fully_fold (t, false, NULL);
+
+      if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_RUNTIME)
+       error_at (here, "schedule %<runtime%> does not take "
+                 "a %<chunk_size%> parameter");
+      else if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_AUTO)
+       error_at (here,
+                 "schedule %<auto%> does not take "
+                 "a %<chunk_size%> parameter");
+      else if (TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE)
+       OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = t;
+      else
+       c_parser_error (parser, "expected integer expression");
+
+      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+    }
+  else
+    c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+                              "expected %<,%> or %<)%>");
+
+  check_no_duplicate_clause (list, OMP_CLAUSE_SCHEDULE, "schedule");
+  OMP_CLAUSE_CHAIN (c) = list;
+  return c;
+
+ invalid_kind:
+  c_parser_error (parser, "invalid schedule kind");
+  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, 0);
+  return list;
+}
+
+/* OpenMP 2.5:
+   shared ( variable-list ) */
+
+static tree
+c_parser_omp_clause_shared (c_parser *parser, tree list)
+{
+  return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_SHARED, list);
+}
+
+/* OpenMP 3.0:
+   untied */
+
+static tree
+c_parser_omp_clause_untied (c_parser *parser ATTRIBUTE_UNUSED, tree list)
+{
+  tree c;
+
+  /* FIXME: Should we allow duplicates?  */
+  check_no_duplicate_clause (list, OMP_CLAUSE_UNTIED, "untied");
+
+  c = build_omp_clause (c_parser_peek_token (parser)->location,
+                       OMP_CLAUSE_UNTIED);
+  OMP_CLAUSE_CHAIN (c) = list;
+
+  return c;
+}
+
+/* Parse all OpenMP clauses.  The set clauses allowed by the directive
+   is a bitmask in MASK.  Return the list of clauses found; the result
+   of clause default goes in *pdefault.  */
+
+static tree
+c_parser_omp_all_clauses (c_parser *parser, unsigned int mask,
+                         const char *where)
+{
+  tree clauses = NULL;
+  bool first = true;
+
+  while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
+    {
+      location_t here;
+      pragma_omp_clause c_kind;
+      const char *c_name;
+      tree prev = clauses;
+
+      if (!first && c_parser_next_token_is (parser, CPP_COMMA))
+       c_parser_consume_token (parser);
+
+      first = false;
+      here = c_parser_peek_token (parser)->location;
+      c_kind = c_parser_omp_clause_name (parser);
+
+      switch (c_kind)
+       {
+       case PRAGMA_OMP_CLAUSE_COLLAPSE:
+         clauses = c_parser_omp_clause_collapse (parser, clauses);
+         c_name = "collapse";
+         break;
+       case PRAGMA_OMP_CLAUSE_COPYIN:
+         clauses = c_parser_omp_clause_copyin (parser, clauses);
+         c_name = "copyin";
+         break;
+       case PRAGMA_OMP_CLAUSE_COPYPRIVATE:
+         clauses = c_parser_omp_clause_copyprivate (parser, clauses);
+         c_name = "copyprivate";
+         break;
+       case PRAGMA_OMP_CLAUSE_DEFAULT:
+         clauses = c_parser_omp_clause_default (parser, clauses);
+         c_name = "default";
+         break;
+       case PRAGMA_OMP_CLAUSE_FIRSTPRIVATE:
+         clauses = c_parser_omp_clause_firstprivate (parser, clauses);
+         c_name = "firstprivate";
+         break;
+       case PRAGMA_OMP_CLAUSE_FINAL:
+         clauses = c_parser_omp_clause_final (parser, clauses);
+         c_name = "final";
+         break;
+       case PRAGMA_OMP_CLAUSE_IF:
+         clauses = c_parser_omp_clause_if (parser, clauses);
+         c_name = "if";
+         break;
+       case PRAGMA_OMP_CLAUSE_LASTPRIVATE:
+         clauses = c_parser_omp_clause_lastprivate (parser, clauses);
+         c_name = "lastprivate";
+         break;
+       case PRAGMA_OMP_CLAUSE_MERGEABLE:
+         clauses = c_parser_omp_clause_mergeable (parser, clauses);
+         c_name = "mergeable";
+         break;
+       case PRAGMA_OMP_CLAUSE_NOWAIT:
+         clauses = c_parser_omp_clause_nowait (parser, clauses);
+         c_name = "nowait";
+         break;
+       case PRAGMA_OMP_CLAUSE_NUM_THREADS:
+         clauses = c_parser_omp_clause_num_threads (parser, clauses);
+         c_name = "num_threads";
+         break;
+       case PRAGMA_OMP_CLAUSE_ORDERED:
+         clauses = c_parser_omp_clause_ordered (parser, clauses);
+         c_name = "ordered";
+         break;
+       case PRAGMA_OMP_CLAUSE_PRIVATE:
+         clauses = c_parser_omp_clause_private (parser, clauses);
+         c_name = "private";
+         break;
+       case PRAGMA_OMP_CLAUSE_REDUCTION:
+         clauses = c_parser_omp_clause_reduction (parser, clauses);
+         c_name = "reduction";
+         break;
+       case PRAGMA_OMP_CLAUSE_SCHEDULE:
+         clauses = c_parser_omp_clause_schedule (parser, clauses);
+         c_name = "schedule";
+         break;
+       case PRAGMA_OMP_CLAUSE_SHARED:
+         clauses = c_parser_omp_clause_shared (parser, clauses);
+         c_name = "shared";
+         break;
+       case PRAGMA_OMP_CLAUSE_UNTIED:
+         clauses = c_parser_omp_clause_untied (parser, clauses);
+         c_name = "untied";
+         break;
+       default:
+         c_parser_error (parser, "expected %<#pragma omp%> clause");
+         goto saw_error;
+       }
+
+      if (((mask >> c_kind) & 1) == 0 && !parser->error)
+       {
+         /* Remove the invalid clause(s) from the list to avoid
+            confusing the rest of the compiler.  */
+         clauses = prev;
+         error_at (here, "%qs is not valid for %qs", c_name, where);
+       }
+    }
+
+ saw_error:
+  c_parser_skip_to_pragma_eol (parser);
+
+  return c_finish_omp_clauses (clauses);
+}
+
+/* OpenMP 2.5:
+   structured-block:
+     statement
+
+   In practice, we're also interested in adding the statement to an
+   outer node.  So it is convenient if we work around the fact that
+   c_parser_statement calls add_stmt.  */
+
+static tree
+c_parser_omp_structured_block (c_parser *parser)
+{
+  tree stmt = push_stmt_list ();
+  c_parser_statement (parser);
+  return pop_stmt_list (stmt);
+}
+
+/* OpenMP 2.5:
+   # pragma omp atomic new-line
+     expression-stmt
+
+   expression-stmt:
+     x binop= expr | x++ | ++x | x-- | --x
+   binop:
+     +, *, -, /, &, ^, |, <<, >>
+
+  where x is an lvalue expression with scalar type.
+
+   OpenMP 3.1:
+   # pragma omp atomic new-line
+     update-stmt
+
+   # pragma omp atomic read new-line
+     read-stmt
+
+   # pragma omp atomic write new-line
+     write-stmt
+
+   # pragma omp atomic update new-line
+     update-stmt
+
+   # pragma omp atomic capture new-line
+     capture-stmt
+
+   # pragma omp atomic capture new-line
+     capture-block
+
+   read-stmt:
+     v = x
+   write-stmt:
+     x = expr
+   update-stmt:
+     expression-stmt | x = x binop expr
+   capture-stmt:
+     v = x binop= expr | v = x++ | v = ++x | v = x-- | v = --x
+   capture-block:
+     { v = x; update-stmt; } | { update-stmt; v = x; }
+
+  where x and v are lvalue expressions with scalar type.
+
+  LOC is the location of the #pragma token.  */
+
+static void
+c_parser_omp_atomic (location_t loc, c_parser *parser)
+{
+  tree lhs = NULL_TREE, rhs = NULL_TREE, v = NULL_TREE;
+  tree lhs1 = NULL_TREE, rhs1 = NULL_TREE;
+  tree stmt, orig_lhs;
+  enum tree_code code = OMP_ATOMIC, opcode = NOP_EXPR;
+  struct c_expr rhs_expr;
+  bool structured_block = false;
+
+  if (c_parser_next_token_is (parser, CPP_NAME))
+    {
+      const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+
+      if (!strcmp (p, "read"))
+       code = OMP_ATOMIC_READ;
+      else if (!strcmp (p, "write"))
+       code = NOP_EXPR;
+      else if (!strcmp (p, "update"))
+       code = OMP_ATOMIC;
+      else if (!strcmp (p, "capture"))
+       code = OMP_ATOMIC_CAPTURE_NEW;
+      else
+       p = NULL;
+      if (p)
+       c_parser_consume_token (parser);
+    }
+  c_parser_skip_to_pragma_eol (parser);
+
+  switch (code)
+    {
+    case OMP_ATOMIC_READ:
+    case NOP_EXPR: /* atomic write */
+      v = c_parser_unary_expression (parser).value;
+      v = c_fully_fold (v, false, NULL);
+      if (v == error_mark_node)
+       goto saw_error;
+      loc = c_parser_peek_token (parser)->location;
+      if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
+       goto saw_error;
+      if (code == NOP_EXPR)
+       lhs = c_parser_expression (parser).value;
+      else
+       lhs = c_parser_unary_expression (parser).value;
+      lhs = c_fully_fold (lhs, false, NULL);
+      if (lhs == error_mark_node)
+       goto saw_error;
+      if (code == NOP_EXPR)
+       {
+         /* atomic write is represented by OMP_ATOMIC with NOP_EXPR
+            opcode.  */
+         code = OMP_ATOMIC;
+         rhs = lhs;
+         lhs = v;
+         v = NULL_TREE;
+       }
+      goto done;
+    case OMP_ATOMIC_CAPTURE_NEW:
+      if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
+       {
+         c_parser_consume_token (parser);
+         structured_block = true;
+       }
+      else
+       {
+         v = c_parser_unary_expression (parser).value;
+         v = c_fully_fold (v, false, NULL);
+         if (v == error_mark_node)
+           goto saw_error;
+         if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
+           goto saw_error;
+       }
+      break;
+    default:
+      break;
+    }
+
+  /* For structured_block case we don't know yet whether
+     old or new x should be captured.  */
+restart:
+  lhs = c_parser_unary_expression (parser).value;
+  lhs = c_fully_fold (lhs, false, NULL);
+  orig_lhs = lhs;
+  switch (TREE_CODE (lhs))
+    {
+    case ERROR_MARK:
+    saw_error:
+      c_parser_skip_to_end_of_block_or_statement (parser);
+      if (structured_block)
+       {
+         if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
+           c_parser_consume_token (parser);
+         else if (code == OMP_ATOMIC_CAPTURE_NEW)
+           {
+             c_parser_skip_to_end_of_block_or_statement (parser);
+             if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
+               c_parser_consume_token (parser);
+           }
+       }
+      return;
+
+    case POSTINCREMENT_EXPR:
+      if (code == OMP_ATOMIC_CAPTURE_NEW && !structured_block)
+       code = OMP_ATOMIC_CAPTURE_OLD;
+      /* FALLTHROUGH */
+    case PREINCREMENT_EXPR:
+      lhs = TREE_OPERAND (lhs, 0);
+      opcode = PLUS_EXPR;
+      rhs = integer_one_node;
+      break;
+
+    case POSTDECREMENT_EXPR:
+      if (code == OMP_ATOMIC_CAPTURE_NEW && !structured_block)
+       code = OMP_ATOMIC_CAPTURE_OLD;
+      /* FALLTHROUGH */
+    case PREDECREMENT_EXPR:
+      lhs = TREE_OPERAND (lhs, 0);
+      opcode = MINUS_EXPR;
+      rhs = integer_one_node;
+      break;
+
+    case COMPOUND_EXPR:
+      if (TREE_CODE (TREE_OPERAND (lhs, 0)) == SAVE_EXPR
+         && TREE_CODE (TREE_OPERAND (lhs, 1)) == COMPOUND_EXPR
+         && TREE_CODE (TREE_OPERAND (TREE_OPERAND (lhs, 1), 0)) == MODIFY_EXPR
+         && TREE_OPERAND (TREE_OPERAND (lhs, 1), 1) == TREE_OPERAND (lhs, 0)
+         && TREE_CODE (TREE_TYPE (TREE_OPERAND (TREE_OPERAND
+                                             (TREE_OPERAND (lhs, 1), 0), 0)))
+            == BOOLEAN_TYPE)
+       /* Undo effects of boolean_increment for post {in,de}crement.  */
+       lhs = TREE_OPERAND (TREE_OPERAND (lhs, 1), 0);
+      /* FALLTHRU */
+    case MODIFY_EXPR:
+      if (TREE_CODE (lhs) == MODIFY_EXPR
+         && TREE_CODE (TREE_TYPE (TREE_OPERAND (lhs, 0))) == BOOLEAN_TYPE)
+       {
+         /* Undo effects of boolean_increment.  */
+         if (integer_onep (TREE_OPERAND (lhs, 1)))
+           {
+             /* This is pre or post increment.  */
+             rhs = TREE_OPERAND (lhs, 1);
+             lhs = TREE_OPERAND (lhs, 0);
+             opcode = NOP_EXPR;
+             if (code == OMP_ATOMIC_CAPTURE_NEW
+                 && !structured_block
+                 && TREE_CODE (orig_lhs) == COMPOUND_EXPR)
+               code = OMP_ATOMIC_CAPTURE_OLD;
+             break;
+           }
+         if (TREE_CODE (TREE_OPERAND (lhs, 1)) == TRUTH_NOT_EXPR
+             && TREE_OPERAND (lhs, 0)
+                == TREE_OPERAND (TREE_OPERAND (lhs, 1), 0))
+           {
+             /* This is pre or post decrement.  */
+             rhs = TREE_OPERAND (lhs, 1);
+             lhs = TREE_OPERAND (lhs, 0);
+             opcode = NOP_EXPR;
+             if (code == OMP_ATOMIC_CAPTURE_NEW
+                 && !structured_block
+                 && TREE_CODE (orig_lhs) == COMPOUND_EXPR)
+               code = OMP_ATOMIC_CAPTURE_OLD;
+             break;
+           }
+       }
+      /* FALLTHRU */
+    default:
+      switch (c_parser_peek_token (parser)->type)
+       {
+       case CPP_MULT_EQ:
+         opcode = MULT_EXPR;
+         break;
+       case CPP_DIV_EQ:
+         opcode = TRUNC_DIV_EXPR;
+         break;
+       case CPP_PLUS_EQ:
+         opcode = PLUS_EXPR;
+         break;
+       case CPP_MINUS_EQ:
+         opcode = MINUS_EXPR;
+         break;
+       case CPP_LSHIFT_EQ:
+         opcode = LSHIFT_EXPR;
+         break;
+       case CPP_RSHIFT_EQ:
+         opcode = RSHIFT_EXPR;
+         break;
+       case CPP_AND_EQ:
+         opcode = BIT_AND_EXPR;
+         break;
+       case CPP_OR_EQ:
+         opcode = BIT_IOR_EXPR;
+         break;
+       case CPP_XOR_EQ:
+         opcode = BIT_XOR_EXPR;
+         break;
+       case CPP_EQ:
+         if (structured_block || code == OMP_ATOMIC)
+           {
+             location_t aloc = c_parser_peek_token (parser)->location;
+             location_t rhs_loc;
+             enum c_parser_prec oprec = PREC_NONE;
+
+             c_parser_consume_token (parser);
+             rhs1 = c_parser_unary_expression (parser).value;
+             rhs1 = c_fully_fold (rhs1, false, NULL);
+             if (rhs1 == error_mark_node)
+               goto saw_error;
+             switch (c_parser_peek_token (parser)->type)
+               {
+               case CPP_SEMICOLON:
+                 if (code == OMP_ATOMIC_CAPTURE_NEW)
+                   {
+                     code = OMP_ATOMIC_CAPTURE_OLD;
+                     v = lhs;
+                     lhs = NULL_TREE;
+                     lhs1 = rhs1;
+                     rhs1 = NULL_TREE;
+                     c_parser_consume_token (parser);
+                     goto restart;
+                   }
+                 c_parser_error (parser,
+                                 "invalid form of %<#pragma omp atomic%>");
+                 goto saw_error;
+               case CPP_MULT:
+                 opcode = MULT_EXPR;
+                 oprec = PREC_MULT;
+                 break;
+               case CPP_DIV:
+                 opcode = TRUNC_DIV_EXPR;
+                 oprec = PREC_MULT;
+                 break;
+               case CPP_PLUS:
+                 opcode = PLUS_EXPR;
+                 oprec = PREC_ADD;
+                 break;
+               case CPP_MINUS:
+                 opcode = MINUS_EXPR;
+                 oprec = PREC_ADD;
+                 break;
+               case CPP_LSHIFT:
+                 opcode = LSHIFT_EXPR;
+                 oprec = PREC_SHIFT;
+                 break;
+               case CPP_RSHIFT:
+                 opcode = RSHIFT_EXPR;
+                 oprec = PREC_SHIFT;
+                 break;
+               case CPP_AND:
+                 opcode = BIT_AND_EXPR;
+                 oprec = PREC_BITAND;
+                 break;
+               case CPP_OR:
+                 opcode = BIT_IOR_EXPR;
+                 oprec = PREC_BITOR;
+                 break;
+               case CPP_XOR:
+                 opcode = BIT_XOR_EXPR;
+                 oprec = PREC_BITXOR;
+                 break;
+               default:
+                 c_parser_error (parser,
+                                 "invalid operator for %<#pragma omp atomic%>");
+                 goto saw_error;
+               }
+             loc = aloc;
+             c_parser_consume_token (parser);
+             rhs_loc = c_parser_peek_token (parser)->location;
+             if (commutative_tree_code (opcode))
+               oprec = (enum c_parser_prec) (oprec - 1);
+             rhs_expr = c_parser_binary_expression (parser, NULL, oprec);
+             rhs_expr = default_function_array_read_conversion (rhs_loc,
+                                                                rhs_expr);
+             rhs = rhs_expr.value;
+             rhs = c_fully_fold (rhs, false, NULL);
+             goto stmt_done; 
+           }
+         /* FALLTHROUGH */
+       default:
+         c_parser_error (parser,
+                         "invalid operator for %<#pragma omp atomic%>");
+         goto saw_error;
+       }
+
+      /* Arrange to pass the location of the assignment operator to
+        c_finish_omp_atomic.  */
+      loc = c_parser_peek_token (parser)->location;
+      c_parser_consume_token (parser);
+      {
+       location_t rhs_loc = c_parser_peek_token (parser)->location;
+       rhs_expr = c_parser_expression (parser);
+       rhs_expr = default_function_array_read_conversion (rhs_loc, rhs_expr);
+      }
+      rhs = rhs_expr.value;
+      rhs = c_fully_fold (rhs, false, NULL);
+      break;
+    }
+stmt_done:
+  if (structured_block && code == OMP_ATOMIC_CAPTURE_NEW)
+    {
+      if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
+       goto saw_error;
+      v = c_parser_unary_expression (parser).value;
+      v = c_fully_fold (v, false, NULL);
+      if (v == error_mark_node)
+       goto saw_error;
+      if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
+       goto saw_error;
+      lhs1 = c_parser_unary_expression (parser).value;
+      lhs1 = c_fully_fold (lhs1, false, NULL);
+      if (lhs1 == error_mark_node)
+       goto saw_error;
+    }
+  if (structured_block)
+    {
+      c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+      c_parser_require (parser, CPP_CLOSE_BRACE, "expected %<}%>");
+    }
+done:
+  stmt = c_finish_omp_atomic (loc, code, opcode, lhs, rhs, v, lhs1, rhs1);
+  if (stmt != error_mark_node)
+    add_stmt (stmt);
+
+  if (!structured_block)
+    c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+}
+
+
+/* OpenMP 2.5:
+   # pragma omp barrier new-line
+*/
+
+static void
+c_parser_omp_barrier (c_parser *parser)
+{
+  location_t loc = c_parser_peek_token (parser)->location;
+  c_parser_consume_pragma (parser);
+  c_parser_skip_to_pragma_eol (parser);
+
+  c_finish_omp_barrier (loc);
+}
+
+/* OpenMP 2.5:
+   # pragma omp critical [(name)] new-line
+     structured-block
+
+  LOC is the location of the #pragma itself.  */
+
+static tree
+c_parser_omp_critical (location_t loc, c_parser *parser)
+{
+  tree stmt, name = NULL;
+
+  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+    {
+      c_parser_consume_token (parser);
+      if (c_parser_next_token_is (parser, CPP_NAME))
+       {
+         name = c_parser_peek_token (parser)->value;
+         c_parser_consume_token (parser);
+         c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+       }
+      else
+       c_parser_error (parser, "expected identifier");
+    }
+  else if (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
+    c_parser_error (parser, "expected %<(%> or end of line");
+  c_parser_skip_to_pragma_eol (parser);
+
+  stmt = c_parser_omp_structured_block (parser);
+  return c_finish_omp_critical (loc, stmt, name);
+}
+
+/* OpenMP 2.5:
+   # pragma omp flush flush-vars[opt] new-line
+
+   flush-vars:
+     ( variable-list ) */
+
+static void
+c_parser_omp_flush (c_parser *parser)
+{
+  location_t loc = c_parser_peek_token (parser)->location;
+  c_parser_consume_pragma (parser);
+  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+    c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ERROR, NULL);
+  else if (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
+    c_parser_error (parser, "expected %<(%> or end of line");
+  c_parser_skip_to_pragma_eol (parser);
+
+  c_finish_omp_flush (loc);
+}
+
+/* Parse the restricted form of the for statement allowed by OpenMP.
+   The real trick here is to determine the loop control variable early
+   so that we can push a new decl if necessary to make it private.
+   LOC is the location of the OMP in "#pragma omp".  */
+
+static tree
+c_parser_omp_for_loop (location_t loc,
+                      c_parser *parser, tree clauses, tree *par_clauses)
+{
+  tree decl, cond, incr, save_break, save_cont, body, init, stmt, cl;
+  tree declv, condv, incrv, initv, ret = NULL;
+  bool fail = false, open_brace_parsed = false;
+  int i, collapse = 1, nbraces = 0;
+  location_t for_loc;
+  VEC(tree,gc) *for_block = make_tree_vector ();
+
+  for (cl = clauses; cl; cl = OMP_CLAUSE_CHAIN (cl))
+    if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_COLLAPSE)
+      collapse = tree_low_cst (OMP_CLAUSE_COLLAPSE_EXPR (cl), 0);
+
+  gcc_assert (collapse >= 1);
+
+  declv = make_tree_vec (collapse);
+  initv = make_tree_vec (collapse);
+  condv = make_tree_vec (collapse);
+  incrv = make_tree_vec (collapse);
+
+  if (!c_parser_next_token_is_keyword (parser, RID_FOR))
+    {
+      c_parser_error (parser, "for statement expected");
+      return NULL;
+    }
+  for_loc = c_parser_peek_token (parser)->location;
+  c_parser_consume_token (parser);
+
+  for (i = 0; i < collapse; i++)
+    {
+      int bracecount = 0;
+
+      if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+       goto pop_scopes;
+
+      /* Parse the initialization declaration or expression.  */
+      if (c_parser_next_tokens_start_declaration (parser))
+       {
+         if (i > 0)
+           VEC_safe_push (tree, gc, for_block, c_begin_compound_stmt (true));
+         c_parser_declaration_or_fndef (parser, true, true, true, true, true, NULL);
+         decl = check_for_loop_decls (for_loc, flag_isoc99);
+         if (decl == NULL)
+           goto error_init;
+         if (DECL_INITIAL (decl) == error_mark_node)
+           decl = error_mark_node;
+         init = decl;
+       }
+      else if (c_parser_next_token_is (parser, CPP_NAME)
+              && c_parser_peek_2nd_token (parser)->type == CPP_EQ)
+       {
+         struct c_expr decl_exp;
+         struct c_expr init_exp;
+         location_t init_loc;
+
+         decl_exp = c_parser_postfix_expression (parser);
+         decl = decl_exp.value;
+
+         c_parser_require (parser, CPP_EQ, "expected %<=%>");
+
+         init_loc = c_parser_peek_token (parser)->location;
+         init_exp = c_parser_expr_no_commas (parser, NULL);
+         init_exp = default_function_array_read_conversion (init_loc,
+                                                            init_exp);
+         init = build_modify_expr (init_loc, decl, decl_exp.original_type,
+                                   NOP_EXPR, init_loc, init_exp.value,
+                                   init_exp.original_type);
+         init = c_process_expr_stmt (init_loc, init);
+
+         c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+       }
+      else
+       {
+       error_init:
+         c_parser_error (parser,
+                         "expected iteration declaration or initialization");
+         c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+                                    "expected %<)%>");
+         fail = true;
+         goto parse_next;
+       }
+
+      /* Parse the loop condition.  */
+      cond = NULL_TREE;
+      if (c_parser_next_token_is_not (parser, CPP_SEMICOLON))
+       {
+         location_t cond_loc = c_parser_peek_token (parser)->location;
+         struct c_expr cond_expr = c_parser_binary_expression (parser, NULL,
+                                                               PREC_NONE);
+
+         cond = cond_expr.value;
+         cond = c_objc_common_truthvalue_conversion (cond_loc, cond);
+         cond = c_fully_fold (cond, false, NULL);
+         switch (cond_expr.original_code)
+           {
+           case GT_EXPR:
+           case GE_EXPR:
+           case LT_EXPR:
+           case LE_EXPR:
+             break;
+           default:
+             /* Can't be cond = error_mark_node, because we want to preserve
+                the location until c_finish_omp_for.  */
+             cond = build1 (NOP_EXPR, boolean_type_node, error_mark_node);
+             break;
+           }
+         protected_set_expr_location (cond, cond_loc);
+       }
+      c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+
+      /* Parse the increment expression.  */
+      incr = NULL_TREE;
+      if (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN))
+       {
+         location_t incr_loc = c_parser_peek_token (parser)->location;
+
+         incr = c_process_expr_stmt (incr_loc,
+                                     c_parser_expression (parser).value);
+       }
+      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+
+      if (decl == NULL || decl == error_mark_node || init == error_mark_node)
+       fail = true;
+      else
+       {
+         TREE_VEC_ELT (declv, i) = decl;
+         TREE_VEC_ELT (initv, i) = init;
+         TREE_VEC_ELT (condv, i) = cond;
+         TREE_VEC_ELT (incrv, i) = incr;
+       }
+
+    parse_next:
+      if (i == collapse - 1)
+       break;
+
+      /* FIXME: OpenMP 3.0 draft isn't very clear on what exactly is allowed
+        in between the collapsed for loops to be still considered perfectly
+        nested.  Hopefully the final version clarifies this.
+        For now handle (multiple) {'s and empty statements.  */
+      do
+       {
+         if (c_parser_next_token_is_keyword (parser, RID_FOR))
+           {
+             c_parser_consume_token (parser);
+             break;
+           }
+         else if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
+           {
+             c_parser_consume_token (parser);
+             bracecount++;
+           }
+         else if (bracecount
+                  && c_parser_next_token_is (parser, CPP_SEMICOLON))
+           c_parser_consume_token (parser);
+         else
+           {
+             c_parser_error (parser, "not enough perfectly nested loops");
+             if (bracecount)
+               {
+                 open_brace_parsed = true;
+                 bracecount--;
+               }
+             fail = true;
+             collapse = 0;
+             break;
+           }
+       }
+      while (1);
+
+      nbraces += bracecount;
+    }
+
+  save_break = c_break_label;
+  c_break_label = size_one_node;
+  save_cont = c_cont_label;
+  c_cont_label = NULL_TREE;
+  body = push_stmt_list ();
+
+  if (open_brace_parsed)
+    {
+      location_t here = c_parser_peek_token (parser)->location;
+      stmt = c_begin_compound_stmt (true);
+      c_parser_compound_statement_nostart (parser);
+      add_stmt (c_end_compound_stmt (here, stmt, true));
+    }
+  else
+    add_stmt (c_parser_c99_block_statement (parser));
+  if (c_cont_label)
+    {
+      tree t = build1 (LABEL_EXPR, void_type_node, c_cont_label);
+      SET_EXPR_LOCATION (t, loc);
+      add_stmt (t);
+    }
+
+  body = pop_stmt_list (body);
+  c_break_label = save_break;
+  c_cont_label = save_cont;
+
+  while (nbraces)
+    {
+      if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
+       {
+         c_parser_consume_token (parser);
+         nbraces--;
+       }
+      else if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+       c_parser_consume_token (parser);
+      else
+       {
+         c_parser_error (parser, "collapsed loops not perfectly nested");
+         while (nbraces)
+           {
+             location_t here = c_parser_peek_token (parser)->location;
+             stmt = c_begin_compound_stmt (true);
+             add_stmt (body);
+             c_parser_compound_statement_nostart (parser);
+             body = c_end_compound_stmt (here, stmt, true);
+             nbraces--;
+           }
+         goto pop_scopes;
+       }
+    }
+
+  /* Only bother calling c_finish_omp_for if we haven't already generated
+     an error from the initialization parsing.  */
+  if (!fail)
+    {
+      stmt = c_finish_omp_for (loc, declv, initv, condv, incrv, body, NULL);
+      if (stmt)
+       {
+         if (par_clauses != NULL)
+           {
+             tree *c;
+             for (c = par_clauses; *c ; )
+               if (OMP_CLAUSE_CODE (*c) != OMP_CLAUSE_FIRSTPRIVATE
+                   && OMP_CLAUSE_CODE (*c) != OMP_CLAUSE_LASTPRIVATE)
+                 c = &OMP_CLAUSE_CHAIN (*c);
+               else
+                 {
+                   for (i = 0; i < collapse; i++)
+                     if (TREE_VEC_ELT (declv, i) == OMP_CLAUSE_DECL (*c))
+                       break;
+                   if (i == collapse)
+                     c = &OMP_CLAUSE_CHAIN (*c);
+                   else if (OMP_CLAUSE_CODE (*c) == OMP_CLAUSE_FIRSTPRIVATE)
+                     {
+                       error_at (loc,
+                                 "iteration variable %qD should not be firstprivate",
+                                 OMP_CLAUSE_DECL (*c));
+                       *c = OMP_CLAUSE_CHAIN (*c);
+                     }
+                   else
+                     {
+                       /* Copy lastprivate (decl) clause to OMP_FOR_CLAUSES,
+                          change it to shared (decl) in
+                          OMP_PARALLEL_CLAUSES.  */
+                       tree l = build_omp_clause (OMP_CLAUSE_LOCATION (*c),
+                                                  OMP_CLAUSE_LASTPRIVATE);
+                       OMP_CLAUSE_DECL (l) = OMP_CLAUSE_DECL (*c);
+                       OMP_CLAUSE_CHAIN (l) = clauses;
+                       clauses = l;
+                       OMP_CLAUSE_SET_CODE (*c, OMP_CLAUSE_SHARED);
+                     }
+                 }
+           }
+         OMP_FOR_CLAUSES (stmt) = clauses;
+       }
+      ret = stmt;
+    }
+pop_scopes:
+  while (!VEC_empty (tree, for_block))
+    {
+      /* FIXME diagnostics: LOC below should be the actual location of
+        this particular for block.  We need to build a list of
+        locations to go along with FOR_BLOCK.  */
+      stmt = c_end_compound_stmt (loc, VEC_pop (tree, for_block), true);
+      add_stmt (stmt);
+    }
+  release_tree_vector (for_block);
+  return ret;
+}
+
+/* OpenMP 2.5:
+   #pragma omp for for-clause[optseq] new-line
+     for-loop
+
+   LOC is the location of the #pragma token.
+*/
+
+#define OMP_FOR_CLAUSE_MASK                            \
+       ( (1u << PRAGMA_OMP_CLAUSE_PRIVATE)             \
+       | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE)        \
+       | (1u << PRAGMA_OMP_CLAUSE_LASTPRIVATE)         \
+       | (1u << PRAGMA_OMP_CLAUSE_REDUCTION)           \
+       | (1u << PRAGMA_OMP_CLAUSE_ORDERED)             \
+       | (1u << PRAGMA_OMP_CLAUSE_SCHEDULE)            \
+       | (1u << PRAGMA_OMP_CLAUSE_COLLAPSE)            \
+       | (1u << PRAGMA_OMP_CLAUSE_NOWAIT))
+
+static tree
+c_parser_omp_for (location_t loc, c_parser *parser)
+{
+  tree block, clauses, ret;
+
+  clauses = c_parser_omp_all_clauses (parser, OMP_FOR_CLAUSE_MASK,
+                                     "#pragma omp for");
+
+  block = c_begin_compound_stmt (true);
+  ret = c_parser_omp_for_loop (loc, parser, clauses, NULL);
+  block = c_end_compound_stmt (loc, block, true);
+  add_stmt (block);
+
+  return ret;
+}
+
+/* OpenMP 2.5:
+   # pragma omp master new-line
+     structured-block
+
+   LOC is the location of the #pragma token.
+*/
+
+static tree
+c_parser_omp_master (location_t loc, c_parser *parser)
+{
+  c_parser_skip_to_pragma_eol (parser);
+  return c_finish_omp_master (loc, c_parser_omp_structured_block (parser));
+}
+
+/* OpenMP 2.5:
+   # pragma omp ordered new-line
+     structured-block
+
+   LOC is the location of the #pragma itself.
+*/
+
+static tree
+c_parser_omp_ordered (location_t loc, c_parser *parser)
+{
+  c_parser_skip_to_pragma_eol (parser);
+  return c_finish_omp_ordered (loc, c_parser_omp_structured_block (parser));
+}
+
+/* OpenMP 2.5:
+
+   section-scope:
+     { section-sequence }
+
+   section-sequence:
+     section-directive[opt] structured-block
+     section-sequence section-directive structured-block
+
+    SECTIONS_LOC is the location of the #pragma omp sections.  */
+
+static tree
+c_parser_omp_sections_scope (location_t sections_loc, c_parser *parser)
+{
+  tree stmt, substmt;
+  bool error_suppress = false;
+  location_t loc;
+
+  loc = c_parser_peek_token (parser)->location;
+  if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
+    {
+      /* Avoid skipping until the end of the block.  */
+      parser->error = false;
+      return NULL_TREE;
+    }
+
+  stmt = push_stmt_list ();
+
+  if (c_parser_peek_token (parser)->pragma_kind != PRAGMA_OMP_SECTION)
+    {
+      substmt = push_stmt_list ();
+
+      while (1)
+       {
+          c_parser_statement (parser);
+
+         if (c_parser_peek_token (parser)->pragma_kind == PRAGMA_OMP_SECTION)
+           break;
+         if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
+           break;
+         if (c_parser_next_token_is (parser, CPP_EOF))
+           break;
+       }
+
+      substmt = pop_stmt_list (substmt);
+      substmt = build1 (OMP_SECTION, void_type_node, substmt);
+      SET_EXPR_LOCATION (substmt, loc);
+      add_stmt (substmt);
+    }
+
+  while (1)
+    {
+      if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
+       break;
+      if (c_parser_next_token_is (parser, CPP_EOF))
+       break;
+
+      loc = c_parser_peek_token (parser)->location;
+      if (c_parser_peek_token (parser)->pragma_kind == PRAGMA_OMP_SECTION)
+       {
+         c_parser_consume_pragma (parser);
+         c_parser_skip_to_pragma_eol (parser);
+         error_suppress = false;
+       }
+      else if (!error_suppress)
+       {
+         error_at (loc, "expected %<#pragma omp section%> or %<}%>");
+         error_suppress = true;
+       }
+
+      substmt = c_parser_omp_structured_block (parser);
+      substmt = build1 (OMP_SECTION, void_type_node, substmt);
+      SET_EXPR_LOCATION (substmt, loc);
+      add_stmt (substmt);
+    }
+  c_parser_skip_until_found (parser, CPP_CLOSE_BRACE,
+                            "expected %<#pragma omp section%> or %<}%>");
+
+  substmt = pop_stmt_list (stmt);
+
+  stmt = make_node (OMP_SECTIONS);
+  SET_EXPR_LOCATION (stmt, sections_loc);
+  TREE_TYPE (stmt) = void_type_node;
+  OMP_SECTIONS_BODY (stmt) = substmt;
+
+  return add_stmt (stmt);
+}
+
+/* OpenMP 2.5:
+   # pragma omp sections sections-clause[optseq] newline
+     sections-scope
+
+   LOC is the location of the #pragma token.
+*/
+
+#define OMP_SECTIONS_CLAUSE_MASK                       \
+       ( (1u << PRAGMA_OMP_CLAUSE_PRIVATE)             \
+       | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE)        \
+       | (1u << PRAGMA_OMP_CLAUSE_LASTPRIVATE)         \
+       | (1u << PRAGMA_OMP_CLAUSE_REDUCTION)           \
+       | (1u << PRAGMA_OMP_CLAUSE_NOWAIT))
+
+static tree
+c_parser_omp_sections (location_t loc, c_parser *parser)
+{
+  tree block, clauses, ret;
+
+  clauses = c_parser_omp_all_clauses (parser, OMP_SECTIONS_CLAUSE_MASK,
+                                     "#pragma omp sections");
+
+  block = c_begin_compound_stmt (true);
+  ret = c_parser_omp_sections_scope (loc, parser);
+  if (ret)
+    OMP_SECTIONS_CLAUSES (ret) = clauses;
+  block = c_end_compound_stmt (loc, block, true);
+  add_stmt (block);
+
+  return ret;
+}
+
+/* OpenMP 2.5:
+   # pragma parallel parallel-clause new-line
+   # pragma parallel for parallel-for-clause new-line
+   # pragma parallel sections parallel-sections-clause new-line
+
+   LOC is the location of the #pragma token.
+*/
+
+#define OMP_PARALLEL_CLAUSE_MASK                       \
+       ( (1u << PRAGMA_OMP_CLAUSE_IF)                  \
+       | (1u << PRAGMA_OMP_CLAUSE_PRIVATE)             \
+       | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE)        \
+       | (1u << PRAGMA_OMP_CLAUSE_DEFAULT)             \
+       | (1u << PRAGMA_OMP_CLAUSE_SHARED)              \
+       | (1u << PRAGMA_OMP_CLAUSE_COPYIN)              \
+       | (1u << PRAGMA_OMP_CLAUSE_REDUCTION)           \
+       | (1u << PRAGMA_OMP_CLAUSE_NUM_THREADS))
+
+static tree
+c_parser_omp_parallel (location_t loc, c_parser *parser)
+{
+  enum pragma_kind p_kind = PRAGMA_OMP_PARALLEL;
+  const char *p_name = "#pragma omp parallel";
+  tree stmt, clauses, par_clause, ws_clause, block;
+  unsigned int mask = OMP_PARALLEL_CLAUSE_MASK;
+
+  if (c_parser_next_token_is_keyword (parser, RID_FOR))
+    {
+      c_parser_consume_token (parser);
+      p_kind = PRAGMA_OMP_PARALLEL_FOR;
+      p_name = "#pragma omp parallel for";
+      mask |= OMP_FOR_CLAUSE_MASK;
+      mask &= ~(1u << PRAGMA_OMP_CLAUSE_NOWAIT);
+    }
+  else if (c_parser_next_token_is (parser, CPP_NAME))
+    {
+      const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+      if (strcmp (p, "sections") == 0)
+       {
+         c_parser_consume_token (parser);
+         p_kind = PRAGMA_OMP_PARALLEL_SECTIONS;
+         p_name = "#pragma omp parallel sections";
+         mask |= OMP_SECTIONS_CLAUSE_MASK;
+         mask &= ~(1u << PRAGMA_OMP_CLAUSE_NOWAIT);
+       }
+    }
+
+  clauses = c_parser_omp_all_clauses (parser, mask, p_name);
+
+  switch (p_kind)
+    {
+    case PRAGMA_OMP_PARALLEL:
+      block = c_begin_omp_parallel ();
+      c_parser_statement (parser);
+      stmt = c_finish_omp_parallel (loc, clauses, block);
+      break;
+
+    case PRAGMA_OMP_PARALLEL_FOR:
+      block = c_begin_omp_parallel ();
+      c_split_parallel_clauses (loc, clauses, &par_clause, &ws_clause);
+      c_parser_omp_for_loop (loc, parser, ws_clause, &par_clause);
+      stmt = c_finish_omp_parallel (loc, par_clause, block);
+      OMP_PARALLEL_COMBINED (stmt) = 1;
+      break;
+
+    case PRAGMA_OMP_PARALLEL_SECTIONS:
+      block = c_begin_omp_parallel ();
+      c_split_parallel_clauses (loc, clauses, &par_clause, &ws_clause);
+      stmt = c_parser_omp_sections_scope (loc, parser);
+      if (stmt)
+       OMP_SECTIONS_CLAUSES (stmt) = ws_clause;
+      stmt = c_finish_omp_parallel (loc, par_clause, block);
+      OMP_PARALLEL_COMBINED (stmt) = 1;
+      break;
+
+    default:
+      gcc_unreachable ();
+    }
+
+  return stmt;
+}
+
+/* OpenMP 2.5:
+   # pragma omp single single-clause[optseq] new-line
+     structured-block
+
+   LOC is the location of the #pragma.
+*/
+
+#define OMP_SINGLE_CLAUSE_MASK                         \
+       ( (1u << PRAGMA_OMP_CLAUSE_PRIVATE)             \
+       | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE)        \
+       | (1u << PRAGMA_OMP_CLAUSE_COPYPRIVATE)         \
+       | (1u << PRAGMA_OMP_CLAUSE_NOWAIT))
+
+static tree
+c_parser_omp_single (location_t loc, c_parser *parser)
+{
+  tree stmt = make_node (OMP_SINGLE);
+  SET_EXPR_LOCATION (stmt, loc);
+  TREE_TYPE (stmt) = void_type_node;
+
+  OMP_SINGLE_CLAUSES (stmt)
+    = c_parser_omp_all_clauses (parser, OMP_SINGLE_CLAUSE_MASK,
+                               "#pragma omp single");
+  OMP_SINGLE_BODY (stmt) = c_parser_omp_structured_block (parser);
+
+  return add_stmt (stmt);
+}
+
+/* OpenMP 3.0:
+   # pragma omp task task-clause[optseq] new-line
+
+   LOC is the location of the #pragma.
+*/
+
+#define OMP_TASK_CLAUSE_MASK                           \
+       ( (1u << PRAGMA_OMP_CLAUSE_IF)                  \
+       | (1u << PRAGMA_OMP_CLAUSE_UNTIED)              \
+       | (1u << PRAGMA_OMP_CLAUSE_DEFAULT)             \
+       | (1u << PRAGMA_OMP_CLAUSE_PRIVATE)             \
+       | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE)        \
+       | (1u << PRAGMA_OMP_CLAUSE_SHARED)              \
+       | (1u << PRAGMA_OMP_CLAUSE_FINAL)               \
+       | (1u << PRAGMA_OMP_CLAUSE_MERGEABLE))
+
+static tree
+c_parser_omp_task (location_t loc, c_parser *parser)
+{
+  tree clauses, block;
+
+  clauses = c_parser_omp_all_clauses (parser, OMP_TASK_CLAUSE_MASK,
+                                     "#pragma omp task");
+
+  block = c_begin_omp_task ();
+  c_parser_statement (parser);
+  return c_finish_omp_task (loc, clauses, block);
+}
+
+/* OpenMP 3.0:
+   # pragma omp taskwait new-line
+*/
+
+static void
+c_parser_omp_taskwait (c_parser *parser)
+{
+  location_t loc = c_parser_peek_token (parser)->location;
+  c_parser_consume_pragma (parser);
+  c_parser_skip_to_pragma_eol (parser);
+
+  c_finish_omp_taskwait (loc);
+}
+
+/* OpenMP 3.1:
+   # pragma omp taskyield new-line
+*/
+
+static void
+c_parser_omp_taskyield (c_parser *parser)
+{
+  location_t loc = c_parser_peek_token (parser)->location;
+  c_parser_consume_pragma (parser);
+  c_parser_skip_to_pragma_eol (parser);
+
+  c_finish_omp_taskyield (loc);
+}
+
+/* Main entry point to parsing most OpenMP pragmas.  */
+
+static void
+c_parser_omp_construct (c_parser *parser)
+{
+  enum pragma_kind p_kind;
+  location_t loc;
+  tree stmt;
+
+  loc = c_parser_peek_token (parser)->location;
+  p_kind = c_parser_peek_token (parser)->pragma_kind;
+  c_parser_consume_pragma (parser);
+
+  switch (p_kind)
+    {
+    case PRAGMA_OMP_ATOMIC:
+      c_parser_omp_atomic (loc, parser);
+      return;
+    case PRAGMA_OMP_CRITICAL:
+      stmt = c_parser_omp_critical (loc, parser);
+      break;
+    case PRAGMA_OMP_FOR:
+      stmt = c_parser_omp_for (loc, parser);
+      break;
+    case PRAGMA_OMP_MASTER:
+      stmt = c_parser_omp_master (loc, parser);
+      break;
+    case PRAGMA_OMP_ORDERED:
+      stmt = c_parser_omp_ordered (loc, parser);
+      break;
+    case PRAGMA_OMP_PARALLEL:
+      stmt = c_parser_omp_parallel (loc, parser);
+      break;
+    case PRAGMA_OMP_SECTIONS:
+      stmt = c_parser_omp_sections (loc, parser);
+      break;
+    case PRAGMA_OMP_SINGLE:
+      stmt = c_parser_omp_single (loc, parser);
+      break;
+    case PRAGMA_OMP_TASK:
+      stmt = c_parser_omp_task (loc, parser);
+      break;
+    default:
+      gcc_unreachable ();
+    }
+
+  if (stmt)
+    gcc_assert (EXPR_LOCATION (stmt) != UNKNOWN_LOCATION);
+}
+
+
+/* OpenMP 2.5:
+   # pragma omp threadprivate (variable-list) */
+
+static void
+c_parser_omp_threadprivate (c_parser *parser)
+{
+  tree vars, t;
+  location_t loc;
+
+  c_parser_consume_pragma (parser);
+  loc = c_parser_peek_token (parser)->location;
+  vars = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ERROR, NULL);
+
+  /* Mark every variable in VARS to be assigned thread local storage.  */
+  for (t = vars; t; t = TREE_CHAIN (t))
+    {
+      tree v = TREE_PURPOSE (t);
+
+      /* FIXME diagnostics: Ideally we should keep individual
+        locations for all the variables in the var list to make the
+        following errors more precise.  Perhaps
+        c_parser_omp_var_list_parens() should construct a list of
+        locations to go along with the var list.  */
+
+      /* If V had already been marked threadprivate, it doesn't matter
+        whether it had been used prior to this point.  */
+      if (TREE_CODE (v) != VAR_DECL)
+       error_at (loc, "%qD is not a variable", v);
+      else if (TREE_USED (v) && !C_DECL_THREADPRIVATE_P (v))
+       error_at (loc, "%qE declared %<threadprivate%> after first use", v);
+      else if (! TREE_STATIC (v) && ! DECL_EXTERNAL (v))
+       error_at (loc, "automatic variable %qE cannot be %<threadprivate%>", v);
+      else if (TREE_TYPE (v) == error_mark_node)
+       ;
+      else if (! COMPLETE_TYPE_P (TREE_TYPE (v)))
+       error_at (loc, "%<threadprivate%> %qE has incomplete type", v);
+      else
+       {
+         if (! DECL_THREAD_LOCAL_P (v))
+           {
+             DECL_TLS_MODEL (v) = decl_default_tls_model (v);
+             /* If rtl has been already set for this var, call
+                make_decl_rtl once again, so that encode_section_info
+                has a chance to look at the new decl flags.  */
+             if (DECL_RTL_SET_P (v))
+               make_decl_rtl (v);
+           }
+         C_DECL_THREADPRIVATE_P (v) = 1;
+       }
+    }
+
+  c_parser_skip_to_pragma_eol (parser);
+}
+
+/* Parse a transaction attribute (GCC Extension).
+
+   transaction-attribute:
+     attributes
+     [ [ any-word ] ]
+
+   The transactional memory language description is written for C++,
+   and uses the C++0x attribute syntax.  For compatibility, allow the
+   bracket style for transactions in C as well.  */
+
+static tree
+c_parser_transaction_attributes (c_parser *parser)
+{
+  tree attr_name, attr = NULL;
+
+  if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
+    return c_parser_attributes (parser);
+
+  if (!c_parser_next_token_is (parser, CPP_OPEN_SQUARE))
+    return NULL_TREE;
+  c_parser_consume_token (parser);
+  if (!c_parser_require (parser, CPP_OPEN_SQUARE, "expected %<[%>"))
+    goto error1;
+
+  attr_name = c_parser_attribute_any_word (parser);
+  if (attr_name)
+    {
+      c_parser_consume_token (parser);
+      attr = build_tree_list (attr_name, NULL_TREE);
+    }
+  else
+    c_parser_error (parser, "expected identifier");
+
+  c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, "expected %<]%>");
+ error1:
+  c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, "expected %<]%>");
+  return attr;
+}
+
+/* Parse a __transaction_atomic or __transaction_relaxed statement
+   (GCC Extension).
+
+   transaction-statement:
+     __transaction_atomic transaction-attribute[opt] compound-statement
+     __transaction_relaxed compound-statement
+
+   Note that the only valid attribute is: "outer".
+*/
+
+static tree
+c_parser_transaction (c_parser *parser, enum rid keyword)
+{
+  unsigned int old_in = parser->in_transaction;
+  unsigned int this_in = 1, new_in;
+  location_t loc = c_parser_peek_token (parser)->location;
+  tree stmt, attrs;
+
+  gcc_assert ((keyword == RID_TRANSACTION_ATOMIC
+      || keyword == RID_TRANSACTION_RELAXED)
+      && c_parser_next_token_is_keyword (parser, keyword));
+  c_parser_consume_token (parser);
+
+  if (keyword == RID_TRANSACTION_RELAXED)
+    this_in |= TM_STMT_ATTR_RELAXED;
+  else
+    {
+      attrs = c_parser_transaction_attributes (parser);
+      if (attrs)
+       this_in |= parse_tm_stmt_attr (attrs, TM_STMT_ATTR_OUTER);
+    }
+
+  /* Keep track if we're in the lexical scope of an outer transaction.  */
+  new_in = this_in | (old_in & TM_STMT_ATTR_OUTER);
+
+  parser->in_transaction = new_in;
+  stmt = c_parser_compound_statement (parser);
+  parser->in_transaction = old_in;
+
+  if (flag_tm)
+    stmt = c_finish_transaction (loc, stmt, this_in);
+  else
+    error_at (loc, (keyword == RID_TRANSACTION_ATOMIC ?
+       "%<__transaction_atomic%> without transactional memory support enabled"
+       : "%<__transaction_relaxed %> "
+       "without transactional memory support enabled"));
+
+  return stmt;
+}
+
+/* Parse a __transaction_atomic or __transaction_relaxed expression
+   (GCC Extension).
+
+   transaction-expression:
+     __transaction_atomic ( expression )
+     __transaction_relaxed ( expression )
+*/
+
+static struct c_expr
+c_parser_transaction_expression (c_parser *parser, enum rid keyword)
+{
+  struct c_expr ret;
+  unsigned int old_in = parser->in_transaction;
+  unsigned int this_in = 1;
+  location_t loc = c_parser_peek_token (parser)->location;
+  tree attrs;
+
+  gcc_assert ((keyword == RID_TRANSACTION_ATOMIC
+      || keyword == RID_TRANSACTION_RELAXED)
+      && c_parser_next_token_is_keyword (parser, keyword));
+  c_parser_consume_token (parser);
+
+  if (keyword == RID_TRANSACTION_RELAXED)
+    this_in |= TM_STMT_ATTR_RELAXED;
+  else
+    {
+      attrs = c_parser_transaction_attributes (parser);
+      if (attrs)
+       this_in |= parse_tm_stmt_attr (attrs, 0);
+    }
+
+  parser->in_transaction = this_in;
+  if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+    {
+      tree expr = c_parser_expression (parser).value;
+      ret.original_type = TREE_TYPE (expr);
+      ret.value = build1 (TRANSACTION_EXPR, ret.original_type, expr);
+      if (this_in & TM_STMT_ATTR_RELAXED)
+       TRANSACTION_EXPR_RELAXED (ret.value) = 1;
+      SET_EXPR_LOCATION (ret.value, loc);
+      ret.original_code = TRANSACTION_EXPR;
+      if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+       {
+         c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+         goto error;
+       }
+    }
+  else
+    {
+     error:
+      ret.value = error_mark_node;
+      ret.original_code = ERROR_MARK;
+      ret.original_type = NULL;
+    }
+  parser->in_transaction = old_in;
+
+  if (!flag_tm)
+    error_at (loc, (keyword == RID_TRANSACTION_ATOMIC ?
+       "%<__transaction_atomic%> without transactional memory support enabled"
+       : "%<__transaction_relaxed %> "
+       "without transactional memory support enabled"));
+
+  return ret;
+}
+
+/* Parse a __transaction_cancel statement (GCC Extension).
+
+   transaction-cancel-statement:
+     __transaction_cancel transaction-attribute[opt] ;
+
+   Note that the only valid attribute is "outer".
+*/
+
+static tree
+c_parser_transaction_cancel(c_parser *parser)
+{
+  location_t loc = c_parser_peek_token (parser)->location;
+  tree attrs;
+  bool is_outer = false;
+
+  gcc_assert (c_parser_next_token_is_keyword (parser, RID_TRANSACTION_CANCEL));
+  c_parser_consume_token (parser);
+
+  attrs = c_parser_transaction_attributes (parser);
+  if (attrs)
+    is_outer = (parse_tm_stmt_attr (attrs, TM_STMT_ATTR_OUTER) != 0);
+
+  if (!flag_tm)
+    {
+      error_at (loc, "%<__transaction_cancel%> without "
+               "transactional memory support enabled");
+      goto ret_error;
+    }
+  else if (parser->in_transaction & TM_STMT_ATTR_RELAXED)
+    {
+      error_at (loc, "%<__transaction_cancel%> within a "
+               "%<__transaction_relaxed%>");
+      goto ret_error;
+    }
+  else if (is_outer)
+    {
+      if ((parser->in_transaction & TM_STMT_ATTR_OUTER) == 0
+         && !is_tm_may_cancel_outer (current_function_decl))
+       {
+         error_at (loc, "outer %<__transaction_cancel%> not "
+                   "within outer %<__transaction_atomic%>");
+         error_at (loc, "  or a %<transaction_may_cancel_outer%> function");
+         goto ret_error;
+       }
+    }
+  else if (parser->in_transaction == 0)
+    {
+      error_at (loc, "%<__transaction_cancel%> not within "
+               "%<__transaction_atomic%>");
+      goto ret_error;
+    }
+
+  return add_stmt (build_tm_abort_call (loc, is_outer));
+
+ ret_error:
+  return build1 (NOP_EXPR, void_type_node, error_mark_node);
+}
+\f
+/* Parse a single source file.  */
+
+void
+c_parse_file (void)
+{
+  /* Use local storage to begin.  If the first token is a pragma, parse it.
+     If it is #pragma GCC pch_preprocess, then this will load a PCH file
+     which will cause garbage collection.  */
+  c_parser tparser;
+
+  memset (&tparser, 0, sizeof tparser);
+  the_parser = &tparser;
+
+  if (c_parser_peek_token (&tparser)->pragma_kind == PRAGMA_GCC_PCH_PREPROCESS)
+    c_parser_pragma_pch_preprocess (&tparser);
+
+  the_parser = ggc_alloc_c_parser ();
+  *the_parser = tparser;
+
+  /* Initialize EH, if we've been told to do so.  */
+  if (flag_exceptions)
+    using_eh_for_cleanups ();
+
+  c_parser_translation_unit (the_parser);
+  the_parser = NULL;
+}
+
+#include "gt-c-c-parser.h"
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
new file mode 100644 (file)
index 0000000..145df35
--- /dev/null
@@ -0,0 +1,676 @@
+/* Definitions for C parsing and type checking.
+   Copyright (C) 1987, 1993, 1994, 1995, 1997, 1998,
+   1999, 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 GCC_C_TREE_H
+#define GCC_C_TREE_H
+
+#include "c-family/c-common.h"
+#include "diagnostic.h"
+
+/* struct lang_identifier is private to c-decl.c, but langhooks.c needs to
+   know how big it is.  This is sanity-checked in c-decl.c.  */
+#define C_SIZEOF_STRUCT_LANG_IDENTIFIER \
+  (sizeof (struct c_common_identifier) + 3 * sizeof (void *))
+
+/* In a RECORD_TYPE or UNION_TYPE, nonzero if any component is read-only.  */
+#define C_TYPE_FIELDS_READONLY(TYPE) TREE_LANG_FLAG_1 (TYPE)
+
+/* In a RECORD_TYPE or UNION_TYPE, nonzero if any component is volatile.  */
+#define C_TYPE_FIELDS_VOLATILE(TYPE) TREE_LANG_FLAG_2 (TYPE)
+
+/* In a RECORD_TYPE or UNION_TYPE or ENUMERAL_TYPE
+   nonzero if the definition of the type has already started.  */
+#define C_TYPE_BEING_DEFINED(TYPE) TYPE_LANG_FLAG_0 (TYPE)
+
+/* In an incomplete RECORD_TYPE or UNION_TYPE, a list of variable
+   declarations whose type would be completed by completing that type.  */
+#define C_TYPE_INCOMPLETE_VARS(TYPE) TYPE_VFIELD (TYPE)
+
+/* In an IDENTIFIER_NODE, nonzero if this identifier is actually a
+   keyword.  C_RID_CODE (node) is then the RID_* value of the keyword,
+   and C_RID_YYCODE is the token number wanted by Yacc.  */
+#define C_IS_RESERVED_WORD(ID) TREE_LANG_FLAG_0 (ID)
+
+/* Record whether a type or decl was written with nonconstant size.
+   Note that TYPE_SIZE may have simplified to a constant.  */
+#define C_TYPE_VARIABLE_SIZE(TYPE) TYPE_LANG_FLAG_1 (TYPE)
+#define C_DECL_VARIABLE_SIZE(TYPE) DECL_LANG_FLAG_0 (TYPE)
+
+/* Record whether a type is defined inside a struct or union type.
+   This is used for -Wc++-compat. */
+#define C_TYPE_DEFINED_IN_STRUCT(TYPE) TYPE_LANG_FLAG_2 (TYPE)
+
+/* Record whether a typedef for type `int' was actually `signed int'.  */
+#define C_TYPEDEF_EXPLICITLY_SIGNED(EXP) DECL_LANG_FLAG_1 (EXP)
+
+/* For a FUNCTION_DECL, nonzero if it was defined without an explicit
+   return type.  */
+#define C_FUNCTION_IMPLICIT_INT(EXP) DECL_LANG_FLAG_1 (EXP)
+
+/* For a FUNCTION_DECL, nonzero if it was an implicit declaration.  */
+#define C_DECL_IMPLICIT(EXP) DECL_LANG_FLAG_2 (EXP)
+
+/* For FUNCTION_DECLs, evaluates true if the decl is built-in but has
+   been declared.  */
+#define C_DECL_DECLARED_BUILTIN(EXP)           \
+  DECL_LANG_FLAG_3 (FUNCTION_DECL_CHECK (EXP))
+
+/* For FUNCTION_DECLs, evaluates true if the decl is built-in, has a
+   built-in prototype and does not have a non-built-in prototype.  */
+#define C_DECL_BUILTIN_PROTOTYPE(EXP)          \
+  DECL_LANG_FLAG_6 (FUNCTION_DECL_CHECK (EXP))
+
+/* Record whether a decl was declared register.  This is strictly a
+   front-end flag, whereas DECL_REGISTER is used for code generation;
+   they may differ for structures with volatile fields.  */
+#define C_DECL_REGISTER(EXP) DECL_LANG_FLAG_4 (EXP)
+
+/* Record whether a decl was used in an expression anywhere except an
+   unevaluated operand of sizeof / typeof / alignof.  This is only
+   used for functions declared static but not defined, though outside
+   sizeof and typeof it is set for other function decls as well.  */
+#define C_DECL_USED(EXP) DECL_LANG_FLAG_5 (FUNCTION_DECL_CHECK (EXP))
+
+/* Record whether a variable has been declared threadprivate by
+   #pragma omp threadprivate.  */
+#define C_DECL_THREADPRIVATE_P(DECL) DECL_LANG_FLAG_3 (VAR_DECL_CHECK (DECL))
+
+/* Nonzero for a decl which either doesn't exist or isn't a prototype.
+   N.B. Could be simplified if all built-in decls had complete prototypes
+   (but this is presently difficult because some of them need FILE*).  */
+#define C_DECL_ISNT_PROTOTYPE(EXP)                     \
+       (EXP == 0                                       \
+       || (!prototype_p (TREE_TYPE (EXP))      \
+           && !DECL_BUILT_IN (EXP)))
+
+/* For FUNCTION_TYPE, a hidden list of types of arguments.  The same as
+   TYPE_ARG_TYPES for functions with prototypes, but created for functions
+   without prototypes.  */
+#define TYPE_ACTUAL_ARG_TYPES(NODE) TYPE_LANG_SLOT_1 (NODE)
+
+/* For a CONSTRUCTOR, whether some initializer contains a
+   subexpression meaning it is not a constant expression.  */
+#define CONSTRUCTOR_NON_CONST(EXPR) TREE_LANG_FLAG_1 (CONSTRUCTOR_CHECK (EXPR))
+
+/* Record parser information about an expression that is irrelevant
+   for code generation alongside a tree representing its value.  */
+struct c_expr
+{
+  /* The value of the expression.  */
+  tree value;
+  /* Record the original unary/binary operator of an expression, which may
+     have been changed by fold, STRING_CST for unparenthesized string
+     constants, C_MAYBE_CONST_EXPR for __builtin_constant_p calls
+     (even if parenthesized), for subexpressions, and for non-constant
+     initializers, or ERROR_MARK for other expressions (including
+     parenthesized expressions).  */
+  enum tree_code original_code;
+  /* If not NULL, the original type of an expression.  This will
+     differ from the type of the value field for an enum constant.
+     The type of an enum constant is a plain integer type, but this
+     field will be the enum type.  */
+  tree original_type;
+};
+
+/* Type alias for struct c_expr. This allows to use the structure
+   inside the VEC types.  */
+typedef struct c_expr c_expr_t;
+
+/* A varray of c_expr_t.  */
+DEF_VEC_O (c_expr_t);
+DEF_VEC_ALLOC_O (c_expr_t, gc);
+DEF_VEC_ALLOC_O (c_expr_t, heap);
+
+/* Append a new c_expr_t element to V.  */
+#define C_EXPR_APPEND(V, ELEM) \
+  do { \
+    c_expr_t *__elem_p = VEC_safe_push (c_expr_t, gc, V, NULL); \
+    *__elem_p = (ELEM); \
+  } while (0)
+
+/* A kind of type specifier.  Note that this information is currently
+   only used to distinguish tag definitions, tag references and typeof
+   uses.  */
+enum c_typespec_kind {
+  /* No typespec.  This appears only in struct c_declspec.  */
+  ctsk_none,
+  /* A reserved keyword type specifier.  */
+  ctsk_resword,
+  /* A reference to a tag, previously declared, such as "struct foo".
+     This includes where the previous declaration was as a different
+     kind of tag, in which case this is only valid if shadowing that
+     tag in an inner scope.  */
+  ctsk_tagref,
+  /* A reference to a tag, not previously declared in a visible
+     scope.  */
+  ctsk_tagfirstref,
+  /* A definition of a tag such as "struct foo { int a; }".  */
+  ctsk_tagdef,
+  /* A typedef name.  */
+  ctsk_typedef,
+  /* An ObjC-specific kind of type specifier.  */
+  ctsk_objc,
+  /* A typeof specifier.  */
+  ctsk_typeof
+};
+
+/* A type specifier: this structure is created in the parser and
+   passed to declspecs_add_type only.  */
+struct c_typespec {
+  /* What kind of type specifier this is.  */
+  enum c_typespec_kind kind;
+  /* Whether the expression has operands suitable for use in constant
+     expressions.  */
+  bool expr_const_operands;
+  /* The specifier itself.  */
+  tree spec;
+  /* An expression to be evaluated before the type specifier, in the
+     case of typeof specifiers, or NULL otherwise or if no such
+     expression is required for a particular typeof specifier.  In
+     particular, when typeof is applied to an expression of variably
+     modified type, that expression must be evaluated in order to
+     determine array sizes that form part of the type, but the
+     expression itself (as opposed to the array sizes) forms no part
+     of the type and so needs to be recorded separately.  */
+  tree expr;
+};
+
+/* A storage class specifier.  */
+enum c_storage_class {
+  csc_none,
+  csc_auto,
+  csc_extern,
+  csc_register,
+  csc_static,
+  csc_typedef
+};
+
+/* A type specifier keyword "void", "_Bool", "char", "int", "float",
+   "double", "_Decimal32", "_Decimal64", "_Decimal128", "_Fract", "_Accum",
+   or none of these.  */
+enum c_typespec_keyword {
+  cts_none,
+  cts_void,
+  cts_bool,
+  cts_char,
+  cts_int,
+  cts_float,
+  cts_int128,
+  cts_double,
+  cts_dfloat32,
+  cts_dfloat64,
+  cts_dfloat128,
+  cts_fract,
+  cts_accum
+};
+
+/* This enum lists all the possible declarator specifiers, storage
+   class or attribute that a user can write.  There is at least one
+   enumerator per possible declarator specifier in the struct
+   c_declspecs below.
+
+   It is used to index the array of declspec locations in struct
+   c_declspecs.  */
+enum c_declspec_word {
+  cdw_typespec /* A catch-all for a typespec.  */,
+  cdw_storage_class  /* A catch-all for a storage class */,
+  cdw_attributes,
+  cdw_typedef,
+  cdw_explicit_signed,
+  cdw_deprecated,
+  cdw_default_int,
+  cdw_long,
+  cdw_long_long,
+  cdw_short,
+  cdw_signed,
+  cdw_unsigned,
+  cdw_complex,
+  cdw_inline,
+  cdw_noreturn,
+  cdw_thread,
+  cdw_const,
+  cdw_volatile,
+  cdw_restrict,
+  cdw_saturating,
+  cdw_alignas,
+  cdw_address_space,
+  cdw_number_of_elements /* This one must always be the last
+                           enumerator.  */
+};
+
+/* A sequence of declaration specifiers in C.  When a new declaration
+   specifier is added, please update the enum c_declspec_word above
+   accordingly.  */
+struct c_declspecs {
+  source_location locations[cdw_number_of_elements];
+  /* The type specified, if a single type specifier such as a struct,
+     union or enum specifier, typedef name or typeof specifies the
+     whole type, or NULL_TREE if none or a keyword such as "void" or
+     "char" is used.  Does not include qualifiers.  */
+  tree type;
+  /* Any expression to be evaluated before the type, from a typeof
+     specifier.  */
+  tree expr;
+  /* The attributes from a typedef decl.  */
+  tree decl_attr;
+  /* When parsing, the attributes.  Outside the parser, this will be
+     NULL; attributes (possibly from multiple lists) will be passed
+     separately.  */
+  tree attrs;
+  /* The base-2 log of the greatest alignment required by an _Alignas
+     specifier, in bytes, or -1 if no such specifiers with nonzero
+     alignment.  */
+  int align_log;
+  /* The storage class specifier, or csc_none if none.  */
+  enum c_storage_class storage_class;
+  /* Any type specifier keyword used such as "int", not reflecting
+     modifiers such as "short", or cts_none if none.  */
+  ENUM_BITFIELD (c_typespec_keyword) typespec_word : 8;
+  /* The kind of type specifier if one has been seen, ctsk_none
+     otherwise.  */
+  ENUM_BITFIELD (c_typespec_kind) typespec_kind : 3;
+  /* Whether any expressions in typeof specifiers may appear in
+     constant expressions.  */
+  BOOL_BITFIELD expr_const_operands : 1;
+  /* Whether any declaration specifiers have been seen at all.  */
+  BOOL_BITFIELD declspecs_seen_p : 1;
+  /* Whether something other than a storage class specifier or
+     attribute has been seen.  This is used to warn for the
+     obsolescent usage of storage class specifiers other than at the
+     start of the list.  (Doing this properly would require function
+     specifiers to be handled separately from storage class
+     specifiers.)  */
+  BOOL_BITFIELD non_sc_seen_p : 1;
+  /* Whether the type is specified by a typedef or typeof name.  */
+  BOOL_BITFIELD typedef_p : 1;
+  /* Whether the type is explicitly "signed" or specified by a typedef
+     whose type is explicitly "signed".  */
+  BOOL_BITFIELD explicit_signed_p : 1;
+  /* Whether the specifiers include a deprecated typedef.  */
+  BOOL_BITFIELD deprecated_p : 1;
+  /* Whether the type defaulted to "int" because there were no type
+     specifiers.  */
+  BOOL_BITFIELD default_int_p : 1;
+  /* Whether "long" was specified.  */
+  BOOL_BITFIELD long_p : 1;
+  /* Whether "long" was specified more than once.  */
+  BOOL_BITFIELD long_long_p : 1;
+  /* Whether "short" was specified.  */
+  BOOL_BITFIELD short_p : 1;
+  /* Whether "signed" was specified.  */
+  BOOL_BITFIELD signed_p : 1;
+  /* Whether "unsigned" was specified.  */
+  BOOL_BITFIELD unsigned_p : 1;
+  /* Whether "complex" was specified.  */
+  BOOL_BITFIELD complex_p : 1;
+  /* Whether "inline" was specified.  */
+  BOOL_BITFIELD inline_p : 1;
+  /* Whether "_Noreturn" was speciied.  */
+  BOOL_BITFIELD noreturn_p : 1;
+  /* Whether "__thread" was specified.  */
+  BOOL_BITFIELD thread_p : 1;
+  /* Whether "const" was specified.  */
+  BOOL_BITFIELD const_p : 1;
+  /* Whether "volatile" was specified.  */
+  BOOL_BITFIELD volatile_p : 1;
+  /* Whether "restrict" was specified.  */
+  BOOL_BITFIELD restrict_p : 1;
+  /* Whether "_Sat" was specified.  */
+  BOOL_BITFIELD saturating_p : 1;
+  /* Whether any alignment specifier (even with zero alignment) was
+     specified.  */
+  BOOL_BITFIELD alignas_p : 1;
+  /* The address space that the declaration belongs to.  */
+  addr_space_t address_space;
+};
+
+/* The various kinds of declarators in C.  */
+enum c_declarator_kind {
+  /* An identifier.  */
+  cdk_id,
+  /* A function.  */
+  cdk_function,
+  /* An array.  */
+  cdk_array,
+  /* A pointer.  */
+  cdk_pointer,
+  /* Parenthesized declarator with nested attributes.  */
+  cdk_attrs
+};
+
+typedef struct c_arg_tag_d {
+  /* The argument name.  */
+  tree id;
+  /* The type of the argument.  */
+  tree type;
+} c_arg_tag;
+
+DEF_VEC_O(c_arg_tag);
+DEF_VEC_ALLOC_O(c_arg_tag,gc);
+
+/* Information about the parameters in a function declarator.  */
+struct c_arg_info {
+  /* A list of parameter decls.  */
+  tree parms;
+  /* A list of structure, union and enum tags defined.  */
+  VEC(c_arg_tag,gc) *tags;
+  /* A list of argument types to go in the FUNCTION_TYPE.  */
+  tree types;
+  /* A list of non-parameter decls (notably enumeration constants)
+     defined with the parameters.  */
+  tree others;
+  /* A compound expression of VLA sizes from the parameters, or NULL.
+     In a function definition, these are used to ensure that
+     side-effects in sizes of arrays converted to pointers (such as a
+     parameter int i[n++]) take place; otherwise, they are
+     ignored.  */
+  tree pending_sizes;
+  /* True when these arguments had [*].  */
+  BOOL_BITFIELD had_vla_unspec : 1;
+};
+
+/* A declarator.  */
+struct c_declarator {
+  /* The kind of declarator.  */
+  enum c_declarator_kind kind;
+  location_t id_loc; /* Currently only set for cdk_id, cdk_array. */
+  /* Except for cdk_id, the contained declarator.  For cdk_id, NULL.  */
+  struct c_declarator *declarator;
+  union {
+    /* For identifiers, an IDENTIFIER_NODE or NULL_TREE if an abstract
+       declarator.  */
+    tree id;
+    /* For functions.  */
+    struct c_arg_info *arg_info;
+    /* For arrays.  */
+    struct {
+      /* The array dimension, or NULL for [] and [*].  */
+      tree dimen;
+      /* The qualifiers inside [].  */
+      int quals;
+      /* The attributes (currently ignored) inside [].  */
+      tree attrs;
+      /* Whether [static] was used.  */
+      BOOL_BITFIELD static_p : 1;
+      /* Whether [*] was used.  */
+      BOOL_BITFIELD vla_unspec_p : 1;
+    } array;
+    /* For pointers, the qualifiers on the pointer type.  */
+    int pointer_quals;
+    /* For attributes.  */
+    tree attrs;
+  } u;
+};
+
+/* A type name.  */
+struct c_type_name {
+  /* The declaration specifiers.  */
+  struct c_declspecs *specs;
+  /* The declarator.  */
+  struct c_declarator *declarator;
+};
+
+/* A parameter.  */
+struct c_parm {
+  /* The declaration specifiers, minus any prefix attributes.  */
+  struct c_declspecs *specs;
+  /* The attributes.  */
+  tree attrs;
+  /* The declarator.  */
+  struct c_declarator *declarator;
+};
+
+/* Used when parsing an enum.  Initialized by start_enum.  */
+struct c_enum_contents
+{
+  /* While defining an enum type, this is 1 plus the last enumerator
+     constant value.  */
+  tree enum_next_value;
+
+  /* Nonzero means that there was overflow computing enum_next_value.  */
+  int enum_overflow;
+};
+
+/* A type of reference to a static identifier in an inline
+   function.  */
+enum c_inline_static_type {
+  /* Identifier with internal linkage used in function that may be an
+     inline definition (i.e., file-scope static).  */
+  csi_internal,
+  /* Modifiable object with static storage duration defined in
+     function that may be an inline definition (i.e., local
+     static).  */
+  csi_modifiable
+};
+
+\f
+/* in c-parser.c */
+extern void c_parse_init (void);
+
+/* in c-aux-info.c */
+extern void gen_aux_info_record (tree, int, int, int);
+
+/* in c-decl.c */
+struct c_spot_bindings;
+struct c_struct_parse_info;
+extern struct obstack parser_obstack;
+extern tree c_break_label;
+extern tree c_cont_label;
+
+extern bool global_bindings_p (void);
+extern void push_scope (void);
+extern tree pop_scope (void);
+extern void c_bindings_start_stmt_expr (struct c_spot_bindings *);
+extern void c_bindings_end_stmt_expr (struct c_spot_bindings *);
+
+extern void record_inline_static (location_t, tree, tree,
+                                 enum c_inline_static_type);
+extern void c_init_decl_processing (void);
+extern void c_print_identifier (FILE *, tree, int);
+extern int quals_from_declspecs (const struct c_declspecs *);
+extern struct c_declarator *build_array_declarator (location_t, tree,
+                                                   struct c_declspecs *,
+                                                   bool, bool);
+extern tree build_enumerator (location_t, location_t, struct c_enum_contents *,
+                             tree, tree);
+extern tree check_for_loop_decls (location_t, bool);
+extern void mark_forward_parm_decls (void);
+extern void declare_parm_level (void);
+extern void undeclared_variable (location_t, tree);
+extern tree lookup_label_for_goto (location_t, tree);
+extern tree declare_label (tree);
+extern tree define_label (location_t, tree);
+extern struct c_spot_bindings *c_get_switch_bindings (void);
+extern void c_release_switch_bindings (struct c_spot_bindings *);
+extern bool c_check_switch_jump_warnings (struct c_spot_bindings *,
+                                         location_t, location_t);
+extern void finish_decl (tree, location_t, tree, tree, tree);
+extern tree finish_enum (tree, tree, tree);
+extern void finish_function (void);
+extern tree finish_struct (location_t, tree, tree, tree,
+                          struct c_struct_parse_info *);
+extern struct c_arg_info *build_arg_info (void);
+extern struct c_arg_info *get_parm_info (bool, tree);
+extern tree grokfield (location_t, struct c_declarator *,
+                      struct c_declspecs *, tree, tree *);
+extern tree groktypename (struct c_type_name *, tree *, bool *);
+extern tree grokparm (const struct c_parm *, tree *);
+extern tree implicitly_declare (location_t, tree);
+extern void keep_next_level (void);
+extern void pending_xref_error (void);
+extern void c_push_function_context (void);
+extern void c_pop_function_context (void);
+extern void push_parm_decl (const struct c_parm *, tree *);
+extern struct c_declarator *set_array_declarator_inner (struct c_declarator *,
+                                                       struct c_declarator *);
+extern tree c_builtin_function (tree);
+extern tree c_builtin_function_ext_scope (tree);
+extern void shadow_tag (const struct c_declspecs *);
+extern void shadow_tag_warned (const struct c_declspecs *, int);
+extern tree start_enum (location_t, struct c_enum_contents *, tree);
+extern int  start_function (struct c_declspecs *, struct c_declarator *, tree);
+extern tree start_decl (struct c_declarator *, struct c_declspecs *, bool,
+                       tree);
+extern tree start_struct (location_t, enum tree_code, tree,
+                         struct c_struct_parse_info **);
+extern void store_parm_decls (void);
+extern void store_parm_decls_from (struct c_arg_info *);
+extern tree xref_tag (enum tree_code, tree);
+extern struct c_typespec parser_xref_tag (location_t, enum tree_code, tree);
+extern struct c_parm *build_c_parm (struct c_declspecs *, tree,
+                                   struct c_declarator *);
+extern struct c_declarator *build_attrs_declarator (tree,
+                                                   struct c_declarator *);
+extern struct c_declarator *build_function_declarator (struct c_arg_info *,
+                                                      struct c_declarator *);
+extern struct c_declarator *build_id_declarator (tree);
+extern struct c_declarator *make_pointer_declarator (struct c_declspecs *,
+                                                    struct c_declarator *);
+extern struct c_declspecs *build_null_declspecs (void);
+extern struct c_declspecs *declspecs_add_qual (source_location,
+                                              struct c_declspecs *, tree);
+extern struct c_declspecs *declspecs_add_type (location_t,
+                                              struct c_declspecs *,
+                                              struct c_typespec);
+extern struct c_declspecs *declspecs_add_scspec (source_location,
+                                                struct c_declspecs *, tree);
+extern struct c_declspecs *declspecs_add_attrs (source_location,
+                                               struct c_declspecs *, tree);
+extern struct c_declspecs *declspecs_add_addrspace (source_location,
+                                                   struct c_declspecs *,
+                                                   addr_space_t);
+extern struct c_declspecs *declspecs_add_alignas (source_location,
+                                                 struct c_declspecs *, tree);
+extern struct c_declspecs *finish_declspecs (struct c_declspecs *);
+
+/* in c-objc-common.c */
+extern bool c_objc_common_init (void);
+extern bool c_missing_noreturn_ok_p (tree);
+extern bool c_warn_unused_global_decl (const_tree);
+extern void c_initialize_diagnostics (diagnostic_context *);
+extern bool c_vla_unspec_p (tree x, tree fn);
+
+/* in c-typeck.c */
+extern int in_alignof;
+extern int in_sizeof;
+extern int in_typeof;
+
+extern struct c_switch *c_switch_stack;
+
+extern tree c_objc_common_truthvalue_conversion (location_t, tree);
+extern tree require_complete_type (tree);
+extern int same_translation_unit_p (const_tree, const_tree);
+extern int comptypes (tree, tree);
+extern int comptypes_check_different_types (tree, tree, bool *);
+extern bool c_vla_type_p (const_tree);
+extern bool c_mark_addressable (tree);
+extern void c_incomplete_type_error (const_tree, const_tree);
+extern tree c_type_promotes_to (tree);
+extern struct c_expr default_function_array_conversion (location_t,
+                                                       struct c_expr);
+extern struct c_expr default_function_array_read_conversion (location_t,
+                                                            struct c_expr);
+extern void mark_exp_read (tree);
+extern tree composite_type (tree, tree);
+extern tree build_component_ref (location_t, tree, tree);
+extern tree build_array_ref (location_t, tree, tree);
+extern tree build_external_ref (location_t, tree, int, tree *);
+extern void pop_maybe_used (bool);
+extern struct c_expr c_expr_sizeof_expr (location_t, struct c_expr);
+extern struct c_expr c_expr_sizeof_type (location_t, struct c_type_name *);
+extern struct c_expr parser_build_unary_op (location_t, enum tree_code,
+                                           struct c_expr);
+extern struct c_expr parser_build_binary_op (location_t,
+                                            enum tree_code, struct c_expr,
+                                            struct c_expr);
+extern tree build_conditional_expr (location_t, tree, bool, tree, tree,
+                                   tree, tree);
+extern tree build_compound_expr (location_t, tree, tree);
+extern tree c_cast_expr (location_t, struct c_type_name *, tree);
+extern tree build_c_cast (location_t, tree, tree);
+extern void store_init_value (location_t, tree, tree, tree);
+extern void error_init (const char *);
+extern void pedwarn_init (location_t, int opt, const char *);
+extern void maybe_warn_string_init (tree, struct c_expr);
+extern void start_init (tree, tree, int);
+extern void finish_init (void);
+extern void really_start_incremental_init (tree);
+extern void push_init_level (int, struct obstack *);
+extern struct c_expr pop_init_level (int, struct obstack *);
+extern void set_init_index (tree, tree, struct obstack *);
+extern void set_init_label (tree, struct obstack *);
+extern void process_init_element (struct c_expr, bool, struct obstack *);
+extern tree build_compound_literal (location_t, tree, tree, bool);
+extern void check_compound_literal_type (location_t, struct c_type_name *);
+extern tree c_start_case (location_t, location_t, tree);
+extern void c_finish_case (tree);
+extern tree build_asm_expr (location_t, tree, tree, tree, tree, tree, bool);
+extern tree build_asm_stmt (tree, tree);
+extern int c_types_compatible_p (tree, tree);
+extern tree c_begin_compound_stmt (bool);
+extern tree c_end_compound_stmt (location_t, tree, bool);
+extern void c_finish_if_stmt (location_t, tree, tree, tree, bool);
+extern void c_finish_loop (location_t, tree, tree, tree, tree, tree, bool);
+extern tree c_begin_stmt_expr (void);
+extern tree c_finish_stmt_expr (location_t, tree);
+extern tree c_process_expr_stmt (location_t, tree);
+extern tree c_finish_expr_stmt (location_t, tree);
+extern tree c_finish_return (location_t, tree, tree);
+extern tree c_finish_bc_stmt (location_t, tree *, bool);
+extern tree c_finish_goto_label (location_t, tree);
+extern tree c_finish_goto_ptr (location_t, tree);
+extern tree c_expr_to_decl (tree, bool *, bool *);
+extern tree c_begin_omp_parallel (void);
+extern tree c_finish_omp_parallel (location_t, tree, tree);
+extern tree c_begin_omp_task (void);
+extern tree c_finish_omp_task (location_t, tree, tree);
+extern tree c_finish_omp_clauses (tree);
+extern tree c_build_va_arg (location_t, tree, tree);
+extern tree c_finish_transaction (location_t, tree, int);
+
+/* Set to 0 at beginning of a function definition, set to 1 if
+   a return statement that specifies a return value is seen.  */
+
+extern int current_function_returns_value;
+
+/* Set to 0 at beginning of a function definition, set to 1 if
+   a return statement with no argument is seen.  */
+
+extern int current_function_returns_null;
+
+/* Set to 0 at beginning of a function definition, set to 1 if
+   a call to a noreturn function is seen.  */
+
+extern int current_function_returns_abnormally;
+
+/* Mode used to build pointers (VOIDmode means ptr_mode).  */
+
+extern enum machine_mode c_default_pointer_mode;
+
+/* In c-decl.c */
+extern void c_finish_incomplete_decl (tree);
+extern void c_write_global_declarations (void);
+
+/* In c-errors.c */
+extern void pedwarn_c90 (location_t, int opt, const char *, ...) ATTRIBUTE_GCC_DIAG(3,4);
+extern void pedwarn_c99 (location_t, int opt, const char *, ...) ATTRIBUTE_GCC_DIAG(3,4);
+
+#endif /* ! GCC_C_TREE_H */
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
new file mode 100644 (file)
index 0000000..c2f713e
--- /dev/null
@@ -0,0 +1,10939 @@
+/* Build expressions with type checking for C compiler.
+   Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 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 file is part of the C front end.
+   It contains routines to build C expressions given their operands,
+   including computing the types of the result, C-specific error checks,
+   and some optimization.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "tree.h"
+#include "langhooks.h"
+#include "c-tree.h"
+#include "c-lang.h"
+#include "flags.h"
+#include "intl.h"
+#include "target.h"
+#include "tree-iterator.h"
+#include "bitmap.h"
+#include "gimple.h"
+#include "c-family/c-objc.h"
+
+/* Possible cases of implicit bad conversions.  Used to select
+   diagnostic messages in convert_for_assignment.  */
+enum impl_conv {
+  ic_argpass,
+  ic_assign,
+  ic_init,
+  ic_return
+};
+
+/* Possibe cases of scalar_to_vector conversion.  */
+enum stv_conv {
+  stv_error,        /* Error occured.  */
+  stv_nothing,      /* Nothing happened.  */
+  stv_firstarg,     /* First argument must be expanded.  */
+  stv_secondarg     /* Second argument must be expanded.  */
+};
+
+/* The level of nesting inside "__alignof__".  */
+int in_alignof;
+
+/* The level of nesting inside "sizeof".  */
+int in_sizeof;
+
+/* The level of nesting inside "typeof".  */
+int in_typeof;
+
+/* Nonzero if we've already printed a "missing braces around initializer"
+   message within this initializer.  */
+static int missing_braces_mentioned;
+
+static int require_constant_value;
+static int require_constant_elements;
+
+static bool null_pointer_constant_p (const_tree);
+static tree qualify_type (tree, tree);
+static int tagged_types_tu_compatible_p (const_tree, const_tree, bool *,
+                                        bool *);
+static int comp_target_types (location_t, tree, tree);
+static int function_types_compatible_p (const_tree, const_tree, bool *,
+                                       bool *);
+static int type_lists_compatible_p (const_tree, const_tree, bool *, bool *);
+static tree lookup_field (tree, tree);
+static int convert_arguments (tree, VEC(tree,gc) *, VEC(tree,gc) *, tree,
+                             tree);
+static tree pointer_diff (location_t, tree, tree);
+static tree convert_for_assignment (location_t, tree, tree, tree,
+                                   enum impl_conv, bool, tree, tree, int);
+static tree valid_compound_expr_initializer (tree, tree);
+static void push_string (const char *);
+static void push_member_name (tree);
+static int spelling_length (void);
+static char *print_spelling (char *);
+static void warning_init (int, const char *);
+static tree digest_init (location_t, tree, tree, tree, bool, bool, int);
+static void output_init_element (tree, tree, bool, tree, tree, int, bool,
+                                struct obstack *);
+static void output_pending_init_elements (int, struct obstack *);
+static int set_designator (int, struct obstack *);
+static void push_range_stack (tree, struct obstack *);
+static void add_pending_init (tree, tree, tree, bool, struct obstack *);
+static void set_nonincremental_init (struct obstack *);
+static void set_nonincremental_init_from_string (tree, struct obstack *);
+static tree find_init_member (tree, struct obstack *);
+static void readonly_warning (tree, enum lvalue_use);
+static int lvalue_or_else (location_t, const_tree, enum lvalue_use);
+static void record_maybe_used_decl (tree);
+static int comptypes_internal (const_tree, const_tree, bool *, bool *);
+\f
+/* Return true if EXP is a null pointer constant, false otherwise.  */
+
+static bool
+null_pointer_constant_p (const_tree expr)
+{
+  /* This should really operate on c_expr structures, but they aren't
+     yet available everywhere required.  */
+  tree type = TREE_TYPE (expr);
+  return (TREE_CODE (expr) == INTEGER_CST
+         && !TREE_OVERFLOW (expr)
+         && integer_zerop (expr)
+         && (INTEGRAL_TYPE_P (type)
+             || (TREE_CODE (type) == POINTER_TYPE
+                 && VOID_TYPE_P (TREE_TYPE (type))
+                 && TYPE_QUALS (TREE_TYPE (type)) == TYPE_UNQUALIFIED)));
+}
+
+/* EXPR may appear in an unevaluated part of an integer constant
+   expression, but not in an evaluated part.  Wrap it in a
+   C_MAYBE_CONST_EXPR, or mark it with TREE_OVERFLOW if it is just an
+   INTEGER_CST and we cannot create a C_MAYBE_CONST_EXPR.  */
+
+static tree
+note_integer_operands (tree expr)
+{
+  tree ret;
+  if (TREE_CODE (expr) == INTEGER_CST && in_late_binary_op)
+    {
+      ret = copy_node (expr);
+      TREE_OVERFLOW (ret) = 1;
+    }
+  else
+    {
+      ret = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (expr), NULL_TREE, expr);
+      C_MAYBE_CONST_EXPR_INT_OPERANDS (ret) = 1;
+    }
+  return ret;
+}
+
+/* Having checked whether EXPR may appear in an unevaluated part of an
+   integer constant expression and found that it may, remove any
+   C_MAYBE_CONST_EXPR noting this fact and return the resulting
+   expression.  */
+
+static inline tree
+remove_c_maybe_const_expr (tree expr)
+{
+  if (TREE_CODE (expr) == C_MAYBE_CONST_EXPR)
+    return C_MAYBE_CONST_EXPR_EXPR (expr);
+  else
+    return expr;
+}
+
+\f/* This is a cache to hold if two types are compatible or not.  */
+
+struct tagged_tu_seen_cache {
+  const struct tagged_tu_seen_cache * next;
+  const_tree t1;
+  const_tree t2;
+  /* The return value of tagged_types_tu_compatible_p if we had seen
+     these two types already.  */
+  int val;
+};
+
+static const struct tagged_tu_seen_cache * tagged_tu_seen_base;
+static void free_all_tagged_tu_seen_up_to (const struct tagged_tu_seen_cache *);
+
+/* Do `exp = require_complete_type (exp);' to make sure exp
+   does not have an incomplete type.  (That includes void types.)  */
+
+tree
+require_complete_type (tree value)
+{
+  tree type = TREE_TYPE (value);
+
+  if (value == error_mark_node || type == error_mark_node)
+    return error_mark_node;
+
+  /* First, detect a valid value with a complete type.  */
+  if (COMPLETE_TYPE_P (type))
+    return value;
+
+  c_incomplete_type_error (value, type);
+  return error_mark_node;
+}
+
+/* Print an error message for invalid use of an incomplete type.
+   VALUE is the expression that was used (or 0 if that isn't known)
+   and TYPE is the type that was invalid.  */
+
+void
+c_incomplete_type_error (const_tree value, const_tree type)
+{
+  const char *type_code_string;
+
+  /* Avoid duplicate error message.  */
+  if (TREE_CODE (type) == ERROR_MARK)
+    return;
+
+  if (value != 0 && (TREE_CODE (value) == VAR_DECL
+                    || TREE_CODE (value) == PARM_DECL))
+    error ("%qD has an incomplete type", value);
+  else
+    {
+    retry:
+      /* We must print an error message.  Be clever about what it says.  */
+
+      switch (TREE_CODE (type))
+       {
+       case RECORD_TYPE:
+         type_code_string = "struct";
+         break;
+
+       case UNION_TYPE:
+         type_code_string = "union";
+         break;
+
+       case ENUMERAL_TYPE:
+         type_code_string = "enum";
+         break;
+
+       case VOID_TYPE:
+         error ("invalid use of void expression");
+         return;
+
+       case ARRAY_TYPE:
+         if (TYPE_DOMAIN (type))
+           {
+             if (TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL)
+               {
+                 error ("invalid use of flexible array member");
+                 return;
+               }
+             type = TREE_TYPE (type);
+             goto retry;
+           }
+         error ("invalid use of array with unspecified bounds");
+         return;
+
+       default:
+         gcc_unreachable ();
+       }
+
+      if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
+       error ("invalid use of undefined type %<%s %E%>",
+              type_code_string, TYPE_NAME (type));
+      else
+       /* If this type has a typedef-name, the TYPE_NAME is a TYPE_DECL.  */
+       error ("invalid use of incomplete typedef %qD", TYPE_NAME (type));
+    }
+}
+
+/* Given a type, apply default promotions wrt unnamed function
+   arguments and return the new type.  */
+
+tree
+c_type_promotes_to (tree type)
+{
+  if (TYPE_MAIN_VARIANT (type) == float_type_node)
+    return double_type_node;
+
+  if (c_promoting_integer_type_p (type))
+    {
+      /* Preserve unsignedness if not really getting any wider.  */
+      if (TYPE_UNSIGNED (type)
+         && (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node)))
+       return unsigned_type_node;
+      return integer_type_node;
+    }
+
+  return type;
+}
+
+/* Return true if between two named address spaces, whether there is a superset
+   named address space that encompasses both address spaces.  If there is a
+   superset, return which address space is the superset.  */
+
+static bool
+addr_space_superset (addr_space_t as1, addr_space_t as2, addr_space_t *common)
+{
+  if (as1 == as2)
+    {
+      *common = as1;
+      return true;
+    }
+  else if (targetm.addr_space.subset_p (as1, as2))
+    {
+      *common = as2;
+      return true;
+    }
+  else if (targetm.addr_space.subset_p (as2, as1))
+    {
+      *common = as1;
+      return true;
+    }
+  else
+    return false;
+}
+
+/* Return a variant of TYPE which has all the type qualifiers of LIKE
+   as well as those of TYPE.  */
+
+static tree
+qualify_type (tree type, tree like)
+{
+  addr_space_t as_type = TYPE_ADDR_SPACE (type);
+  addr_space_t as_like = TYPE_ADDR_SPACE (like);
+  addr_space_t as_common;
+
+  /* If the two named address spaces are different, determine the common
+     superset address space.  If there isn't one, raise an error.  */
+  if (!addr_space_superset (as_type, as_like, &as_common))
+    {
+      as_common = as_type;
+      error ("%qT and %qT are in disjoint named address spaces",
+            type, like);
+    }
+
+  return c_build_qualified_type (type,
+                                TYPE_QUALS_NO_ADDR_SPACE (type)
+                                | TYPE_QUALS_NO_ADDR_SPACE (like)
+                                | ENCODE_QUAL_ADDR_SPACE (as_common));
+}
+
+/* Return true iff the given tree T is a variable length array.  */
+
+bool
+c_vla_type_p (const_tree t)
+{
+  if (TREE_CODE (t) == ARRAY_TYPE
+      && C_TYPE_VARIABLE_SIZE (t))
+    return true;
+  return false;
+}
+\f
+/* Return the composite type of two compatible types.
+
+   We assume that comptypes has already been done and returned
+   nonzero; if that isn't so, this may crash.  In particular, we
+   assume that qualifiers match.  */
+
+tree
+composite_type (tree t1, tree t2)
+{
+  enum tree_code code1;
+  enum tree_code code2;
+  tree attributes;
+
+  /* Save time if the two types are the same.  */
+
+  if (t1 == t2) return t1;
+
+  /* If one type is nonsense, use the other.  */
+  if (t1 == error_mark_node)
+    return t2;
+  if (t2 == error_mark_node)
+    return t1;
+
+  code1 = TREE_CODE (t1);
+  code2 = TREE_CODE (t2);
+
+  /* Merge the attributes.  */
+  attributes = targetm.merge_type_attributes (t1, t2);
+
+  /* If one is an enumerated type and the other is the compatible
+     integer type, the composite type might be either of the two
+     (DR#013 question 3).  For consistency, use the enumerated type as
+     the composite type.  */
+
+  if (code1 == ENUMERAL_TYPE && code2 == INTEGER_TYPE)
+    return t1;
+  if (code2 == ENUMERAL_TYPE && code1 == INTEGER_TYPE)
+    return t2;
+
+  gcc_assert (code1 == code2);
+
+  switch (code1)
+    {
+    case POINTER_TYPE:
+      /* For two pointers, do this recursively on the target type.  */
+      {
+       tree pointed_to_1 = TREE_TYPE (t1);
+       tree pointed_to_2 = TREE_TYPE (t2);
+       tree target = composite_type (pointed_to_1, pointed_to_2);
+        t1 = build_pointer_type_for_mode (target, TYPE_MODE (t1), false);
+       t1 = build_type_attribute_variant (t1, attributes);
+       return qualify_type (t1, t2);
+      }
+
+    case ARRAY_TYPE:
+      {
+       tree elt = composite_type (TREE_TYPE (t1), TREE_TYPE (t2));
+       int quals;
+       tree unqual_elt;
+       tree d1 = TYPE_DOMAIN (t1);
+       tree d2 = TYPE_DOMAIN (t2);
+       bool d1_variable, d2_variable;
+       bool d1_zero, d2_zero;
+       bool t1_complete, t2_complete;
+
+       /* We should not have any type quals on arrays at all.  */
+       gcc_assert (!TYPE_QUALS_NO_ADDR_SPACE (t1)
+                   && !TYPE_QUALS_NO_ADDR_SPACE (t2));
+
+       t1_complete = COMPLETE_TYPE_P (t1);
+       t2_complete = COMPLETE_TYPE_P (t2);
+
+       d1_zero = d1 == 0 || !TYPE_MAX_VALUE (d1);
+       d2_zero = d2 == 0 || !TYPE_MAX_VALUE (d2);
+
+       d1_variable = (!d1_zero
+                      && (TREE_CODE (TYPE_MIN_VALUE (d1)) != INTEGER_CST
+                          || TREE_CODE (TYPE_MAX_VALUE (d1)) != INTEGER_CST));
+       d2_variable = (!d2_zero
+                      && (TREE_CODE (TYPE_MIN_VALUE (d2)) != INTEGER_CST
+                          || TREE_CODE (TYPE_MAX_VALUE (d2)) != INTEGER_CST));
+       d1_variable = d1_variable || (d1_zero && c_vla_type_p (t1));
+       d2_variable = d2_variable || (d2_zero && c_vla_type_p (t2));
+
+       /* Save space: see if the result is identical to one of the args.  */
+       if (elt == TREE_TYPE (t1) && TYPE_DOMAIN (t1)
+           && (d2_variable || d2_zero || !d1_variable))
+         return build_type_attribute_variant (t1, attributes);
+       if (elt == TREE_TYPE (t2) && TYPE_DOMAIN (t2)
+           && (d1_variable || d1_zero || !d2_variable))
+         return build_type_attribute_variant (t2, attributes);
+
+       if (elt == TREE_TYPE (t1) && !TYPE_DOMAIN (t2) && !TYPE_DOMAIN (t1))
+         return build_type_attribute_variant (t1, attributes);
+       if (elt == TREE_TYPE (t2) && !TYPE_DOMAIN (t2) && !TYPE_DOMAIN (t1))
+         return build_type_attribute_variant (t2, attributes);
+
+       /* Merge the element types, and have a size if either arg has
+          one.  We may have qualifiers on the element types.  To set
+          up TYPE_MAIN_VARIANT correctly, we need to form the
+          composite of the unqualified types and add the qualifiers
+          back at the end.  */
+       quals = TYPE_QUALS (strip_array_types (elt));
+       unqual_elt = c_build_qualified_type (elt, TYPE_UNQUALIFIED);
+       t1 = build_array_type (unqual_elt,
+                              TYPE_DOMAIN ((TYPE_DOMAIN (t1)
+                                            && (d2_variable
+                                                || d2_zero
+                                                || !d1_variable))
+                                           ? t1
+                                           : t2));
+       /* Ensure a composite type involving a zero-length array type
+          is a zero-length type not an incomplete type.  */
+       if (d1_zero && d2_zero
+           && (t1_complete || t2_complete)
+           && !COMPLETE_TYPE_P (t1))
+         {
+           TYPE_SIZE (t1) = bitsize_zero_node;
+           TYPE_SIZE_UNIT (t1) = size_zero_node;
+         }
+       t1 = c_build_qualified_type (t1, quals);
+       return build_type_attribute_variant (t1, attributes);
+      }
+
+    case ENUMERAL_TYPE:
+    case RECORD_TYPE:
+    case UNION_TYPE:
+      if (attributes != NULL)
+       {
+         /* Try harder not to create a new aggregate type.  */
+         if (attribute_list_equal (TYPE_ATTRIBUTES (t1), attributes))
+           return t1;
+         if (attribute_list_equal (TYPE_ATTRIBUTES (t2), attributes))
+           return t2;
+       }
+      return build_type_attribute_variant (t1, attributes);
+
+    case FUNCTION_TYPE:
+      /* Function types: prefer the one that specified arg types.
+        If both do, merge the arg types.  Also merge the return types.  */
+      {
+       tree valtype = composite_type (TREE_TYPE (t1), TREE_TYPE (t2));
+       tree p1 = TYPE_ARG_TYPES (t1);
+       tree p2 = TYPE_ARG_TYPES (t2);
+       int len;
+       tree newargs, n;
+       int i;
+
+       /* Save space: see if the result is identical to one of the args.  */
+       if (valtype == TREE_TYPE (t1) && !TYPE_ARG_TYPES (t2))
+         return build_type_attribute_variant (t1, attributes);
+       if (valtype == TREE_TYPE (t2) && !TYPE_ARG_TYPES (t1))
+         return build_type_attribute_variant (t2, attributes);
+
+       /* Simple way if one arg fails to specify argument types.  */
+       if (TYPE_ARG_TYPES (t1) == 0)
+        {
+           t1 = build_function_type (valtype, TYPE_ARG_TYPES (t2));
+           t1 = build_type_attribute_variant (t1, attributes);
+           return qualify_type (t1, t2);
+        }
+       if (TYPE_ARG_TYPES (t2) == 0)
+        {
+          t1 = build_function_type (valtype, TYPE_ARG_TYPES (t1));
+          t1 = build_type_attribute_variant (t1, attributes);
+          return qualify_type (t1, t2);
+        }
+
+       /* If both args specify argument types, we must merge the two
+          lists, argument by argument.  */
+
+       len = list_length (p1);
+       newargs = 0;
+
+       for (i = 0; i < len; i++)
+         newargs = tree_cons (NULL_TREE, NULL_TREE, newargs);
+
+       n = newargs;
+
+       for (; p1;
+            p1 = TREE_CHAIN (p1), p2 = TREE_CHAIN (p2), n = TREE_CHAIN (n))
+         {
+           /* A null type means arg type is not specified.
+              Take whatever the other function type has.  */
+           if (TREE_VALUE (p1) == 0)
+             {
+               TREE_VALUE (n) = TREE_VALUE (p2);
+               goto parm_done;
+             }
+           if (TREE_VALUE (p2) == 0)
+             {
+               TREE_VALUE (n) = TREE_VALUE (p1);
+               goto parm_done;
+             }
+
+           /* Given  wait (union {union wait *u; int *i} *)
+              and  wait (union wait *),
+              prefer  union wait *  as type of parm.  */
+           if (TREE_CODE (TREE_VALUE (p1)) == UNION_TYPE
+               && TREE_VALUE (p1) != TREE_VALUE (p2))
+             {
+               tree memb;
+               tree mv2 = TREE_VALUE (p2);
+               if (mv2 && mv2 != error_mark_node
+                   && TREE_CODE (mv2) != ARRAY_TYPE)
+                 mv2 = TYPE_MAIN_VARIANT (mv2);
+               for (memb = TYPE_FIELDS (TREE_VALUE (p1));
+                    memb; memb = DECL_CHAIN (memb))
+                 {
+                   tree mv3 = TREE_TYPE (memb);
+                   if (mv3 && mv3 != error_mark_node
+                       && TREE_CODE (mv3) != ARRAY_TYPE)
+                     mv3 = TYPE_MAIN_VARIANT (mv3);
+                   if (comptypes (mv3, mv2))
+                     {
+                       TREE_VALUE (n) = composite_type (TREE_TYPE (memb),
+                                                        TREE_VALUE (p2));
+                       pedwarn (input_location, OPT_Wpedantic,
+                                "function types not truly compatible in ISO C");
+                       goto parm_done;
+                     }
+                 }
+             }
+           if (TREE_CODE (TREE_VALUE (p2)) == UNION_TYPE
+               && TREE_VALUE (p2) != TREE_VALUE (p1))
+             {
+               tree memb;
+               tree mv1 = TREE_VALUE (p1);
+               if (mv1 && mv1 != error_mark_node
+                   && TREE_CODE (mv1) != ARRAY_TYPE)
+                 mv1 = TYPE_MAIN_VARIANT (mv1);
+               for (memb = TYPE_FIELDS (TREE_VALUE (p2));
+                    memb; memb = DECL_CHAIN (memb))
+                 {
+                   tree mv3 = TREE_TYPE (memb);
+                   if (mv3 && mv3 != error_mark_node
+                       && TREE_CODE (mv3) != ARRAY_TYPE)
+                     mv3 = TYPE_MAIN_VARIANT (mv3);
+                   if (comptypes (mv3, mv1))
+                     {
+                       TREE_VALUE (n) = composite_type (TREE_TYPE (memb),
+                                                        TREE_VALUE (p1));
+                       pedwarn (input_location, OPT_Wpedantic,
+                                "function types not truly compatible in ISO C");
+                       goto parm_done;
+                     }
+                 }
+             }
+           TREE_VALUE (n) = composite_type (TREE_VALUE (p1), TREE_VALUE (p2));
+         parm_done: ;
+         }
+
+       t1 = build_function_type (valtype, newargs);
+       t1 = qualify_type (t1, t2);
+       /* ... falls through ...  */
+      }
+
+    default:
+      return build_type_attribute_variant (t1, attributes);
+    }
+
+}
+
+/* Return the type of a conditional expression between pointers to
+   possibly differently qualified versions of compatible types.
+
+   We assume that comp_target_types has already been done and returned
+   nonzero; if that isn't so, this may crash.  */
+
+static tree
+common_pointer_type (tree t1, tree t2)
+{
+  tree attributes;
+  tree pointed_to_1, mv1;
+  tree pointed_to_2, mv2;
+  tree target;
+  unsigned target_quals;
+  addr_space_t as1, as2, as_common;
+  int quals1, quals2;
+
+  /* Save time if the two types are the same.  */
+
+  if (t1 == t2) return t1;
+
+  /* If one type is nonsense, use the other.  */
+  if (t1 == error_mark_node)
+    return t2;
+  if (t2 == error_mark_node)
+    return t1;
+
+  gcc_assert (TREE_CODE (t1) == POINTER_TYPE
+             && TREE_CODE (t2) == POINTER_TYPE);
+
+  /* Merge the attributes.  */
+  attributes = targetm.merge_type_attributes (t1, t2);
+
+  /* Find the composite type of the target types, and combine the
+     qualifiers of the two types' targets.  Do not lose qualifiers on
+     array element types by taking the TYPE_MAIN_VARIANT.  */
+  mv1 = pointed_to_1 = TREE_TYPE (t1);
+  mv2 = pointed_to_2 = TREE_TYPE (t2);
+  if (TREE_CODE (mv1) != ARRAY_TYPE)
+    mv1 = TYPE_MAIN_VARIANT (pointed_to_1);
+  if (TREE_CODE (mv2) != ARRAY_TYPE)
+    mv2 = TYPE_MAIN_VARIANT (pointed_to_2);
+  target = composite_type (mv1, mv2);
+
+  /* For function types do not merge const qualifiers, but drop them
+     if used inconsistently.  The middle-end uses these to mark const
+     and noreturn functions.  */
+  quals1 = TYPE_QUALS_NO_ADDR_SPACE (pointed_to_1);
+  quals2 = TYPE_QUALS_NO_ADDR_SPACE (pointed_to_2);
+
+  if (TREE_CODE (pointed_to_1) == FUNCTION_TYPE)
+    target_quals = (quals1 & quals2);
+  else
+    target_quals = (quals1 | quals2);
+
+  /* If the two named address spaces are different, determine the common
+     superset address space.  This is guaranteed to exist due to the
+     assumption that comp_target_type returned non-zero.  */
+  as1 = TYPE_ADDR_SPACE (pointed_to_1);
+  as2 = TYPE_ADDR_SPACE (pointed_to_2);
+  if (!addr_space_superset (as1, as2, &as_common))
+    gcc_unreachable ();
+
+  target_quals |= ENCODE_QUAL_ADDR_SPACE (as_common);
+
+  t1 = build_pointer_type (c_build_qualified_type (target, target_quals));
+  return build_type_attribute_variant (t1, attributes);
+}
+
+/* Return the common type for two arithmetic types under the usual
+   arithmetic conversions.  The default conversions have already been
+   applied, and enumerated types converted to their compatible integer
+   types.  The resulting type is unqualified and has no attributes.
+
+   This is the type for the result of most arithmetic operations
+   if the operands have the given two types.  */
+
+static tree
+c_common_type (tree t1, tree t2)
+{
+  enum tree_code code1;
+  enum tree_code code2;
+
+  /* If one type is nonsense, use the other.  */
+  if (t1 == error_mark_node)
+    return t2;
+  if (t2 == error_mark_node)
+    return t1;
+
+  if (TYPE_QUALS (t1) != TYPE_UNQUALIFIED)
+    t1 = TYPE_MAIN_VARIANT (t1);
+
+  if (TYPE_QUALS (t2) != TYPE_UNQUALIFIED)
+    t2 = TYPE_MAIN_VARIANT (t2);
+
+  if (TYPE_ATTRIBUTES (t1) != NULL_TREE)
+    t1 = build_type_attribute_variant (t1, NULL_TREE);
+
+  if (TYPE_ATTRIBUTES (t2) != NULL_TREE)
+    t2 = build_type_attribute_variant (t2, NULL_TREE);
+
+  /* Save time if the two types are the same.  */
+
+  if (t1 == t2) return t1;
+
+  code1 = TREE_CODE (t1);
+  code2 = TREE_CODE (t2);
+
+  gcc_assert (code1 == VECTOR_TYPE || code1 == COMPLEX_TYPE
+             || code1 == FIXED_POINT_TYPE || code1 == REAL_TYPE
+             || code1 == INTEGER_TYPE);
+  gcc_assert (code2 == VECTOR_TYPE || code2 == COMPLEX_TYPE
+             || code2 == FIXED_POINT_TYPE || code2 == REAL_TYPE
+             || code2 == INTEGER_TYPE);
+
+  /* When one operand is a decimal float type, the other operand cannot be
+     a generic float type or a complex type.  We also disallow vector types
+     here.  */
+  if ((DECIMAL_FLOAT_TYPE_P (t1) || DECIMAL_FLOAT_TYPE_P (t2))
+      && !(DECIMAL_FLOAT_TYPE_P (t1) && DECIMAL_FLOAT_TYPE_P (t2)))
+    {
+      if (code1 == VECTOR_TYPE || code2 == VECTOR_TYPE)
+       {
+         error ("can%'t mix operands of decimal float and vector types");
+         return error_mark_node;
+       }
+      if (code1 == COMPLEX_TYPE || code2 == COMPLEX_TYPE)
+       {
+         error ("can%'t mix operands of decimal float and complex types");
+         return error_mark_node;
+       }
+      if (code1 == REAL_TYPE && code2 == REAL_TYPE)
+       {
+         error ("can%'t mix operands of decimal float and other float types");
+         return error_mark_node;
+       }
+    }
+
+  /* If one type is a vector type, return that type.  (How the usual
+     arithmetic conversions apply to the vector types extension is not
+     precisely specified.)  */
+  if (code1 == VECTOR_TYPE)
+    return t1;
+
+  if (code2 == VECTOR_TYPE)
+    return t2;
+
+  /* If one type is complex, form the common type of the non-complex
+     components, then make that complex.  Use T1 or T2 if it is the
+     required type.  */
+  if (code1 == COMPLEX_TYPE || code2 == COMPLEX_TYPE)
+    {
+      tree subtype1 = code1 == COMPLEX_TYPE ? TREE_TYPE (t1) : t1;
+      tree subtype2 = code2 == COMPLEX_TYPE ? TREE_TYPE (t2) : t2;
+      tree subtype = c_common_type (subtype1, subtype2);
+
+      if (code1 == COMPLEX_TYPE && TREE_TYPE (t1) == subtype)
+       return t1;
+      else if (code2 == COMPLEX_TYPE && TREE_TYPE (t2) == subtype)
+       return t2;
+      else
+       return build_complex_type (subtype);
+    }
+
+  /* If only one is real, use it as the result.  */
+
+  if (code1 == REAL_TYPE && code2 != REAL_TYPE)
+    return t1;
+
+  if (code2 == REAL_TYPE && code1 != REAL_TYPE)
+    return t2;
+
+  /* If both are real and either are decimal floating point types, use
+     the decimal floating point type with the greater precision. */
+
+  if (code1 == REAL_TYPE && code2 == REAL_TYPE)
+    {
+      if (TYPE_MAIN_VARIANT (t1) == dfloat128_type_node
+         || TYPE_MAIN_VARIANT (t2) == dfloat128_type_node)
+       return dfloat128_type_node;
+      else if (TYPE_MAIN_VARIANT (t1) == dfloat64_type_node
+              || TYPE_MAIN_VARIANT (t2) == dfloat64_type_node)
+       return dfloat64_type_node;
+      else if (TYPE_MAIN_VARIANT (t1) == dfloat32_type_node
+              || TYPE_MAIN_VARIANT (t2) == dfloat32_type_node)
+       return dfloat32_type_node;
+    }
+
+  /* Deal with fixed-point types.  */
+  if (code1 == FIXED_POINT_TYPE || code2 == FIXED_POINT_TYPE)
+    {
+      unsigned int unsignedp = 0, satp = 0;
+      enum machine_mode m1, m2;
+      unsigned int fbit1, ibit1, fbit2, ibit2, max_fbit, max_ibit;
+
+      m1 = TYPE_MODE (t1);
+      m2 = TYPE_MODE (t2);
+
+      /* If one input type is saturating, the result type is saturating.  */
+      if (TYPE_SATURATING (t1) || TYPE_SATURATING (t2))
+       satp = 1;
+
+      /* If both fixed-point types are unsigned, the result type is unsigned.
+        When mixing fixed-point and integer types, follow the sign of the
+        fixed-point type.
+        Otherwise, the result type is signed.  */
+      if ((TYPE_UNSIGNED (t1) && TYPE_UNSIGNED (t2)
+          && code1 == FIXED_POINT_TYPE && code2 == FIXED_POINT_TYPE)
+         || (code1 == FIXED_POINT_TYPE && code2 != FIXED_POINT_TYPE
+             && TYPE_UNSIGNED (t1))
+         || (code1 != FIXED_POINT_TYPE && code2 == FIXED_POINT_TYPE
+             && TYPE_UNSIGNED (t2)))
+       unsignedp = 1;
+
+      /* The result type is signed.  */
+      if (unsignedp == 0)
+       {
+         /* If the input type is unsigned, we need to convert to the
+            signed type.  */
+         if (code1 == FIXED_POINT_TYPE && TYPE_UNSIGNED (t1))
+           {
+             enum mode_class mclass = (enum mode_class) 0;
+             if (GET_MODE_CLASS (m1) == MODE_UFRACT)
+               mclass = MODE_FRACT;
+             else if (GET_MODE_CLASS (m1) == MODE_UACCUM)
+               mclass = MODE_ACCUM;
+             else
+               gcc_unreachable ();
+             m1 = mode_for_size (GET_MODE_PRECISION (m1), mclass, 0);
+           }
+         if (code2 == FIXED_POINT_TYPE && TYPE_UNSIGNED (t2))
+           {
+             enum mode_class mclass = (enum mode_class) 0;
+             if (GET_MODE_CLASS (m2) == MODE_UFRACT)
+               mclass = MODE_FRACT;
+             else if (GET_MODE_CLASS (m2) == MODE_UACCUM)
+               mclass = MODE_ACCUM;
+             else
+               gcc_unreachable ();
+             m2 = mode_for_size (GET_MODE_PRECISION (m2), mclass, 0);
+           }
+       }
+
+      if (code1 == FIXED_POINT_TYPE)
+       {
+         fbit1 = GET_MODE_FBIT (m1);
+         ibit1 = GET_MODE_IBIT (m1);
+       }
+      else
+       {
+         fbit1 = 0;
+         /* Signed integers need to subtract one sign bit.  */
+         ibit1 = TYPE_PRECISION (t1) - (!TYPE_UNSIGNED (t1));
+       }
+
+      if (code2 == FIXED_POINT_TYPE)
+       {
+         fbit2 = GET_MODE_FBIT (m2);
+         ibit2 = GET_MODE_IBIT (m2);
+       }
+      else
+       {
+         fbit2 = 0;
+         /* Signed integers need to subtract one sign bit.  */
+         ibit2 = TYPE_PRECISION (t2) - (!TYPE_UNSIGNED (t2));
+       }
+
+      max_ibit = ibit1 >= ibit2 ?  ibit1 : ibit2;
+      max_fbit = fbit1 >= fbit2 ?  fbit1 : fbit2;
+      return c_common_fixed_point_type_for_size (max_ibit, max_fbit, unsignedp,
+                                                satp);
+    }
+
+  /* Both real or both integers; use the one with greater precision.  */
+
+  if (TYPE_PRECISION (t1) > TYPE_PRECISION (t2))
+    return t1;
+  else if (TYPE_PRECISION (t2) > TYPE_PRECISION (t1))
+    return t2;
+
+  /* Same precision.  Prefer long longs to longs to ints when the
+     same precision, following the C99 rules on integer type rank
+     (which are equivalent to the C90 rules for C90 types).  */
+
+  if (TYPE_MAIN_VARIANT (t1) == long_long_unsigned_type_node
+      || TYPE_MAIN_VARIANT (t2) == long_long_unsigned_type_node)
+    return long_long_unsigned_type_node;
+
+  if (TYPE_MAIN_VARIANT (t1) == long_long_integer_type_node
+      || TYPE_MAIN_VARIANT (t2) == long_long_integer_type_node)
+    {
+      if (TYPE_UNSIGNED (t1) || TYPE_UNSIGNED (t2))
+       return long_long_unsigned_type_node;
+      else
+       return long_long_integer_type_node;
+    }
+
+  if (TYPE_MAIN_VARIANT (t1) == long_unsigned_type_node
+      || TYPE_MAIN_VARIANT (t2) == long_unsigned_type_node)
+    return long_unsigned_type_node;
+
+  if (TYPE_MAIN_VARIANT (t1) == long_integer_type_node
+      || TYPE_MAIN_VARIANT (t2) == long_integer_type_node)
+    {
+      /* But preserve unsignedness from the other type,
+        since long cannot hold all the values of an unsigned int.  */
+      if (TYPE_UNSIGNED (t1) || TYPE_UNSIGNED (t2))
+       return long_unsigned_type_node;
+      else
+       return long_integer_type_node;
+    }
+
+  /* Likewise, prefer long double to double even if same size.  */
+  if (TYPE_MAIN_VARIANT (t1) == long_double_type_node
+      || TYPE_MAIN_VARIANT (t2) == long_double_type_node)
+    return long_double_type_node;
+
+  /* Otherwise prefer the unsigned one.  */
+
+  if (TYPE_UNSIGNED (t1))
+    return t1;
+  else
+    return t2;
+}
+\f
+/* Wrapper around c_common_type that is used by c-common.c and other
+   front end optimizations that remove promotions.  ENUMERAL_TYPEs
+   are allowed here and are converted to their compatible integer types.
+   BOOLEAN_TYPEs are allowed here and return either boolean_type_node or
+   preferably a non-Boolean type as the common type.  */
+tree
+common_type (tree t1, tree t2)
+{
+  if (TREE_CODE (t1) == ENUMERAL_TYPE)
+    t1 = c_common_type_for_size (TYPE_PRECISION (t1), 1);
+  if (TREE_CODE (t2) == ENUMERAL_TYPE)
+    t2 = c_common_type_for_size (TYPE_PRECISION (t2), 1);
+
+  /* If both types are BOOLEAN_TYPE, then return boolean_type_node.  */
+  if (TREE_CODE (t1) == BOOLEAN_TYPE
+      && TREE_CODE (t2) == BOOLEAN_TYPE)
+    return boolean_type_node;
+
+  /* If either type is BOOLEAN_TYPE, then return the other.  */
+  if (TREE_CODE (t1) == BOOLEAN_TYPE)
+    return t2;
+  if (TREE_CODE (t2) == BOOLEAN_TYPE)
+    return t1;
+
+  return c_common_type (t1, t2);
+}
+
+/* Return 1 if TYPE1 and TYPE2 are compatible types for assignment
+   or various other operations.  Return 2 if they are compatible
+   but a warning may be needed if you use them together.  */
+
+int
+comptypes (tree type1, tree type2)
+{
+  const struct tagged_tu_seen_cache * tagged_tu_seen_base1 = tagged_tu_seen_base;
+  int val;
+
+  val = comptypes_internal (type1, type2, NULL, NULL);
+  free_all_tagged_tu_seen_up_to (tagged_tu_seen_base1);
+
+  return val;
+}
+
+/* Like comptypes, but if it returns non-zero because enum and int are
+   compatible, it sets *ENUM_AND_INT_P to true.  */
+
+static int
+comptypes_check_enum_int (tree type1, tree type2, bool *enum_and_int_p)
+{
+  const struct tagged_tu_seen_cache * tagged_tu_seen_base1 = tagged_tu_seen_base;
+  int val;
+
+  val = comptypes_internal (type1, type2, enum_and_int_p, NULL);
+  free_all_tagged_tu_seen_up_to (tagged_tu_seen_base1);
+
+  return val;
+}
+
+/* Like comptypes, but if it returns nonzero for different types, it
+   sets *DIFFERENT_TYPES_P to true.  */
+
+int
+comptypes_check_different_types (tree type1, tree type2,
+                                bool *different_types_p)
+{
+  const struct tagged_tu_seen_cache * tagged_tu_seen_base1 = tagged_tu_seen_base;
+  int val;
+
+  val = comptypes_internal (type1, type2, NULL, different_types_p);
+  free_all_tagged_tu_seen_up_to (tagged_tu_seen_base1);
+
+  return val;
+}
+\f
+/* Return 1 if TYPE1 and TYPE2 are compatible types for assignment
+   or various other operations.  Return 2 if they are compatible
+   but a warning may be needed if you use them together.  If
+   ENUM_AND_INT_P is not NULL, and one type is an enum and the other a
+   compatible integer type, then this sets *ENUM_AND_INT_P to true;
+   *ENUM_AND_INT_P is never set to false.  If DIFFERENT_TYPES_P is not
+   NULL, and the types are compatible but different enough not to be
+   permitted in C11 typedef redeclarations, then this sets
+   *DIFFERENT_TYPES_P to true; *DIFFERENT_TYPES_P is never set to
+   false, but may or may not be set if the types are incompatible.
+   This differs from comptypes, in that we don't free the seen
+   types.  */
+
+static int
+comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p,
+                   bool *different_types_p)
+{
+  const_tree t1 = type1;
+  const_tree t2 = type2;
+  int attrval, val;
+
+  /* Suppress errors caused by previously reported errors.  */
+
+  if (t1 == t2 || !t1 || !t2
+      || TREE_CODE (t1) == ERROR_MARK || TREE_CODE (t2) == ERROR_MARK)
+    return 1;
+
+  /* Enumerated types are compatible with integer types, but this is
+     not transitive: two enumerated types in the same translation unit
+     are compatible with each other only if they are the same type.  */
+
+  if (TREE_CODE (t1) == ENUMERAL_TYPE && TREE_CODE (t2) != ENUMERAL_TYPE)
+    {
+      t1 = c_common_type_for_size (TYPE_PRECISION (t1), TYPE_UNSIGNED (t1));
+      if (TREE_CODE (t2) != VOID_TYPE)
+       {
+         if (enum_and_int_p != NULL)
+           *enum_and_int_p = true;
+         if (different_types_p != NULL)
+           *different_types_p = true;
+       }
+    }
+  else if (TREE_CODE (t2) == ENUMERAL_TYPE && TREE_CODE (t1) != ENUMERAL_TYPE)
+    {
+      t2 = c_common_type_for_size (TYPE_PRECISION (t2), TYPE_UNSIGNED (t2));
+      if (TREE_CODE (t1) != VOID_TYPE)
+       {
+         if (enum_and_int_p != NULL)
+           *enum_and_int_p = true;
+         if (different_types_p != NULL)
+           *different_types_p = true;
+       }
+    }
+
+  if (t1 == t2)
+    return 1;
+
+  /* Different classes of types can't be compatible.  */
+
+  if (TREE_CODE (t1) != TREE_CODE (t2))
+    return 0;
+
+  /* Qualifiers must match. C99 6.7.3p9 */
+
+  if (TYPE_QUALS (t1) != TYPE_QUALS (t2))
+    return 0;
+
+  /* Allow for two different type nodes which have essentially the same
+     definition.  Note that we already checked for equality of the type
+     qualifiers (just above).  */
+
+  if (TREE_CODE (t1) != ARRAY_TYPE
+      && TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
+    return 1;
+
+  /* 1 if no need for warning yet, 2 if warning cause has been seen.  */
+  if (!(attrval = comp_type_attributes (t1, t2)))
+     return 0;
+
+  /* 1 if no need for warning yet, 2 if warning cause has been seen.  */
+  val = 0;
+
+  switch (TREE_CODE (t1))
+    {
+    case POINTER_TYPE:
+      /* Do not remove mode or aliasing information.  */
+      if (TYPE_MODE (t1) != TYPE_MODE (t2)
+         || TYPE_REF_CAN_ALIAS_ALL (t1) != TYPE_REF_CAN_ALIAS_ALL (t2))
+       break;
+      val = (TREE_TYPE (t1) == TREE_TYPE (t2)
+            ? 1 : comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2),
+                                      enum_and_int_p, different_types_p));
+      break;
+
+    case FUNCTION_TYPE:
+      val = function_types_compatible_p (t1, t2, enum_and_int_p,
+                                        different_types_p);
+      break;
+
+    case ARRAY_TYPE:
+      {
+       tree d1 = TYPE_DOMAIN (t1);
+       tree d2 = TYPE_DOMAIN (t2);
+       bool d1_variable, d2_variable;
+       bool d1_zero, d2_zero;
+       val = 1;
+
+       /* Target types must match incl. qualifiers.  */
+       if (TREE_TYPE (t1) != TREE_TYPE (t2)
+           && 0 == (val = comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2),
+                                              enum_and_int_p,
+                                              different_types_p)))
+         return 0;
+
+       if (different_types_p != NULL
+           && (d1 == 0) != (d2 == 0))
+         *different_types_p = true;
+       /* Sizes must match unless one is missing or variable.  */
+       if (d1 == 0 || d2 == 0 || d1 == d2)
+         break;
+
+       d1_zero = !TYPE_MAX_VALUE (d1);
+       d2_zero = !TYPE_MAX_VALUE (d2);
+
+       d1_variable = (!d1_zero
+                      && (TREE_CODE (TYPE_MIN_VALUE (d1)) != INTEGER_CST
+                          || TREE_CODE (TYPE_MAX_VALUE (d1)) != INTEGER_CST));
+       d2_variable = (!d2_zero
+                      && (TREE_CODE (TYPE_MIN_VALUE (d2)) != INTEGER_CST
+                          || TREE_CODE (TYPE_MAX_VALUE (d2)) != INTEGER_CST));
+       d1_variable = d1_variable || (d1_zero && c_vla_type_p (t1));
+       d2_variable = d2_variable || (d2_zero && c_vla_type_p (t2));
+
+       if (different_types_p != NULL
+           && d1_variable != d2_variable)
+         *different_types_p = true;
+       if (d1_variable || d2_variable)
+         break;
+       if (d1_zero && d2_zero)
+         break;
+       if (d1_zero || d2_zero
+           || !tree_int_cst_equal (TYPE_MIN_VALUE (d1), TYPE_MIN_VALUE (d2))
+           || !tree_int_cst_equal (TYPE_MAX_VALUE (d1), TYPE_MAX_VALUE (d2)))
+         val = 0;
+
+       break;
+      }
+
+    case ENUMERAL_TYPE:
+    case RECORD_TYPE:
+    case UNION_TYPE:
+      if (val != 1 && !same_translation_unit_p (t1, t2))
+       {
+         tree a1 = TYPE_ATTRIBUTES (t1);
+         tree a2 = TYPE_ATTRIBUTES (t2);
+
+         if (! attribute_list_contained (a1, a2)
+             && ! attribute_list_contained (a2, a1))
+           break;
+
+         if (attrval != 2)
+           return tagged_types_tu_compatible_p (t1, t2, enum_and_int_p,
+                                                different_types_p);
+         val = tagged_types_tu_compatible_p (t1, t2, enum_and_int_p,
+                                             different_types_p);
+       }
+      break;
+
+    case VECTOR_TYPE:
+      val = (TYPE_VECTOR_SUBPARTS (t1) == TYPE_VECTOR_SUBPARTS (t2)
+            && comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2),
+                                   enum_and_int_p, different_types_p));
+      break;
+
+    default:
+      break;
+    }
+  return attrval == 2 && val == 1 ? 2 : val;
+}
+
+/* Return 1 if TTL and TTR are pointers to types that are equivalent, ignoring
+   their qualifiers, except for named address spaces.  If the pointers point to
+   different named addresses, then we must determine if one address space is a
+   subset of the other.  */
+
+static int
+comp_target_types (location_t location, tree ttl, tree ttr)
+{
+  int val;
+  tree mvl = TREE_TYPE (ttl);
+  tree mvr = TREE_TYPE (ttr);
+  addr_space_t asl = TYPE_ADDR_SPACE (mvl);
+  addr_space_t asr = TYPE_ADDR_SPACE (mvr);
+  addr_space_t as_common;
+  bool enum_and_int_p;
+
+  /* Fail if pointers point to incompatible address spaces.  */
+  if (!addr_space_superset (asl, asr, &as_common))
+    return 0;
+
+  /* Do not lose qualifiers on element types of array types that are
+     pointer targets by taking their TYPE_MAIN_VARIANT.  */
+  if (TREE_CODE (mvl) != ARRAY_TYPE)
+    mvl = TYPE_MAIN_VARIANT (mvl);
+  if (TREE_CODE (mvr) != ARRAY_TYPE)
+    mvr = TYPE_MAIN_VARIANT (mvr);
+  enum_and_int_p = false;
+  val = comptypes_check_enum_int (mvl, mvr, &enum_and_int_p);
+
+  if (val == 2)
+    pedwarn (location, OPT_Wpedantic, "types are not quite compatible");
+
+  if (val == 1 && enum_and_int_p && warn_cxx_compat)
+    warning_at (location, OPT_Wc___compat,
+               "pointer target types incompatible in C++");
+
+  return val;
+}
+\f
+/* Subroutines of `comptypes'.  */
+
+/* Determine whether two trees derive from the same translation unit.
+   If the CONTEXT chain ends in a null, that tree's context is still
+   being parsed, so if two trees have context chains ending in null,
+   they're in the same translation unit.  */
+int
+same_translation_unit_p (const_tree t1, const_tree t2)
+{
+  while (t1 && TREE_CODE (t1) != TRANSLATION_UNIT_DECL)
+    switch (TREE_CODE_CLASS (TREE_CODE (t1)))
+      {
+      case tcc_declaration:
+       t1 = DECL_CONTEXT (t1); break;
+      case tcc_type:
+       t1 = TYPE_CONTEXT (t1); break;
+      case tcc_exceptional:
+       t1 = BLOCK_SUPERCONTEXT (t1); break;  /* assume block */
+      default: gcc_unreachable ();
+      }
+
+  while (t2 && TREE_CODE (t2) != TRANSLATION_UNIT_DECL)
+    switch (TREE_CODE_CLASS (TREE_CODE (t2)))
+      {
+      case tcc_declaration:
+       t2 = DECL_CONTEXT (t2); break;
+      case tcc_type:
+       t2 = TYPE_CONTEXT (t2); break;
+      case tcc_exceptional:
+       t2 = BLOCK_SUPERCONTEXT (t2); break;  /* assume block */
+      default: gcc_unreachable ();
+      }
+
+  return t1 == t2;
+}
+
+/* Allocate the seen two types, assuming that they are compatible. */
+
+static struct tagged_tu_seen_cache *
+alloc_tagged_tu_seen_cache (const_tree t1, const_tree t2)
+{
+  struct tagged_tu_seen_cache *tu = XNEW (struct tagged_tu_seen_cache);
+  tu->next = tagged_tu_seen_base;
+  tu->t1 = t1;
+  tu->t2 = t2;
+
+  tagged_tu_seen_base = tu;
+
+  /* The C standard says that two structures in different translation
+     units are compatible with each other only if the types of their
+     fields are compatible (among other things).  We assume that they
+     are compatible until proven otherwise when building the cache.
+     An example where this can occur is:
+     struct a
+     {
+       struct a *next;
+     };
+     If we are comparing this against a similar struct in another TU,
+     and did not assume they were compatible, we end up with an infinite
+     loop.  */
+  tu->val = 1;
+  return tu;
+}
+
+/* Free the seen types until we get to TU_TIL. */
+
+static void
+free_all_tagged_tu_seen_up_to (const struct tagged_tu_seen_cache *tu_til)
+{
+  const struct tagged_tu_seen_cache *tu = tagged_tu_seen_base;
+  while (tu != tu_til)
+    {
+      const struct tagged_tu_seen_cache *const tu1
+       = (const struct tagged_tu_seen_cache *) tu;
+      tu = tu1->next;
+      free (CONST_CAST (struct tagged_tu_seen_cache *, tu1));
+    }
+  tagged_tu_seen_base = tu_til;
+}
+
+/* Return 1 if two 'struct', 'union', or 'enum' types T1 and T2 are
+   compatible.  If the two types are not the same (which has been
+   checked earlier), this can only happen when multiple translation
+   units are being compiled.  See C99 6.2.7 paragraph 1 for the exact
+   rules.  ENUM_AND_INT_P and DIFFERENT_TYPES_P are as in
+   comptypes_internal.  */
+
+static int
+tagged_types_tu_compatible_p (const_tree t1, const_tree t2,
+                             bool *enum_and_int_p, bool *different_types_p)
+{
+  tree s1, s2;
+  bool needs_warning = false;
+
+  /* We have to verify that the tags of the types are the same.  This
+     is harder than it looks because this may be a typedef, so we have
+     to go look at the original type.  It may even be a typedef of a
+     typedef...
+     In the case of compiler-created builtin structs the TYPE_DECL
+     may be a dummy, with no DECL_ORIGINAL_TYPE.  Don't fault.  */
+  while (TYPE_NAME (t1)
+        && TREE_CODE (TYPE_NAME (t1)) == TYPE_DECL
+        && DECL_ORIGINAL_TYPE (TYPE_NAME (t1)))
+    t1 = DECL_ORIGINAL_TYPE (TYPE_NAME (t1));
+
+  while (TYPE_NAME (t2)
+        && TREE_CODE (TYPE_NAME (t2)) == TYPE_DECL
+        && DECL_ORIGINAL_TYPE (TYPE_NAME (t2)))
+    t2 = DECL_ORIGINAL_TYPE (TYPE_NAME (t2));
+
+  /* C90 didn't have the requirement that the two tags be the same.  */
+  if (flag_isoc99 && TYPE_NAME (t1) != TYPE_NAME (t2))
+    return 0;
+
+  /* C90 didn't say what happened if one or both of the types were
+     incomplete; we choose to follow C99 rules here, which is that they
+     are compatible.  */
+  if (TYPE_SIZE (t1) == NULL
+      || TYPE_SIZE (t2) == NULL)
+    return 1;
+
+  {
+    const struct tagged_tu_seen_cache * tts_i;
+    for (tts_i = tagged_tu_seen_base; tts_i != NULL; tts_i = tts_i->next)
+      if (tts_i->t1 == t1 && tts_i->t2 == t2)
+       return tts_i->val;
+  }
+
+  switch (TREE_CODE (t1))
+    {
+    case ENUMERAL_TYPE:
+      {
+       struct tagged_tu_seen_cache *tu = alloc_tagged_tu_seen_cache (t1, t2);
+       /* Speed up the case where the type values are in the same order.  */
+       tree tv1 = TYPE_VALUES (t1);
+       tree tv2 = TYPE_VALUES (t2);
+
+       if (tv1 == tv2)
+         {
+           return 1;
+         }
+
+       for (;tv1 && tv2; tv1 = TREE_CHAIN (tv1), tv2 = TREE_CHAIN (tv2))
+         {
+           if (TREE_PURPOSE (tv1) != TREE_PURPOSE (tv2))
+             break;
+           if (simple_cst_equal (TREE_VALUE (tv1), TREE_VALUE (tv2)) != 1)
+             {
+               tu->val = 0;
+               return 0;
+             }
+         }
+
+       if (tv1 == NULL_TREE && tv2 == NULL_TREE)
+         {
+           return 1;
+         }
+       if (tv1 == NULL_TREE || tv2 == NULL_TREE)
+         {
+           tu->val = 0;
+           return 0;
+         }
+
+       if (list_length (TYPE_VALUES (t1)) != list_length (TYPE_VALUES (t2)))
+         {
+           tu->val = 0;
+           return 0;
+         }
+
+       for (s1 = TYPE_VALUES (t1); s1; s1 = TREE_CHAIN (s1))
+         {
+           s2 = purpose_member (TREE_PURPOSE (s1), TYPE_VALUES (t2));
+           if (s2 == NULL
+               || simple_cst_equal (TREE_VALUE (s1), TREE_VALUE (s2)) != 1)
+             {
+               tu->val = 0;
+               return 0;
+             }
+         }
+       return 1;
+      }
+
+    case UNION_TYPE:
+      {
+       struct tagged_tu_seen_cache *tu = alloc_tagged_tu_seen_cache (t1, t2);
+       if (list_length (TYPE_FIELDS (t1)) != list_length (TYPE_FIELDS (t2)))
+         {
+           tu->val = 0;
+           return 0;
+         }
+
+       /*  Speed up the common case where the fields are in the same order. */
+       for (s1 = TYPE_FIELDS (t1), s2 = TYPE_FIELDS (t2); s1 && s2;
+            s1 = DECL_CHAIN (s1), s2 = DECL_CHAIN (s2))
+         {
+           int result;
+
+           if (DECL_NAME (s1) != DECL_NAME (s2))
+             break;
+           result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2),
+                                        enum_and_int_p, different_types_p);
+
+           if (result != 1 && !DECL_NAME (s1))
+             break;
+           if (result == 0)
+             {
+               tu->val = 0;
+               return 0;
+             }
+           if (result == 2)
+             needs_warning = true;
+
+           if (TREE_CODE (s1) == FIELD_DECL
+               && simple_cst_equal (DECL_FIELD_BIT_OFFSET (s1),
+                                    DECL_FIELD_BIT_OFFSET (s2)) != 1)
+             {
+               tu->val = 0;
+               return 0;
+             }
+         }
+       if (!s1 && !s2)
+         {
+           tu->val = needs_warning ? 2 : 1;
+           return tu->val;
+         }
+
+       for (s1 = TYPE_FIELDS (t1); s1; s1 = DECL_CHAIN (s1))
+         {
+           bool ok = false;
+
+           for (s2 = TYPE_FIELDS (t2); s2; s2 = DECL_CHAIN (s2))
+             if (DECL_NAME (s1) == DECL_NAME (s2))
+               {
+                 int result;
+
+                 result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2),
+                                              enum_and_int_p,
+                                              different_types_p);
+
+                 if (result != 1 && !DECL_NAME (s1))
+                   continue;
+                 if (result == 0)
+                   {
+                     tu->val = 0;
+                     return 0;
+                   }
+                 if (result == 2)
+                   needs_warning = true;
+
+                 if (TREE_CODE (s1) == FIELD_DECL
+                     && simple_cst_equal (DECL_FIELD_BIT_OFFSET (s1),
+                                          DECL_FIELD_BIT_OFFSET (s2)) != 1)
+                   break;
+
+                 ok = true;
+                 break;
+               }
+           if (!ok)
+             {
+               tu->val = 0;
+               return 0;
+             }
+         }
+       tu->val = needs_warning ? 2 : 10;
+       return tu->val;
+      }
+
+    case RECORD_TYPE:
+      {
+       struct tagged_tu_seen_cache *tu = alloc_tagged_tu_seen_cache (t1, t2);
+
+       for (s1 = TYPE_FIELDS (t1), s2 = TYPE_FIELDS (t2);
+            s1 && s2;
+            s1 = DECL_CHAIN (s1), s2 = DECL_CHAIN (s2))
+         {
+           int result;
+           if (TREE_CODE (s1) != TREE_CODE (s2)
+               || DECL_NAME (s1) != DECL_NAME (s2))
+             break;
+           result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2),
+                                        enum_and_int_p, different_types_p);
+           if (result == 0)
+             break;
+           if (result == 2)
+             needs_warning = true;
+
+           if (TREE_CODE (s1) == FIELD_DECL
+               && simple_cst_equal (DECL_FIELD_BIT_OFFSET (s1),
+                                    DECL_FIELD_BIT_OFFSET (s2)) != 1)
+             break;
+         }
+       if (s1 && s2)
+         tu->val = 0;
+       else
+         tu->val = needs_warning ? 2 : 1;
+       return tu->val;
+      }
+
+    default:
+      gcc_unreachable ();
+    }
+}
+
+/* Return 1 if two function types F1 and F2 are compatible.
+   If either type specifies no argument types,
+   the other must specify a fixed number of self-promoting arg types.
+   Otherwise, if one type specifies only the number of arguments,
+   the other must specify that number of self-promoting arg types.
+   Otherwise, the argument types must match.
+   ENUM_AND_INT_P and DIFFERENT_TYPES_P are as in comptypes_internal.  */
+
+static int
+function_types_compatible_p (const_tree f1, const_tree f2,
+                            bool *enum_and_int_p, bool *different_types_p)
+{
+  tree args1, args2;
+  /* 1 if no need for warning yet, 2 if warning cause has been seen.  */
+  int val = 1;
+  int val1;
+  tree ret1, ret2;
+
+  ret1 = TREE_TYPE (f1);
+  ret2 = TREE_TYPE (f2);
+
+  /* 'volatile' qualifiers on a function's return type used to mean
+     the function is noreturn.  */
+  if (TYPE_VOLATILE (ret1) != TYPE_VOLATILE (ret2))
+    pedwarn (input_location, 0, "function return types not compatible due to %<volatile%>");
+  if (TYPE_VOLATILE (ret1))
+    ret1 = build_qualified_type (TYPE_MAIN_VARIANT (ret1),
+                                TYPE_QUALS (ret1) & ~TYPE_QUAL_VOLATILE);
+  if (TYPE_VOLATILE (ret2))
+    ret2 = build_qualified_type (TYPE_MAIN_VARIANT (ret2),
+                                TYPE_QUALS (ret2) & ~TYPE_QUAL_VOLATILE);
+  val = comptypes_internal (ret1, ret2, enum_and_int_p, different_types_p);
+  if (val == 0)
+    return 0;
+
+  args1 = TYPE_ARG_TYPES (f1);
+  args2 = TYPE_ARG_TYPES (f2);
+
+  if (different_types_p != NULL
+      && (args1 == 0) != (args2 == 0))
+    *different_types_p = true;
+
+  /* An unspecified parmlist matches any specified parmlist
+     whose argument types don't need default promotions.  */
+
+  if (args1 == 0)
+    {
+      if (!self_promoting_args_p (args2))
+       return 0;
+      /* If one of these types comes from a non-prototype fn definition,
+        compare that with the other type's arglist.
+        If they don't match, ask for a warning (but no error).  */
+      if (TYPE_ACTUAL_ARG_TYPES (f1)
+         && 1 != type_lists_compatible_p (args2, TYPE_ACTUAL_ARG_TYPES (f1),
+                                          enum_and_int_p, different_types_p))
+       val = 2;
+      return val;
+    }
+  if (args2 == 0)
+    {
+      if (!self_promoting_args_p (args1))
+       return 0;
+      if (TYPE_ACTUAL_ARG_TYPES (f2)
+         && 1 != type_lists_compatible_p (args1, TYPE_ACTUAL_ARG_TYPES (f2),
+                                          enum_and_int_p, different_types_p))
+       val = 2;
+      return val;
+    }
+
+  /* Both types have argument lists: compare them and propagate results.  */
+  val1 = type_lists_compatible_p (args1, args2, enum_and_int_p,
+                                 different_types_p);
+  return val1 != 1 ? val1 : val;
+}
+
+/* Check two lists of types for compatibility, returning 0 for
+   incompatible, 1 for compatible, or 2 for compatible with
+   warning.  ENUM_AND_INT_P and DIFFERENT_TYPES_P are as in
+   comptypes_internal.  */
+
+static int
+type_lists_compatible_p (const_tree args1, const_tree args2,
+                        bool *enum_and_int_p, bool *different_types_p)
+{
+  /* 1 if no need for warning yet, 2 if warning cause has been seen.  */
+  int val = 1;
+  int newval = 0;
+
+  while (1)
+    {
+      tree a1, mv1, a2, mv2;
+      if (args1 == 0 && args2 == 0)
+       return val;
+      /* If one list is shorter than the other,
+        they fail to match.  */
+      if (args1 == 0 || args2 == 0)
+       return 0;
+      mv1 = a1 = TREE_VALUE (args1);
+      mv2 = a2 = TREE_VALUE (args2);
+      if (mv1 && mv1 != error_mark_node && TREE_CODE (mv1) != ARRAY_TYPE)
+       mv1 = TYPE_MAIN_VARIANT (mv1);
+      if (mv2 && mv2 != error_mark_node && TREE_CODE (mv2) != ARRAY_TYPE)
+       mv2 = TYPE_MAIN_VARIANT (mv2);
+      /* A null pointer instead of a type
+        means there is supposed to be an argument
+        but nothing is specified about what type it has.
+        So match anything that self-promotes.  */
+      if (different_types_p != NULL
+         && (a1 == 0) != (a2 == 0))
+       *different_types_p = true;
+      if (a1 == 0)
+       {
+         if (c_type_promotes_to (a2) != a2)
+           return 0;
+       }
+      else if (a2 == 0)
+       {
+         if (c_type_promotes_to (a1) != a1)
+           return 0;
+       }
+      /* If one of the lists has an error marker, ignore this arg.  */
+      else if (TREE_CODE (a1) == ERROR_MARK
+              || TREE_CODE (a2) == ERROR_MARK)
+       ;
+      else if (!(newval = comptypes_internal (mv1, mv2, enum_and_int_p,
+                                             different_types_p)))
+       {
+         if (different_types_p != NULL)
+           *different_types_p = true;
+         /* Allow  wait (union {union wait *u; int *i} *)
+            and  wait (union wait *)  to be compatible.  */
+         if (TREE_CODE (a1) == UNION_TYPE
+             && (TYPE_NAME (a1) == 0
+                 || TYPE_TRANSPARENT_AGGR (a1))
+             && TREE_CODE (TYPE_SIZE (a1)) == INTEGER_CST
+             && tree_int_cst_equal (TYPE_SIZE (a1),
+                                    TYPE_SIZE (a2)))
+           {
+             tree memb;
+             for (memb = TYPE_FIELDS (a1);
+                  memb; memb = DECL_CHAIN (memb))
+               {
+                 tree mv3 = TREE_TYPE (memb);
+                 if (mv3 && mv3 != error_mark_node
+                     && TREE_CODE (mv3) != ARRAY_TYPE)
+                   mv3 = TYPE_MAIN_VARIANT (mv3);
+                 if (comptypes_internal (mv3, mv2, enum_and_int_p,
+                                         different_types_p))
+                   break;
+               }
+             if (memb == 0)
+               return 0;
+           }
+         else if (TREE_CODE (a2) == UNION_TYPE
+                  && (TYPE_NAME (a2) == 0
+                      || TYPE_TRANSPARENT_AGGR (a2))
+                  && TREE_CODE (TYPE_SIZE (a2)) == INTEGER_CST
+                  && tree_int_cst_equal (TYPE_SIZE (a2),
+                                         TYPE_SIZE (a1)))
+           {
+             tree memb;
+             for (memb = TYPE_FIELDS (a2);
+                  memb; memb = DECL_CHAIN (memb))
+               {
+                 tree mv3 = TREE_TYPE (memb);
+                 if (mv3 && mv3 != error_mark_node
+                     && TREE_CODE (mv3) != ARRAY_TYPE)
+                   mv3 = TYPE_MAIN_VARIANT (mv3);
+                 if (comptypes_internal (mv3, mv1, enum_and_int_p,
+                                         different_types_p))
+                   break;
+               }
+             if (memb == 0)
+               return 0;
+           }
+         else
+           return 0;
+       }
+
+      /* comptypes said ok, but record if it said to warn.  */
+      if (newval > val)
+       val = newval;
+
+      args1 = TREE_CHAIN (args1);
+      args2 = TREE_CHAIN (args2);
+    }
+}
+\f
+/* Compute the size to increment a pointer by.  */
+
+static tree
+c_size_in_bytes (const_tree type)
+{
+  enum tree_code code = TREE_CODE (type);
+
+  if (code == FUNCTION_TYPE || code == VOID_TYPE || code == ERROR_MARK)
+    return size_one_node;
+
+  if (!COMPLETE_OR_VOID_TYPE_P (type))
+    {
+      error ("arithmetic on pointer to an incomplete type");
+      return size_one_node;
+    }
+
+  /* Convert in case a char is more than one unit.  */
+  return size_binop_loc (input_location, CEIL_DIV_EXPR, TYPE_SIZE_UNIT (type),
+                        size_int (TYPE_PRECISION (char_type_node)
+                                  / BITS_PER_UNIT));
+}
+\f
+/* Return either DECL or its known constant value (if it has one).  */
+
+tree
+decl_constant_value (tree decl)
+{
+  if (/* Don't change a variable array bound or initial value to a constant
+        in a place where a variable is invalid.  Note that DECL_INITIAL
+        isn't valid for a PARM_DECL.  */
+      current_function_decl != 0
+      && TREE_CODE (decl) != PARM_DECL
+      && !TREE_THIS_VOLATILE (decl)
+      && TREE_READONLY (decl)
+      && DECL_INITIAL (decl) != 0
+      && TREE_CODE (DECL_INITIAL (decl)) != ERROR_MARK
+      /* This is invalid if initial value is not constant.
+        If it has either a function call, a memory reference,
+        or a variable, then re-evaluating it could give different results.  */
+      && TREE_CONSTANT (DECL_INITIAL (decl))
+      /* Check for cases where this is sub-optimal, even though valid.  */
+      && TREE_CODE (DECL_INITIAL (decl)) != CONSTRUCTOR)
+    return DECL_INITIAL (decl);
+  return decl;
+}
+
+/* Convert the array expression EXP to a pointer.  */
+static tree
+array_to_pointer_conversion (location_t loc, tree exp)
+{
+  tree orig_exp = exp;
+  tree type = TREE_TYPE (exp);
+  tree adr;
+  tree restype = TREE_TYPE (type);
+  tree ptrtype;
+
+  gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
+
+  STRIP_TYPE_NOPS (exp);
+
+  if (TREE_NO_WARNING (orig_exp))
+    TREE_NO_WARNING (exp) = 1;
+
+  ptrtype = build_pointer_type (restype);
+
+  if (TREE_CODE (exp) == INDIRECT_REF)
+    return convert (ptrtype, TREE_OPERAND (exp, 0));
+
+  /* In C++ array compound literals are temporary objects unless they are
+     const or appear in namespace scope, so they are destroyed too soon
+     to use them for much of anything  (c++/53220).  */
+  if (warn_cxx_compat && TREE_CODE (exp) == COMPOUND_LITERAL_EXPR)
+    {
+      tree decl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
+      if (!TREE_READONLY (decl) && !TREE_STATIC (decl))
+       warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wc___compat,
+                   "converting an array compound literal to a pointer "
+                   "is ill-formed in C++");
+    }
+
+  adr = build_unary_op (loc, ADDR_EXPR, exp, 1);
+  return convert (ptrtype, adr);
+}
+
+/* Convert the function expression EXP to a pointer.  */
+static tree
+function_to_pointer_conversion (location_t loc, tree exp)
+{
+  tree orig_exp = exp;
+
+  gcc_assert (TREE_CODE (TREE_TYPE (exp)) == FUNCTION_TYPE);
+
+  STRIP_TYPE_NOPS (exp);
+
+  if (TREE_NO_WARNING (orig_exp))
+    TREE_NO_WARNING (exp) = 1;
+
+  return build_unary_op (loc, ADDR_EXPR, exp, 0);
+}
+
+/* Mark EXP as read, not just set, for set but not used -Wunused
+   warning purposes.  */
+
+void
+mark_exp_read (tree exp)
+{
+  switch (TREE_CODE (exp))
+    {
+    case VAR_DECL:
+    case PARM_DECL:
+      DECL_READ_P (exp) = 1;
+      break;
+    case ARRAY_REF:
+    case COMPONENT_REF:
+    case MODIFY_EXPR:
+    case REALPART_EXPR:
+    case IMAGPART_EXPR:
+    CASE_CONVERT:
+    case ADDR_EXPR:
+      mark_exp_read (TREE_OPERAND (exp, 0));
+      break;
+    case COMPOUND_EXPR:
+    case C_MAYBE_CONST_EXPR:
+      mark_exp_read (TREE_OPERAND (exp, 1));
+      break;
+    default:
+      break;
+    }
+}
+
+/* Perform the default conversion of arrays and functions to pointers.
+   Return the result of converting EXP.  For any other expression, just
+   return EXP.
+
+   LOC is the location of the expression.  */
+
+struct c_expr
+default_function_array_conversion (location_t loc, struct c_expr exp)
+{
+  tree orig_exp = exp.value;
+  tree type = TREE_TYPE (exp.value);
+  enum tree_code code = TREE_CODE (type);
+
+  switch (code)
+    {
+    case ARRAY_TYPE:
+      {
+       bool not_lvalue = false;
+       bool lvalue_array_p;
+
+       while ((TREE_CODE (exp.value) == NON_LVALUE_EXPR
+               || CONVERT_EXPR_P (exp.value))
+              && TREE_TYPE (TREE_OPERAND (exp.value, 0)) == type)
+         {
+           if (TREE_CODE (exp.value) == NON_LVALUE_EXPR)
+             not_lvalue = true;
+           exp.value = TREE_OPERAND (exp.value, 0);
+         }
+
+       if (TREE_NO_WARNING (orig_exp))
+         TREE_NO_WARNING (exp.value) = 1;
+
+       lvalue_array_p = !not_lvalue && lvalue_p (exp.value);
+       if (!flag_isoc99 && !lvalue_array_p)
+         {
+           /* Before C99, non-lvalue arrays do not decay to pointers.
+              Normally, using such an array would be invalid; but it can
+              be used correctly inside sizeof or as a statement expression.
+              Thus, do not give an error here; an error will result later.  */
+           return exp;
+         }
+
+       exp.value = array_to_pointer_conversion (loc, exp.value);
+      }
+      break;
+    case FUNCTION_TYPE:
+      exp.value = function_to_pointer_conversion (loc, exp.value);
+      break;
+    default:
+      break;
+    }
+
+  return exp;
+}
+
+struct c_expr
+default_function_array_read_conversion (location_t loc, struct c_expr exp)
+{
+  mark_exp_read (exp.value);
+  return default_function_array_conversion (loc, exp);
+}
+
+/* EXP is an expression of integer type.  Apply the integer promotions
+   to it and return the promoted value.  */
+
+tree
+perform_integral_promotions (tree exp)
+{
+  tree type = TREE_TYPE (exp);
+  enum tree_code code = TREE_CODE (type);
+
+  gcc_assert (INTEGRAL_TYPE_P (type));
+
+  /* Normally convert enums to int,
+     but convert wide enums to something wider.  */
+  if (code == ENUMERAL_TYPE)
+    {
+      type = c_common_type_for_size (MAX (TYPE_PRECISION (type),
+                                         TYPE_PRECISION (integer_type_node)),
+                                    ((TYPE_PRECISION (type)
+                                      >= TYPE_PRECISION (integer_type_node))
+                                     && TYPE_UNSIGNED (type)));
+
+      return convert (type, exp);
+    }
+
+  /* ??? This should no longer be needed now bit-fields have their
+     proper types.  */
+  if (TREE_CODE (exp) == COMPONENT_REF
+      && DECL_C_BIT_FIELD (TREE_OPERAND (exp, 1))
+      /* If it's thinner than an int, promote it like a
+        c_promoting_integer_type_p, otherwise leave it alone.  */
+      && 0 > compare_tree_int (DECL_SIZE (TREE_OPERAND (exp, 1)),
+                              TYPE_PRECISION (integer_type_node)))
+    return convert (integer_type_node, exp);
+
+  if (c_promoting_integer_type_p (type))
+    {
+      /* Preserve unsignedness if not really getting any wider.  */
+      if (TYPE_UNSIGNED (type)
+         && TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node))
+       return convert (unsigned_type_node, exp);
+
+      return convert (integer_type_node, exp);
+    }
+
+  return exp;
+}
+
+
+/* Perform default promotions for C data used in expressions.
+   Enumeral types or short or char are converted to int.
+   In addition, manifest constants symbols are replaced by their values.  */
+
+tree
+default_conversion (tree exp)
+{
+  tree orig_exp;
+  tree type = TREE_TYPE (exp);
+  enum tree_code code = TREE_CODE (type);
+  tree promoted_type;
+
+  mark_exp_read (exp);
+
+  /* Functions and arrays have been converted during parsing.  */
+  gcc_assert (code != FUNCTION_TYPE);
+  if (code == ARRAY_TYPE)
+    return exp;
+
+  /* Constants can be used directly unless they're not loadable.  */
+  if (TREE_CODE (exp) == CONST_DECL)
+    exp = DECL_INITIAL (exp);
+
+  /* Strip no-op conversions.  */
+  orig_exp = exp;
+  STRIP_TYPE_NOPS (exp);
+
+  if (TREE_NO_WARNING (orig_exp))
+    TREE_NO_WARNING (exp) = 1;
+
+  if (code == VOID_TYPE)
+    {
+      error ("void value not ignored as it ought to be");
+      return error_mark_node;
+    }
+
+  exp = require_complete_type (exp);
+  if (exp == error_mark_node)
+    return error_mark_node;
+
+  promoted_type = targetm.promoted_type (type);
+  if (promoted_type)
+    return convert (promoted_type, exp);
+
+  if (INTEGRAL_TYPE_P (type))
+    return perform_integral_promotions (exp);
+
+  return exp;
+}
+\f
+/* Look up COMPONENT in a structure or union TYPE.
+
+   If the component name is not found, returns NULL_TREE.  Otherwise,
+   the return value is a TREE_LIST, with each TREE_VALUE a FIELD_DECL
+   stepping down the chain to the component, which is in the last
+   TREE_VALUE of the list.  Normally the list is of length one, but if
+   the component is embedded within (nested) anonymous structures or
+   unions, the list steps down the chain to the component.  */
+
+static tree
+lookup_field (tree type, tree component)
+{
+  tree field;
+
+  /* If TYPE_LANG_SPECIFIC is set, then it is a sorted array of pointers
+     to the field elements.  Use a binary search on this array to quickly
+     find the element.  Otherwise, do a linear search.  TYPE_LANG_SPECIFIC
+     will always be set for structures which have many elements.  */
+
+  if (TYPE_LANG_SPECIFIC (type) && TYPE_LANG_SPECIFIC (type)->s)
+    {
+      int bot, top, half;
+      tree *field_array = &TYPE_LANG_SPECIFIC (type)->s->elts[0];
+
+      field = TYPE_FIELDS (type);
+      bot = 0;
+      top = TYPE_LANG_SPECIFIC (type)->s->len;
+      while (top - bot > 1)
+       {
+         half = (top - bot + 1) >> 1;
+         field = field_array[bot+half];
+
+         if (DECL_NAME (field) == NULL_TREE)
+           {
+             /* Step through all anon unions in linear fashion.  */
+             while (DECL_NAME (field_array[bot]) == NULL_TREE)
+               {
+                 field = field_array[bot++];
+                 if (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
+                     || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
+                   {
+                     tree anon = lookup_field (TREE_TYPE (field), component);
+
+                     if (anon)
+                       return tree_cons (NULL_TREE, field, anon);
+
+                     /* The Plan 9 compiler permits referring
+                        directly to an anonymous struct/union field
+                        using a typedef name.  */
+                     if (flag_plan9_extensions
+                         && TYPE_NAME (TREE_TYPE (field)) != NULL_TREE
+                         && (TREE_CODE (TYPE_NAME (TREE_TYPE (field)))
+                             == TYPE_DECL)
+                         && (DECL_NAME (TYPE_NAME (TREE_TYPE (field)))
+                             == component))
+                       break;
+                   }
+               }
+
+             /* Entire record is only anon unions.  */
+             if (bot > top)
+               return NULL_TREE;
+
+             /* Restart the binary search, with new lower bound.  */
+             continue;
+           }
+
+         if (DECL_NAME (field) == component)
+           break;
+         if (DECL_NAME (field) < component)
+           bot += half;
+         else
+           top = bot + half;
+       }
+
+      if (DECL_NAME (field_array[bot]) == component)
+       field = field_array[bot];
+      else if (DECL_NAME (field) != component)
+       return NULL_TREE;
+    }
+  else
+    {
+      for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
+       {
+         if (DECL_NAME (field) == NULL_TREE
+             && (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
+                 || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE))
+           {
+             tree anon = lookup_field (TREE_TYPE (field), component);
+
+             if (anon)
+               return tree_cons (NULL_TREE, field, anon);
+
+             /* The Plan 9 compiler permits referring directly to an
+                anonymous struct/union field using a typedef
+                name.  */
+             if (flag_plan9_extensions
+                 && TYPE_NAME (TREE_TYPE (field)) != NULL_TREE
+                 && TREE_CODE (TYPE_NAME (TREE_TYPE (field))) == TYPE_DECL
+                 && (DECL_NAME (TYPE_NAME (TREE_TYPE (field)))
+                     == component))
+               break;
+           }
+
+         if (DECL_NAME (field) == component)
+           break;
+       }
+
+      if (field == NULL_TREE)
+       return NULL_TREE;
+    }
+
+  return tree_cons (NULL_TREE, field, NULL_TREE);
+}
+
+/* Make an expression to refer to the COMPONENT field of structure or
+   union value DATUM.  COMPONENT is an IDENTIFIER_NODE.  LOC is the
+   location of the COMPONENT_REF.  */
+
+tree
+build_component_ref (location_t loc, tree datum, tree component)
+{
+  tree type = TREE_TYPE (datum);
+  enum tree_code code = TREE_CODE (type);
+  tree field = NULL;
+  tree ref;
+  bool datum_lvalue = lvalue_p (datum);
+
+  if (!objc_is_public (datum, component))
+    return error_mark_node;
+
+  /* Detect Objective-C property syntax object.property.  */
+  if (c_dialect_objc ()
+      && (ref = objc_maybe_build_component_ref (datum, component)))
+    return ref;
+
+  /* See if there is a field or component with name COMPONENT.  */
+
+  if (code == RECORD_TYPE || code == UNION_TYPE)
+    {
+      if (!COMPLETE_TYPE_P (type))
+       {
+         c_incomplete_type_error (NULL_TREE, type);
+         return error_mark_node;
+       }
+
+      field = lookup_field (type, component);
+
+      if (!field)
+       {
+         error_at (loc, "%qT has no member named %qE", type, component);
+         return error_mark_node;
+       }
+
+      /* Chain the COMPONENT_REFs if necessary down to the FIELD.
+        This might be better solved in future the way the C++ front
+        end does it - by giving the anonymous entities each a
+        separate name and type, and then have build_component_ref
+        recursively call itself.  We can't do that here.  */
+      do
+       {
+         tree subdatum = TREE_VALUE (field);
+         int quals;
+         tree subtype;
+         bool use_datum_quals;
+
+         if (TREE_TYPE (subdatum) == error_mark_node)
+           return error_mark_node;
+
+         /* If this is an rvalue, it does not have qualifiers in C
+            standard terms and we must avoid propagating such
+            qualifiers down to a non-lvalue array that is then
+            converted to a pointer.  */
+         use_datum_quals = (datum_lvalue
+                            || TREE_CODE (TREE_TYPE (subdatum)) != ARRAY_TYPE);
+
+         quals = TYPE_QUALS (strip_array_types (TREE_TYPE (subdatum)));
+         if (use_datum_quals)
+           quals |= TYPE_QUALS (TREE_TYPE (datum));
+         subtype = c_build_qualified_type (TREE_TYPE (subdatum), quals);
+
+         ref = build3 (COMPONENT_REF, subtype, datum, subdatum,
+                       NULL_TREE);
+         SET_EXPR_LOCATION (ref, loc);
+         if (TREE_READONLY (subdatum)
+             || (use_datum_quals && TREE_READONLY (datum)))
+           TREE_READONLY (ref) = 1;
+         if (TREE_THIS_VOLATILE (subdatum)
+             || (use_datum_quals && TREE_THIS_VOLATILE (datum)))
+           TREE_THIS_VOLATILE (ref) = 1;
+
+         if (TREE_DEPRECATED (subdatum))
+           warn_deprecated_use (subdatum, NULL_TREE);
+
+         datum = ref;
+
+         field = TREE_CHAIN (field);
+       }
+      while (field);
+
+      return ref;
+    }
+  else if (code != ERROR_MARK)
+    error_at (loc,
+             "request for member %qE in something not a structure or union",
+             component);
+
+  return error_mark_node;
+}
+\f
+/* Given an expression PTR for a pointer, return an expression
+   for the value pointed to.
+   ERRORSTRING is the name of the operator to appear in error messages.
+
+   LOC is the location to use for the generated tree.  */
+
+tree
+build_indirect_ref (location_t loc, tree ptr, ref_operator errstring)
+{
+  tree pointer = default_conversion (ptr);
+  tree type = TREE_TYPE (pointer);
+  tree ref;
+
+  if (TREE_CODE (type) == POINTER_TYPE)
+    {
+      if (CONVERT_EXPR_P (pointer)
+          || TREE_CODE (pointer) == VIEW_CONVERT_EXPR)
+       {
+         /* If a warning is issued, mark it to avoid duplicates from
+            the backend.  This only needs to be done at
+            warn_strict_aliasing > 2.  */
+         if (warn_strict_aliasing > 2)
+           if (strict_aliasing_warning (TREE_TYPE (TREE_OPERAND (pointer, 0)),
+                                        type, TREE_OPERAND (pointer, 0)))
+             TREE_NO_WARNING (pointer) = 1;
+       }
+
+      if (TREE_CODE (pointer) == ADDR_EXPR
+         && (TREE_TYPE (TREE_OPERAND (pointer, 0))
+             == TREE_TYPE (type)))
+       {
+         ref = TREE_OPERAND (pointer, 0);
+         protected_set_expr_location (ref, loc);
+         return ref;
+       }
+      else
+       {
+         tree t = TREE_TYPE (type);
+
+         ref = build1 (INDIRECT_REF, t, pointer);
+
+         if (!COMPLETE_OR_VOID_TYPE_P (t) && TREE_CODE (t) != ARRAY_TYPE)
+           {
+             error_at (loc, "dereferencing pointer to incomplete type");
+             return error_mark_node;
+           }
+         if (VOID_TYPE_P (t) && c_inhibit_evaluation_warnings == 0)
+           warning_at (loc, 0, "dereferencing %<void *%> pointer");
+
+         /* We *must* set TREE_READONLY when dereferencing a pointer to const,
+            so that we get the proper error message if the result is used
+            to assign to.  Also, &* is supposed to be a no-op.
+            And ANSI C seems to specify that the type of the result
+            should be the const type.  */
+         /* A de-reference of a pointer to const is not a const.  It is valid
+            to change it via some other pointer.  */
+         TREE_READONLY (ref) = TYPE_READONLY (t);
+         TREE_SIDE_EFFECTS (ref)
+           = TYPE_VOLATILE (t) || TREE_SIDE_EFFECTS (pointer);
+         TREE_THIS_VOLATILE (ref) = TYPE_VOLATILE (t);
+         protected_set_expr_location (ref, loc);
+         return ref;
+       }
+    }
+  else if (TREE_CODE (pointer) != ERROR_MARK)
+    invalid_indirection_error (loc, type, errstring);
+
+  return error_mark_node;
+}
+
+/* This handles expressions of the form "a[i]", which denotes
+   an array reference.
+
+   This is logically equivalent in C to *(a+i), but we may do it differently.
+   If A is a variable or a member, we generate a primitive ARRAY_REF.
+   This avoids forcing the array out of registers, and can work on
+   arrays that are not lvalues (for example, members of structures returned
+   by functions).
+
+   For vector types, allow vector[i] but not i[vector], and create
+   *(((type*)&vectortype) + i) for the expression.
+
+   LOC is the location to use for the returned expression.  */
+
+tree
+build_array_ref (location_t loc, tree array, tree index)
+{
+  tree ret;
+  bool swapped = false;
+  if (TREE_TYPE (array) == error_mark_node
+      || TREE_TYPE (index) == error_mark_node)
+    return error_mark_node;
+
+  if (TREE_CODE (TREE_TYPE (array)) != ARRAY_TYPE
+      && TREE_CODE (TREE_TYPE (array)) != POINTER_TYPE
+      /* Allow vector[index] but not index[vector].  */
+      && TREE_CODE (TREE_TYPE (array)) != VECTOR_TYPE)
+    {
+      tree temp;
+      if (TREE_CODE (TREE_TYPE (index)) != ARRAY_TYPE
+         && TREE_CODE (TREE_TYPE (index)) != POINTER_TYPE)
+       {
+          error_at (loc,
+            "subscripted value is neither array nor pointer nor vector");
+
+         return error_mark_node;
+       }
+      temp = array;
+      array = index;
+      index = temp;
+      swapped = true;
+    }
+
+  if (!INTEGRAL_TYPE_P (TREE_TYPE (index)))
+    {
+      error_at (loc, "array subscript is not an integer");
+      return error_mark_node;
+    }
+
+  if (TREE_CODE (TREE_TYPE (TREE_TYPE (array))) == FUNCTION_TYPE)
+    {
+      error_at (loc, "subscripted value is pointer to function");
+      return error_mark_node;
+    }
+
+  /* ??? Existing practice has been to warn only when the char
+     index is syntactically the index, not for char[array].  */
+  if (!swapped)
+     warn_array_subscript_with_type_char (index);
+
+  /* Apply default promotions *after* noticing character types.  */
+  index = default_conversion (index);
+
+  gcc_assert (TREE_CODE (TREE_TYPE (index)) == INTEGER_TYPE);
+
+  convert_vector_to_pointer_for_subscript (loc, &array, index);
+
+  if (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE)
+    {
+      tree rval, type;
+
+      /* An array that is indexed by a non-constant
+        cannot be stored in a register; we must be able to do
+        address arithmetic on its address.
+        Likewise an array of elements of variable size.  */
+      if (TREE_CODE (index) != INTEGER_CST
+         || (COMPLETE_TYPE_P (TREE_TYPE (TREE_TYPE (array)))
+             && TREE_CODE (TYPE_SIZE (TREE_TYPE (TREE_TYPE (array)))) != INTEGER_CST))
+       {
+         if (!c_mark_addressable (array))
+           return error_mark_node;
+       }
+      /* An array that is indexed by a constant value which is not within
+        the array bounds cannot be stored in a register either; because we
+        would get a crash in store_bit_field/extract_bit_field when trying
+        to access a non-existent part of the register.  */
+      if (TREE_CODE (index) == INTEGER_CST
+         && TYPE_DOMAIN (TREE_TYPE (array))
+         && !int_fits_type_p (index, TYPE_DOMAIN (TREE_TYPE (array))))
+       {
+         if (!c_mark_addressable (array))
+           return error_mark_node;
+       }
+
+      if (pedantic)
+       {
+         tree foo = array;
+         while (TREE_CODE (foo) == COMPONENT_REF)
+           foo = TREE_OPERAND (foo, 0);
+         if (TREE_CODE (foo) == VAR_DECL && C_DECL_REGISTER (foo))
+           pedwarn (loc, OPT_Wpedantic,
+                    "ISO C forbids subscripting %<register%> array");
+         else if (!flag_isoc99 && !lvalue_p (foo))
+           pedwarn (loc, OPT_Wpedantic,
+                    "ISO C90 forbids subscripting non-lvalue array");
+       }
+
+      type = TREE_TYPE (TREE_TYPE (array));
+      rval = build4 (ARRAY_REF, type, array, index, NULL_TREE, NULL_TREE);
+      /* Array ref is const/volatile if the array elements are
+        or if the array is.  */
+      TREE_READONLY (rval)
+       |= (TYPE_READONLY (TREE_TYPE (TREE_TYPE (array)))
+           | TREE_READONLY (array));
+      TREE_SIDE_EFFECTS (rval)
+       |= (TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (array)))
+           | TREE_SIDE_EFFECTS (array));
+      TREE_THIS_VOLATILE (rval)
+       |= (TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (array)))
+           /* This was added by rms on 16 Nov 91.
+              It fixes  vol struct foo *a;  a->elts[1]
+              in an inline function.
+              Hope it doesn't break something else.  */
+           | TREE_THIS_VOLATILE (array));
+      ret = require_complete_type (rval);
+      protected_set_expr_location (ret, loc);
+      return ret;
+    }
+  else
+    {
+      tree ar = default_conversion (array);
+
+      if (ar == error_mark_node)
+       return ar;
+
+      gcc_assert (TREE_CODE (TREE_TYPE (ar)) == POINTER_TYPE);
+      gcc_assert (TREE_CODE (TREE_TYPE (TREE_TYPE (ar))) != FUNCTION_TYPE);
+
+      return build_indirect_ref
+       (loc, build_binary_op (loc, PLUS_EXPR, ar, index, 0),
+        RO_ARRAY_INDEXING);
+    }
+}
+\f
+/* Build an external reference to identifier ID.  FUN indicates
+   whether this will be used for a function call.  LOC is the source
+   location of the identifier.  This sets *TYPE to the type of the
+   identifier, which is not the same as the type of the returned value
+   for CONST_DECLs defined as enum constants.  If the type of the
+   identifier is not available, *TYPE is set to NULL.  */
+tree
+build_external_ref (location_t loc, tree id, int fun, tree *type)
+{
+  tree ref;
+  tree decl = lookup_name (id);
+
+  /* In Objective-C, an instance variable (ivar) may be preferred to
+     whatever lookup_name() found.  */
+  decl = objc_lookup_ivar (decl, id);
+
+  *type = NULL;
+  if (decl && decl != error_mark_node)
+    {
+      ref = decl;
+      *type = TREE_TYPE (ref);
+    }
+  else if (fun)
+    /* Implicit function declaration.  */
+    ref = implicitly_declare (loc, id);
+  else if (decl == error_mark_node)
+    /* Don't complain about something that's already been
+       complained about.  */
+    return error_mark_node;
+  else
+    {
+      undeclared_variable (loc, id);
+      return error_mark_node;
+    }
+
+  if (TREE_TYPE (ref) == error_mark_node)
+    return error_mark_node;
+
+  if (TREE_DEPRECATED (ref))
+    warn_deprecated_use (ref, NULL_TREE);
+
+  /* Recursive call does not count as usage.  */
+  if (ref != current_function_decl)
+    {
+      TREE_USED (ref) = 1;
+    }
+
+  if (TREE_CODE (ref) == FUNCTION_DECL && !in_alignof)
+    {
+      if (!in_sizeof && !in_typeof)
+       C_DECL_USED (ref) = 1;
+      else if (DECL_INITIAL (ref) == 0
+              && DECL_EXTERNAL (ref)
+              && !TREE_PUBLIC (ref))
+       record_maybe_used_decl (ref);
+    }
+
+  if (TREE_CODE (ref) == CONST_DECL)
+    {
+      used_types_insert (TREE_TYPE (ref));
+
+      if (warn_cxx_compat
+         && TREE_CODE (TREE_TYPE (ref)) == ENUMERAL_TYPE
+         && C_TYPE_DEFINED_IN_STRUCT (TREE_TYPE (ref)))
+       {
+         warning_at (loc, OPT_Wc___compat,
+                     ("enum constant defined in struct or union "
+                      "is not visible in C++"));
+         inform (DECL_SOURCE_LOCATION (ref), "enum constant defined here");
+       }
+
+      ref = DECL_INITIAL (ref);
+      TREE_CONSTANT (ref) = 1;
+    }
+  else if (current_function_decl != 0
+          && !DECL_FILE_SCOPE_P (current_function_decl)
+          && (TREE_CODE (ref) == VAR_DECL
+              || TREE_CODE (ref) == PARM_DECL
+              || TREE_CODE (ref) == FUNCTION_DECL))
+    {
+      tree context = decl_function_context (ref);
+
+      if (context != 0 && context != current_function_decl)
+       DECL_NONLOCAL (ref) = 1;
+    }
+  /* C99 6.7.4p3: An inline definition of a function with external
+     linkage ... shall not contain a reference to an identifier with
+     internal linkage.  */
+  else if (current_function_decl != 0
+          && DECL_DECLARED_INLINE_P (current_function_decl)
+          && DECL_EXTERNAL (current_function_decl)
+          && VAR_OR_FUNCTION_DECL_P (ref)
+          && (TREE_CODE (ref) != VAR_DECL || TREE_STATIC (ref))
+          && ! TREE_PUBLIC (ref)
+          && DECL_CONTEXT (ref) != current_function_decl)
+    record_inline_static (loc, current_function_decl, ref,
+                         csi_internal);
+
+  return ref;
+}
+
+/* Record details of decls possibly used inside sizeof or typeof.  */
+struct maybe_used_decl
+{
+  /* The decl.  */
+  tree decl;
+  /* The level seen at (in_sizeof + in_typeof).  */
+  int level;
+  /* The next one at this level or above, or NULL.  */
+  struct maybe_used_decl *next;
+};
+
+static struct maybe_used_decl *maybe_used_decls;
+
+/* Record that DECL, an undefined static function reference seen
+   inside sizeof or typeof, might be used if the operand of sizeof is
+   a VLA type or the operand of typeof is a variably modified
+   type.  */
+
+static void
+record_maybe_used_decl (tree decl)
+{
+  struct maybe_used_decl *t = XOBNEW (&parser_obstack, struct maybe_used_decl);
+  t->decl = decl;
+  t->level = in_sizeof + in_typeof;
+  t->next = maybe_used_decls;
+  maybe_used_decls = t;
+}
+
+/* Pop the stack of decls possibly used inside sizeof or typeof.  If
+   USED is false, just discard them.  If it is true, mark them used
+   (if no longer inside sizeof or typeof) or move them to the next
+   level up (if still inside sizeof or typeof).  */
+
+void
+pop_maybe_used (bool used)
+{
+  struct maybe_used_decl *p = maybe_used_decls;
+  int cur_level = in_sizeof + in_typeof;
+  while (p && p->level > cur_level)
+    {
+      if (used)
+       {
+         if (cur_level == 0)
+           C_DECL_USED (p->decl) = 1;
+         else
+           p->level = cur_level;
+       }
+      p = p->next;
+    }
+  if (!used || cur_level == 0)
+    maybe_used_decls = p;
+}
+
+/* Return the result of sizeof applied to EXPR.  */
+
+struct c_expr
+c_expr_sizeof_expr (location_t loc, struct c_expr expr)
+{
+  struct c_expr ret;
+  if (expr.value == error_mark_node)
+    {
+      ret.value = error_mark_node;
+      ret.original_code = ERROR_MARK;
+      ret.original_type = NULL;
+      pop_maybe_used (false);
+    }
+  else
+    {
+      bool expr_const_operands = true;
+      tree folded_expr = c_fully_fold (expr.value, require_constant_value,
+                                      &expr_const_operands);
+      ret.value = c_sizeof (loc, TREE_TYPE (folded_expr));
+      ret.original_code = ERROR_MARK;
+      ret.original_type = NULL;
+      if (c_vla_type_p (TREE_TYPE (folded_expr)))
+       {
+         /* sizeof is evaluated when given a vla (C99 6.5.3.4p2).  */
+         ret.value = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (ret.value),
+                             folded_expr, ret.value);
+         C_MAYBE_CONST_EXPR_NON_CONST (ret.value) = !expr_const_operands;
+         SET_EXPR_LOCATION (ret.value, loc);
+       }
+      pop_maybe_used (C_TYPE_VARIABLE_SIZE (TREE_TYPE (folded_expr)));
+    }
+  return ret;
+}
+
+/* Return the result of sizeof applied to T, a structure for the type
+   name passed to sizeof (rather than the type itself).  LOC is the
+   location of the original expression.  */
+
+struct c_expr
+c_expr_sizeof_type (location_t loc, struct c_type_name *t)
+{
+  tree type;
+  struct c_expr ret;
+  tree type_expr = NULL_TREE;
+  bool type_expr_const = true;
+  type = groktypename (t, &type_expr, &type_expr_const);
+  ret.value = c_sizeof (loc, type);
+  ret.original_code = ERROR_MARK;
+  ret.original_type = NULL;
+  if ((type_expr || TREE_CODE (ret.value) == INTEGER_CST)
+      && c_vla_type_p (type))
+    {
+      /* If the type is a [*] array, it is a VLA but is represented as
+        having a size of zero.  In such a case we must ensure that
+        the result of sizeof does not get folded to a constant by
+        c_fully_fold, because if the size is evaluated the result is
+        not constant and so constraints on zero or negative size
+        arrays must not be applied when this sizeof call is inside
+        another array declarator.  */
+      if (!type_expr)
+       type_expr = integer_zero_node;
+      ret.value = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (ret.value),
+                         type_expr, ret.value);
+      C_MAYBE_CONST_EXPR_NON_CONST (ret.value) = !type_expr_const;
+    }
+  pop_maybe_used (type != error_mark_node
+                 ? C_TYPE_VARIABLE_SIZE (type) : false);
+  return ret;
+}
+
+/* Build a function call to function FUNCTION with parameters PARAMS.
+   The function call is at LOC.
+   PARAMS is a list--a chain of TREE_LIST nodes--in which the
+   TREE_VALUE of each node is a parameter-expression.
+   FUNCTION's data type may be a function type or a pointer-to-function.  */
+
+tree
+build_function_call (location_t loc, tree function, tree params)
+{
+  VEC(tree,gc) *vec;
+  tree ret;
+
+  vec = VEC_alloc (tree, gc, list_length (params));
+  for (; params; params = TREE_CHAIN (params))
+    VEC_quick_push (tree, vec, TREE_VALUE (params));
+  ret = build_function_call_vec (loc, function, vec, NULL);
+  VEC_free (tree, gc, vec);
+  return ret;
+}
+
+/* Give a note about the location of the declaration of DECL.  */
+
+static void inform_declaration (tree decl)
+{
+  if (decl && (TREE_CODE (decl) != FUNCTION_DECL || !DECL_BUILT_IN (decl)))
+    inform (DECL_SOURCE_LOCATION (decl), "declared here");
+}
+
+/* Build a function call to function FUNCTION with parameters PARAMS.
+   ORIGTYPES, if not NULL, is a vector of types; each element is
+   either NULL or the original type of the corresponding element in
+   PARAMS.  The original type may differ from TREE_TYPE of the
+   parameter for enums.  FUNCTION's data type may be a function type
+   or pointer-to-function.  This function changes the elements of
+   PARAMS.  */
+
+tree
+build_function_call_vec (location_t loc, tree function, VEC(tree,gc) *params,
+                        VEC(tree,gc) *origtypes)
+{
+  tree fntype, fundecl = 0;
+  tree name = NULL_TREE, result;
+  tree tem;
+  int nargs;
+  tree *argarray;
+
+
+  /* Strip NON_LVALUE_EXPRs, etc., since we aren't using as an lvalue.  */
+  STRIP_TYPE_NOPS (function);
+
+  /* Convert anything with function type to a pointer-to-function.  */
+  if (TREE_CODE (function) == FUNCTION_DECL)
+    {
+      /* Implement type-directed function overloading for builtins.
+        resolve_overloaded_builtin and targetm.resolve_overloaded_builtin
+        handle all the type checking.  The result is a complete expression
+        that implements this function call.  */
+      tem = resolve_overloaded_builtin (loc, function, params);
+      if (tem)
+       return tem;
+
+      name = DECL_NAME (function);
+
+      if (flag_tm)
+       tm_malloc_replacement (function);
+      fundecl = function;
+      /* Atomic functions have type checking/casting already done.  They are 
+        often rewritten and don't match the original parameter list.  */
+      if (name && !strncmp (IDENTIFIER_POINTER (name), "__atomic_", 9))
+        origtypes = NULL;
+    }
+  if (TREE_CODE (TREE_TYPE (function)) == FUNCTION_TYPE)
+    function = function_to_pointer_conversion (loc, function);
+
+  /* For Objective-C, convert any calls via a cast to OBJC_TYPE_REF
+     expressions, like those used for ObjC messenger dispatches.  */
+  if (!VEC_empty (tree, params))
+    function = objc_rewrite_function_call (function,
+                                          VEC_index (tree, params, 0));
+
+  function = c_fully_fold (function, false, NULL);
+
+  fntype = TREE_TYPE (function);
+
+  if (TREE_CODE (fntype) == ERROR_MARK)
+    return error_mark_node;
+
+  if (!(TREE_CODE (fntype) == POINTER_TYPE
+       && TREE_CODE (TREE_TYPE (fntype)) == FUNCTION_TYPE))
+    {
+      if (!flag_diagnostics_show_caret)
+       error_at (loc,
+                 "called object %qE is not a function or function pointer",
+                 function);
+      else if (DECL_P (function))
+       {
+         error_at (loc,
+                   "called object %qD is not a function or function pointer",
+                   function);
+         inform_declaration (function);
+       }
+      else
+       error_at (loc,
+                 "called object is not a function or function pointer");
+      return error_mark_node;
+    }
+
+  if (fundecl && TREE_THIS_VOLATILE (fundecl))
+    current_function_returns_abnormally = 1;
+
+  /* fntype now gets the type of function pointed to.  */
+  fntype = TREE_TYPE (fntype);
+
+  /* Convert the parameters to the types declared in the
+     function prototype, or apply default promotions.  */
+
+  nargs = convert_arguments (TYPE_ARG_TYPES (fntype), params, origtypes,
+                            function, fundecl);
+  if (nargs < 0)
+    return error_mark_node;
+
+  /* Check that the function is called through a compatible prototype.
+     If it is not, replace the call by a trap, wrapped up in a compound
+     expression if necessary.  This has the nice side-effect to prevent
+     the tree-inliner from generating invalid assignment trees which may
+     blow up in the RTL expander later.  */
+  if (CONVERT_EXPR_P (function)
+      && TREE_CODE (tem = TREE_OPERAND (function, 0)) == ADDR_EXPR
+      && TREE_CODE (tem = TREE_OPERAND (tem, 0)) == FUNCTION_DECL
+      && !comptypes (fntype, TREE_TYPE (tem)))
+    {
+      tree return_type = TREE_TYPE (fntype);
+      tree trap = build_function_call (loc,
+                                      builtin_decl_explicit (BUILT_IN_TRAP),
+                                      NULL_TREE);
+      int i;
+
+      /* This situation leads to run-time undefined behavior.  We can't,
+        therefore, simply error unless we can prove that all possible
+        executions of the program must execute the code.  */
+      if (warning_at (loc, 0, "function called through a non-compatible type"))
+       /* We can, however, treat "undefined" any way we please.
+          Call abort to encourage the user to fix the program.  */
+       inform (loc, "if this code is reached, the program will abort");
+      /* Before the abort, allow the function arguments to exit or
+        call longjmp.  */
+      for (i = 0; i < nargs; i++)
+       trap = build2 (COMPOUND_EXPR, void_type_node,
+                      VEC_index (tree, params, i), trap);
+
+      if (VOID_TYPE_P (return_type))
+       {
+         if (TYPE_QUALS (return_type) != TYPE_UNQUALIFIED)
+           pedwarn (loc, 0,
+                    "function with qualified void return type called");
+         return trap;
+       }
+      else
+       {
+         tree rhs;
+
+         if (AGGREGATE_TYPE_P (return_type))
+           rhs = build_compound_literal (loc, return_type,
+                                         build_constructor (return_type, 0),
+                                         false);
+         else
+           rhs = build_zero_cst (return_type);
+
+         return require_complete_type (build2 (COMPOUND_EXPR, return_type,
+                                               trap, rhs));
+       }
+    }
+
+  argarray = VEC_address (tree, params);
+
+  /* Check that arguments to builtin functions match the expectations.  */
+  if (fundecl
+      && DECL_BUILT_IN (fundecl)
+      && DECL_BUILT_IN_CLASS (fundecl) == BUILT_IN_NORMAL
+      && !check_builtin_function_arguments (fundecl, nargs, argarray))
+    return error_mark_node;
+
+  /* Check that the arguments to the function are valid.  */
+  check_function_arguments (fntype, nargs, argarray);
+
+  if (name != NULL_TREE
+      && !strncmp (IDENTIFIER_POINTER (name), "__builtin_", 10))
+    {
+      if (require_constant_value)
+       result =
+         fold_build_call_array_initializer_loc (loc, TREE_TYPE (fntype),
+                                                function, nargs, argarray);
+      else
+       result = fold_build_call_array_loc (loc, TREE_TYPE (fntype),
+                                           function, nargs, argarray);
+      if (TREE_CODE (result) == NOP_EXPR
+         && TREE_CODE (TREE_OPERAND (result, 0)) == INTEGER_CST)
+       STRIP_TYPE_NOPS (result);
+    }
+  else
+    result = build_call_array_loc (loc, TREE_TYPE (fntype),
+                                  function, nargs, argarray);
+
+  if (VOID_TYPE_P (TREE_TYPE (result)))
+    {
+      if (TYPE_QUALS (TREE_TYPE (result)) != TYPE_UNQUALIFIED)
+       pedwarn (loc, 0,
+                "function with qualified void return type called");
+      return result;
+    }
+  return require_complete_type (result);
+}
+\f
+/* Convert the argument expressions in the vector VALUES
+   to the types in the list TYPELIST.
+
+   If TYPELIST is exhausted, or when an element has NULL as its type,
+   perform the default conversions.
+
+   ORIGTYPES is the original types of the expressions in VALUES.  This
+   holds the type of enum values which have been converted to integral
+   types.  It may be NULL.
+
+   FUNCTION is a tree for the called function.  It is used only for
+   error messages, where it is formatted with %qE.
+
+   This is also where warnings about wrong number of args are generated.
+
+   Returns the actual number of arguments processed (which may be less
+   than the length of VALUES in some error situations), or -1 on
+   failure.  */
+
+static int
+convert_arguments (tree typelist, VEC(tree,gc) *values,
+                  VEC(tree,gc) *origtypes, tree function, tree fundecl)
+{
+  tree typetail, val;
+  unsigned int parmnum;
+  bool error_args = false;
+  const bool type_generic = fundecl
+    && lookup_attribute ("type generic", TYPE_ATTRIBUTES(TREE_TYPE (fundecl)));
+  bool type_generic_remove_excess_precision = false;
+  tree selector;
+
+  /* Change pointer to function to the function itself for
+     diagnostics.  */
+  if (TREE_CODE (function) == ADDR_EXPR
+      && TREE_CODE (TREE_OPERAND (function, 0)) == FUNCTION_DECL)
+    function = TREE_OPERAND (function, 0);
+
+  /* Handle an ObjC selector specially for diagnostics.  */
+  selector = objc_message_selector ();
+
+  /* For type-generic built-in functions, determine whether excess
+     precision should be removed (classification) or not
+     (comparison).  */
+  if (type_generic
+      && DECL_BUILT_IN (fundecl)
+      && DECL_BUILT_IN_CLASS (fundecl) == BUILT_IN_NORMAL)
+    {
+      switch (DECL_FUNCTION_CODE (fundecl))
+       {
+       case BUILT_IN_ISFINITE:
+       case BUILT_IN_ISINF:
+       case BUILT_IN_ISINF_SIGN:
+       case BUILT_IN_ISNAN:
+       case BUILT_IN_ISNORMAL:
+       case BUILT_IN_FPCLASSIFY:
+         type_generic_remove_excess_precision = true;
+         break;
+
+       default:
+         type_generic_remove_excess_precision = false;
+         break;
+       }
+    }
+
+  /* Scan the given expressions and types, producing individual
+     converted arguments.  */
+
+  for (typetail = typelist, parmnum = 0;
+       VEC_iterate (tree, values, parmnum, val);
+       ++parmnum)
+    {
+      tree type = typetail ? TREE_VALUE (typetail) : 0;
+      tree valtype = TREE_TYPE (val);
+      tree rname = function;
+      int argnum = parmnum + 1;
+      const char *invalid_func_diag;
+      bool excess_precision = false;
+      bool npc;
+      tree parmval;
+
+      if (type == void_type_node)
+       {
+         if (selector)
+           error_at (input_location,
+                     "too many arguments to method %qE", selector);
+         else
+           error_at (input_location,
+                     "too many arguments to function %qE", function);
+         inform_declaration (fundecl);
+         return parmnum;
+       }
+
+      if (selector && argnum > 2)
+       {
+         rname = selector;
+         argnum -= 2;
+       }
+
+      npc = null_pointer_constant_p (val);
+
+      /* If there is excess precision and a prototype, convert once to
+        the required type rather than converting via the semantic
+        type.  Likewise without a prototype a float value represented
+        as long double should be converted once to double.  But for
+        type-generic classification functions excess precision must
+        be removed here.  */
+      if (TREE_CODE (val) == EXCESS_PRECISION_EXPR
+         && (type || !type_generic || !type_generic_remove_excess_precision))
+       {
+         val = TREE_OPERAND (val, 0);
+         excess_precision = true;
+       }
+      val = c_fully_fold (val, false, NULL);
+      STRIP_TYPE_NOPS (val);
+
+      val = require_complete_type (val);
+
+      if (type != 0)
+       {
+         /* Formal parm type is specified by a function prototype.  */
+
+         if (type == error_mark_node || !COMPLETE_TYPE_P (type))
+           {
+             error ("type of formal parameter %d is incomplete", parmnum + 1);
+             parmval = val;
+           }
+         else
+           {
+             tree origtype;
+
+             /* Optionally warn about conversions that
+                differ from the default conversions.  */
+             if (warn_traditional_conversion || warn_traditional)
+               {
+                 unsigned int formal_prec = TYPE_PRECISION (type);
+
+                 if (INTEGRAL_TYPE_P (type)
+                     && TREE_CODE (valtype) == REAL_TYPE)
+                   warning (0, "passing argument %d of %qE as integer "
+                            "rather than floating due to prototype",
+                            argnum, rname);
+                 if (INTEGRAL_TYPE_P (type)
+                     && TREE_CODE (valtype) == COMPLEX_TYPE)
+                   warning (0, "passing argument %d of %qE as integer "
+                            "rather than complex due to prototype",
+                            argnum, rname);
+                 else if (TREE_CODE (type) == COMPLEX_TYPE
+                          && TREE_CODE (valtype) == REAL_TYPE)
+                   warning (0, "passing argument %d of %qE as complex "
+                            "rather than floating due to prototype",
+                            argnum, rname);
+                 else if (TREE_CODE (type) == REAL_TYPE
+                          && INTEGRAL_TYPE_P (valtype))
+                   warning (0, "passing argument %d of %qE as floating "
+                            "rather than integer due to prototype",
+                            argnum, rname);
+                 else if (TREE_CODE (type) == COMPLEX_TYPE
+                          && INTEGRAL_TYPE_P (valtype))
+                   warning (0, "passing argument %d of %qE as complex "
+                            "rather than integer due to prototype",
+                            argnum, rname);
+                 else if (TREE_CODE (type) == REAL_TYPE
+                          && TREE_CODE (valtype) == COMPLEX_TYPE)
+                   warning (0, "passing argument %d of %qE as floating "
+                            "rather than complex due to prototype",
+                            argnum, rname);
+                 /* ??? At some point, messages should be written about
+                    conversions between complex types, but that's too messy
+                    to do now.  */
+                 else if (TREE_CODE (type) == REAL_TYPE
+                          && TREE_CODE (valtype) == REAL_TYPE)
+                   {
+                     /* Warn if any argument is passed as `float',
+                        since without a prototype it would be `double'.  */
+                     if (formal_prec == TYPE_PRECISION (float_type_node)
+                         && type != dfloat32_type_node)
+                       warning (0, "passing argument %d of %qE as %<float%> "
+                                "rather than %<double%> due to prototype",
+                                argnum, rname);
+
+                     /* Warn if mismatch between argument and prototype
+                        for decimal float types.  Warn of conversions with
+                        binary float types and of precision narrowing due to
+                        prototype. */
+                     else if (type != valtype
+                              && (type == dfloat32_type_node
+                                  || type == dfloat64_type_node
+                                  || type == dfloat128_type_node
+                                  || valtype == dfloat32_type_node
+                                  || valtype == dfloat64_type_node
+                                  || valtype == dfloat128_type_node)
+                              && (formal_prec
+                                  <= TYPE_PRECISION (valtype)
+                                  || (type == dfloat128_type_node
+                                      && (valtype
+                                          != dfloat64_type_node
+                                          && (valtype
+                                              != dfloat32_type_node)))
+                                  || (type == dfloat64_type_node
+                                      && (valtype
+                                          != dfloat32_type_node))))
+                       warning (0, "passing argument %d of %qE as %qT "
+                                "rather than %qT due to prototype",
+                                argnum, rname, type, valtype);
+
+                   }
+                 /* Detect integer changing in width or signedness.
+                    These warnings are only activated with
+                    -Wtraditional-conversion, not with -Wtraditional.  */
+                 else if (warn_traditional_conversion && INTEGRAL_TYPE_P (type)
+                          && INTEGRAL_TYPE_P (valtype))
+                   {
+                     tree would_have_been = default_conversion (val);
+                     tree type1 = TREE_TYPE (would_have_been);
+
+                     if (TREE_CODE (type) == ENUMERAL_TYPE
+                         && (TYPE_MAIN_VARIANT (type)
+                             == TYPE_MAIN_VARIANT (valtype)))
+                       /* No warning if function asks for enum
+                          and the actual arg is that enum type.  */
+                       ;
+                     else if (formal_prec != TYPE_PRECISION (type1))
+                       warning (OPT_Wtraditional_conversion,
+                                "passing argument %d of %qE "
+                                "with different width due to prototype",
+                                argnum, rname);
+                     else if (TYPE_UNSIGNED (type) == TYPE_UNSIGNED (type1))
+                       ;
+                     /* Don't complain if the formal parameter type
+                        is an enum, because we can't tell now whether
+                        the value was an enum--even the same enum.  */
+                     else if (TREE_CODE (type) == ENUMERAL_TYPE)
+                       ;
+                     else if (TREE_CODE (val) == INTEGER_CST
+                              && int_fits_type_p (val, type))
+                       /* Change in signedness doesn't matter
+                          if a constant value is unaffected.  */
+                       ;
+                     /* If the value is extended from a narrower
+                        unsigned type, it doesn't matter whether we
+                        pass it as signed or unsigned; the value
+                        certainly is the same either way.  */
+                     else if (TYPE_PRECISION (valtype) < TYPE_PRECISION (type)
+                              && TYPE_UNSIGNED (valtype))
+                       ;
+                     else if (TYPE_UNSIGNED (type))
+                       warning (OPT_Wtraditional_conversion,
+                                "passing argument %d of %qE "
+                                "as unsigned due to prototype",
+                                argnum, rname);
+                     else
+                       warning (OPT_Wtraditional_conversion,
+                                "passing argument %d of %qE "
+                                "as signed due to prototype", argnum, rname);
+                   }
+               }
+
+             /* Possibly restore an EXCESS_PRECISION_EXPR for the
+                sake of better warnings from convert_and_check.  */
+             if (excess_precision)
+               val = build1 (EXCESS_PRECISION_EXPR, valtype, val);
+             origtype = (origtypes == NULL
+                         ? NULL_TREE
+                         : VEC_index (tree, origtypes, parmnum));
+             parmval = convert_for_assignment (input_location, type, val,
+                                               origtype, ic_argpass, npc,
+                                               fundecl, function,
+                                               parmnum + 1);
+
+             if (targetm.calls.promote_prototypes (fundecl ? TREE_TYPE (fundecl) : 0)
+                 && INTEGRAL_TYPE_P (type)
+                 && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
+               parmval = default_conversion (parmval);
+           }
+       }
+      else if (TREE_CODE (valtype) == REAL_TYPE
+              && (TYPE_PRECISION (valtype)
+                  < TYPE_PRECISION (double_type_node))
+              && !DECIMAL_FLOAT_MODE_P (TYPE_MODE (valtype)))
+        {
+         if (type_generic)
+           parmval = val;
+         else
+           {
+             /* Convert `float' to `double'.  */
+             if (warn_double_promotion && !c_inhibit_evaluation_warnings)
+               warning (OPT_Wdouble_promotion,
+                        "implicit conversion from %qT to %qT when passing "
+                        "argument to function",
+                        valtype, double_type_node);
+             parmval = convert (double_type_node, val);
+           }
+       }
+      else if (excess_precision && !type_generic)
+       /* A "double" argument with excess precision being passed
+          without a prototype or in variable arguments.  */
+       parmval = convert (valtype, val);
+      else if ((invalid_func_diag =
+               targetm.calls.invalid_arg_for_unprototyped_fn (typelist, fundecl, val)))
+       {
+         error (invalid_func_diag);
+         return -1;
+       }
+      else
+       /* Convert `short' and `char' to full-size `int'.  */
+       parmval = default_conversion (val);
+
+      VEC_replace (tree, values, parmnum, parmval);
+      if (parmval == error_mark_node)
+       error_args = true;
+
+      if (typetail)
+       typetail = TREE_CHAIN (typetail);
+    }
+
+  gcc_assert (parmnum == VEC_length (tree, values));
+
+  if (typetail != 0 && TREE_VALUE (typetail) != void_type_node)
+    {
+      error_at (input_location,
+               "too few arguments to function %qE", function);
+      inform_declaration (fundecl);
+      return -1;
+    }
+
+  return error_args ? -1 : (int) parmnum;
+}
+\f
+/* This is the entry point used by the parser to build unary operators
+   in the input.  CODE, a tree_code, specifies the unary operator, and
+   ARG is the operand.  For unary plus, the C parser currently uses
+   CONVERT_EXPR for code.
+
+   LOC is the location to use for the tree generated.
+*/
+
+struct c_expr
+parser_build_unary_op (location_t loc, enum tree_code code, struct c_expr arg)
+{
+  struct c_expr result;
+
+  result.value = build_unary_op (loc, code, arg.value, 0);
+  result.original_code = code;
+  result.original_type = NULL;
+
+  if (TREE_OVERFLOW_P (result.value) && !TREE_OVERFLOW_P (arg.value))
+    overflow_warning (loc, result.value);
+
+  return result;
+}
+
+/* This is the entry point used by the parser to build binary operators
+   in the input.  CODE, a tree_code, specifies the binary operator, and
+   ARG1 and ARG2 are the operands.  In addition to constructing the
+   expression, we check for operands that were written with other binary
+   operators in a way that is likely to confuse the user.
+
+   LOCATION is the location of the binary operator.  */
+
+struct c_expr
+parser_build_binary_op (location_t location, enum tree_code code,
+                       struct c_expr arg1, struct c_expr arg2)
+{
+  struct c_expr result;
+
+  enum tree_code code1 = arg1.original_code;
+  enum tree_code code2 = arg2.original_code;
+  tree type1 = (arg1.original_type
+                ? arg1.original_type
+                : TREE_TYPE (arg1.value));
+  tree type2 = (arg2.original_type
+                ? arg2.original_type
+                : TREE_TYPE (arg2.value));
+
+  result.value = build_binary_op (location, code,
+                                 arg1.value, arg2.value, 1);
+  result.original_code = code;
+  result.original_type = NULL;
+
+  if (TREE_CODE (result.value) == ERROR_MARK)
+    return result;
+
+  if (location != UNKNOWN_LOCATION)
+    protected_set_expr_location (result.value, location);
+
+  /* Check for cases such as x+y<<z which users are likely
+     to misinterpret.  */
+  if (warn_parentheses)
+    warn_about_parentheses (code, code1, arg1.value, code2, arg2.value);
+
+  if (warn_logical_op)
+    warn_logical_operator (input_location, code, TREE_TYPE (result.value),
+                          code1, arg1.value, code2, arg2.value);
+
+  /* Warn about comparisons against string literals, with the exception
+     of testing for equality or inequality of a string literal with NULL.  */
+  if (code == EQ_EXPR || code == NE_EXPR)
+    {
+      if ((code1 == STRING_CST && !integer_zerop (arg2.value))
+         || (code2 == STRING_CST && !integer_zerop (arg1.value)))
+       warning_at (location, OPT_Waddress,
+                   "comparison with string literal results in unspecified behavior");
+    }
+  else if (TREE_CODE_CLASS (code) == tcc_comparison
+          && (code1 == STRING_CST || code2 == STRING_CST))
+    warning_at (location, OPT_Waddress,
+               "comparison with string literal results in unspecified behavior");
+
+  if (TREE_OVERFLOW_P (result.value)
+      && !TREE_OVERFLOW_P (arg1.value)
+      && !TREE_OVERFLOW_P (arg2.value))
+    overflow_warning (location, result.value);
+
+  /* Warn about comparisons of different enum types.  */
+  if (warn_enum_compare
+      && TREE_CODE_CLASS (code) == tcc_comparison
+      && TREE_CODE (type1) == ENUMERAL_TYPE
+      && TREE_CODE (type2) == ENUMERAL_TYPE
+      && TYPE_MAIN_VARIANT (type1) != TYPE_MAIN_VARIANT (type2))
+    warning_at (location, OPT_Wenum_compare,
+               "comparison between %qT and %qT",
+               type1, type2);
+
+  return result;
+}
+\f
+/* Return a tree for the difference of pointers OP0 and OP1.
+   The resulting tree has type int.  */
+
+static tree
+pointer_diff (location_t loc, tree op0, tree op1)
+{
+  tree restype = ptrdiff_type_node;
+  tree result, inttype;
+
+  addr_space_t as0 = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (op0)));
+  addr_space_t as1 = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (op1)));
+  tree target_type = TREE_TYPE (TREE_TYPE (op0));
+  tree con0, con1, lit0, lit1;
+  tree orig_op1 = op1;
+
+  /* If the operands point into different address spaces, we need to
+     explicitly convert them to pointers into the common address space
+     before we can subtract the numerical address values.  */
+  if (as0 != as1)
+    {
+      addr_space_t as_common;
+      tree common_type;
+
+      /* Determine the common superset address space.  This is guaranteed
+        to exist because the caller verified that comp_target_types
+        returned non-zero.  */
+      if (!addr_space_superset (as0, as1, &as_common))
+       gcc_unreachable ();
+
+      common_type = common_pointer_type (TREE_TYPE (op0), TREE_TYPE (op1));
+      op0 = convert (common_type, op0);
+      op1 = convert (common_type, op1);
+    }
+
+  /* Determine integer type to perform computations in.  This will usually
+     be the same as the result type (ptrdiff_t), but may need to be a wider
+     type if pointers for the address space are wider than ptrdiff_t.  */
+  if (TYPE_PRECISION (restype) < TYPE_PRECISION (TREE_TYPE (op0)))
+    inttype = c_common_type_for_size (TYPE_PRECISION (TREE_TYPE (op0)), 0);
+  else
+    inttype = restype;
+
+
+  if (TREE_CODE (target_type) == VOID_TYPE)
+    pedwarn (loc, pedantic ? OPT_Wpedantic : OPT_Wpointer_arith,
+            "pointer of type %<void *%> used in subtraction");
+  if (TREE_CODE (target_type) == FUNCTION_TYPE)
+    pedwarn (loc, pedantic ? OPT_Wpedantic : OPT_Wpointer_arith,
+            "pointer to a function used in subtraction");
+
+  /* If the conversion to ptrdiff_type does anything like widening or
+     converting a partial to an integral mode, we get a convert_expression
+     that is in the way to do any simplifications.
+     (fold-const.c doesn't know that the extra bits won't be needed.
+     split_tree uses STRIP_SIGN_NOPS, which leaves conversions to a
+     different mode in place.)
+     So first try to find a common term here 'by hand'; we want to cover
+     at least the cases that occur in legal static initializers.  */
+  if (CONVERT_EXPR_P (op0)
+      && (TYPE_PRECISION (TREE_TYPE (op0))
+         == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (op0, 0)))))
+    con0 = TREE_OPERAND (op0, 0);
+  else
+    con0 = op0;
+  if (CONVERT_EXPR_P (op1)
+      && (TYPE_PRECISION (TREE_TYPE (op1))
+         == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (op1, 0)))))
+    con1 = TREE_OPERAND (op1, 0);
+  else
+    con1 = op1;
+
+  if (TREE_CODE (con0) == POINTER_PLUS_EXPR)
+    {
+      lit0 = TREE_OPERAND (con0, 1);
+      con0 = TREE_OPERAND (con0, 0);
+    }
+  else
+    lit0 = integer_zero_node;
+
+  if (TREE_CODE (con1) == POINTER_PLUS_EXPR)
+    {
+      lit1 = TREE_OPERAND (con1, 1);
+      con1 = TREE_OPERAND (con1, 0);
+    }
+  else
+    lit1 = integer_zero_node;
+
+  if (operand_equal_p (con0, con1, 0))
+    {
+      op0 = lit0;
+      op1 = lit1;
+    }
+
+
+  /* First do the subtraction as integers;
+     then drop through to build the divide operator.
+     Do not do default conversions on the minus operator
+     in case restype is a short type.  */
+
+  op0 = build_binary_op (loc,
+                        MINUS_EXPR, convert (inttype, op0),
+                        convert (inttype, op1), 0);
+  /* This generates an error if op1 is pointer to incomplete type.  */
+  if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (TREE_TYPE (orig_op1))))
+    error_at (loc, "arithmetic on pointer to an incomplete type");
+
+  /* This generates an error if op0 is pointer to incomplete type.  */
+  op1 = c_size_in_bytes (target_type);
+
+  /* Divide by the size, in easiest possible way.  */
+  result = fold_build2_loc (loc, EXACT_DIV_EXPR, inttype,
+                           op0, convert (inttype, op1));
+
+  /* Convert to final result type if necessary.  */
+  return convert (restype, result);
+}
+\f
+/* Construct and perhaps optimize a tree representation
+   for a unary operation.  CODE, a tree_code, specifies the operation
+   and XARG is the operand.
+   For any CODE other than ADDR_EXPR, FLAG nonzero suppresses
+   the default promotions (such as from short to int).
+   For ADDR_EXPR, the default promotions are not applied; FLAG nonzero
+   allows non-lvalues; this is only used to handle conversion of non-lvalue
+   arrays to pointers in C99.
+
+   LOCATION is the location of the operator.  */
+
+tree
+build_unary_op (location_t location,
+               enum tree_code code, tree xarg, int flag)
+{
+  /* No default_conversion here.  It causes trouble for ADDR_EXPR.  */
+  tree arg = xarg;
+  tree argtype = 0;
+  enum tree_code typecode;
+  tree val;
+  tree ret = error_mark_node;
+  tree eptype = NULL_TREE;
+  int noconvert = flag;
+  const char *invalid_op_diag;
+  bool int_operands;
+
+  int_operands = EXPR_INT_CONST_OPERANDS (xarg);
+  if (int_operands)
+    arg = remove_c_maybe_const_expr (arg);
+
+  if (code != ADDR_EXPR)
+    arg = require_complete_type (arg);
+
+  typecode = TREE_CODE (TREE_TYPE (arg));
+  if (typecode == ERROR_MARK)
+    return error_mark_node;
+  if (typecode == ENUMERAL_TYPE || typecode == BOOLEAN_TYPE)
+    typecode = INTEGER_TYPE;
+
+  if ((invalid_op_diag
+       = targetm.invalid_unary_op (code, TREE_TYPE (xarg))))
+    {
+      error_at (location, invalid_op_diag);
+      return error_mark_node;
+    }
+
+  if (TREE_CODE (arg) == EXCESS_PRECISION_EXPR)
+    {
+      eptype = TREE_TYPE (arg);
+      arg = TREE_OPERAND (arg, 0);
+    }
+
+  switch (code)
+    {
+    case CONVERT_EXPR:
+      /* This is used for unary plus, because a CONVERT_EXPR
+        is enough to prevent anybody from looking inside for
+        associativity, but won't generate any code.  */
+      if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE
+           || typecode == FIXED_POINT_TYPE || typecode == COMPLEX_TYPE
+           || typecode == VECTOR_TYPE))
+       {
+         error_at (location, "wrong type argument to unary plus");
+         return error_mark_node;
+       }
+      else if (!noconvert)
+       arg = default_conversion (arg);
+      arg = non_lvalue_loc (location, arg);
+      break;
+
+    case NEGATE_EXPR:
+      if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE
+           || typecode == FIXED_POINT_TYPE || typecode == COMPLEX_TYPE
+           || typecode == VECTOR_TYPE))
+       {
+         error_at (location, "wrong type argument to unary minus");
+         return error_mark_node;
+       }
+      else if (!noconvert)
+       arg = default_conversion (arg);
+      break;
+
+    case BIT_NOT_EXPR:
+      /* ~ works on integer types and non float vectors. */
+      if (typecode == INTEGER_TYPE
+         || (typecode == VECTOR_TYPE
+             && !VECTOR_FLOAT_TYPE_P (TREE_TYPE (arg))))
+       {
+         if (!noconvert)
+           arg = default_conversion (arg);
+       }
+      else if (typecode == COMPLEX_TYPE)
+       {
+         code = CONJ_EXPR;
+         pedwarn (location, OPT_Wpedantic,
+                  "ISO C does not support %<~%> for complex conjugation");
+         if (!noconvert)
+           arg = default_conversion (arg);
+       }
+      else
+       {
+         error_at (location, "wrong type argument to bit-complement");
+         return error_mark_node;
+       }
+      break;
+
+    case ABS_EXPR:
+      if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE))
+       {
+         error_at (location, "wrong type argument to abs");
+         return error_mark_node;
+       }
+      else if (!noconvert)
+       arg = default_conversion (arg);
+      break;
+
+    case CONJ_EXPR:
+      /* Conjugating a real value is a no-op, but allow it anyway.  */
+      if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE
+           || typecode == COMPLEX_TYPE))
+       {
+         error_at (location, "wrong type argument to conjugation");
+         return error_mark_node;
+       }
+      else if (!noconvert)
+       arg = default_conversion (arg);
+      break;
+
+    case TRUTH_NOT_EXPR:
+      if (typecode != INTEGER_TYPE && typecode != FIXED_POINT_TYPE
+         && typecode != REAL_TYPE && typecode != POINTER_TYPE
+         && typecode != COMPLEX_TYPE)
+       {
+         error_at (location,
+                   "wrong type argument to unary exclamation mark");
+         return error_mark_node;
+       }
+      arg = c_objc_common_truthvalue_conversion (location, arg);
+      ret = invert_truthvalue_loc (location, arg);
+      /* If the TRUTH_NOT_EXPR has been folded, reset the location.  */
+      if (EXPR_P (ret) && EXPR_HAS_LOCATION (ret))
+       location = EXPR_LOCATION (ret);
+      goto return_build_unary_op;
+
+    case REALPART_EXPR:
+    case IMAGPART_EXPR:
+      ret = build_real_imag_expr (location, code, arg);
+      if (ret == error_mark_node)
+       return error_mark_node;
+      if (eptype && TREE_CODE (eptype) == COMPLEX_TYPE)
+       eptype = TREE_TYPE (eptype);
+      goto return_build_unary_op;
+
+    case PREINCREMENT_EXPR:
+    case POSTINCREMENT_EXPR:
+    case PREDECREMENT_EXPR:
+    case POSTDECREMENT_EXPR:
+
+      if (TREE_CODE (arg) == C_MAYBE_CONST_EXPR)
+       {
+         tree inner = build_unary_op (location, code,
+                                      C_MAYBE_CONST_EXPR_EXPR (arg), flag);
+         if (inner == error_mark_node)
+           return error_mark_node;
+         ret = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (inner),
+                       C_MAYBE_CONST_EXPR_PRE (arg), inner);
+         gcc_assert (!C_MAYBE_CONST_EXPR_INT_OPERANDS (arg));
+         C_MAYBE_CONST_EXPR_NON_CONST (ret) = 1;
+         goto return_build_unary_op;
+       }
+
+      /* Complain about anything that is not a true lvalue.  In
+        Objective-C, skip this check for property_refs.  */
+      if (!objc_is_property_ref (arg)
+         && !lvalue_or_else (location,
+                             arg, ((code == PREINCREMENT_EXPR
+                                    || code == POSTINCREMENT_EXPR)
+                                   ? lv_increment
+                                   : lv_decrement)))
+       return error_mark_node;
+
+      if (warn_cxx_compat && TREE_CODE (TREE_TYPE (arg)) == ENUMERAL_TYPE)
+       {
+         if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR)
+           warning_at (location, OPT_Wc___compat,
+                       "increment of enumeration value is invalid in C++");
+         else
+           warning_at (location, OPT_Wc___compat,
+                       "decrement of enumeration value is invalid in C++");
+       }
+
+      /* Ensure the argument is fully folded inside any SAVE_EXPR.  */
+      arg = c_fully_fold (arg, false, NULL);
+
+      /* Increment or decrement the real part of the value,
+        and don't change the imaginary part.  */
+      if (typecode == COMPLEX_TYPE)
+       {
+         tree real, imag;
+
+         pedwarn (location, OPT_Wpedantic,
+                  "ISO C does not support %<++%> and %<--%> on complex types");
+
+         arg = stabilize_reference (arg);
+         real = build_unary_op (EXPR_LOCATION (arg), REALPART_EXPR, arg, 1);
+         imag = build_unary_op (EXPR_LOCATION (arg), IMAGPART_EXPR, arg, 1);
+         real = build_unary_op (EXPR_LOCATION (arg), code, real, 1);
+         if (real == error_mark_node || imag == error_mark_node)
+           return error_mark_node;
+         ret = build2 (COMPLEX_EXPR, TREE_TYPE (arg),
+                       real, imag);
+         goto return_build_unary_op;
+       }
+
+      /* Report invalid types.  */
+
+      if (typecode != POINTER_TYPE && typecode != FIXED_POINT_TYPE
+         && typecode != INTEGER_TYPE && typecode != REAL_TYPE)
+       {
+         if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR)
+           error_at (location, "wrong type argument to increment");
+         else
+           error_at (location, "wrong type argument to decrement");
+
+         return error_mark_node;
+       }
+
+      {
+       tree inc;
+
+       argtype = TREE_TYPE (arg);
+
+       /* Compute the increment.  */
+
+       if (typecode == POINTER_TYPE)
+         {
+           /* If pointer target is an undefined struct,
+              we just cannot know how to do the arithmetic.  */
+           if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (argtype)))
+             {
+               if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR)
+                 error_at (location,
+                           "increment of pointer to unknown structure");
+               else
+                 error_at (location,
+                           "decrement of pointer to unknown structure");
+             }
+           else if (TREE_CODE (TREE_TYPE (argtype)) == FUNCTION_TYPE
+                    || TREE_CODE (TREE_TYPE (argtype)) == VOID_TYPE)
+             {
+               if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR)
+                 pedwarn (location, pedantic ? OPT_Wpedantic : OPT_Wpointer_arith,
+                          "wrong type argument to increment");
+               else
+                 pedwarn (location, pedantic ? OPT_Wpedantic : OPT_Wpointer_arith,
+                          "wrong type argument to decrement");
+             }
+
+           inc = c_size_in_bytes (TREE_TYPE (argtype));
+           inc = convert_to_ptrofftype_loc (location, inc);
+         }
+       else if (FRACT_MODE_P (TYPE_MODE (argtype)))
+         {
+           /* For signed fract types, we invert ++ to -- or
+              -- to ++, and change inc from 1 to -1, because
+              it is not possible to represent 1 in signed fract constants.
+              For unsigned fract types, the result always overflows and
+              we get an undefined (original) or the maximum value.  */
+           if (code == PREINCREMENT_EXPR)
+             code = PREDECREMENT_EXPR;
+           else if (code == PREDECREMENT_EXPR)
+             code = PREINCREMENT_EXPR;
+           else if (code == POSTINCREMENT_EXPR)
+             code = POSTDECREMENT_EXPR;
+           else /* code == POSTDECREMENT_EXPR  */
+             code = POSTINCREMENT_EXPR;
+
+           inc = integer_minus_one_node;
+           inc = convert (argtype, inc);
+         }
+       else
+         {
+           inc = integer_one_node;
+           inc = convert (argtype, inc);
+         }
+
+       /* If 'arg' is an Objective-C PROPERTY_REF expression, then we
+          need to ask Objective-C to build the increment or decrement
+          expression for it.  */
+       if (objc_is_property_ref (arg))
+         return objc_build_incr_expr_for_property_ref (location, code,
+                                                       arg, inc);
+
+       /* Report a read-only lvalue.  */
+       if (TYPE_READONLY (argtype))
+         {
+           readonly_error (arg,
+                           ((code == PREINCREMENT_EXPR
+                             || code == POSTINCREMENT_EXPR)
+                            ? lv_increment : lv_decrement));
+           return error_mark_node;
+         }
+       else if (TREE_READONLY (arg))
+         readonly_warning (arg,
+                           ((code == PREINCREMENT_EXPR
+                             || code == POSTINCREMENT_EXPR)
+                            ? lv_increment : lv_decrement));
+
+       if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE)
+         val = boolean_increment (code, arg);
+       else
+         val = build2 (code, TREE_TYPE (arg), arg, inc);
+       TREE_SIDE_EFFECTS (val) = 1;
+       if (TREE_CODE (val) != code)
+         TREE_NO_WARNING (val) = 1;
+       ret = val;
+       goto return_build_unary_op;
+      }
+
+    case ADDR_EXPR:
+      /* Note that this operation never does default_conversion.  */
+
+      /* The operand of unary '&' must be an lvalue (which excludes
+        expressions of type void), or, in C99, the result of a [] or
+        unary '*' operator.  */
+      if (VOID_TYPE_P (TREE_TYPE (arg))
+         && TYPE_QUALS (TREE_TYPE (arg)) == TYPE_UNQUALIFIED
+         && (TREE_CODE (arg) != INDIRECT_REF
+             || !flag_isoc99))
+       pedwarn (location, 0, "taking address of expression of type %<void%>");
+
+      /* Let &* cancel out to simplify resulting code.  */
+      if (TREE_CODE (arg) == INDIRECT_REF)
+       {
+         /* Don't let this be an lvalue.  */
+         if (lvalue_p (TREE_OPERAND (arg, 0)))
+           return non_lvalue_loc (location, TREE_OPERAND (arg, 0));
+         ret = TREE_OPERAND (arg, 0);
+         goto return_build_unary_op;
+       }
+
+      /* For &x[y], return x+y */
+      if (TREE_CODE (arg) == ARRAY_REF)
+       {
+         tree op0 = TREE_OPERAND (arg, 0);
+         if (!c_mark_addressable (op0))
+           return error_mark_node;
+       }
+
+      /* Anything not already handled and not a true memory reference
+        or a non-lvalue array is an error.  */
+      else if (typecode != FUNCTION_TYPE && !flag
+              && !lvalue_or_else (location, arg, lv_addressof))
+       return error_mark_node;
+
+      /* Move address operations inside C_MAYBE_CONST_EXPR to simplify
+        folding later.  */
+      if (TREE_CODE (arg) == C_MAYBE_CONST_EXPR)
+       {
+         tree inner = build_unary_op (location, code,
+                                      C_MAYBE_CONST_EXPR_EXPR (arg), flag);
+         ret = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (inner),
+                       C_MAYBE_CONST_EXPR_PRE (arg), inner);
+         gcc_assert (!C_MAYBE_CONST_EXPR_INT_OPERANDS (arg));
+         C_MAYBE_CONST_EXPR_NON_CONST (ret)
+           = C_MAYBE_CONST_EXPR_NON_CONST (arg);
+         goto return_build_unary_op;
+       }
+
+      /* Ordinary case; arg is a COMPONENT_REF or a decl.  */
+      argtype = TREE_TYPE (arg);
+
+      /* If the lvalue is const or volatile, merge that into the type
+        to which the address will point.  This is only needed
+        for function types.  */
+      if ((DECL_P (arg) || REFERENCE_CLASS_P (arg))
+         && (TREE_READONLY (arg) || TREE_THIS_VOLATILE (arg))
+         && TREE_CODE (argtype) == FUNCTION_TYPE)
+       {
+         int orig_quals = TYPE_QUALS (strip_array_types (argtype));
+         int quals = orig_quals;
+
+         if (TREE_READONLY (arg))
+           quals |= TYPE_QUAL_CONST;
+         if (TREE_THIS_VOLATILE (arg))
+           quals |= TYPE_QUAL_VOLATILE;
+
+         argtype = c_build_qualified_type (argtype, quals);
+       }
+
+      if (!c_mark_addressable (arg))
+       return error_mark_node;
+
+      gcc_assert (TREE_CODE (arg) != COMPONENT_REF
+                 || !DECL_C_BIT_FIELD (TREE_OPERAND (arg, 1)));
+
+      argtype = build_pointer_type (argtype);
+
+      /* ??? Cope with user tricks that amount to offsetof.  Delete this
+        when we have proper support for integer constant expressions.  */
+      val = get_base_address (arg);
+      if (val && TREE_CODE (val) == INDIRECT_REF
+          && TREE_CONSTANT (TREE_OPERAND (val, 0)))
+       {
+         ret = fold_convert_loc (location, argtype, fold_offsetof_1 (arg));
+         goto return_build_unary_op;
+       }
+
+      val = build1 (ADDR_EXPR, argtype, arg);
+
+      ret = val;
+      goto return_build_unary_op;
+
+    default:
+      gcc_unreachable ();
+    }
+
+  if (argtype == 0)
+    argtype = TREE_TYPE (arg);
+  if (TREE_CODE (arg) == INTEGER_CST)
+    ret = (require_constant_value
+          ? fold_build1_initializer_loc (location, code, argtype, arg)
+          : fold_build1_loc (location, code, argtype, arg));
+  else
+    ret = build1 (code, argtype, arg);
+ return_build_unary_op:
+  gcc_assert (ret != error_mark_node);
+  if (TREE_CODE (ret) == INTEGER_CST && !TREE_OVERFLOW (ret)
+      && !(TREE_CODE (xarg) == INTEGER_CST && !TREE_OVERFLOW (xarg)))
+    ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret);
+  else if (TREE_CODE (ret) != INTEGER_CST && int_operands)
+    ret = note_integer_operands (ret);
+  if (eptype)
+    ret = build1 (EXCESS_PRECISION_EXPR, eptype, ret);
+  protected_set_expr_location (ret, location);
+  return ret;
+}
+
+/* Return nonzero if REF is an lvalue valid for this language.
+   Lvalues can be assigned, unless their type has TYPE_READONLY.
+   Lvalues can have their address taken, unless they have C_DECL_REGISTER.  */
+
+bool
+lvalue_p (const_tree ref)
+{
+  const enum tree_code code = TREE_CODE (ref);
+
+  switch (code)
+    {
+    case REALPART_EXPR:
+    case IMAGPART_EXPR:
+    case COMPONENT_REF:
+      return lvalue_p (TREE_OPERAND (ref, 0));
+
+    case C_MAYBE_CONST_EXPR:
+      return lvalue_p (TREE_OPERAND (ref, 1));
+
+    case COMPOUND_LITERAL_EXPR:
+    case STRING_CST:
+      return 1;
+
+    case INDIRECT_REF:
+    case ARRAY_REF:
+    case VAR_DECL:
+    case PARM_DECL:
+    case RESULT_DECL:
+    case ERROR_MARK:
+      return (TREE_CODE (TREE_TYPE (ref)) != FUNCTION_TYPE
+             && TREE_CODE (TREE_TYPE (ref)) != METHOD_TYPE);
+
+    case BIND_EXPR:
+      return TREE_CODE (TREE_TYPE (ref)) == ARRAY_TYPE;
+
+    default:
+      return 0;
+    }
+}
+\f
+/* Give a warning for storing in something that is read-only in GCC
+   terms but not const in ISO C terms.  */
+
+static void
+readonly_warning (tree arg, enum lvalue_use use)
+{
+  switch (use)
+    {
+    case lv_assign:
+      warning (0, "assignment of read-only location %qE", arg);
+      break;
+    case lv_increment:
+      warning (0, "increment of read-only location %qE", arg);
+      break;
+    case lv_decrement:
+      warning (0, "decrement of read-only location %qE", arg);
+      break;
+    default:
+      gcc_unreachable ();
+    }
+  return;
+}
+
+
+/* Return nonzero if REF is an lvalue valid for this language;
+   otherwise, print an error message and return zero.  USE says
+   how the lvalue is being used and so selects the error message.
+   LOCATION is the location at which any error should be reported.  */
+
+static int
+lvalue_or_else (location_t loc, const_tree ref, enum lvalue_use use)
+{
+  int win = lvalue_p (ref);
+
+  if (!win)
+    lvalue_error (loc, use);
+
+  return win;
+}
+\f
+/* Mark EXP saying that we need to be able to take the
+   address of it; it should not be allocated in a register.
+   Returns true if successful.  */
+
+bool
+c_mark_addressable (tree exp)
+{
+  tree x = exp;
+
+  while (1)
+    switch (TREE_CODE (x))
+      {
+      case COMPONENT_REF:
+       if (DECL_C_BIT_FIELD (TREE_OPERAND (x, 1)))
+         {
+           error
+             ("cannot take address of bit-field %qD", TREE_OPERAND (x, 1));
+           return false;
+         }
+
+       /* ... fall through ...  */
+
+      case ADDR_EXPR:
+      case ARRAY_REF:
+      case REALPART_EXPR:
+      case IMAGPART_EXPR:
+       x = TREE_OPERAND (x, 0);
+       break;
+
+      case COMPOUND_LITERAL_EXPR:
+      case CONSTRUCTOR:
+       TREE_ADDRESSABLE (x) = 1;
+       return true;
+
+      case VAR_DECL:
+      case CONST_DECL:
+      case PARM_DECL:
+      case RESULT_DECL:
+       if (C_DECL_REGISTER (x)
+           && DECL_NONLOCAL (x))
+         {
+           if (TREE_PUBLIC (x) || TREE_STATIC (x) || DECL_EXTERNAL (x))
+             {
+               error
+                 ("global register variable %qD used in nested function", x);
+               return false;
+             }
+           pedwarn (input_location, 0, "register variable %qD used in nested function", x);
+         }
+       else if (C_DECL_REGISTER (x))
+         {
+           if (TREE_PUBLIC (x) || TREE_STATIC (x) || DECL_EXTERNAL (x))
+             error ("address of global register variable %qD requested", x);
+           else
+             error ("address of register variable %qD requested", x);
+           return false;
+         }
+
+       /* drops in */
+      case FUNCTION_DECL:
+       TREE_ADDRESSABLE (x) = 1;
+       /* drops out */
+      default:
+       return true;
+    }
+}
+\f
+/* Convert EXPR to TYPE, warning about conversion problems with
+   constants.  SEMANTIC_TYPE is the type this conversion would use
+   without excess precision. If SEMANTIC_TYPE is NULL, this function
+   is equivalent to convert_and_check. This function is a wrapper that
+   handles conversions that may be different than
+   the usual ones because of excess precision.  */
+
+static tree
+ep_convert_and_check (tree type, tree expr, tree semantic_type)
+{
+  if (TREE_TYPE (expr) == type)
+    return expr;
+
+  if (!semantic_type)
+    return convert_and_check (type, expr);
+
+  if (TREE_CODE (TREE_TYPE (expr)) == INTEGER_TYPE
+      && TREE_TYPE (expr) != semantic_type)
+    {
+      /* For integers, we need to check the real conversion, not
+        the conversion to the excess precision type.  */
+      expr = convert_and_check (semantic_type, expr);
+    }
+  /* Result type is the excess precision type, which should be
+     large enough, so do not check.  */
+  return convert (type, expr);
+}
+
+/* Build and return a conditional expression IFEXP ? OP1 : OP2.  If
+   IFEXP_BCP then the condition is a call to __builtin_constant_p, and
+   if folded to an integer constant then the unselected half may
+   contain arbitrary operations not normally permitted in constant
+   expressions.  Set the location of the expression to LOC.  */
+
+tree
+build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
+                       tree op1, tree op1_original_type, tree op2,
+                       tree op2_original_type)
+{
+  tree type1;
+  tree type2;
+  enum tree_code code1;
+  enum tree_code code2;
+  tree result_type = NULL;
+  tree semantic_result_type = NULL;
+  tree orig_op1 = op1, orig_op2 = op2;
+  bool int_const, op1_int_operands, op2_int_operands, int_operands;
+  bool ifexp_int_operands;
+  tree ret;
+
+  op1_int_operands = EXPR_INT_CONST_OPERANDS (orig_op1);
+  if (op1_int_operands)
+    op1 = remove_c_maybe_const_expr (op1);
+  op2_int_operands = EXPR_INT_CONST_OPERANDS (orig_op2);
+  if (op2_int_operands)
+    op2 = remove_c_maybe_const_expr (op2);
+  ifexp_int_operands = EXPR_INT_CONST_OPERANDS (ifexp);
+  if (ifexp_int_operands)
+    ifexp = remove_c_maybe_const_expr (ifexp);
+
+  /* Promote both alternatives.  */
+
+  if (TREE_CODE (TREE_TYPE (op1)) != VOID_TYPE)
+    op1 = default_conversion (op1);
+  if (TREE_CODE (TREE_TYPE (op2)) != VOID_TYPE)
+    op2 = default_conversion (op2);
+
+  if (TREE_CODE (ifexp) == ERROR_MARK
+      || TREE_CODE (TREE_TYPE (op1)) == ERROR_MARK
+      || TREE_CODE (TREE_TYPE (op2)) == ERROR_MARK)
+    return error_mark_node;
+
+  type1 = TREE_TYPE (op1);
+  code1 = TREE_CODE (type1);
+  type2 = TREE_TYPE (op2);
+  code2 = TREE_CODE (type2);
+
+  /* C90 does not permit non-lvalue arrays in conditional expressions.
+     In C99 they will be pointers by now.  */
+  if (code1 == ARRAY_TYPE || code2 == ARRAY_TYPE)
+    {
+      error_at (colon_loc, "non-lvalue array in conditional expression");
+      return error_mark_node;
+    }
+
+  if ((TREE_CODE (op1) == EXCESS_PRECISION_EXPR
+       || TREE_CODE (op2) == EXCESS_PRECISION_EXPR)
+      && (code1 == INTEGER_TYPE || code1 == REAL_TYPE
+         || code1 == COMPLEX_TYPE)
+      && (code2 == INTEGER_TYPE || code2 == REAL_TYPE
+         || code2 == COMPLEX_TYPE))
+    {
+      semantic_result_type = c_common_type (type1, type2);
+      if (TREE_CODE (op1) == EXCESS_PRECISION_EXPR)
+       {
+         op1 = TREE_OPERAND (op1, 0);
+         type1 = TREE_TYPE (op1);
+         gcc_assert (TREE_CODE (type1) == code1);
+       }
+      if (TREE_CODE (op2) == EXCESS_PRECISION_EXPR)
+       {
+         op2 = TREE_OPERAND (op2, 0);
+         type2 = TREE_TYPE (op2);
+         gcc_assert (TREE_CODE (type2) == code2);
+       }
+    }
+
+  if (warn_cxx_compat)
+    {
+      tree t1 = op1_original_type ? op1_original_type : TREE_TYPE (orig_op1);
+      tree t2 = op2_original_type ? op2_original_type : TREE_TYPE (orig_op2);
+
+      if (TREE_CODE (t1) == ENUMERAL_TYPE
+         && TREE_CODE (t2) == ENUMERAL_TYPE
+         && TYPE_MAIN_VARIANT (t1) != TYPE_MAIN_VARIANT (t2))
+       warning_at (colon_loc, OPT_Wc___compat,
+                   ("different enum types in conditional is "
+                    "invalid in C++: %qT vs %qT"),
+                   t1, t2);
+    }
+
+  /* Quickly detect the usual case where op1 and op2 have the same type
+     after promotion.  */
+  if (TYPE_MAIN_VARIANT (type1) == TYPE_MAIN_VARIANT (type2))
+    {
+      if (type1 == type2)
+       result_type = type1;
+      else
+       result_type = TYPE_MAIN_VARIANT (type1);
+    }
+  else if ((code1 == INTEGER_TYPE || code1 == REAL_TYPE
+           || code1 == COMPLEX_TYPE)
+          && (code2 == INTEGER_TYPE || code2 == REAL_TYPE
+              || code2 == COMPLEX_TYPE))
+    {
+      result_type = c_common_type (type1, type2);
+      do_warn_double_promotion (result_type, type1, type2,
+                               "implicit conversion from %qT to %qT to "
+                               "match other result of conditional",
+                               colon_loc);
+
+      /* If -Wsign-compare, warn here if type1 and type2 have
+        different signedness.  We'll promote the signed to unsigned
+        and later code won't know it used to be different.
+        Do this check on the original types, so that explicit casts
+        will be considered, but default promotions won't.  */
+      if (c_inhibit_evaluation_warnings == 0)
+       {
+         int unsigned_op1 = TYPE_UNSIGNED (TREE_TYPE (orig_op1));
+         int unsigned_op2 = TYPE_UNSIGNED (TREE_TYPE (orig_op2));
+
+         if (unsigned_op1 ^ unsigned_op2)
+           {
+             bool ovf;
+
+             /* Do not warn if the result type is signed, since the
+                signed type will only be chosen if it can represent
+                all the values of the unsigned type.  */
+             if (!TYPE_UNSIGNED (result_type))
+               /* OK */;
+             else
+               {
+                 bool op1_maybe_const = true;
+                 bool op2_maybe_const = true;
+
+                 /* Do not warn if the signed quantity is an
+                    unsuffixed integer literal (or some static
+                    constant expression involving such literals) and
+                    it is non-negative.  This warning requires the
+                    operands to be folded for best results, so do
+                    that folding in this case even without
+                    warn_sign_compare to avoid warning options
+                    possibly affecting code generation.  */
+                 c_inhibit_evaluation_warnings
+                   += (ifexp == truthvalue_false_node);
+                 op1 = c_fully_fold (op1, require_constant_value,
+                                     &op1_maybe_const);
+                 c_inhibit_evaluation_warnings
+                   -= (ifexp == truthvalue_false_node);
+
+                 c_inhibit_evaluation_warnings
+                   += (ifexp == truthvalue_true_node);
+                 op2 = c_fully_fold (op2, require_constant_value,
+                                     &op2_maybe_const);
+                 c_inhibit_evaluation_warnings
+                   -= (ifexp == truthvalue_true_node);
+
+                 if (warn_sign_compare)
+                   {
+                     if ((unsigned_op2
+                          && tree_expr_nonnegative_warnv_p (op1, &ovf))
+                         || (unsigned_op1
+                             && tree_expr_nonnegative_warnv_p (op2, &ovf)))
+                       /* OK */;
+                     else
+                       warning_at (colon_loc, OPT_Wsign_compare,
+                                   ("signed and unsigned type in "
+                                    "conditional expression"));
+                   }
+                 if (!op1_maybe_const || TREE_CODE (op1) != INTEGER_CST)
+                   op1 = c_wrap_maybe_const (op1, !op1_maybe_const);
+                 if (!op2_maybe_const || TREE_CODE (op2) != INTEGER_CST)
+                   op2 = c_wrap_maybe_const (op2, !op2_maybe_const);
+               }
+           }
+       }
+    }
+  else if (code1 == VOID_TYPE || code2 == VOID_TYPE)
+    {
+      if (code1 != VOID_TYPE || code2 != VOID_TYPE)
+       pedwarn (colon_loc, OPT_Wpedantic,
+                "ISO C forbids conditional expr with only one void side");
+      result_type = void_type_node;
+    }
+  else if (code1 == POINTER_TYPE && code2 == POINTER_TYPE)
+    {
+      addr_space_t as1 = TYPE_ADDR_SPACE (TREE_TYPE (type1));
+      addr_space_t as2 = TYPE_ADDR_SPACE (TREE_TYPE (type2));
+      addr_space_t as_common;
+
+      if (comp_target_types (colon_loc, type1, type2))
+       result_type = common_pointer_type (type1, type2);
+      else if (null_pointer_constant_p (orig_op1))
+       result_type = type2;
+      else if (null_pointer_constant_p (orig_op2))
+       result_type = type1;
+      else if (!addr_space_superset (as1, as2, &as_common))
+       {
+         error_at (colon_loc, "pointers to disjoint address spaces "
+                   "used in conditional expression");
+         return error_mark_node;
+       }
+      else if (VOID_TYPE_P (TREE_TYPE (type1)))
+       {
+         if (TREE_CODE (TREE_TYPE (type2)) == FUNCTION_TYPE)
+           pedwarn (colon_loc, OPT_Wpedantic,
+                    "ISO C forbids conditional expr between "
+                    "%<void *%> and function pointer");
+         result_type = build_pointer_type (qualify_type (TREE_TYPE (type1),
+                                                         TREE_TYPE (type2)));
+       }
+      else if (VOID_TYPE_P (TREE_TYPE (type2)))
+       {
+         if (TREE_CODE (TREE_TYPE (type1)) == FUNCTION_TYPE)
+           pedwarn (colon_loc, OPT_Wpedantic,
+                    "ISO C forbids conditional expr between "
+                    "%<void *%> and function pointer");
+         result_type = build_pointer_type (qualify_type (TREE_TYPE (type2),
+                                                         TREE_TYPE (type1)));
+       }
+      /* Objective-C pointer comparisons are a bit more lenient.  */
+      else if (objc_have_common_type (type1, type2, -3, NULL_TREE))
+       result_type = objc_common_type (type1, type2);
+      else
+       {
+         int qual = ENCODE_QUAL_ADDR_SPACE (as_common);
+
+         pedwarn (colon_loc, 0,
+                  "pointer type mismatch in conditional expression");
+         result_type = build_pointer_type
+                         (build_qualified_type (void_type_node, qual));
+       }
+    }
+  else if (code1 == POINTER_TYPE && code2 == INTEGER_TYPE)
+    {
+      if (!null_pointer_constant_p (orig_op2))
+       pedwarn (colon_loc, 0,
+                "pointer/integer type mismatch in conditional expression");
+      else
+       {
+         op2 = null_pointer_node;
+       }
+      result_type = type1;
+    }
+  else if (code2 == POINTER_TYPE && code1 == INTEGER_TYPE)
+    {
+      if (!null_pointer_constant_p (orig_op1))
+       pedwarn (colon_loc, 0,
+                "pointer/integer type mismatch in conditional expression");
+      else
+       {
+         op1 = null_pointer_node;
+       }
+      result_type = type2;
+    }
+
+  if (!result_type)
+    {
+      if (flag_cond_mismatch)
+       result_type = void_type_node;
+      else
+       {
+         error_at (colon_loc, "type mismatch in conditional expression");
+         return error_mark_node;
+       }
+    }
+
+  /* Merge const and volatile flags of the incoming types.  */
+  result_type
+    = build_type_variant (result_type,
+                         TYPE_READONLY (type1) || TYPE_READONLY (type2),
+                         TYPE_VOLATILE (type1) || TYPE_VOLATILE (type2));
+
+  op1 = ep_convert_and_check (result_type, op1, semantic_result_type);
+  op2 = ep_convert_and_check (result_type, op2, semantic_result_type);
+
+  if (ifexp_bcp && ifexp == truthvalue_true_node)
+    {
+      op2_int_operands = true;
+      op1 = c_fully_fold (op1, require_constant_value, NULL);
+    }
+  if (ifexp_bcp && ifexp == truthvalue_false_node)
+    {
+      op1_int_operands = true;
+      op2 = c_fully_fold (op2, require_constant_value, NULL);
+    }
+  int_const = int_operands = (ifexp_int_operands
+                             && op1_int_operands
+                             && op2_int_operands);
+  if (int_operands)
+    {
+      int_const = ((ifexp == truthvalue_true_node
+                   && TREE_CODE (orig_op1) == INTEGER_CST
+                   && !TREE_OVERFLOW (orig_op1))
+                  || (ifexp == truthvalue_false_node
+                      && TREE_CODE (orig_op2) == INTEGER_CST
+                      && !TREE_OVERFLOW (orig_op2)));
+    }
+  if (int_const || (ifexp_bcp && TREE_CODE (ifexp) == INTEGER_CST))
+    ret = fold_build3_loc (colon_loc, COND_EXPR, result_type, ifexp, op1, op2);
+  else
+    {
+      if (int_operands)
+       {
+         op1 = remove_c_maybe_const_expr (op1);
+         op2 = remove_c_maybe_const_expr (op2);
+       }
+      ret = build3 (COND_EXPR, result_type, ifexp, op1, op2);
+      if (int_operands)
+       ret = note_integer_operands (ret);
+    }
+  if (semantic_result_type)
+    ret = build1 (EXCESS_PRECISION_EXPR, semantic_result_type, ret);
+
+  protected_set_expr_location (ret, colon_loc);
+  return ret;
+}
+\f
+/* Return a compound expression that performs two expressions and
+   returns the value of the second of them.
+
+   LOC is the location of the COMPOUND_EXPR.  */
+
+tree
+build_compound_expr (location_t loc, tree expr1, tree expr2)
+{
+  bool expr1_int_operands, expr2_int_operands;
+  tree eptype = NULL_TREE;
+  tree ret;
+
+  expr1_int_operands = EXPR_INT_CONST_OPERANDS (expr1);
+  if (expr1_int_operands)
+    expr1 = remove_c_maybe_const_expr (expr1);
+  expr2_int_operands = EXPR_INT_CONST_OPERANDS (expr2);
+  if (expr2_int_operands)
+    expr2 = remove_c_maybe_const_expr (expr2);
+
+  if (TREE_CODE (expr1) == EXCESS_PRECISION_EXPR)
+    expr1 = TREE_OPERAND (expr1, 0);
+  if (TREE_CODE (expr2) == EXCESS_PRECISION_EXPR)
+    {
+      eptype = TREE_TYPE (expr2);
+      expr2 = TREE_OPERAND (expr2, 0);
+    }
+
+  if (!TREE_SIDE_EFFECTS (expr1))
+    {
+      /* The left-hand operand of a comma expression is like an expression
+        statement: with -Wunused, we should warn if it doesn't have
+        any side-effects, unless it was explicitly cast to (void).  */
+      if (warn_unused_value)
+       {
+         if (VOID_TYPE_P (TREE_TYPE (expr1))
+             && CONVERT_EXPR_P (expr1))
+           ; /* (void) a, b */
+         else if (VOID_TYPE_P (TREE_TYPE (expr1))
+                  && TREE_CODE (expr1) == COMPOUND_EXPR
+                  && CONVERT_EXPR_P (TREE_OPERAND (expr1, 1)))
+           ; /* (void) a, (void) b, c */
+         else
+           warning_at (loc, OPT_Wunused_value,
+                       "left-hand operand of comma expression has no effect");
+       }
+    }
+
+  /* With -Wunused, we should also warn if the left-hand operand does have
+     side-effects, but computes a value which is not used.  For example, in
+     `foo() + bar(), baz()' the result of the `+' operator is not used,
+     so we should issue a warning.  */
+  else if (warn_unused_value)
+    warn_if_unused_value (expr1, loc);
+
+  if (expr2 == error_mark_node)
+    return error_mark_node;
+
+  ret = build2 (COMPOUND_EXPR, TREE_TYPE (expr2), expr1, expr2);
+
+  if (flag_isoc99
+      && expr1_int_operands
+      && expr2_int_operands)
+    ret = note_integer_operands (ret);
+
+  if (eptype)
+    ret = build1 (EXCESS_PRECISION_EXPR, eptype, ret);
+
+  protected_set_expr_location (ret, loc);
+  return ret;
+}
+
+/* Issue -Wcast-qual warnings when appropriate.  TYPE is the type to
+   which we are casting.  OTYPE is the type of the expression being
+   cast.  Both TYPE and OTYPE are pointer types.  LOC is the location
+   of the cast.  -Wcast-qual appeared on the command line.  Named
+   address space qualifiers are not handled here, because they result
+   in different warnings.  */
+
+static void
+handle_warn_cast_qual (location_t loc, tree type, tree otype)
+{
+  tree in_type = type;
+  tree in_otype = otype;
+  int added = 0;
+  int discarded = 0;
+  bool is_const;
+
+  /* Check that the qualifiers on IN_TYPE are a superset of the
+     qualifiers of IN_OTYPE.  The outermost level of POINTER_TYPE
+     nodes is uninteresting and we stop as soon as we hit a
+     non-POINTER_TYPE node on either type.  */
+  do
+    {
+      in_otype = TREE_TYPE (in_otype);
+      in_type = TREE_TYPE (in_type);
+
+      /* GNU C allows cv-qualified function types.  'const' means the
+        function is very pure, 'volatile' means it can't return.  We
+        need to warn when such qualifiers are added, not when they're
+        taken away.  */
+      if (TREE_CODE (in_otype) == FUNCTION_TYPE
+         && TREE_CODE (in_type) == FUNCTION_TYPE)
+       added |= (TYPE_QUALS_NO_ADDR_SPACE (in_type)
+                 & ~TYPE_QUALS_NO_ADDR_SPACE (in_otype));
+      else
+       discarded |= (TYPE_QUALS_NO_ADDR_SPACE (in_otype)
+                     & ~TYPE_QUALS_NO_ADDR_SPACE (in_type));
+    }
+  while (TREE_CODE (in_type) == POINTER_TYPE
+        && TREE_CODE (in_otype) == POINTER_TYPE);
+
+  if (added)
+    warning_at (loc, OPT_Wcast_qual,
+               "cast adds %q#v qualifier to function type", added);
+
+  if (discarded)
+    /* There are qualifiers present in IN_OTYPE that are not present
+       in IN_TYPE.  */
+    warning_at (loc, OPT_Wcast_qual,
+               "cast discards %q#v qualifier from pointer target type",
+               discarded);
+
+  if (added || discarded)
+    return;
+
+  /* A cast from **T to const **T is unsafe, because it can cause a
+     const value to be changed with no additional warning.  We only
+     issue this warning if T is the same on both sides, and we only
+     issue the warning if there are the same number of pointers on
+     both sides, as otherwise the cast is clearly unsafe anyhow.  A
+     cast is unsafe when a qualifier is added at one level and const
+     is not present at all outer levels.
+
+     To issue this warning, we check at each level whether the cast
+     adds new qualifiers not already seen.  We don't need to special
+     case function types, as they won't have the same
+     TYPE_MAIN_VARIANT.  */
+
+  if (TYPE_MAIN_VARIANT (in_type) != TYPE_MAIN_VARIANT (in_otype))
+    return;
+  if (TREE_CODE (TREE_TYPE (type)) != POINTER_TYPE)
+    return;
+
+  in_type = type;
+  in_otype = otype;
+  is_const = TYPE_READONLY (TREE_TYPE (in_type));
+  do
+    {
+      in_type = TREE_TYPE (in_type);
+      in_otype = TREE_TYPE (in_otype);
+      if ((TYPE_QUALS (in_type) &~ TYPE_QUALS (in_otype)) != 0
+         && !is_const)
+       {
+         warning_at (loc, OPT_Wcast_qual,
+                     "to be safe all intermediate pointers in cast from "
+                      "%qT to %qT must be %<const%> qualified",
+                     otype, type);
+         break;
+       }
+      if (is_const)
+       is_const = TYPE_READONLY (in_type);
+    }
+  while (TREE_CODE (in_type) == POINTER_TYPE);
+}
+
+/* Build an expression representing a cast to type TYPE of expression EXPR.
+   LOC is the location of the cast-- typically the open paren of the cast.  */
+
+tree
+build_c_cast (location_t loc, tree type, tree expr)
+{
+  tree value;
+
+  if (TREE_CODE (expr) == EXCESS_PRECISION_EXPR)
+    expr = TREE_OPERAND (expr, 0);
+
+  value = expr;
+
+  if (type == error_mark_node || expr == error_mark_node)
+    return error_mark_node;
+
+  /* The ObjC front-end uses TYPE_MAIN_VARIANT to tie together types differing
+     only in <protocol> qualifications.  But when constructing cast expressions,
+     the protocols do matter and must be kept around.  */
+  if (objc_is_object_ptr (type) && objc_is_object_ptr (TREE_TYPE (expr)))
+    return build1 (NOP_EXPR, type, expr);
+
+  type = TYPE_MAIN_VARIANT (type);
+
+  if (TREE_CODE (type) == ARRAY_TYPE)
+    {
+      error_at (loc, "cast specifies array type");
+      return error_mark_node;
+    }
+
+  if (TREE_CODE (type) == FUNCTION_TYPE)
+    {
+      error_at (loc, "cast specifies function type");
+      return error_mark_node;
+    }
+
+  if (!VOID_TYPE_P (type))
+    {
+      value = require_complete_type (value);
+      if (value == error_mark_node)
+       return error_mark_node;
+    }
+
+  if (type == TYPE_MAIN_VARIANT (TREE_TYPE (value)))
+    {
+      if (TREE_CODE (type) == RECORD_TYPE
+         || TREE_CODE (type) == UNION_TYPE)
+       pedwarn (loc, OPT_Wpedantic,
+                "ISO C forbids casting nonscalar to the same type");
+    }
+  else if (TREE_CODE (type) == UNION_TYPE)
+    {
+      tree field;
+
+      for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
+       if (TREE_TYPE (field) != error_mark_node
+           && comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (field)),
+                         TYPE_MAIN_VARIANT (TREE_TYPE (value))))
+         break;
+
+      if (field)
+       {
+         tree t;
+         bool maybe_const = true;
+
+         pedwarn (loc, OPT_Wpedantic, "ISO C forbids casts to union type");
+         t = c_fully_fold (value, false, &maybe_const);
+         t = build_constructor_single (type, field, t);
+         if (!maybe_const)
+           t = c_wrap_maybe_const (t, true);
+         t = digest_init (loc, type, t,
+                          NULL_TREE, false, true, 0);
+         TREE_CONSTANT (t) = TREE_CONSTANT (value);
+         return t;
+       }
+      error_at (loc, "cast to union type from type not present in union");
+      return error_mark_node;
+    }
+  else
+    {
+      tree otype, ovalue;
+
+      if (type == void_type_node)
+       {
+         tree t = build1 (CONVERT_EXPR, type, value);
+         SET_EXPR_LOCATION (t, loc);
+         return t;
+       }
+
+      otype = TREE_TYPE (value);
+
+      /* Optionally warn about potentially worrisome casts.  */
+      if (warn_cast_qual
+         && TREE_CODE (type) == POINTER_TYPE
+         && TREE_CODE (otype) == POINTER_TYPE)
+       handle_warn_cast_qual (loc, type, otype);
+
+      /* Warn about conversions between pointers to disjoint
+        address spaces.  */
+      if (TREE_CODE (type) == POINTER_TYPE
+         && TREE_CODE (otype) == POINTER_TYPE
+         && !null_pointer_constant_p (value))
+       {
+         addr_space_t as_to = TYPE_ADDR_SPACE (TREE_TYPE (type));
+         addr_space_t as_from = TYPE_ADDR_SPACE (TREE_TYPE (otype));
+         addr_space_t as_common;
+
+         if (!addr_space_superset (as_to, as_from, &as_common))
+           {
+             if (ADDR_SPACE_GENERIC_P (as_from))
+               warning_at (loc, 0, "cast to %s address space pointer "
+                           "from disjoint generic address space pointer",
+                           c_addr_space_name (as_to));
+
+             else if (ADDR_SPACE_GENERIC_P (as_to))
+               warning_at (loc, 0, "cast to generic address space pointer "
+                           "from disjoint %s address space pointer",
+                           c_addr_space_name (as_from));
+
+             else
+               warning_at (loc, 0, "cast to %s address space pointer "
+                           "from disjoint %s address space pointer",
+                           c_addr_space_name (as_to),
+                           c_addr_space_name (as_from));
+           }
+       }
+
+      /* Warn about possible alignment problems.  */
+      if (STRICT_ALIGNMENT
+         && TREE_CODE (type) == POINTER_TYPE
+         && TREE_CODE (otype) == POINTER_TYPE
+         && TREE_CODE (TREE_TYPE (otype)) != VOID_TYPE
+         && TREE_CODE (TREE_TYPE (otype)) != FUNCTION_TYPE
+         /* Don't warn about opaque types, where the actual alignment
+            restriction is unknown.  */
+         && !((TREE_CODE (TREE_TYPE (otype)) == UNION_TYPE
+               || TREE_CODE (TREE_TYPE (otype)) == RECORD_TYPE)
+              && TYPE_MODE (TREE_TYPE (otype)) == VOIDmode)
+         && TYPE_ALIGN (TREE_TYPE (type)) > TYPE_ALIGN (TREE_TYPE (otype)))
+       warning_at (loc, OPT_Wcast_align,
+                   "cast increases required alignment of target type");
+
+      if (TREE_CODE (type) == INTEGER_TYPE
+         && TREE_CODE (otype) == POINTER_TYPE
+         && TYPE_PRECISION (type) != TYPE_PRECISION (otype))
+      /* Unlike conversion of integers to pointers, where the
+         warning is disabled for converting constants because
+         of cases such as SIG_*, warn about converting constant
+         pointers to integers. In some cases it may cause unwanted
+         sign extension, and a warning is appropriate.  */
+       warning_at (loc, OPT_Wpointer_to_int_cast,
+                   "cast from pointer to integer of different size");
+
+      if (TREE_CODE (value) == CALL_EXPR
+         && TREE_CODE (type) != TREE_CODE (otype))
+       warning_at (loc, OPT_Wbad_function_cast,
+                   "cast from function call of type %qT "
+                   "to non-matching type %qT", otype, type);
+
+      if (TREE_CODE (type) == POINTER_TYPE
+         && TREE_CODE (otype) == INTEGER_TYPE
+         && TYPE_PRECISION (type) != TYPE_PRECISION (otype)
+         /* Don't warn about converting any constant.  */
+         && !TREE_CONSTANT (value))
+       warning_at (loc,
+                   OPT_Wint_to_pointer_cast, "cast to pointer from integer "
+                   "of different size");
+
+      if (warn_strict_aliasing <= 2)
+        strict_aliasing_warning (otype, type, expr);
+
+      /* If pedantic, warn for conversions between function and object
+        pointer types, except for converting a null pointer constant
+        to function pointer type.  */
+      if (pedantic
+         && TREE_CODE (type) == POINTER_TYPE
+         && TREE_CODE (otype) == POINTER_TYPE
+         && TREE_CODE (TREE_TYPE (otype)) == FUNCTION_TYPE
+         && TREE_CODE (TREE_TYPE (type)) != FUNCTION_TYPE)
+       pedwarn (loc, OPT_Wpedantic, "ISO C forbids "
+                "conversion of function pointer to object pointer type");
+
+      if (pedantic
+         && TREE_CODE (type) == POINTER_TYPE
+         && TREE_CODE (otype) == POINTER_TYPE
+         && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE
+         && TREE_CODE (TREE_TYPE (otype)) != FUNCTION_TYPE
+         && !null_pointer_constant_p (value))
+       pedwarn (loc, OPT_Wpedantic, "ISO C forbids "
+                "conversion of object pointer to function pointer type");
+
+      ovalue = value;
+      value = convert (type, value);
+
+      /* Ignore any integer overflow caused by the cast.  */
+      if (TREE_CODE (value) == INTEGER_CST && !FLOAT_TYPE_P (otype))
+       {
+         if (CONSTANT_CLASS_P (ovalue) && TREE_OVERFLOW (ovalue))
+           {
+             if (!TREE_OVERFLOW (value))
+               {
+                 /* Avoid clobbering a shared constant.  */
+                 value = copy_node (value);
+                 TREE_OVERFLOW (value) = TREE_OVERFLOW (ovalue);
+               }
+           }
+         else if (TREE_OVERFLOW (value))
+           /* Reset VALUE's overflow flags, ensuring constant sharing.  */
+           value = build_int_cst_wide (TREE_TYPE (value),
+                                       TREE_INT_CST_LOW (value),
+                                       TREE_INT_CST_HIGH (value));
+       }
+    }
+
+  /* Don't let a cast be an lvalue.  */
+  if (value == expr)
+    value = non_lvalue_loc (loc, value);
+
+  /* Don't allow the results of casting to floating-point or complex
+     types be confused with actual constants, or casts involving
+     integer and pointer types other than direct integer-to-integer
+     and integer-to-pointer be confused with integer constant
+     expressions and null pointer constants.  */
+  if (TREE_CODE (value) == REAL_CST
+      || TREE_CODE (value) == COMPLEX_CST
+      || (TREE_CODE (value) == INTEGER_CST
+         && !((TREE_CODE (expr) == INTEGER_CST
+               && INTEGRAL_TYPE_P (TREE_TYPE (expr)))
+              || TREE_CODE (expr) == REAL_CST
+              || TREE_CODE (expr) == COMPLEX_CST)))
+      value = build1 (NOP_EXPR, type, value);
+
+  if (CAN_HAVE_LOCATION_P (value))
+    SET_EXPR_LOCATION (value, loc);
+  return value;
+}
+
+/* Interpret a cast of expression EXPR to type TYPE.  LOC is the
+   location of the open paren of the cast, or the position of the cast
+   expr.  */
+tree
+c_cast_expr (location_t loc, struct c_type_name *type_name, tree expr)
+{
+  tree type;
+  tree type_expr = NULL_TREE;
+  bool type_expr_const = true;
+  tree ret;
+  int saved_wsp = warn_strict_prototypes;
+
+  /* This avoids warnings about unprototyped casts on
+     integers.  E.g. "#define SIG_DFL (void(*)())0".  */
+  if (TREE_CODE (expr) == INTEGER_CST)
+    warn_strict_prototypes = 0;
+  type = groktypename (type_name, &type_expr, &type_expr_const);
+  warn_strict_prototypes = saved_wsp;
+
+  ret = build_c_cast (loc, type, expr);
+  if (type_expr)
+    {
+      ret = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (ret), type_expr, ret);
+      C_MAYBE_CONST_EXPR_NON_CONST (ret) = !type_expr_const;
+      SET_EXPR_LOCATION (ret, loc);
+    }
+
+  if (CAN_HAVE_LOCATION_P (ret) && !EXPR_HAS_LOCATION (ret))
+    SET_EXPR_LOCATION (ret, loc);
+
+  /* C++ does not permits types to be defined in a cast, but it
+     allows references to incomplete types.  */
+  if (warn_cxx_compat && type_name->specs->typespec_kind == ctsk_tagdef)
+    warning_at (loc, OPT_Wc___compat,
+               "defining a type in a cast is invalid in C++");
+
+  return ret;
+}
+\f
+/* Build an assignment expression of lvalue LHS from value RHS.
+   If LHS_ORIGTYPE is not NULL, it is the original type of LHS, which
+   may differ from TREE_TYPE (LHS) for an enum bitfield.
+   MODIFYCODE is the code for a binary operator that we use
+   to combine the old value of LHS with RHS to get the new value.
+   Or else MODIFYCODE is NOP_EXPR meaning do a simple assignment.
+   If RHS_ORIGTYPE is not NULL_TREE, it is the original type of RHS,
+   which may differ from TREE_TYPE (RHS) for an enum value.
+
+   LOCATION is the location of the MODIFYCODE operator.
+   RHS_LOC is the location of the RHS.  */
+
+tree
+build_modify_expr (location_t location, tree lhs, tree lhs_origtype,
+                  enum tree_code modifycode,
+                  location_t rhs_loc, tree rhs, tree rhs_origtype)
+{
+  tree result;
+  tree newrhs;
+  tree rhs_semantic_type = NULL_TREE;
+  tree lhstype = TREE_TYPE (lhs);
+  tree olhstype = lhstype;
+  bool npc;
+
+  /* Types that aren't fully specified cannot be used in assignments.  */
+  lhs = require_complete_type (lhs);
+
+  /* Avoid duplicate error messages from operands that had errors.  */
+  if (TREE_CODE (lhs) == ERROR_MARK || TREE_CODE (rhs) == ERROR_MARK)
+    return error_mark_node;
+
+  /* For ObjC properties, defer this check.  */
+  if (!objc_is_property_ref (lhs) && !lvalue_or_else (location, lhs, lv_assign))
+    return error_mark_node;
+
+  if (TREE_CODE (rhs) == EXCESS_PRECISION_EXPR)
+    {
+      rhs_semantic_type = TREE_TYPE (rhs);
+      rhs = TREE_OPERAND (rhs, 0);
+    }
+
+  newrhs = rhs;
+
+  if (TREE_CODE (lhs) == C_MAYBE_CONST_EXPR)
+    {
+      tree inner = build_modify_expr (location, C_MAYBE_CONST_EXPR_EXPR (lhs),
+                                     lhs_origtype, modifycode, rhs_loc, rhs,
+                                     rhs_origtype);
+      if (inner == error_mark_node)
+       return error_mark_node;
+      result = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (inner),
+                      C_MAYBE_CONST_EXPR_PRE (lhs), inner);
+      gcc_assert (!C_MAYBE_CONST_EXPR_INT_OPERANDS (lhs));
+      C_MAYBE_CONST_EXPR_NON_CONST (result) = 1;
+      protected_set_expr_location (result, location);
+      return result;
+    }
+
+  /* If a binary op has been requested, combine the old LHS value with the RHS
+     producing the value we should actually store into the LHS.  */
+
+  if (modifycode != NOP_EXPR)
+    {
+      lhs = c_fully_fold (lhs, false, NULL);
+      lhs = stabilize_reference (lhs);
+      newrhs = build_binary_op (location,
+                               modifycode, lhs, rhs, 1);
+
+      /* The original type of the right hand side is no longer
+        meaningful.  */
+      rhs_origtype = NULL_TREE;
+    }
+
+  if (c_dialect_objc ())
+    {
+      /* Check if we are modifying an Objective-C property reference;
+        if so, we need to generate setter calls.  */
+      result = objc_maybe_build_modify_expr (lhs, newrhs);
+      if (result)
+       return result;
+
+      /* Else, do the check that we postponed for Objective-C.  */
+      if (!lvalue_or_else (location, lhs, lv_assign))
+       return error_mark_node;
+    }
+
+  /* Give an error for storing in something that is 'const'.  */
+
+  if (TYPE_READONLY (lhstype)
+      || ((TREE_CODE (lhstype) == RECORD_TYPE
+          || TREE_CODE (lhstype) == UNION_TYPE)
+         && C_TYPE_FIELDS_READONLY (lhstype)))
+    {
+      readonly_error (lhs, lv_assign);
+      return error_mark_node;
+    }
+  else if (TREE_READONLY (lhs))
+    readonly_warning (lhs, lv_assign);
+
+  /* If storing into a structure or union member,
+     it has probably been given type `int'.
+     Compute the type that would go with
+     the actual amount of storage the member occupies.  */
+
+  if (TREE_CODE (lhs) == COMPONENT_REF
+      && (TREE_CODE (lhstype) == INTEGER_TYPE
+         || TREE_CODE (lhstype) == BOOLEAN_TYPE
+         || TREE_CODE (lhstype) == REAL_TYPE
+         || TREE_CODE (lhstype) == ENUMERAL_TYPE))
+    lhstype = TREE_TYPE (get_unwidened (lhs, 0));
+
+  /* If storing in a field that is in actuality a short or narrower than one,
+     we must store in the field in its actual type.  */
+
+  if (lhstype != TREE_TYPE (lhs))
+    {
+      lhs = copy_node (lhs);
+      TREE_TYPE (lhs) = lhstype;
+    }
+
+  /* Issue -Wc++-compat warnings about an assignment to an enum type
+     when LHS does not have its original type.  This happens for,
+     e.g., an enum bitfield in a struct.  */
+  if (warn_cxx_compat
+      && lhs_origtype != NULL_TREE
+      && lhs_origtype != lhstype
+      && TREE_CODE (lhs_origtype) == ENUMERAL_TYPE)
+    {
+      tree checktype = (rhs_origtype != NULL_TREE
+                       ? rhs_origtype
+                       : TREE_TYPE (rhs));
+      if (checktype != error_mark_node
+         && TYPE_MAIN_VARIANT (checktype) != TYPE_MAIN_VARIANT (lhs_origtype))
+       warning_at (location, OPT_Wc___compat,
+                   "enum conversion in assignment is invalid in C++");
+    }
+
+  /* Convert new value to destination type.  Fold it first, then
+     restore any excess precision information, for the sake of
+     conversion warnings.  */
+
+  npc = null_pointer_constant_p (newrhs);
+  newrhs = c_fully_fold (newrhs, false, NULL);
+  if (rhs_semantic_type)
+    newrhs = build1 (EXCESS_PRECISION_EXPR, rhs_semantic_type, newrhs);
+  newrhs = convert_for_assignment (location, lhstype, newrhs, rhs_origtype,
+                                  ic_assign, npc, NULL_TREE, NULL_TREE, 0);
+  if (TREE_CODE (newrhs) == ERROR_MARK)
+    return error_mark_node;
+
+  /* Emit ObjC write barrier, if necessary.  */
+  if (c_dialect_objc () && flag_objc_gc)
+    {
+      result = objc_generate_write_barrier (lhs, modifycode, newrhs);
+      if (result)
+       {
+         protected_set_expr_location (result, location);
+         return result;
+       }
+    }
+
+  /* Scan operands.  */
+
+  result = build2 (MODIFY_EXPR, lhstype, lhs, newrhs);
+  TREE_SIDE_EFFECTS (result) = 1;
+  protected_set_expr_location (result, location);
+
+  /* If we got the LHS in a different type for storing in,
+     convert the result back to the nominal type of LHS
+     so that the value we return always has the same type
+     as the LHS argument.  */
+
+  if (olhstype == TREE_TYPE (result))
+    return result;
+
+  result = convert_for_assignment (location, olhstype, result, rhs_origtype,
+                                  ic_assign, false, NULL_TREE, NULL_TREE, 0);
+  protected_set_expr_location (result, location);
+  return result;
+}
+\f
+/* Return whether STRUCT_TYPE has an anonymous field with type TYPE.
+   This is used to implement -fplan9-extensions.  */
+
+static bool
+find_anonymous_field_with_type (tree struct_type, tree type)
+{
+  tree field;
+  bool found;
+
+  gcc_assert (TREE_CODE (struct_type) == RECORD_TYPE
+             || TREE_CODE (struct_type) == UNION_TYPE);
+  found = false;
+  for (field = TYPE_FIELDS (struct_type);
+       field != NULL_TREE;
+       field = TREE_CHAIN (field))
+    {
+      if (DECL_NAME (field) == NULL
+         && comptypes (type, TYPE_MAIN_VARIANT (TREE_TYPE (field))))
+       {
+         if (found)
+           return false;
+         found = true;
+       }
+      else if (DECL_NAME (field) == NULL
+              && (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
+                  || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
+              && find_anonymous_field_with_type (TREE_TYPE (field), type))
+       {
+         if (found)
+           return false;
+         found = true;
+       }
+    }
+  return found;
+}
+
+/* RHS is an expression whose type is pointer to struct.  If there is
+   an anonymous field in RHS with type TYPE, then return a pointer to
+   that field in RHS.  This is used with -fplan9-extensions.  This
+   returns NULL if no conversion could be found.  */
+
+static tree
+convert_to_anonymous_field (location_t location, tree type, tree rhs)
+{
+  tree rhs_struct_type, lhs_main_type;
+  tree field, found_field;
+  bool found_sub_field;
+  tree ret;
+
+  gcc_assert (POINTER_TYPE_P (TREE_TYPE (rhs)));
+  rhs_struct_type = TREE_TYPE (TREE_TYPE (rhs));
+  gcc_assert (TREE_CODE (rhs_struct_type) == RECORD_TYPE
+             || TREE_CODE (rhs_struct_type) == UNION_TYPE);
+
+  gcc_assert (POINTER_TYPE_P (type));
+  lhs_main_type = TYPE_MAIN_VARIANT (TREE_TYPE (type));
+
+  found_field = NULL_TREE;
+  found_sub_field = false;
+  for (field = TYPE_FIELDS (rhs_struct_type);
+       field != NULL_TREE;
+       field = TREE_CHAIN (field))
+    {
+      if (DECL_NAME (field) != NULL_TREE
+         || (TREE_CODE (TREE_TYPE (field)) != RECORD_TYPE
+             && TREE_CODE (TREE_TYPE (field)) != UNION_TYPE))
+       continue;
+      if (comptypes (lhs_main_type, TYPE_MAIN_VARIANT (TREE_TYPE (field))))
+       {
+         if (found_field != NULL_TREE)
+           return NULL_TREE;
+         found_field = field;
+       }
+      else if (find_anonymous_field_with_type (TREE_TYPE (field),
+                                              lhs_main_type))
+       {
+         if (found_field != NULL_TREE)
+           return NULL_TREE;
+         found_field = field;
+         found_sub_field = true;
+       }
+    }
+
+  if (found_field == NULL_TREE)
+    return NULL_TREE;
+
+  ret = fold_build3_loc (location, COMPONENT_REF, TREE_TYPE (found_field),
+                        build_fold_indirect_ref (rhs), found_field,
+                        NULL_TREE);
+  ret = build_fold_addr_expr_loc (location, ret);
+
+  if (found_sub_field)
+    {
+      ret = convert_to_anonymous_field (location, type, ret);
+      gcc_assert (ret != NULL_TREE);
+    }
+
+  return ret;
+}
+
+/* Convert value RHS to type TYPE as preparation for an assignment to
+   an lvalue of type TYPE.  If ORIGTYPE is not NULL_TREE, it is the
+   original type of RHS; this differs from TREE_TYPE (RHS) for enum
+   types.  NULL_POINTER_CONSTANT says whether RHS was a null pointer
+   constant before any folding.
+   The real work of conversion is done by `convert'.
+   The purpose of this function is to generate error messages
+   for assignments that are not allowed in C.
+   ERRTYPE says whether it is argument passing, assignment,
+   initialization or return.
+
+   LOCATION is the location of the RHS.
+   FUNCTION is a tree for the function being called.
+   PARMNUM is the number of the argument, for printing in error messages.  */
+
+static tree
+convert_for_assignment (location_t location, tree type, tree rhs,
+                       tree origtype, enum impl_conv errtype,
+                       bool null_pointer_constant, tree fundecl,
+                       tree function, int parmnum)
+{
+  enum tree_code codel = TREE_CODE (type);
+  tree orig_rhs = rhs;
+  tree rhstype;
+  enum tree_code coder;
+  tree rname = NULL_TREE;
+  bool objc_ok = false;
+
+  if (errtype == ic_argpass)
+    {
+      tree selector;
+      /* Change pointer to function to the function itself for
+        diagnostics.  */
+      if (TREE_CODE (function) == ADDR_EXPR
+         && TREE_CODE (TREE_OPERAND (function, 0)) == FUNCTION_DECL)
+       function = TREE_OPERAND (function, 0);
+
+      /* Handle an ObjC selector specially for diagnostics.  */
+      selector = objc_message_selector ();
+      rname = function;
+      if (selector && parmnum > 2)
+       {
+         rname = selector;
+         parmnum -= 2;
+       }
+    }
+
+  /* This macro is used to emit diagnostics to ensure that all format
+     strings are complete sentences, visible to gettext and checked at
+     compile time.  */
+#define WARN_FOR_ASSIGNMENT(LOCATION, OPT, AR, AS, IN, RE)                      \
+  do {                                                                   \
+    switch (errtype)                                                     \
+      {                                                                  \
+      case ic_argpass:                                                   \
+        if (pedwarn (LOCATION, OPT, AR, parmnum, rname))                 \
+          inform ((fundecl && !DECL_IS_BUILTIN (fundecl))               \
+                 ? DECL_SOURCE_LOCATION (fundecl) : LOCATION,           \
+                  "expected %qT but argument is of type %qT",            \
+                  type, rhstype);                                        \
+        break;                                                           \
+      case ic_assign:                                                    \
+        pedwarn (LOCATION, OPT, AS);                                     \
+        break;                                                           \
+      case ic_init:                                                      \
+        pedwarn_init (LOCATION, OPT, IN);                                \
+        break;                                                           \
+      case ic_return:                                                    \
+        pedwarn (LOCATION, OPT, RE);                                    \
+        break;                                                           \
+      default:                                                           \
+        gcc_unreachable ();                                              \
+      }                                                                  \
+  } while (0)
+
+  /* This macro is used to emit diagnostics to ensure that all format
+     strings are complete sentences, visible to gettext and checked at
+     compile time.  It is the same as WARN_FOR_ASSIGNMENT but with an
+     extra parameter to enumerate qualifiers.  */
+
+#define WARN_FOR_QUALIFIERS(LOCATION, OPT, AR, AS, IN, RE, QUALS)        \
+  do {                                                                   \
+    switch (errtype)                                                     \
+      {                                                                  \
+      case ic_argpass:                                                   \
+        if (pedwarn (LOCATION, OPT, AR, parmnum, rname, QUALS))          \
+          inform ((fundecl && !DECL_IS_BUILTIN (fundecl))               \
+                 ? DECL_SOURCE_LOCATION (fundecl) : LOCATION,           \
+                  "expected %qT but argument is of type %qT",            \
+                  type, rhstype);                                        \
+        break;                                                           \
+      case ic_assign:                                                    \
+        pedwarn (LOCATION, OPT, AS, QUALS);                          \
+        break;                                                           \
+      case ic_init:                                                      \
+        pedwarn (LOCATION, OPT, IN, QUALS);                          \
+        break;                                                           \
+      case ic_return:                                                    \
+        pedwarn (LOCATION, OPT, RE, QUALS);                             \
+        break;                                                           \
+      default:                                                           \
+        gcc_unreachable ();                                              \
+      }                                                                  \
+  } while (0)
+
+  if (TREE_CODE (rhs) == EXCESS_PRECISION_EXPR)
+    rhs = TREE_OPERAND (rhs, 0);
+
+  rhstype = TREE_TYPE (rhs);
+  coder = TREE_CODE (rhstype);
+
+  if (coder == ERROR_MARK)
+    return error_mark_node;
+
+  if (c_dialect_objc ())
+    {
+      int parmno;
+
+      switch (errtype)
+       {
+       case ic_return:
+         parmno = 0;
+         break;
+
+       case ic_assign:
+         parmno = -1;
+         break;
+
+       case ic_init:
+         parmno = -2;
+         break;
+
+       default:
+         parmno = parmnum;
+         break;
+       }
+
+      objc_ok = objc_compare_types (type, rhstype, parmno, rname);
+    }
+
+  if (warn_cxx_compat)
+    {
+      tree checktype = origtype != NULL_TREE ? origtype : rhstype;
+      if (checktype != error_mark_node
+         && TREE_CODE (type) == ENUMERAL_TYPE
+         && TYPE_MAIN_VARIANT (checktype) != TYPE_MAIN_VARIANT (type))
+       {
+         WARN_FOR_ASSIGNMENT (input_location, OPT_Wc___compat,
+                              G_("enum conversion when passing argument "
+                                 "%d of %qE is invalid in C++"),
+                              G_("enum conversion in assignment is "
+                                 "invalid in C++"),
+                              G_("enum conversion in initialization is "
+                                 "invalid in C++"),
+                              G_("enum conversion in return is "
+                                 "invalid in C++"));
+       }
+    }
+
+  if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (rhstype))
+    return rhs;
+
+  if (coder == VOID_TYPE)
+    {
+      /* Except for passing an argument to an unprototyped function,
+        this is a constraint violation.  When passing an argument to
+        an unprototyped function, it is compile-time undefined;
+        making it a constraint in that case was rejected in
+        DR#252.  */
+      error_at (location, "void value not ignored as it ought to be");
+      return error_mark_node;
+    }
+  rhs = require_complete_type (rhs);
+  if (rhs == error_mark_node)
+    return error_mark_node;
+  /* A type converts to a reference to it.
+     This code doesn't fully support references, it's just for the
+     special case of va_start and va_copy.  */
+  if (codel == REFERENCE_TYPE
+      && comptypes (TREE_TYPE (type), TREE_TYPE (rhs)) == 1)
+    {
+      if (!lvalue_p (rhs))
+       {
+         error_at (location, "cannot pass rvalue to reference parameter");
+         return error_mark_node;
+       }
+      if (!c_mark_addressable (rhs))
+       return error_mark_node;
+      rhs = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (rhs)), rhs);
+      SET_EXPR_LOCATION (rhs, location);
+
+      /* We already know that these two types are compatible, but they
+        may not be exactly identical.  In fact, `TREE_TYPE (type)' is
+        likely to be __builtin_va_list and `TREE_TYPE (rhs)' is
+        likely to be va_list, a typedef to __builtin_va_list, which
+        is different enough that it will cause problems later.  */
+      if (TREE_TYPE (TREE_TYPE (rhs)) != TREE_TYPE (type))
+       {
+         rhs = build1 (NOP_EXPR, build_pointer_type (TREE_TYPE (type)), rhs);
+         SET_EXPR_LOCATION (rhs, location);
+       }
+
+      rhs = build1 (NOP_EXPR, type, rhs);
+      SET_EXPR_LOCATION (rhs, location);
+      return rhs;
+    }
+  /* Some types can interconvert without explicit casts.  */
+  else if (codel == VECTOR_TYPE && coder == VECTOR_TYPE
+          && vector_types_convertible_p (type, TREE_TYPE (rhs), true))
+    return convert (type, rhs);
+  /* Arithmetic types all interconvert, and enum is treated like int.  */
+  else if ((codel == INTEGER_TYPE || codel == REAL_TYPE
+           || codel == FIXED_POINT_TYPE
+           || codel == ENUMERAL_TYPE || codel == COMPLEX_TYPE
+           || codel == BOOLEAN_TYPE)
+          && (coder == INTEGER_TYPE || coder == REAL_TYPE
+              || coder == FIXED_POINT_TYPE
+              || coder == ENUMERAL_TYPE || coder == COMPLEX_TYPE
+              || coder == BOOLEAN_TYPE))
+    {
+      tree ret;
+      bool save = in_late_binary_op;
+      if (codel == BOOLEAN_TYPE || codel == COMPLEX_TYPE)
+       in_late_binary_op = true;
+      ret = convert_and_check (type, orig_rhs);
+      if (codel == BOOLEAN_TYPE || codel == COMPLEX_TYPE)
+       in_late_binary_op = save;
+      return ret;
+    }
+
+  /* Aggregates in different TUs might need conversion.  */
+  if ((codel == RECORD_TYPE || codel == UNION_TYPE)
+      && codel == coder
+      && comptypes (type, rhstype))
+    return convert_and_check (type, rhs);
+
+  /* Conversion to a transparent union or record from its member types.
+     This applies only to function arguments.  */
+  if (((codel == UNION_TYPE || codel == RECORD_TYPE)
+      && TYPE_TRANSPARENT_AGGR (type))
+      && errtype == ic_argpass)
+    {
+      tree memb, marginal_memb = NULL_TREE;
+
+      for (memb = TYPE_FIELDS (type); memb ; memb = DECL_CHAIN (memb))
+       {
+         tree memb_type = TREE_TYPE (memb);
+
+         if (comptypes (TYPE_MAIN_VARIANT (memb_type),
+                        TYPE_MAIN_VARIANT (rhstype)))
+           break;
+
+         if (TREE_CODE (memb_type) != POINTER_TYPE)
+           continue;
+
+         if (coder == POINTER_TYPE)
+           {
+             tree ttl = TREE_TYPE (memb_type);
+             tree ttr = TREE_TYPE (rhstype);
+
+             /* Any non-function converts to a [const][volatile] void *
+                and vice versa; otherwise, targets must be the same.
+                Meanwhile, the lhs target must have all the qualifiers of
+                the rhs.  */
+             if (VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr)
+                 || comp_target_types (location, memb_type, rhstype))
+               {
+                 /* If this type won't generate any warnings, use it.  */
+                 if (TYPE_QUALS (ttl) == TYPE_QUALS (ttr)
+                     || ((TREE_CODE (ttr) == FUNCTION_TYPE
+                          && TREE_CODE (ttl) == FUNCTION_TYPE)
+                         ? ((TYPE_QUALS (ttl) | TYPE_QUALS (ttr))
+                            == TYPE_QUALS (ttr))
+                         : ((TYPE_QUALS (ttl) | TYPE_QUALS (ttr))
+                            == TYPE_QUALS (ttl))))
+                   break;
+
+                 /* Keep looking for a better type, but remember this one.  */
+                 if (!marginal_memb)
+                   marginal_memb = memb;
+               }
+           }
+
+         /* Can convert integer zero to any pointer type.  */
+         if (null_pointer_constant)
+           {
+             rhs = null_pointer_node;
+             break;
+           }
+       }
+
+      if (memb || marginal_memb)
+       {
+         if (!memb)
+           {
+             /* We have only a marginally acceptable member type;
+                it needs a warning.  */
+             tree ttl = TREE_TYPE (TREE_TYPE (marginal_memb));
+             tree ttr = TREE_TYPE (rhstype);
+
+             /* Const and volatile mean something different for function
+                types, so the usual warnings are not appropriate.  */
+             if (TREE_CODE (ttr) == FUNCTION_TYPE
+                 && TREE_CODE (ttl) == FUNCTION_TYPE)
+               {
+                 /* Because const and volatile on functions are
+                    restrictions that say the function will not do
+                    certain things, it is okay to use a const or volatile
+                    function where an ordinary one is wanted, but not
+                    vice-versa.  */
+                 if (TYPE_QUALS_NO_ADDR_SPACE (ttl)
+                     & ~TYPE_QUALS_NO_ADDR_SPACE (ttr))
+                   WARN_FOR_QUALIFIERS (location, 0,
+                                        G_("passing argument %d of %qE "
+                                           "makes %q#v qualified function "
+                                           "pointer from unqualified"),
+                                        G_("assignment makes %q#v qualified "
+                                           "function pointer from "
+                                           "unqualified"),
+                                        G_("initialization makes %q#v qualified "
+                                           "function pointer from "
+                                           "unqualified"),
+                                        G_("return makes %q#v qualified function "
+                                           "pointer from unqualified"),
+                                        TYPE_QUALS (ttl) & ~TYPE_QUALS (ttr));
+               }
+             else if (TYPE_QUALS_NO_ADDR_SPACE (ttr)
+                      & ~TYPE_QUALS_NO_ADDR_SPACE (ttl))
+               WARN_FOR_QUALIFIERS (location, 0,
+                                    G_("passing argument %d of %qE discards "
+                                       "%qv qualifier from pointer target type"),
+                                    G_("assignment discards %qv qualifier "
+                                       "from pointer target type"),
+                                    G_("initialization discards %qv qualifier "
+                                       "from pointer target type"),
+                                    G_("return discards %qv qualifier from "
+                                       "pointer target type"),
+                                    TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl));
+
+             memb = marginal_memb;
+           }
+
+         if (!fundecl || !DECL_IN_SYSTEM_HEADER (fundecl))
+           pedwarn (location, OPT_Wpedantic,
+                    "ISO C prohibits argument conversion to union type");
+
+         rhs = fold_convert_loc (location, TREE_TYPE (memb), rhs);
+         return build_constructor_single (type, memb, rhs);
+       }
+    }
+
+  /* Conversions among pointers */
+  else if ((codel == POINTER_TYPE || codel == REFERENCE_TYPE)
+          && (coder == codel))
+    {
+      tree ttl = TREE_TYPE (type);
+      tree ttr = TREE_TYPE (rhstype);
+      tree mvl = ttl;
+      tree mvr = ttr;
+      bool is_opaque_pointer;
+      int target_cmp = 0;   /* Cache comp_target_types () result.  */
+      addr_space_t asl;
+      addr_space_t asr;
+
+      if (TREE_CODE (mvl) != ARRAY_TYPE)
+       mvl = TYPE_MAIN_VARIANT (mvl);
+      if (TREE_CODE (mvr) != ARRAY_TYPE)
+       mvr = TYPE_MAIN_VARIANT (mvr);
+      /* Opaque pointers are treated like void pointers.  */
+      is_opaque_pointer = vector_targets_convertible_p (ttl, ttr);
+
+      /* The Plan 9 compiler permits a pointer to a struct to be
+        automatically converted into a pointer to an anonymous field
+        within the struct.  */
+      if (flag_plan9_extensions
+         && (TREE_CODE (mvl) == RECORD_TYPE || TREE_CODE(mvl) == UNION_TYPE)
+         && (TREE_CODE (mvr) == RECORD_TYPE || TREE_CODE(mvr) == UNION_TYPE)
+         && mvl != mvr)
+       {
+         tree new_rhs = convert_to_anonymous_field (location, type, rhs);
+         if (new_rhs != NULL_TREE)
+           {
+             rhs = new_rhs;
+             rhstype = TREE_TYPE (rhs);
+             coder = TREE_CODE (rhstype);
+             ttr = TREE_TYPE (rhstype);
+             mvr = TYPE_MAIN_VARIANT (ttr);
+           }
+       }
+
+      /* C++ does not allow the implicit conversion void* -> T*.  However,
+        for the purpose of reducing the number of false positives, we
+        tolerate the special case of
+
+               int *p = NULL;
+
+        where NULL is typically defined in C to be '(void *) 0'.  */
+      if (VOID_TYPE_P (ttr) && rhs != null_pointer_node && !VOID_TYPE_P (ttl))
+       warning_at (location, OPT_Wc___compat,
+                   "request for implicit conversion "
+                   "from %qT to %qT not permitted in C++", rhstype, type);
+
+      /* See if the pointers point to incompatible address spaces.  */
+      asl = TYPE_ADDR_SPACE (ttl);
+      asr = TYPE_ADDR_SPACE (ttr);
+      if (!null_pointer_constant_p (rhs)
+         && asr != asl && !targetm.addr_space.subset_p (asr, asl))
+       {
+         switch (errtype)
+           {
+           case ic_argpass:
+             error_at (location, "passing argument %d of %qE from pointer to "
+                       "non-enclosed address space", parmnum, rname);
+             break;
+           case ic_assign:
+             error_at (location, "assignment from pointer to "
+                       "non-enclosed address space");
+             break;
+           case ic_init:
+             error_at (location, "initialization from pointer to "
+                       "non-enclosed address space");
+             break;
+           case ic_return:
+             error_at (location, "return from pointer to "
+                       "non-enclosed address space");
+             break;
+           default:
+             gcc_unreachable ();
+           }
+         return error_mark_node;
+       }
+
+      /* Check if the right-hand side has a format attribute but the
+        left-hand side doesn't.  */
+      if (warn_suggest_attribute_format
+         && check_missing_format_attribute (type, rhstype))
+       {
+         switch (errtype)
+         {
+         case ic_argpass:
+           warning_at (location, OPT_Wsuggest_attribute_format,
+                       "argument %d of %qE might be "
+                       "a candidate for a format attribute",
+                       parmnum, rname);
+           break;
+         case ic_assign:
+           warning_at (location, OPT_Wsuggest_attribute_format,
+                       "assignment left-hand side might be "
+                       "a candidate for a format attribute");
+           break;
+         case ic_init:
+           warning_at (location, OPT_Wsuggest_attribute_format,
+                       "initialization left-hand side might be "
+                       "a candidate for a format attribute");
+           break;
+         case ic_return:
+           warning_at (location, OPT_Wsuggest_attribute_format,
+                       "return type might be "
+                       "a candidate for a format attribute");
+           break;
+         default:
+           gcc_unreachable ();
+         }
+       }
+
+      /* Any non-function converts to a [const][volatile] void *
+        and vice versa; otherwise, targets must be the same.
+        Meanwhile, the lhs target must have all the qualifiers of the rhs.  */
+      if (VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr)
+         || (target_cmp = comp_target_types (location, type, rhstype))
+         || is_opaque_pointer
+         || (c_common_unsigned_type (mvl)
+             == c_common_unsigned_type (mvr)))
+       {
+         if (pedantic
+             && ((VOID_TYPE_P (ttl) && TREE_CODE (ttr) == FUNCTION_TYPE)
+                 ||
+                 (VOID_TYPE_P (ttr)
+                  && !null_pointer_constant
+                  && TREE_CODE (ttl) == FUNCTION_TYPE)))
+           WARN_FOR_ASSIGNMENT (location, OPT_Wpedantic,
+                                G_("ISO C forbids passing argument %d of "
+                                   "%qE between function pointer "
+                                   "and %<void *%>"),
+                                G_("ISO C forbids assignment between "
+                                   "function pointer and %<void *%>"),
+                                G_("ISO C forbids initialization between "
+                                   "function pointer and %<void *%>"),
+                                G_("ISO C forbids return between function "
+                                   "pointer and %<void *%>"));
+         /* Const and volatile mean something different for function types,
+            so the usual warnings are not appropriate.  */
+         else if (TREE_CODE (ttr) != FUNCTION_TYPE
+                  && TREE_CODE (ttl) != FUNCTION_TYPE)
+           {
+             if (TYPE_QUALS_NO_ADDR_SPACE (ttr)
+                 & ~TYPE_QUALS_NO_ADDR_SPACE (ttl))
+               {
+                 WARN_FOR_QUALIFIERS (location, 0,
+                                      G_("passing argument %d of %qE discards "
+                                         "%qv qualifier from pointer target type"),
+                                      G_("assignment discards %qv qualifier "
+                                         "from pointer target type"),
+                                      G_("initialization discards %qv qualifier "
+                                         "from pointer target type"),
+                                      G_("return discards %qv qualifier from "
+                                         "pointer target type"),
+                                      TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl));
+               }
+             /* If this is not a case of ignoring a mismatch in signedness,
+                no warning.  */
+             else if (VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr)
+                      || target_cmp)
+               ;
+             /* If there is a mismatch, do warn.  */
+             else if (warn_pointer_sign)
+               WARN_FOR_ASSIGNMENT (location, OPT_Wpointer_sign,
+                                    G_("pointer targets in passing argument "
+                                       "%d of %qE differ in signedness"),
+                                    G_("pointer targets in assignment "
+                                       "differ in signedness"),
+                                    G_("pointer targets in initialization "
+                                       "differ in signedness"),
+                                    G_("pointer targets in return differ "
+                                       "in signedness"));
+           }
+         else if (TREE_CODE (ttl) == FUNCTION_TYPE
+                  && TREE_CODE (ttr) == FUNCTION_TYPE)
+           {
+             /* Because const and volatile on functions are restrictions
+                that say the function will not do certain things,
+                it is okay to use a const or volatile function
+                where an ordinary one is wanted, but not vice-versa.  */
+             if (TYPE_QUALS_NO_ADDR_SPACE (ttl)
+                 & ~TYPE_QUALS_NO_ADDR_SPACE (ttr))
+               WARN_FOR_QUALIFIERS (location, 0,
+                                    G_("passing argument %d of %qE makes "
+                                       "%q#v qualified function pointer "
+                                       "from unqualified"),
+                                    G_("assignment makes %q#v qualified function "
+                                       "pointer from unqualified"),
+                                    G_("initialization makes %q#v qualified "
+                                       "function pointer from unqualified"),
+                                    G_("return makes %q#v qualified function "
+                                       "pointer from unqualified"),
+                                    TYPE_QUALS (ttl) & ~TYPE_QUALS (ttr));
+           }
+       }
+      else
+       /* Avoid warning about the volatile ObjC EH puts on decls.  */
+       if (!objc_ok)
+         WARN_FOR_ASSIGNMENT (location, 0,
+                              G_("passing argument %d of %qE from "
+                                 "incompatible pointer type"),
+                              G_("assignment from incompatible pointer type"),
+                              G_("initialization from incompatible "
+                                 "pointer type"),
+                              G_("return from incompatible pointer type"));
+
+      return convert (type, rhs);
+    }
+  else if (codel == POINTER_TYPE && coder == ARRAY_TYPE)
+    {
+      /* ??? This should not be an error when inlining calls to
+        unprototyped functions.  */
+      error_at (location, "invalid use of non-lvalue array");
+      return error_mark_node;
+    }
+  else if (codel == POINTER_TYPE && coder == INTEGER_TYPE)
+    {
+      /* An explicit constant 0 can convert to a pointer,
+        or one that results from arithmetic, even including
+        a cast to integer type.  */
+      if (!null_pointer_constant)
+       WARN_FOR_ASSIGNMENT (location, 0,
+                            G_("passing argument %d of %qE makes "
+                               "pointer from integer without a cast"),
+                            G_("assignment makes pointer from integer "
+                               "without a cast"),
+                            G_("initialization makes pointer from "
+                               "integer without a cast"),
+                            G_("return makes pointer from integer "
+                               "without a cast"));
+
+      return convert (type, rhs);
+    }
+  else if (codel == INTEGER_TYPE && coder == POINTER_TYPE)
+    {
+      WARN_FOR_ASSIGNMENT (location, 0,
+                          G_("passing argument %d of %qE makes integer "
+                             "from pointer without a cast"),
+                          G_("assignment makes integer from pointer "
+                             "without a cast"),
+                          G_("initialization makes integer from pointer "
+                             "without a cast"),
+                          G_("return makes integer from pointer "
+                             "without a cast"));
+      return convert (type, rhs);
+    }
+  else if (codel == BOOLEAN_TYPE && coder == POINTER_TYPE)
+    {
+      tree ret;
+      bool save = in_late_binary_op;
+      in_late_binary_op = true;
+      ret = convert (type, rhs);
+      in_late_binary_op = save;
+      return ret;
+    }
+
+  switch (errtype)
+    {
+    case ic_argpass:
+      error_at (location, "incompatible type for argument %d of %qE", parmnum, rname);
+      inform ((fundecl && !DECL_IS_BUILTIN (fundecl))
+             ? DECL_SOURCE_LOCATION (fundecl) : input_location,
+             "expected %qT but argument is of type %qT", type, rhstype);
+      break;
+    case ic_assign:
+      error_at (location, "incompatible types when assigning to type %qT from "
+               "type %qT", type, rhstype);
+      break;
+    case ic_init:
+      error_at (location,
+               "incompatible types when initializing type %qT using type %qT",
+               type, rhstype);
+      break;
+    case ic_return:
+      error_at (location,
+               "incompatible types when returning type %qT but %qT was "
+               "expected", rhstype, type);
+      break;
+    default:
+      gcc_unreachable ();
+    }
+
+  return error_mark_node;
+}
+\f
+/* If VALUE is a compound expr all of whose expressions are constant, then
+   return its value.  Otherwise, return error_mark_node.
+
+   This is for handling COMPOUND_EXPRs as initializer elements
+   which is allowed with a warning when -pedantic is specified.  */
+
+static tree
+valid_compound_expr_initializer (tree value, tree endtype)
+{
+  if (TREE_CODE (value) == COMPOUND_EXPR)
+    {
+      if (valid_compound_expr_initializer (TREE_OPERAND (value, 0), endtype)
+         == error_mark_node)
+       return error_mark_node;
+      return valid_compound_expr_initializer (TREE_OPERAND (value, 1),
+                                             endtype);
+    }
+  else if (!initializer_constant_valid_p (value, endtype))
+    return error_mark_node;
+  else
+    return value;
+}
+\f
+/* Perform appropriate conversions on the initial value of a variable,
+   store it in the declaration DECL,
+   and print any error messages that are appropriate.
+   If ORIGTYPE is not NULL_TREE, it is the original type of INIT.
+   If the init is invalid, store an ERROR_MARK.
+
+   INIT_LOC is the location of the initial value.  */
+
+void
+store_init_value (location_t init_loc, tree decl, tree init, tree origtype)
+{
+  tree value, type;
+  bool npc = false;
+
+  /* If variable's type was invalidly declared, just ignore it.  */
+
+  type = TREE_TYPE (decl);
+  if (TREE_CODE (type) == ERROR_MARK)
+    return;
+
+  /* Digest the specified initializer into an expression.  */
+
+  if (init)
+    npc = null_pointer_constant_p (init);
+  value = digest_init (init_loc, type, init, origtype, npc,
+                      true, TREE_STATIC (decl));
+
+  /* Store the expression if valid; else report error.  */
+
+  if (!in_system_header
+      && AGGREGATE_TYPE_P (TREE_TYPE (decl)) && !TREE_STATIC (decl))
+    warning (OPT_Wtraditional, "traditional C rejects automatic "
+            "aggregate initialization");
+
+  DECL_INITIAL (decl) = value;
+
+  /* ANSI wants warnings about out-of-range constant initializers.  */
+  STRIP_TYPE_NOPS (value);
+  if (TREE_STATIC (decl))
+    constant_expression_warning (value);
+
+  /* Check if we need to set array size from compound literal size.  */
+  if (TREE_CODE (type) == ARRAY_TYPE
+      && TYPE_DOMAIN (type) == 0
+      && value != error_mark_node)
+    {
+      tree inside_init = init;
+
+      STRIP_TYPE_NOPS (inside_init);
+      inside_init = fold (inside_init);
+
+      if (TREE_CODE (inside_init) == COMPOUND_LITERAL_EXPR)
+       {
+         tree cldecl = COMPOUND_LITERAL_EXPR_DECL (inside_init);
+
+         if (TYPE_DOMAIN (TREE_TYPE (cldecl)))
+           {
+             /* For int foo[] = (int [3]){1}; we need to set array size
+                now since later on array initializer will be just the
+                brace enclosed list of the compound literal.  */
+             tree etype = strip_array_types (TREE_TYPE (decl));
+             type = build_distinct_type_copy (TYPE_MAIN_VARIANT (type));
+             TYPE_DOMAIN (type) = TYPE_DOMAIN (TREE_TYPE (cldecl));
+             layout_type (type);
+             layout_decl (cldecl, 0);
+             TREE_TYPE (decl)
+               = c_build_qualified_type (type, TYPE_QUALS (etype));
+           }
+       }
+    }
+}
+\f
+/* Methods for storing and printing names for error messages.  */
+
+/* Implement a spelling stack that allows components of a name to be pushed
+   and popped.  Each element on the stack is this structure.  */
+
+struct spelling
+{
+  int kind;
+  union
+    {
+      unsigned HOST_WIDE_INT i;
+      const char *s;
+    } u;
+};
+
+#define SPELLING_STRING 1
+#define SPELLING_MEMBER 2
+#define SPELLING_BOUNDS 3
+
+static struct spelling *spelling;      /* Next stack element (unused).  */
+static struct spelling *spelling_base; /* Spelling stack base.  */
+static int spelling_size;              /* Size of the spelling stack.  */
+
+/* Macros to save and restore the spelling stack around push_... functions.
+   Alternative to SAVE_SPELLING_STACK.  */
+
+#define SPELLING_DEPTH() (spelling - spelling_base)
+#define RESTORE_SPELLING_DEPTH(DEPTH) (spelling = spelling_base + (DEPTH))
+
+/* Push an element on the spelling stack with type KIND and assign VALUE
+   to MEMBER.  */
+
+#define PUSH_SPELLING(KIND, VALUE, MEMBER)                             \
+{                                                                      \
+  int depth = SPELLING_DEPTH ();                                       \
+                                                                       \
+  if (depth >= spelling_size)                                          \
+    {                                                                  \
+      spelling_size += 10;                                             \
+      spelling_base = XRESIZEVEC (struct spelling, spelling_base,      \
+                                 spelling_size);                       \
+      RESTORE_SPELLING_DEPTH (depth);                                  \
+    }                                                                  \
+                                                                       \
+  spelling->kind = (KIND);                                             \
+  spelling->MEMBER = (VALUE);                                          \
+  spelling++;                                                          \
+}
+
+/* Push STRING on the stack.  Printed literally.  */
+
+static void
+push_string (const char *string)
+{
+  PUSH_SPELLING (SPELLING_STRING, string, u.s);
+}
+
+/* Push a member name on the stack.  Printed as '.' STRING.  */
+
+static void
+push_member_name (tree decl)
+{
+  const char *const string
+    = (DECL_NAME (decl)
+       ? identifier_to_locale (IDENTIFIER_POINTER (DECL_NAME (decl)))
+       : _("<anonymous>"));
+  PUSH_SPELLING (SPELLING_MEMBER, string, u.s);
+}
+
+/* Push an array bounds on the stack.  Printed as [BOUNDS].  */
+
+static void
+push_array_bounds (unsigned HOST_WIDE_INT bounds)
+{
+  PUSH_SPELLING (SPELLING_BOUNDS, bounds, u.i);
+}
+
+/* Compute the maximum size in bytes of the printed spelling.  */
+
+static int
+spelling_length (void)
+{
+  int size = 0;
+  struct spelling *p;
+
+  for (p = spelling_base; p < spelling; p++)
+    {
+      if (p->kind == SPELLING_BOUNDS)
+       size += 25;
+      else
+       size += strlen (p->u.s) + 1;
+    }
+
+  return size;
+}
+
+/* Print the spelling to BUFFER and return it.  */
+
+static char *
+print_spelling (char *buffer)
+{
+  char *d = buffer;
+  struct spelling *p;
+
+  for (p = spelling_base; p < spelling; p++)
+    if (p->kind == SPELLING_BOUNDS)
+      {
+       sprintf (d, "[" HOST_WIDE_INT_PRINT_UNSIGNED "]", p->u.i);
+       d += strlen (d);
+      }
+    else
+      {
+       const char *s;
+       if (p->kind == SPELLING_MEMBER)
+         *d++ = '.';
+       for (s = p->u.s; (*d = *s++); d++)
+         ;
+      }
+  *d++ = '\0';
+  return buffer;
+}
+
+/* Issue an error message for a bad initializer component.
+   GMSGID identifies the message.
+   The component name is taken from the spelling stack.  */
+
+void
+error_init (const char *gmsgid)
+{
+  char *ofwhat;
+
+  /* The gmsgid may be a format string with %< and %>. */
+  error (gmsgid);
+  ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
+  if (*ofwhat)
+    error ("(near initialization for %qs)", ofwhat);
+}
+
+/* Issue a pedantic warning for a bad initializer component.  OPT is
+   the option OPT_* (from options.h) controlling this warning or 0 if
+   it is unconditionally given.  GMSGID identifies the message.  The
+   component name is taken from the spelling stack.  */
+
+void
+pedwarn_init (location_t location, int opt, const char *gmsgid)
+{
+  char *ofwhat;
+
+  /* The gmsgid may be a format string with %< and %>. */
+  pedwarn (location, opt, gmsgid);
+  ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
+  if (*ofwhat)
+    pedwarn (location, opt, "(near initialization for %qs)", ofwhat);
+}
+
+/* Issue a warning for a bad initializer component.
+
+   OPT is the OPT_W* value corresponding to the warning option that
+   controls this warning.  GMSGID identifies the message.  The
+   component name is taken from the spelling stack.  */
+
+static void
+warning_init (int opt, const char *gmsgid)
+{
+  char *ofwhat;
+
+  /* The gmsgid may be a format string with %< and %>. */
+  warning (opt, gmsgid);
+  ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
+  if (*ofwhat)
+    warning (opt, "(near initialization for %qs)", ofwhat);
+}
+\f
+/* If TYPE is an array type and EXPR is a parenthesized string
+   constant, warn if pedantic that EXPR is being used to initialize an
+   object of type TYPE.  */
+
+void
+maybe_warn_string_init (tree type, struct c_expr expr)
+{
+  if (pedantic
+      && TREE_CODE (type) == ARRAY_TYPE
+      && TREE_CODE (expr.value) == STRING_CST
+      && expr.original_code != STRING_CST)
+    pedwarn_init (input_location, OPT_Wpedantic,
+                 "array initialized from parenthesized string constant");
+}
+
+/* Digest the parser output INIT as an initializer for type TYPE.
+   Return a C expression of type TYPE to represent the initial value.
+
+   If ORIGTYPE is not NULL_TREE, it is the original type of INIT.
+
+   NULL_POINTER_CONSTANT is true if INIT is a null pointer constant.
+
+   If INIT is a string constant, STRICT_STRING is true if it is
+   unparenthesized or we should not warn here for it being parenthesized.
+   For other types of INIT, STRICT_STRING is not used.
+
+   INIT_LOC is the location of the INIT.
+
+   REQUIRE_CONSTANT requests an error if non-constant initializers or
+   elements are seen.  */
+
+static tree
+digest_init (location_t init_loc, tree type, tree init, tree origtype,
+            bool null_pointer_constant, bool strict_string,
+            int require_constant)
+{
+  enum tree_code code = TREE_CODE (type);
+  tree inside_init = init;
+  tree semantic_type = NULL_TREE;
+  bool maybe_const = true;
+
+  if (type == error_mark_node
+      || !init
+      || init == error_mark_node
+      || TREE_TYPE (init) == error_mark_node)
+    return error_mark_node;
+
+  STRIP_TYPE_NOPS (inside_init);
+
+  if (TREE_CODE (inside_init) == EXCESS_PRECISION_EXPR)
+    {
+      semantic_type = TREE_TYPE (inside_init);
+      inside_init = TREE_OPERAND (inside_init, 0);
+    }
+  inside_init = c_fully_fold (inside_init, require_constant, &maybe_const);
+  inside_init = decl_constant_value_for_optimization (inside_init);
+
+  /* Initialization of an array of chars from a string constant
+     optionally enclosed in braces.  */
+
+  if (code == ARRAY_TYPE && inside_init
+      && TREE_CODE (inside_init) == STRING_CST)
+    {
+      tree typ1 = TYPE_MAIN_VARIANT (TREE_TYPE (type));
+      /* Note that an array could be both an array of character type
+        and an array of wchar_t if wchar_t is signed char or unsigned
+        char.  */
+      bool char_array = (typ1 == char_type_node
+                        || typ1 == signed_char_type_node
+                        || typ1 == unsigned_char_type_node);
+      bool wchar_array = !!comptypes (typ1, wchar_type_node);
+      bool char16_array = !!comptypes (typ1, char16_type_node);
+      bool char32_array = !!comptypes (typ1, char32_type_node);
+
+      if (char_array || wchar_array || char16_array || char32_array)
+       {
+         struct c_expr expr;
+         tree typ2 = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (inside_init)));
+         expr.value = inside_init;
+         expr.original_code = (strict_string ? STRING_CST : ERROR_MARK);
+         expr.original_type = NULL;
+         maybe_warn_string_init (type, expr);
+
+         if (TYPE_DOMAIN (type) && !TYPE_MAX_VALUE (TYPE_DOMAIN (type)))
+           pedwarn_init (init_loc, OPT_Wpedantic,
+                         "initialization of a flexible array member");
+
+         if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (inside_init)),
+                        TYPE_MAIN_VARIANT (type)))
+           return inside_init;
+
+         if (char_array)
+           {
+             if (typ2 != char_type_node)
+               {
+                 error_init ("char-array initialized from wide string");
+                 return error_mark_node;
+               }
+           }
+         else
+           {
+             if (typ2 == char_type_node)
+               {
+                 error_init ("wide character array initialized from non-wide "
+                             "string");
+                 return error_mark_node;
+               }
+             else if (!comptypes(typ1, typ2))
+               {
+                 error_init ("wide character array initialized from "
+                             "incompatible wide string");
+                 return error_mark_node;
+               }
+           }
+
+         TREE_TYPE (inside_init) = type;
+         if (TYPE_DOMAIN (type) != 0
+             && TYPE_SIZE (type) != 0
+             && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST)
+           {
+             unsigned HOST_WIDE_INT len = TREE_STRING_LENGTH (inside_init);
+
+             /* Subtract the size of a single (possibly wide) character
+                because it's ok to ignore the terminating null char
+                that is counted in the length of the constant.  */
+             if (0 > compare_tree_int (TYPE_SIZE_UNIT (type),
+                                       (len
+                                        - (TYPE_PRECISION (typ1)
+                                           / BITS_PER_UNIT))))
+               pedwarn_init (init_loc, 0,
+                             ("initializer-string for array of chars "
+                              "is too long"));
+             else if (warn_cxx_compat
+                      && 0 > compare_tree_int (TYPE_SIZE_UNIT (type), len))
+               warning_at (init_loc, OPT_Wc___compat,
+                           ("initializer-string for array chars "
+                            "is too long for C++"));
+           }
+
+         return inside_init;
+       }
+      else if (INTEGRAL_TYPE_P (typ1))
+       {
+         error_init ("array of inappropriate type initialized "
+                     "from string constant");
+         return error_mark_node;
+       }
+    }
+
+  /* Build a VECTOR_CST from a *constant* vector constructor.  If the
+     vector constructor is not constant (e.g. {1,2,3,foo()}) then punt
+     below and handle as a constructor.  */
+  if (code == VECTOR_TYPE
+      && TREE_CODE (TREE_TYPE (inside_init)) == VECTOR_TYPE
+      && vector_types_convertible_p (TREE_TYPE (inside_init), type, true)
+      && TREE_CONSTANT (inside_init))
+    {
+      if (TREE_CODE (inside_init) == VECTOR_CST
+         && comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (inside_init)),
+                       TYPE_MAIN_VARIANT (type)))
+       return inside_init;
+
+      if (TREE_CODE (inside_init) == CONSTRUCTOR)
+       {
+         unsigned HOST_WIDE_INT ix;
+         tree value;
+         bool constant_p = true;
+
+         /* Iterate through elements and check if all constructor
+            elements are *_CSTs.  */
+         FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (inside_init), ix, value)
+           if (!CONSTANT_CLASS_P (value))
+             {
+               constant_p = false;
+               break;
+             }
+
+         if (constant_p)
+           return build_vector_from_ctor (type,
+                                          CONSTRUCTOR_ELTS (inside_init));
+       }
+    }
+
+  if (warn_sequence_point)
+    verify_sequence_points (inside_init);
+
+  /* Any type can be initialized
+     from an expression of the same type, optionally with braces.  */
+
+  if (inside_init && TREE_TYPE (inside_init) != 0
+      && (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (inside_init)),
+                    TYPE_MAIN_VARIANT (type))
+         || (code == ARRAY_TYPE
+             && comptypes (TREE_TYPE (inside_init), type))
+         || (code == VECTOR_TYPE
+             && comptypes (TREE_TYPE (inside_init), type))
+         || (code == POINTER_TYPE
+             && TREE_CODE (TREE_TYPE (inside_init)) == ARRAY_TYPE
+             && comptypes (TREE_TYPE (TREE_TYPE (inside_init)),
+                           TREE_TYPE (type)))))
+    {
+      if (code == POINTER_TYPE)
+       {
+         if (TREE_CODE (TREE_TYPE (inside_init)) == ARRAY_TYPE)
+           {
+             if (TREE_CODE (inside_init) == STRING_CST
+                 || TREE_CODE (inside_init) == COMPOUND_LITERAL_EXPR)
+               inside_init = array_to_pointer_conversion
+                 (init_loc, inside_init);
+             else
+               {
+                 error_init ("invalid use of non-lvalue array");
+                 return error_mark_node;
+               }
+           }
+       }
+
+      if (code == VECTOR_TYPE)
+       /* Although the types are compatible, we may require a
+          conversion.  */
+       inside_init = convert (type, inside_init);
+
+      if (require_constant
+         && (code == VECTOR_TYPE || !flag_isoc99)
+         && TREE_CODE (inside_init) == COMPOUND_LITERAL_EXPR)
+       {
+         /* As an extension, allow initializing objects with static storage
+            duration with compound literals (which are then treated just as
+            the brace enclosed list they contain).  Also allow this for
+            vectors, as we can only assign them with compound literals.  */
+         tree decl = COMPOUND_LITERAL_EXPR_DECL (inside_init);
+         inside_init = DECL_INITIAL (decl);
+       }
+
+      if (code == ARRAY_TYPE && TREE_CODE (inside_init) != STRING_CST
+         && TREE_CODE (inside_init) != CONSTRUCTOR)
+       {
+         error_init ("array initialized from non-constant array expression");
+         return error_mark_node;
+       }
+
+      /* Compound expressions can only occur here if -Wpedantic or
+        -pedantic-errors is specified.  In the later case, we always want
+        an error.  In the former case, we simply want a warning.  */
+      if (require_constant && pedantic
+         && TREE_CODE (inside_init) == COMPOUND_EXPR)
+       {
+         inside_init
+           = valid_compound_expr_initializer (inside_init,
+                                              TREE_TYPE (inside_init));
+         if (inside_init == error_mark_node)
+           error_init ("initializer element is not constant");
+         else
+           pedwarn_init (init_loc, OPT_Wpedantic,
+                         "initializer element is not constant");
+         if (flag_pedantic_errors)
+           inside_init = error_mark_node;
+       }
+      else if (require_constant
+              && !initializer_constant_valid_p (inside_init,
+                                                TREE_TYPE (inside_init)))
+       {
+         error_init ("initializer element is not constant");
+         inside_init = error_mark_node;
+       }
+      else if (require_constant && !maybe_const)
+       pedwarn_init (init_loc, 0,
+                     "initializer element is not a constant expression");
+
+      /* Added to enable additional -Wsuggest-attribute=format warnings.  */
+      if (TREE_CODE (TREE_TYPE (inside_init)) == POINTER_TYPE)
+       inside_init = convert_for_assignment (init_loc, type, inside_init,
+                                             origtype,
+                                             ic_init, null_pointer_constant,
+                                             NULL_TREE, NULL_TREE, 0);
+      return inside_init;
+    }
+
+  /* Handle scalar types, including conversions.  */
+
+  if (code == INTEGER_TYPE || code == REAL_TYPE || code == FIXED_POINT_TYPE
+      || code == POINTER_TYPE || code == ENUMERAL_TYPE || code == BOOLEAN_TYPE
+      || code == COMPLEX_TYPE || code == VECTOR_TYPE)
+    {
+      if (TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE
+         && (TREE_CODE (init) == STRING_CST
+             || TREE_CODE (init) == COMPOUND_LITERAL_EXPR))
+       inside_init = init = array_to_pointer_conversion (init_loc, init);
+      if (semantic_type)
+       inside_init = build1 (EXCESS_PRECISION_EXPR, semantic_type,
+                             inside_init);
+      inside_init
+       = convert_for_assignment (init_loc, type, inside_init, origtype,
+                                 ic_init, null_pointer_constant,
+                                 NULL_TREE, NULL_TREE, 0);
+
+      /* Check to see if we have already given an error message.  */
+      if (inside_init == error_mark_node)
+       ;
+      else if (require_constant && !TREE_CONSTANT (inside_init))
+       {
+         error_init ("initializer element is not constant");
+         inside_init = error_mark_node;
+       }
+      else if (require_constant
+              && !initializer_constant_valid_p (inside_init,
+                                                TREE_TYPE (inside_init)))
+       {
+         error_init ("initializer element is not computable at load time");
+         inside_init = error_mark_node;
+       }
+      else if (require_constant && !maybe_const)
+       pedwarn_init (init_loc, 0,
+                     "initializer element is not a constant expression");
+
+      return inside_init;
+    }
+
+  /* Come here only for records and arrays.  */
+
+  if (COMPLETE_TYPE_P (type) && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
+    {
+      error_init ("variable-sized object may not be initialized");
+      return error_mark_node;
+    }
+
+  error_init ("invalid initializer");
+  return error_mark_node;
+}
+\f
+/* Handle initializers that use braces.  */
+
+/* Type of object we are accumulating a constructor for.
+   This type is always a RECORD_TYPE, UNION_TYPE or ARRAY_TYPE.  */
+static tree constructor_type;
+
+/* For a RECORD_TYPE or UNION_TYPE, this is the chain of fields
+   left to fill.  */
+static tree constructor_fields;
+
+/* For an ARRAY_TYPE, this is the specified index
+   at which to store the next element we get.  */
+static tree constructor_index;
+
+/* For an ARRAY_TYPE, this is the maximum index.  */
+static tree constructor_max_index;
+
+/* For a RECORD_TYPE, this is the first field not yet written out.  */
+static tree constructor_unfilled_fields;
+
+/* For an ARRAY_TYPE, this is the index of the first element
+   not yet written out.  */
+static tree constructor_unfilled_index;
+
+/* In a RECORD_TYPE, the byte index of the next consecutive field.
+   This is so we can generate gaps between fields, when appropriate.  */
+static tree constructor_bit_index;
+
+/* If we are saving up the elements rather than allocating them,
+   this is the list of elements so far (in reverse order,
+   most recent first).  */
+static VEC(constructor_elt,gc) *constructor_elements;
+
+/* 1 if constructor should be incrementally stored into a constructor chain,
+   0 if all the elements should be kept in AVL tree.  */
+static int constructor_incremental;
+
+/* 1 if so far this constructor's elements are all compile-time constants.  */
+static int constructor_constant;
+
+/* 1 if so far this constructor's elements are all valid address constants.  */
+static int constructor_simple;
+
+/* 1 if this constructor has an element that cannot be part of a
+   constant expression.  */
+static int constructor_nonconst;
+
+/* 1 if this constructor is erroneous so far.  */
+static int constructor_erroneous;
+
+/* Structure for managing pending initializer elements, organized as an
+   AVL tree.  */
+
+struct init_node
+{
+  struct init_node *left, *right;
+  struct init_node *parent;
+  int balance;
+  tree purpose;
+  tree value;
+  tree origtype;
+};
+
+/* Tree of pending elements at this constructor level.
+   These are elements encountered out of order
+   which belong at places we haven't reached yet in actually
+   writing the output.
+   Will never hold tree nodes across GC runs.  */
+static struct init_node *constructor_pending_elts;
+
+/* The SPELLING_DEPTH of this constructor.  */
+static int constructor_depth;
+
+/* DECL node for which an initializer is being read.
+   0 means we are reading a constructor expression
+   such as (struct foo) {...}.  */
+static tree constructor_decl;
+
+/* Nonzero if this is an initializer for a top-level decl.  */
+static int constructor_top_level;
+
+/* Nonzero if there were any member designators in this initializer.  */
+static int constructor_designated;
+
+/* Nesting depth of designator list.  */
+static int designator_depth;
+
+/* Nonzero if there were diagnosed errors in this designator list.  */
+static int designator_erroneous;
+
+\f
+/* This stack has a level for each implicit or explicit level of
+   structuring in the initializer, including the outermost one.  It
+   saves the values of most of the variables above.  */
+
+struct constructor_range_stack;
+
+struct constructor_stack
+{
+  struct constructor_stack *next;
+  tree type;
+  tree fields;
+  tree index;
+  tree max_index;
+  tree unfilled_index;
+  tree unfilled_fields;
+  tree bit_index;
+  VEC(constructor_elt,gc) *elements;
+  struct init_node *pending_elts;
+  int offset;
+  int depth;
+  /* If value nonzero, this value should replace the entire
+     constructor at this level.  */
+  struct c_expr replacement_value;
+  struct constructor_range_stack *range_stack;
+  char constant;
+  char simple;
+  char nonconst;
+  char implicit;
+  char erroneous;
+  char outer;
+  char incremental;
+  char designated;
+};
+
+static struct constructor_stack *constructor_stack;
+
+/* This stack represents designators from some range designator up to
+   the last designator in the list.  */
+
+struct constructor_range_stack
+{
+  struct constructor_range_stack *next, *prev;
+  struct constructor_stack *stack;
+  tree range_start;
+  tree index;
+  tree range_end;
+  tree fields;
+};
+
+static struct constructor_range_stack *constructor_range_stack;
+
+/* This stack records separate initializers that are nested.
+   Nested initializers can't happen in ANSI C, but GNU C allows them
+   in cases like { ... (struct foo) { ... } ... }.  */
+
+struct initializer_stack
+{
+  struct initializer_stack *next;
+  tree decl;
+  struct constructor_stack *constructor_stack;
+  struct constructor_range_stack *constructor_range_stack;
+  VEC(constructor_elt,gc) *elements;
+  struct spelling *spelling;
+  struct spelling *spelling_base;
+  int spelling_size;
+  char top_level;
+  char require_constant_value;
+  char require_constant_elements;
+};
+
+static struct initializer_stack *initializer_stack;
+\f
+/* Prepare to parse and output the initializer for variable DECL.  */
+
+void
+start_init (tree decl, tree asmspec_tree ATTRIBUTE_UNUSED, int top_level)
+{
+  const char *locus;
+  struct initializer_stack *p = XNEW (struct initializer_stack);
+
+  p->decl = constructor_decl;
+  p->require_constant_value = require_constant_value;
+  p->require_constant_elements = require_constant_elements;
+  p->constructor_stack = constructor_stack;
+  p->constructor_range_stack = constructor_range_stack;
+  p->elements = constructor_elements;
+  p->spelling = spelling;
+  p->spelling_base = spelling_base;
+  p->spelling_size = spelling_size;
+  p->top_level = constructor_top_level;
+  p->next = initializer_stack;
+  initializer_stack = p;
+
+  constructor_decl = decl;
+  constructor_designated = 0;
+  constructor_top_level = top_level;
+
+  if (decl != 0 && decl != error_mark_node)
+    {
+      require_constant_value = TREE_STATIC (decl);
+      require_constant_elements
+       = ((TREE_STATIC (decl) || (pedantic && !flag_isoc99))
+          /* For a scalar, you can always use any value to initialize,
+             even within braces.  */
+          && (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
+              || TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE
+              || TREE_CODE (TREE_TYPE (decl)) == UNION_TYPE
+              || TREE_CODE (TREE_TYPE (decl)) == QUAL_UNION_TYPE));
+      locus = identifier_to_locale (IDENTIFIER_POINTER (DECL_NAME (decl)));
+    }
+  else
+    {
+      require_constant_value = 0;
+      require_constant_elements = 0;
+      locus = _("(anonymous)");
+    }
+
+  constructor_stack = 0;
+  constructor_range_stack = 0;
+
+  missing_braces_mentioned = 0;
+
+  spelling_base = 0;
+  spelling_size = 0;
+  RESTORE_SPELLING_DEPTH (0);
+
+  if (locus)
+    push_string (locus);
+}
+
+void
+finish_init (void)
+{
+  struct initializer_stack *p = initializer_stack;
+
+  /* Free the whole constructor stack of this initializer.  */
+  while (constructor_stack)
+    {
+      struct constructor_stack *q = constructor_stack;
+      constructor_stack = q->next;
+      free (q);
+    }
+
+  gcc_assert (!constructor_range_stack);
+
+  /* Pop back to the data of the outer initializer (if any).  */
+  free (spelling_base);
+
+  constructor_decl = p->decl;
+  require_constant_value = p->require_constant_value;
+  require_constant_elements = p->require_constant_elements;
+  constructor_stack = p->constructor_stack;
+  constructor_range_stack = p->constructor_range_stack;
+  constructor_elements = p->elements;
+  spelling = p->spelling;
+  spelling_base = p->spelling_base;
+  spelling_size = p->spelling_size;
+  constructor_top_level = p->top_level;
+  initializer_stack = p->next;
+  free (p);
+}
+\f
+/* Call here when we see the initializer is surrounded by braces.
+   This is instead of a call to push_init_level;
+   it is matched by a call to pop_init_level.
+
+   TYPE is the type to initialize, for a constructor expression.
+   For an initializer for a decl, TYPE is zero.  */
+
+void
+really_start_incremental_init (tree type)
+{
+  struct constructor_stack *p = XNEW (struct constructor_stack);
+
+  if (type == 0)
+    type = TREE_TYPE (constructor_decl);
+
+  if (TREE_CODE (type) == VECTOR_TYPE
+      && TYPE_VECTOR_OPAQUE (type))
+    error ("opaque vector types cannot be initialized");
+
+  p->type = constructor_type;
+  p->fields = constructor_fields;
+  p->index = constructor_index;
+  p->max_index = constructor_max_index;
+  p->unfilled_index = constructor_unfilled_index;
+  p->unfilled_fields = constructor_unfilled_fields;
+  p->bit_index = constructor_bit_index;
+  p->elements = constructor_elements;
+  p->constant = constructor_constant;
+  p->simple = constructor_simple;
+  p->nonconst = constructor_nonconst;
+  p->erroneous = constructor_erroneous;
+  p->pending_elts = constructor_pending_elts;
+  p->depth = constructor_depth;
+  p->replacement_value.value = 0;
+  p->replacement_value.original_code = ERROR_MARK;
+  p->replacement_value.original_type = NULL;
+  p->implicit = 0;
+  p->range_stack = 0;
+  p->outer = 0;
+  p->incremental = constructor_incremental;
+  p->designated = constructor_designated;
+  p->next = 0;
+  constructor_stack = p;
+
+  constructor_constant = 1;
+  constructor_simple = 1;
+  constructor_nonconst = 0;
+  constructor_depth = SPELLING_DEPTH ();
+  constructor_elements = 0;
+  constructor_pending_elts = 0;
+  constructor_type = type;
+  constructor_incremental = 1;
+  constructor_designated = 0;
+  designator_depth = 0;
+  designator_erroneous = 0;
+
+  if (TREE_CODE (constructor_type) == RECORD_TYPE
+      || TREE_CODE (constructor_type) == UNION_TYPE)
+    {
+      constructor_fields = TYPE_FIELDS (constructor_type);
+      /* Skip any nameless bit fields at the beginning.  */
+      while (constructor_fields != 0 && DECL_C_BIT_FIELD (constructor_fields)
+            && DECL_NAME (constructor_fields) == 0)
+       constructor_fields = DECL_CHAIN (constructor_fields);
+
+      constructor_unfilled_fields = constructor_fields;
+      constructor_bit_index = bitsize_zero_node;
+    }
+  else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
+    {
+      if (TYPE_DOMAIN (constructor_type))
+       {
+         constructor_max_index
+           = TYPE_MAX_VALUE (TYPE_DOMAIN (constructor_type));
+
+         /* Detect non-empty initializations of zero-length arrays.  */
+         if (constructor_max_index == NULL_TREE
+             && TYPE_SIZE (constructor_type))
+           constructor_max_index = integer_minus_one_node;
+
+         /* constructor_max_index needs to be an INTEGER_CST.  Attempts
+            to initialize VLAs will cause a proper error; avoid tree
+            checking errors as well by setting a safe value.  */
+         if (constructor_max_index
+             && TREE_CODE (constructor_max_index) != INTEGER_CST)
+           constructor_max_index = integer_minus_one_node;
+
+         constructor_index
+           = convert (bitsizetype,
+                      TYPE_MIN_VALUE (TYPE_DOMAIN (constructor_type)));
+       }
+      else
+       {
+         constructor_index = bitsize_zero_node;
+         constructor_max_index = NULL_TREE;
+       }
+
+      constructor_unfilled_index = constructor_index;
+    }
+  else if (TREE_CODE (constructor_type) == VECTOR_TYPE)
+    {
+      /* Vectors are like simple fixed-size arrays.  */
+      constructor_max_index =
+       bitsize_int (TYPE_VECTOR_SUBPARTS (constructor_type) - 1);
+      constructor_index = bitsize_zero_node;
+      constructor_unfilled_index = constructor_index;
+    }
+  else
+    {
+      /* Handle the case of int x = {5}; */
+      constructor_fields = constructor_type;
+      constructor_unfilled_fields = constructor_type;
+    }
+}
+\f
+/* Push down into a subobject, for initialization.
+   If this is for an explicit set of braces, IMPLICIT is 0.
+   If it is because the next element belongs at a lower level,
+   IMPLICIT is 1 (or 2 if the push is because of designator list).  */
+
+void
+push_init_level (int implicit, struct obstack * braced_init_obstack)
+{
+  struct constructor_stack *p;
+  tree value = NULL_TREE;
+
+  /* If we've exhausted any levels that didn't have braces,
+     pop them now.  If implicit == 1, this will have been done in
+     process_init_element; do not repeat it here because in the case
+     of excess initializers for an empty aggregate this leads to an
+     infinite cycle of popping a level and immediately recreating
+     it.  */
+  if (implicit != 1)
+    {
+      while (constructor_stack->implicit)
+       {
+         if ((TREE_CODE (constructor_type) == RECORD_TYPE
+              || TREE_CODE (constructor_type) == UNION_TYPE)
+             && constructor_fields == 0)
+           process_init_element (pop_init_level (1, braced_init_obstack),
+                                 true, braced_init_obstack);
+         else if (TREE_CODE (constructor_type) == ARRAY_TYPE
+                  && constructor_max_index
+                  && tree_int_cst_lt (constructor_max_index,
+                                      constructor_index))
+           process_init_element (pop_init_level (1, braced_init_obstack),
+                                 true, braced_init_obstack);
+         else
+           break;
+       }
+    }
+
+  /* Unless this is an explicit brace, we need to preserve previous
+     content if any.  */
+  if (implicit)
+    {
+      if ((TREE_CODE (constructor_type) == RECORD_TYPE
+          || TREE_CODE (constructor_type) == UNION_TYPE)
+         && constructor_fields)
+       value = find_init_member (constructor_fields, braced_init_obstack);
+      else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
+       value = find_init_member (constructor_index, braced_init_obstack);
+    }
+
+  p = XNEW (struct constructor_stack);
+  p->type = constructor_type;
+  p->fields = constructor_fields;
+  p->index = constructor_index;
+  p->max_index = constructor_max_index;
+  p->unfilled_index = constructor_unfilled_index;
+  p->unfilled_fields = constructor_unfilled_fields;
+  p->bit_index = constructor_bit_index;
+  p->elements = constructor_elements;
+  p->constant = constructor_constant;
+  p->simple = constructor_simple;
+  p->nonconst = constructor_nonconst;
+  p->erroneous = constructor_erroneous;
+  p->pending_elts = constructor_pending_elts;
+  p->depth = constructor_depth;
+  p->replacement_value.value = 0;
+  p->replacement_value.original_code = ERROR_MARK;
+  p->replacement_value.original_type = NULL;
+  p->implicit = implicit;
+  p->outer = 0;
+  p->incremental = constructor_incremental;
+  p->designated = constructor_designated;
+  p->next = constructor_stack;
+  p->range_stack = 0;
+  constructor_stack = p;
+
+  constructor_constant = 1;
+  constructor_simple = 1;
+  constructor_nonconst = 0;
+  constructor_depth = SPELLING_DEPTH ();
+  constructor_elements = 0;
+  constructor_incremental = 1;
+  constructor_designated = 0;
+  constructor_pending_elts = 0;
+  if (!implicit)
+    {
+      p->range_stack = constructor_range_stack;
+      constructor_range_stack = 0;
+      designator_depth = 0;
+      designator_erroneous = 0;
+    }
+
+  /* Don't die if an entire brace-pair level is superfluous
+     in the containing level.  */
+  if (constructor_type == 0)
+    ;
+  else if (TREE_CODE (constructor_type) == RECORD_TYPE
+          || TREE_CODE (constructor_type) == UNION_TYPE)
+    {
+      /* Don't die if there are extra init elts at the end.  */
+      if (constructor_fields == 0)
+       constructor_type = 0;
+      else
+       {
+         constructor_type = TREE_TYPE (constructor_fields);
+         push_member_name (constructor_fields);
+         constructor_depth++;
+       }
+    }
+  else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
+    {
+      constructor_type = TREE_TYPE (constructor_type);
+      push_array_bounds (tree_low_cst (constructor_index, 1));
+      constructor_depth++;
+    }
+
+  if (constructor_type == 0)
+    {
+      error_init ("extra brace group at end of initializer");
+      constructor_fields = 0;
+      constructor_unfilled_fields = 0;
+      return;
+    }
+
+  if (value && TREE_CODE (value) == CONSTRUCTOR)
+    {
+      constructor_constant = TREE_CONSTANT (value);
+      constructor_simple = TREE_STATIC (value);
+      constructor_nonconst = CONSTRUCTOR_NON_CONST (value);
+      constructor_elements = CONSTRUCTOR_ELTS (value);
+      if (!VEC_empty (constructor_elt, constructor_elements)
+         && (TREE_CODE (constructor_type) == RECORD_TYPE
+             || TREE_CODE (constructor_type) == ARRAY_TYPE))
+       set_nonincremental_init (braced_init_obstack);
+    }
+
+  if (implicit == 1 && warn_missing_braces && !missing_braces_mentioned)
+    {
+      missing_braces_mentioned = 1;
+      warning_init (OPT_Wmissing_braces, "missing braces around initializer");
+    }
+
+  if (TREE_CODE (constructor_type) == RECORD_TYPE
+          || TREE_CODE (constructor_type) == UNION_TYPE)
+    {
+      constructor_fields = TYPE_FIELDS (constructor_type);
+      /* Skip any nameless bit fields at the beginning.  */
+      while (constructor_fields != 0 && DECL_C_BIT_FIELD (constructor_fields)
+            && DECL_NAME (constructor_fields) == 0)
+       constructor_fields = DECL_CHAIN (constructor_fields);
+
+      constructor_unfilled_fields = constructor_fields;
+      constructor_bit_index = bitsize_zero_node;
+    }
+  else if (TREE_CODE (constructor_type) == VECTOR_TYPE)
+    {
+      /* Vectors are like simple fixed-size arrays.  */
+      constructor_max_index =
+       bitsize_int (TYPE_VECTOR_SUBPARTS (constructor_type) - 1);
+      constructor_index = bitsize_int (0);
+      constructor_unfilled_index = constructor_index;
+    }
+  else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
+    {
+      if (TYPE_DOMAIN (constructor_type))
+       {
+         constructor_max_index
+           = TYPE_MAX_VALUE (TYPE_DOMAIN (constructor_type));
+
+         /* Detect non-empty initializations of zero-length arrays.  */
+         if (constructor_max_index == NULL_TREE
+             && TYPE_SIZE (constructor_type))
+           constructor_max_index = integer_minus_one_node;
+
+         /* constructor_max_index needs to be an INTEGER_CST.  Attempts
+            to initialize VLAs will cause a proper error; avoid tree
+            checking errors as well by setting a safe value.  */
+         if (constructor_max_index
+             && TREE_CODE (constructor_max_index) != INTEGER_CST)
+           constructor_max_index = integer_minus_one_node;
+
+         constructor_index
+           = convert (bitsizetype,
+                      TYPE_MIN_VALUE (TYPE_DOMAIN (constructor_type)));
+       }
+      else
+       constructor_index = bitsize_zero_node;
+
+      constructor_unfilled_index = constructor_index;
+      if (value && TREE_CODE (value) == STRING_CST)
+       {
+         /* We need to split the char/wchar array into individual
+            characters, so that we don't have to special case it
+            everywhere.  */
+         set_nonincremental_init_from_string (value, braced_init_obstack);
+       }
+    }
+  else
+    {
+      if (constructor_type != error_mark_node)
+       warning_init (0, "braces around scalar initializer");
+      constructor_fields = constructor_type;
+      constructor_unfilled_fields = constructor_type;
+    }
+}
+
+/* At the end of an implicit or explicit brace level,
+   finish up that level of constructor.  If a single expression
+   with redundant braces initialized that level, return the
+   c_expr structure for that expression.  Otherwise, the original_code
+   element is set to ERROR_MARK.
+   If we were outputting the elements as they are read, return 0 as the value
+   from inner levels (process_init_element ignores that),
+   but return error_mark_node as the value from the outermost level
+   (that's what we want to put in DECL_INITIAL).
+   Otherwise, return a CONSTRUCTOR expression as the value.  */
+
+struct c_expr
+pop_init_level (int implicit, struct obstack * braced_init_obstack)
+{
+  struct constructor_stack *p;
+  struct c_expr ret;
+  ret.value = 0;
+  ret.original_code = ERROR_MARK;
+  ret.original_type = NULL;
+
+  if (implicit == 0)
+    {
+      /* When we come to an explicit close brace,
+        pop any inner levels that didn't have explicit braces.  */
+      while (constructor_stack->implicit)
+       {
+         process_init_element (pop_init_level (1, braced_init_obstack),
+                               true, braced_init_obstack);
+       }
+      gcc_assert (!constructor_range_stack);
+    }
+
+  /* Now output all pending elements.  */
+  constructor_incremental = 1;
+  output_pending_init_elements (1, braced_init_obstack);
+
+  p = constructor_stack;
+
+  /* Error for initializing a flexible array member, or a zero-length
+     array member in an inappropriate context.  */
+  if (constructor_type && constructor_fields
+      && TREE_CODE (constructor_type) == ARRAY_TYPE
+      && TYPE_DOMAIN (constructor_type)
+      && !TYPE_MAX_VALUE (TYPE_DOMAIN (constructor_type)))
+    {
+      /* Silently discard empty initializations.  The parser will
+        already have pedwarned for empty brackets.  */
+      if (integer_zerop (constructor_unfilled_index))
+       constructor_type = NULL_TREE;
+      else
+       {
+         gcc_assert (!TYPE_SIZE (constructor_type));
+
+         if (constructor_depth > 2)
+           error_init ("initialization of flexible array member in a nested context");
+         else
+           pedwarn_init (input_location, OPT_Wpedantic,
+                         "initialization of a flexible array member");
+
+         /* We have already issued an error message for the existence
+            of a flexible array member not at the end of the structure.
+            Discard the initializer so that we do not die later.  */
+         if (DECL_CHAIN (constructor_fields) != NULL_TREE)
+           constructor_type = NULL_TREE;
+       }
+    }
+
+  /* Warn when some struct elements are implicitly initialized to zero.  */
+  if (warn_missing_field_initializers
+      && constructor_type
+      && TREE_CODE (constructor_type) == RECORD_TYPE
+      && constructor_unfilled_fields)
+    {
+       bool constructor_zeroinit =
+        (VEC_length (constructor_elt, constructor_elements) == 1
+         && integer_zerop
+             (VEC_index (constructor_elt, constructor_elements, 0)->value));
+
+       /* Do not warn for flexible array members or zero-length arrays.  */
+       while (constructor_unfilled_fields
+              && (!DECL_SIZE (constructor_unfilled_fields)
+                  || integer_zerop (DECL_SIZE (constructor_unfilled_fields))))
+         constructor_unfilled_fields = DECL_CHAIN (constructor_unfilled_fields);
+
+       if (constructor_unfilled_fields
+           /* Do not warn if this level of the initializer uses member
+              designators; it is likely to be deliberate.  */
+           && !constructor_designated
+           /* Do not warn about initializing with ` = {0}'.  */
+           && !constructor_zeroinit)
+         {
+           if (warning_at (input_location, OPT_Wmissing_field_initializers,
+                           "missing initializer for field %qD of %qT",
+                           constructor_unfilled_fields,
+                           constructor_type))
+             inform (DECL_SOURCE_LOCATION (constructor_unfilled_fields),
+                     "%qD declared here", constructor_unfilled_fields);
+         }
+    }
+
+  /* Pad out the end of the structure.  */
+  if (p->replacement_value.value)
+    /* If this closes a superfluous brace pair,
+       just pass out the element between them.  */
+    ret = p->replacement_value;
+  else if (constructor_type == 0)
+    ;
+  else if (TREE_CODE (constructor_type) != RECORD_TYPE
+          && TREE_CODE (constructor_type) != UNION_TYPE
+          && TREE_CODE (constructor_type) != ARRAY_TYPE
+          && TREE_CODE (constructor_type) != VECTOR_TYPE)
+    {
+      /* A nonincremental scalar initializer--just return
+        the element, after verifying there is just one.  */
+      if (VEC_empty (constructor_elt,constructor_elements))
+       {
+         if (!constructor_erroneous)
+           error_init ("empty scalar initializer");
+         ret.value = error_mark_node;
+       }
+      else if (VEC_length (constructor_elt,constructor_elements) != 1)
+       {
+         error_init ("extra elements in scalar initializer");
+         ret.value = VEC_index (constructor_elt,constructor_elements,0)->value;
+       }
+      else
+       ret.value = VEC_index (constructor_elt,constructor_elements,0)->value;
+    }
+  else
+    {
+      if (constructor_erroneous)
+       ret.value = error_mark_node;
+      else
+       {
+         ret.value = build_constructor (constructor_type,
+                                        constructor_elements);
+         if (constructor_constant)
+           TREE_CONSTANT (ret.value) = 1;
+         if (constructor_constant && constructor_simple)
+           TREE_STATIC (ret.value) = 1;
+         if (constructor_nonconst)
+           CONSTRUCTOR_NON_CONST (ret.value) = 1;
+       }
+    }
+
+  if (ret.value && TREE_CODE (ret.value) != CONSTRUCTOR)
+    {
+      if (constructor_nonconst)
+       ret.original_code = C_MAYBE_CONST_EXPR;
+      else if (ret.original_code == C_MAYBE_CONST_EXPR)
+       ret.original_code = ERROR_MARK;
+    }
+
+  constructor_type = p->type;
+  constructor_fields = p->fields;
+  constructor_index = p->index;
+  constructor_max_index = p->max_index;
+  constructor_unfilled_index = p->unfilled_index;
+  constructor_unfilled_fields = p->unfilled_fields;
+  constructor_bit_index = p->bit_index;
+  constructor_elements = p->elements;
+  constructor_constant = p->constant;
+  constructor_simple = p->simple;
+  constructor_nonconst = p->nonconst;
+  constructor_erroneous = p->erroneous;
+  constructor_incremental = p->incremental;
+  constructor_designated = p->designated;
+  constructor_pending_elts = p->pending_elts;
+  constructor_depth = p->depth;
+  if (!p->implicit)
+    constructor_range_stack = p->range_stack;
+  RESTORE_SPELLING_DEPTH (constructor_depth);
+
+  constructor_stack = p->next;
+  free (p);
+
+  if (ret.value == 0 && constructor_stack == 0)
+    ret.value = error_mark_node;
+  return ret;
+}
+
+/* Common handling for both array range and field name designators.
+   ARRAY argument is nonzero for array ranges.  Returns zero for success.  */
+
+static int
+set_designator (int array, struct obstack * braced_init_obstack)
+{
+  tree subtype;
+  enum tree_code subcode;
+
+  /* Don't die if an entire brace-pair level is superfluous
+     in the containing level.  */
+  if (constructor_type == 0)
+    return 1;
+
+  /* If there were errors in this designator list already, bail out
+     silently.  */
+  if (designator_erroneous)
+    return 1;
+
+  if (!designator_depth)
+    {
+      gcc_assert (!constructor_range_stack);
+
+      /* Designator list starts at the level of closest explicit
+        braces.  */
+      while (constructor_stack->implicit)
+       {
+         process_init_element (pop_init_level (1, braced_init_obstack),
+                               true, braced_init_obstack);
+       }
+      constructor_designated = 1;
+      return 0;
+    }
+
+  switch (TREE_CODE (constructor_type))
+    {
+    case  RECORD_TYPE:
+    case  UNION_TYPE:
+      subtype = TREE_TYPE (constructor_fields);
+      if (subtype != error_mark_node)
+       subtype = TYPE_MAIN_VARIANT (subtype);
+      break;
+    case ARRAY_TYPE:
+      subtype = TYPE_MAIN_VARIANT (TREE_TYPE (constructor_type));
+      break;
+    default:
+      gcc_unreachable ();
+    }
+
+  subcode = TREE_CODE (subtype);
+  if (array && subcode != ARRAY_TYPE)
+    {
+      error_init ("array index in non-array initializer");
+      return 1;
+    }
+  else if (!array && subcode != RECORD_TYPE && subcode != UNION_TYPE)
+    {
+      error_init ("field name not in record or union initializer");
+      return 1;
+    }
+
+  constructor_designated = 1;
+  push_init_level (2, braced_init_obstack);
+  return 0;
+}
+
+/* If there are range designators in designator list, push a new designator
+   to constructor_range_stack.  RANGE_END is end of such stack range or
+   NULL_TREE if there is no range designator at this level.  */
+
+static void
+push_range_stack (tree range_end, struct obstack * braced_init_obstack)
+{
+  struct constructor_range_stack *p;
+
+  p = (struct constructor_range_stack *)
+    obstack_alloc (braced_init_obstack,
+                  sizeof (struct constructor_range_stack));
+  p->prev = constructor_range_stack;
+  p->next = 0;
+  p->fields = constructor_fields;
+  p->range_start = constructor_index;
+  p->index = constructor_index;
+  p->stack = constructor_stack;
+  p->range_end = range_end;
+  if (constructor_range_stack)
+    constructor_range_stack->next = p;
+  constructor_range_stack = p;
+}
+
+/* Within an array initializer, specify the next index to be initialized.
+   FIRST is that index.  If LAST is nonzero, then initialize a range
+   of indices, running from FIRST through LAST.  */
+
+void
+set_init_index (tree first, tree last,
+               struct obstack * braced_init_obstack)
+{
+  if (set_designator (1, braced_init_obstack))
+    return;
+
+  designator_erroneous = 1;
+
+  if (!INTEGRAL_TYPE_P (TREE_TYPE (first))
+      || (last && !INTEGRAL_TYPE_P (TREE_TYPE (last))))
+    {
+      error_init ("array index in initializer not of integer type");
+      return;
+    }
+
+  if (TREE_CODE (first) != INTEGER_CST)
+    {
+      first = c_fully_fold (first, false, NULL);
+      if (TREE_CODE (first) == INTEGER_CST)
+       pedwarn_init (input_location, OPT_Wpedantic,
+                     "array index in initializer is not "
+                     "an integer constant expression");
+    }
+
+  if (last && TREE_CODE (last) != INTEGER_CST)
+    {
+      last = c_fully_fold (last, false, NULL);
+      if (TREE_CODE (last) == INTEGER_CST)
+       pedwarn_init (input_location, OPT_Wpedantic,
+                     "array index in initializer is not "
+                     "an integer constant expression");
+    }
+
+  if (TREE_CODE (first) != INTEGER_CST)
+    error_init ("nonconstant array index in initializer");
+  else if (last != 0 && TREE_CODE (last) != INTEGER_CST)
+    error_init ("nonconstant array index in initializer");
+  else if (TREE_CODE (constructor_type) != ARRAY_TYPE)
+    error_init ("array index in non-array initializer");
+  else if (tree_int_cst_sgn (first) == -1)
+    error_init ("array index in initializer exceeds array bounds");
+  else if (constructor_max_index
+          && tree_int_cst_lt (constructor_max_index, first))
+    error_init ("array index in initializer exceeds array bounds");
+  else
+    {
+      constant_expression_warning (first);
+      if (last)
+       constant_expression_warning (last);
+      constructor_index = convert (bitsizetype, first);
+
+      if (last)
+       {
+         if (tree_int_cst_equal (first, last))
+           last = 0;
+         else if (tree_int_cst_lt (last, first))
+           {
+             error_init ("empty index range in initializer");
+             last = 0;
+           }
+         else
+           {
+             last = convert (bitsizetype, last);
+             if (constructor_max_index != 0
+                 && tree_int_cst_lt (constructor_max_index, last))
+               {
+                 error_init ("array index range in initializer exceeds array bounds");
+                 last = 0;
+               }
+           }
+       }
+
+      designator_depth++;
+      designator_erroneous = 0;
+      if (constructor_range_stack || last)
+       push_range_stack (last, braced_init_obstack);
+    }
+}
+
+/* Within a struct initializer, specify the next field to be initialized.  */
+
+void
+set_init_label (tree fieldname, struct obstack * braced_init_obstack)
+{
+  tree field;
+
+  if (set_designator (0, braced_init_obstack))
+    return;
+
+  designator_erroneous = 1;
+
+  if (TREE_CODE (constructor_type) != RECORD_TYPE
+      && TREE_CODE (constructor_type) != UNION_TYPE)
+    {
+      error_init ("field name not in record or union initializer");
+      return;
+    }
+
+  field = lookup_field (constructor_type, fieldname);
+
+  if (field == 0)
+    error ("unknown field %qE specified in initializer", fieldname);
+  else
+    do
+      {
+       constructor_fields = TREE_VALUE (field);
+       designator_depth++;
+       designator_erroneous = 0;
+       if (constructor_range_stack)
+         push_range_stack (NULL_TREE, braced_init_obstack);
+       field = TREE_CHAIN (field);
+       if (field)
+         {
+           if (set_designator (0, braced_init_obstack))
+             return;
+         }
+      }
+    while (field != NULL_TREE);
+}
+\f
+/* Add a new initializer to the tree of pending initializers.  PURPOSE
+   identifies the initializer, either array index or field in a structure.
+   VALUE is the value of that index or field.  If ORIGTYPE is not
+   NULL_TREE, it is the original type of VALUE.
+
+   IMPLICIT is true if value comes from pop_init_level (1),
+   the new initializer has been merged with the existing one
+   and thus no warnings should be emitted about overriding an
+   existing initializer.  */
+
+static void
+add_pending_init (tree purpose, tree value, tree origtype, bool implicit,
+                 struct obstack * braced_init_obstack)
+{
+  struct init_node *p, **q, *r;
+
+  q = &constructor_pending_elts;
+  p = 0;
+
+  if (TREE_CODE (constructor_type) == ARRAY_TYPE)
+    {
+      while (*q != 0)
+       {
+         p = *q;
+         if (tree_int_cst_lt (purpose, p->purpose))
+           q = &p->left;
+         else if (tree_int_cst_lt (p->purpose, purpose))
+           q = &p->right;
+         else
+           {
+             if (!implicit)
+               {
+                 if (TREE_SIDE_EFFECTS (p->value))
+                   warning_init (0, "initialized field with side-effects overwritten");
+                 else if (warn_override_init)
+                   warning_init (OPT_Woverride_init, "initialized field overwritten");
+               }
+             p->value = value;
+             p->origtype = origtype;
+             return;
+           }
+       }
+    }
+  else
+    {
+      tree bitpos;
+
+      bitpos = bit_position (purpose);
+      while (*q != NULL)
+       {
+         p = *q;
+         if (tree_int_cst_lt (bitpos, bit_position (p->purpose)))
+           q = &p->left;
+         else if (p->purpose != purpose)
+           q = &p->right;
+         else
+           {
+             if (!implicit)
+               {
+                 if (TREE_SIDE_EFFECTS (p->value))
+                   warning_init (0, "initialized field with side-effects overwritten");
+                 else if (warn_override_init)
+                   warning_init (OPT_Woverride_init, "initialized field overwritten");
+               }
+             p->value = value;
+             p->origtype = origtype;
+             return;
+           }
+       }
+    }
+
+  r = (struct init_node *) obstack_alloc (braced_init_obstack,
+                                         sizeof (struct init_node));
+  r->purpose = purpose;
+  r->value = value;
+  r->origtype = origtype;
+
+  *q = r;
+  r->parent = p;
+  r->left = 0;
+  r->right = 0;
+  r->balance = 0;
+
+  while (p)
+    {
+      struct init_node *s;
+
+      if (r == p->left)
+       {
+         if (p->balance == 0)
+           p->balance = -1;
+         else if (p->balance < 0)
+           {
+             if (r->balance < 0)
+               {
+                 /* L rotation.  */
+                 p->left = r->right;
+                 if (p->left)
+                   p->left->parent = p;
+                 r->right = p;
+
+                 p->balance = 0;
+                 r->balance = 0;
+
+                 s = p->parent;
+                 p->parent = r;
+                 r->parent = s;
+                 if (s)
+                   {
+                     if (s->left == p)
+                       s->left = r;
+                     else
+                       s->right = r;
+                   }
+                 else
+                   constructor_pending_elts = r;
+               }
+             else
+               {
+                 /* LR rotation.  */
+                 struct init_node *t = r->right;
+
+                 r->right = t->left;
+                 if (r->right)
+                   r->right->parent = r;
+                 t->left = r;
+
+                 p->left = t->right;
+                 if (p->left)
+                   p->left->parent = p;
+                 t->right = p;
+
+                 p->balance = t->balance < 0;
+                 r->balance = -(t->balance > 0);
+                 t->balance = 0;
+
+                 s = p->parent;
+                 p->parent = t;
+                 r->parent = t;
+                 t->parent = s;
+                 if (s)
+                   {
+                     if (s->left == p)
+                       s->left = t;
+                     else
+                       s->right = t;
+                   }
+                 else
+                   constructor_pending_elts = t;
+               }
+             break;
+           }
+         else
+           {
+             /* p->balance == +1; growth of left side balances the node.  */
+             p->balance = 0;
+             break;
+           }
+       }
+      else /* r == p->right */
+       {
+         if (p->balance == 0)
+           /* Growth propagation from right side.  */
+           p->balance++;
+         else if (p->balance > 0)
+           {
+             if (r->balance > 0)
+               {
+                 /* R rotation.  */
+                 p->right = r->left;
+                 if (p->right)
+                   p->right->parent = p;
+                 r->left = p;
+
+                 p->balance = 0;
+                 r->balance = 0;
+
+                 s = p->parent;
+                 p->parent = r;
+                 r->parent = s;
+                 if (s)
+                   {
+                     if (s->left == p)
+                       s->left = r;
+                     else
+                       s->right = r;
+                   }
+                 else
+                   constructor_pending_elts = r;
+               }
+             else /* r->balance == -1 */
+               {
+                 /* RL rotation */
+                 struct init_node *t = r->left;
+
+                 r->left = t->right;
+                 if (r->left)
+                   r->left->parent = r;
+                 t->right = r;
+
+                 p->right = t->left;
+                 if (p->right)
+                   p->right->parent = p;
+                 t->left = p;
+
+                 r->balance = (t->balance < 0);
+                 p->balance = -(t->balance > 0);
+                 t->balance = 0;
+
+                 s = p->parent;
+                 p->parent = t;
+                 r->parent = t;
+                 t->parent = s;
+                 if (s)
+                   {
+                     if (s->left == p)
+                       s->left = t;
+                     else
+                       s->right = t;
+                   }
+                 else
+                   constructor_pending_elts = t;
+               }
+             break;
+           }
+         else
+           {
+             /* p->balance == -1; growth of right side balances the node.  */
+             p->balance = 0;
+             break;
+           }
+       }
+
+      r = p;
+      p = p->parent;
+    }
+}
+
+/* Build AVL tree from a sorted chain.  */
+
+static void
+set_nonincremental_init (struct obstack * braced_init_obstack)
+{
+  unsigned HOST_WIDE_INT ix;
+  tree index, value;
+
+  if (TREE_CODE (constructor_type) != RECORD_TYPE
+      && TREE_CODE (constructor_type) != ARRAY_TYPE)
+    return;
+
+  FOR_EACH_CONSTRUCTOR_ELT (constructor_elements, ix, index, value)
+    {
+      add_pending_init (index, value, NULL_TREE, true,
+                       braced_init_obstack);
+    }
+  constructor_elements = 0;
+  if (TREE_CODE (constructor_type) == RECORD_TYPE)
+    {
+      constructor_unfilled_fields = TYPE_FIELDS (constructor_type);
+      /* Skip any nameless bit fields at the beginning.  */
+      while (constructor_unfilled_fields != 0
+            && DECL_C_BIT_FIELD (constructor_unfilled_fields)
+            && DECL_NAME (constructor_unfilled_fields) == 0)
+       constructor_unfilled_fields = TREE_CHAIN (constructor_unfilled_fields);
+
+    }
+  else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
+    {
+      if (TYPE_DOMAIN (constructor_type))
+       constructor_unfilled_index
+           = convert (bitsizetype,
+                      TYPE_MIN_VALUE (TYPE_DOMAIN (constructor_type)));
+      else
+       constructor_unfilled_index = bitsize_zero_node;
+    }
+  constructor_incremental = 0;
+}
+
+/* Build AVL tree from a string constant.  */
+
+static void
+set_nonincremental_init_from_string (tree str,
+                                    struct obstack * braced_init_obstack)
+{
+  tree value, purpose, type;
+  HOST_WIDE_INT val[2];
+  const char *p, *end;
+  int byte, wchar_bytes, charwidth, bitpos;
+
+  gcc_assert (TREE_CODE (constructor_type) == ARRAY_TYPE);
+
+  wchar_bytes = TYPE_PRECISION (TREE_TYPE (TREE_TYPE (str))) / BITS_PER_UNIT;
+  charwidth = TYPE_PRECISION (char_type_node);
+  type = TREE_TYPE (constructor_type);
+  p = TREE_STRING_POINTER (str);
+  end = p + TREE_STRING_LENGTH (str);
+
+  for (purpose = bitsize_zero_node;
+       p < end && !tree_int_cst_lt (constructor_max_index, purpose);
+       purpose = size_binop (PLUS_EXPR, purpose, bitsize_one_node))
+    {
+      if (wchar_bytes == 1)
+       {
+         val[1] = (unsigned char) *p++;
+         val[0] = 0;
+       }
+      else
+       {
+         val[0] = 0;
+         val[1] = 0;
+         for (byte = 0; byte < wchar_bytes; byte++)
+           {
+             if (BYTES_BIG_ENDIAN)
+               bitpos = (wchar_bytes - byte - 1) * charwidth;
+             else
+               bitpos = byte * charwidth;
+             val[bitpos < HOST_BITS_PER_WIDE_INT]
+               |= ((unsigned HOST_WIDE_INT) ((unsigned char) *p++))
+                  << (bitpos % HOST_BITS_PER_WIDE_INT);
+           }
+       }
+
+      if (!TYPE_UNSIGNED (type))
+       {
+         bitpos = ((wchar_bytes - 1) * charwidth) + HOST_BITS_PER_CHAR;
+         if (bitpos < HOST_BITS_PER_WIDE_INT)
+           {
+             if (val[1] & (((HOST_WIDE_INT) 1) << (bitpos - 1)))
+               {
+                 val[1] |= ((HOST_WIDE_INT) -1) << bitpos;
+                 val[0] = -1;
+               }
+           }
+         else if (bitpos == HOST_BITS_PER_WIDE_INT)
+           {
+             if (val[1] < 0)
+               val[0] = -1;
+           }
+         else if (val[0] & (((HOST_WIDE_INT) 1)
+                            << (bitpos - 1 - HOST_BITS_PER_WIDE_INT)))
+           val[0] |= ((HOST_WIDE_INT) -1)
+                     << (bitpos - HOST_BITS_PER_WIDE_INT);
+       }
+
+      value = build_int_cst_wide (type, val[1], val[0]);
+      add_pending_init (purpose, value, NULL_TREE, true,
+                        braced_init_obstack);
+    }
+
+  constructor_incremental = 0;
+}
+
+/* Return value of FIELD in pending initializer or zero if the field was
+   not initialized yet.  */
+
+static tree
+find_init_member (tree field, struct obstack * braced_init_obstack)
+{
+  struct init_node *p;
+
+  if (TREE_CODE (constructor_type) == ARRAY_TYPE)
+    {
+      if (constructor_incremental
+         && tree_int_cst_lt (field, constructor_unfilled_index))
+       set_nonincremental_init (braced_init_obstack);
+
+      p = constructor_pending_elts;
+      while (p)
+       {
+         if (tree_int_cst_lt (field, p->purpose))
+           p = p->left;
+         else if (tree_int_cst_lt (p->purpose, field))
+           p = p->right;
+         else
+           return p->value;
+       }
+    }
+  else if (TREE_CODE (constructor_type) == RECORD_TYPE)
+    {
+      tree bitpos = bit_position (field);
+
+      if (constructor_incremental
+         && (!constructor_unfilled_fields
+             || tree_int_cst_lt (bitpos,
+                                 bit_position (constructor_unfilled_fields))))
+       set_nonincremental_init (braced_init_obstack);
+
+      p = constructor_pending_elts;
+      while (p)
+       {
+         if (field == p->purpose)
+           return p->value;
+         else if (tree_int_cst_lt (bitpos, bit_position (p->purpose)))
+           p = p->left;
+         else
+           p = p->right;
+       }
+    }
+  else if (TREE_CODE (constructor_type) == UNION_TYPE)
+    {
+      if (!VEC_empty (constructor_elt, constructor_elements)
+         && (VEC_last (constructor_elt, constructor_elements)->index
+             == field))
+       return VEC_last (constructor_elt, constructor_elements)->value;
+    }
+  return 0;
+}
+
+/* "Output" the next constructor element.
+   At top level, really output it to assembler code now.
+   Otherwise, collect it in a list from which we will make a CONSTRUCTOR.
+   If ORIGTYPE is not NULL_TREE, it is the original type of VALUE.
+   TYPE is the data type that the containing data type wants here.
+   FIELD is the field (a FIELD_DECL) or the index that this element fills.
+   If VALUE is a string constant, STRICT_STRING is true if it is
+   unparenthesized or we should not warn here for it being parenthesized.
+   For other types of VALUE, STRICT_STRING is not used.
+
+   PENDING if non-nil means output pending elements that belong
+   right after this element.  (PENDING is normally 1;
+   it is 0 while outputting pending elements, to avoid recursion.)
+
+   IMPLICIT is true if value comes from pop_init_level (1),
+   the new initializer has been merged with the existing one
+   and thus no warnings should be emitted about overriding an
+   existing initializer.  */
+
+static void
+output_init_element (tree value, tree origtype, bool strict_string, tree type,
+                    tree field, int pending, bool implicit,
+                    struct obstack * braced_init_obstack)
+{
+  tree semantic_type = NULL_TREE;
+  constructor_elt *celt;
+  bool maybe_const = true;
+  bool npc;
+
+  if (type == error_mark_node || value == error_mark_node)
+    {
+      constructor_erroneous = 1;
+      return;
+    }
+  if (TREE_CODE (TREE_TYPE (value)) == ARRAY_TYPE
+      && (TREE_CODE (value) == STRING_CST
+         || TREE_CODE (value) == COMPOUND_LITERAL_EXPR)
+      && !(TREE_CODE (value) == STRING_CST
+          && TREE_CODE (type) == ARRAY_TYPE
+          && INTEGRAL_TYPE_P (TREE_TYPE (type)))
+      && !comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (value)),
+                    TYPE_MAIN_VARIANT (type)))
+    value = array_to_pointer_conversion (input_location, value);
+
+  if (TREE_CODE (value) == COMPOUND_LITERAL_EXPR
+      && require_constant_value && !flag_isoc99 && pending)
+    {
+      /* As an extension, allow initializing objects with static storage
+        duration with compound literals (which are then treated just as
+        the brace enclosed list they contain).  */
+      tree decl = COMPOUND_LITERAL_EXPR_DECL (value);
+      value = DECL_INITIAL (decl);
+    }
+
+  npc = null_pointer_constant_p (value);
+  if (TREE_CODE (value) == EXCESS_PRECISION_EXPR)
+    {
+      semantic_type = TREE_TYPE (value);
+      value = TREE_OPERAND (value, 0);
+    }
+  value = c_fully_fold (value, require_constant_value, &maybe_const);
+
+  if (value == error_mark_node)
+    constructor_erroneous = 1;
+  else if (!TREE_CONSTANT (value))
+    constructor_constant = 0;
+  else if (!initializer_constant_valid_p (value, TREE_TYPE (value))
+          || ((TREE_CODE (constructor_type) == RECORD_TYPE
+               || TREE_CODE (constructor_type) == UNION_TYPE)
+              && DECL_C_BIT_FIELD (field)
+              && TREE_CODE (value) != INTEGER_CST))
+    constructor_simple = 0;
+  if (!maybe_const)
+    constructor_nonconst = 1;
+
+  if (!initializer_constant_valid_p (value, TREE_TYPE (value)))
+    {
+      if (require_constant_value)
+       {
+         error_init ("initializer element is not constant");
+         value = error_mark_node;
+       }
+      else if (require_constant_elements)
+       pedwarn (input_location, 0,
+                "initializer element is not computable at load time");
+    }
+  else if (!maybe_const
+          && (require_constant_value || require_constant_elements))
+    pedwarn_init (input_location, 0,
+                 "initializer element is not a constant expression");
+
+  /* Issue -Wc++-compat warnings about initializing a bitfield with
+     enum type.  */
+  if (warn_cxx_compat
+      && field != NULL_TREE
+      && TREE_CODE (field) == FIELD_DECL
+      && DECL_BIT_FIELD_TYPE (field) != NULL_TREE
+      && (TYPE_MAIN_VARIANT (DECL_BIT_FIELD_TYPE (field))
+         != TYPE_MAIN_VARIANT (type))
+      && TREE_CODE (DECL_BIT_FIELD_TYPE (field)) == ENUMERAL_TYPE)
+    {
+      tree checktype = origtype != NULL_TREE ? origtype : TREE_TYPE (value);
+      if (checktype != error_mark_node
+         && (TYPE_MAIN_VARIANT (checktype)
+             != TYPE_MAIN_VARIANT (DECL_BIT_FIELD_TYPE (field))))
+       warning_init (OPT_Wc___compat,
+                     "enum conversion in initialization is invalid in C++");
+    }
+
+  /* If this field is empty (and not at the end of structure),
+     don't do anything other than checking the initializer.  */
+  if (field
+      && (TREE_TYPE (field) == error_mark_node
+         || (COMPLETE_TYPE_P (TREE_TYPE (field))
+             && integer_zerop (TYPE_SIZE (TREE_TYPE (field)))
+             && (TREE_CODE (constructor_type) == ARRAY_TYPE
+                 || DECL_CHAIN (field)))))
+    return;
+
+  if (semantic_type)
+    value = build1 (EXCESS_PRECISION_EXPR, semantic_type, value);
+  value = digest_init (input_location, type, value, origtype, npc,
+                      strict_string, require_constant_value);
+  if (value == error_mark_node)
+    {
+      constructor_erroneous = 1;
+      return;
+    }
+  if (require_constant_value || require_constant_elements)
+    constant_expression_warning (value);
+
+  /* If this element doesn't come next in sequence,
+     put it on constructor_pending_elts.  */
+  if (TREE_CODE (constructor_type) == ARRAY_TYPE
+      && (!constructor_incremental
+         || !tree_int_cst_equal (field, constructor_unfilled_index)))
+    {
+      if (constructor_incremental
+         && tree_int_cst_lt (field, constructor_unfilled_index))
+       set_nonincremental_init (braced_init_obstack);
+
+      add_pending_init (field, value, origtype, implicit,
+                       braced_init_obstack);
+      return;
+    }
+  else if (TREE_CODE (constructor_type) == RECORD_TYPE
+          && (!constructor_incremental
+              || field != constructor_unfilled_fields))
+    {
+      /* We do this for records but not for unions.  In a union,
+        no matter which field is specified, it can be initialized
+        right away since it starts at the beginning of the union.  */
+      if (constructor_incremental)
+       {
+         if (!constructor_unfilled_fields)
+           set_nonincremental_init (braced_init_obstack);
+         else
+           {
+             tree bitpos, unfillpos;
+
+             bitpos = bit_position (field);
+             unfillpos = bit_position (constructor_unfilled_fields);
+
+             if (tree_int_cst_lt (bitpos, unfillpos))
+               set_nonincremental_init (braced_init_obstack);
+           }
+       }
+
+      add_pending_init (field, value, origtype, implicit,
+                       braced_init_obstack);
+      return;
+    }
+  else if (TREE_CODE (constructor_type) == UNION_TYPE
+          && !VEC_empty (constructor_elt, constructor_elements))
+    {
+      if (!implicit)
+       {
+         if (TREE_SIDE_EFFECTS (VEC_last (constructor_elt,
+                                          constructor_elements)->value))
+           warning_init (0,
+                         "initialized field with side-effects overwritten");
+         else if (warn_override_init)
+           warning_init (OPT_Woverride_init, "initialized field overwritten");
+       }
+
+      /* We can have just one union field set.  */
+      constructor_elements = 0;
+    }
+
+  /* Otherwise, output this element either to
+     constructor_elements or to the assembler file.  */
+
+  celt = VEC_safe_push (constructor_elt, gc, constructor_elements, NULL);
+  celt->index = field;
+  celt->value = value;
+
+  /* Advance the variable that indicates sequential elements output.  */
+  if (TREE_CODE (constructor_type) == ARRAY_TYPE)
+    constructor_unfilled_index
+      = size_binop_loc (input_location, PLUS_EXPR, constructor_unfilled_index,
+                       bitsize_one_node);
+  else if (TREE_CODE (constructor_type) == RECORD_TYPE)
+    {
+      constructor_unfilled_fields
+       = DECL_CHAIN (constructor_unfilled_fields);
+
+      /* Skip any nameless bit fields.  */
+      while (constructor_unfilled_fields != 0
+            && DECL_C_BIT_FIELD (constructor_unfilled_fields)
+            && DECL_NAME (constructor_unfilled_fields) == 0)
+       constructor_unfilled_fields =
+         DECL_CHAIN (constructor_unfilled_fields);
+    }
+  else if (TREE_CODE (constructor_type) == UNION_TYPE)
+    constructor_unfilled_fields = 0;
+
+  /* Now output any pending elements which have become next.  */
+  if (pending)
+    output_pending_init_elements (0, braced_init_obstack);
+}
+
+/* Output any pending elements which have become next.
+   As we output elements, constructor_unfilled_{fields,index}
+   advances, which may cause other elements to become next;
+   if so, they too are output.
+
+   If ALL is 0, we return when there are
+   no more pending elements to output now.
+
+   If ALL is 1, we output space as necessary so that
+   we can output all the pending elements.  */
+static void
+output_pending_init_elements (int all, struct obstack * braced_init_obstack)
+{
+  struct init_node *elt = constructor_pending_elts;
+  tree next;
+
+ retry:
+
+  /* Look through the whole pending tree.
+     If we find an element that should be output now,
+     output it.  Otherwise, set NEXT to the element
+     that comes first among those still pending.  */
+
+  next = 0;
+  while (elt)
+    {
+      if (TREE_CODE (constructor_type) == ARRAY_TYPE)
+       {
+         if (tree_int_cst_equal (elt->purpose,
+                                 constructor_unfilled_index))
+           output_init_element (elt->value, elt->origtype, true,
+                                TREE_TYPE (constructor_type),
+                                constructor_unfilled_index, 0, false,
+                                braced_init_obstack);
+         else if (tree_int_cst_lt (constructor_unfilled_index,
+                                   elt->purpose))
+           {
+             /* Advance to the next smaller node.  */
+             if (elt->left)
+               elt = elt->left;
+             else
+               {
+                 /* We have reached the smallest node bigger than the
+                    current unfilled index.  Fill the space first.  */
+                 next = elt->purpose;
+                 break;
+               }
+           }
+         else
+           {
+             /* Advance to the next bigger node.  */
+             if (elt->right)
+               elt = elt->right;
+             else
+               {
+                 /* We have reached the biggest node in a subtree.  Find
+                    the parent of it, which is the next bigger node.  */
+                 while (elt->parent && elt->parent->right == elt)
+                   elt = elt->parent;
+                 elt = elt->parent;
+                 if (elt && tree_int_cst_lt (constructor_unfilled_index,
+                                             elt->purpose))
+                   {
+                     next = elt->purpose;
+                     break;
+                   }
+               }
+           }
+       }
+      else if (TREE_CODE (constructor_type) == RECORD_TYPE
+              || TREE_CODE (constructor_type) == UNION_TYPE)
+       {
+         tree ctor_unfilled_bitpos, elt_bitpos;
+
+         /* If the current record is complete we are done.  */
+         if (constructor_unfilled_fields == 0)
+           break;
+
+         ctor_unfilled_bitpos = bit_position (constructor_unfilled_fields);
+         elt_bitpos = bit_position (elt->purpose);
+         /* We can't compare fields here because there might be empty
+            fields in between.  */
+         if (tree_int_cst_equal (elt_bitpos, ctor_unfilled_bitpos))
+           {
+             constructor_unfilled_fields = elt->purpose;
+             output_init_element (elt->value, elt->origtype, true,
+                                  TREE_TYPE (elt->purpose),
+                                  elt->purpose, 0, false,
+                                  braced_init_obstack);
+           }
+         else if (tree_int_cst_lt (ctor_unfilled_bitpos, elt_bitpos))
+           {
+             /* Advance to the next smaller node.  */
+             if (elt->left)
+               elt = elt->left;
+             else
+               {
+                 /* We have reached the smallest node bigger than the
+                    current unfilled field.  Fill the space first.  */
+                 next = elt->purpose;
+                 break;
+               }
+           }
+         else
+           {
+             /* Advance to the next bigger node.  */
+             if (elt->right)
+               elt = elt->right;
+             else
+               {
+                 /* We have reached the biggest node in a subtree.  Find
+                    the parent of it, which is the next bigger node.  */
+                 while (elt->parent && elt->parent->right == elt)
+                   elt = elt->parent;
+                 elt = elt->parent;
+                 if (elt
+                     && (tree_int_cst_lt (ctor_unfilled_bitpos,
+                                          bit_position (elt->purpose))))
+                   {
+                     next = elt->purpose;
+                     break;
+                   }
+               }
+           }
+       }
+    }
+
+  /* Ordinarily return, but not if we want to output all
+     and there are elements left.  */
+  if (!(all && next != 0))
+    return;
+
+  /* If it's not incremental, just skip over the gap, so that after
+     jumping to retry we will output the next successive element.  */
+  if (TREE_CODE (constructor_type) == RECORD_TYPE
+      || TREE_CODE (constructor_type) == UNION_TYPE)
+    constructor_unfilled_fields = next;
+  else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
+    constructor_unfilled_index = next;
+
+  /* ELT now points to the node in the pending tree with the next
+     initializer to output.  */
+  goto retry;
+}
+\f
+/* Add one non-braced element to the current constructor level.
+   This adjusts the current position within the constructor's type.
+   This may also start or terminate implicit levels
+   to handle a partly-braced initializer.
+
+   Once this has found the correct level for the new element,
+   it calls output_init_element.
+
+   IMPLICIT is true if value comes from pop_init_level (1),
+   the new initializer has been merged with the existing one
+   and thus no warnings should be emitted about overriding an
+   existing initializer.  */
+
+void
+process_init_element (struct c_expr value, bool implicit,
+                     struct obstack * braced_init_obstack)
+{
+  tree orig_value = value.value;
+  int string_flag = orig_value != 0 && TREE_CODE (orig_value) == STRING_CST;
+  bool strict_string = value.original_code == STRING_CST;
+
+  designator_depth = 0;
+  designator_erroneous = 0;
+
+  /* Handle superfluous braces around string cst as in
+     char x[] = {"foo"}; */
+  if (string_flag
+      && constructor_type
+      && TREE_CODE (constructor_type) == ARRAY_TYPE
+      && INTEGRAL_TYPE_P (TREE_TYPE (constructor_type))
+      && integer_zerop (constructor_unfilled_index))
+    {
+      if (constructor_stack->replacement_value.value)
+       error_init ("excess elements in char array initializer");
+      constructor_stack->replacement_value = value;
+      return;
+    }
+
+  if (constructor_stack->replacement_value.value != 0)
+    {
+      error_init ("excess elements in struct initializer");
+      return;
+    }
+
+  /* Ignore elements of a brace group if it is entirely superfluous
+     and has already been diagnosed.  */
+  if (constructor_type == 0)
+    return;
+
+  /* If we've exhausted any levels that didn't have braces,
+     pop them now.  */
+  while (constructor_stack->implicit)
+    {
+      if ((TREE_CODE (constructor_type) == RECORD_TYPE
+          || TREE_CODE (constructor_type) == UNION_TYPE)
+         && constructor_fields == 0)
+       process_init_element (pop_init_level (1, braced_init_obstack),
+                             true, braced_init_obstack);
+      else if ((TREE_CODE (constructor_type) == ARRAY_TYPE
+               || TREE_CODE (constructor_type) == VECTOR_TYPE)
+              && (constructor_max_index == 0
+                  || tree_int_cst_lt (constructor_max_index,
+                                      constructor_index)))
+       process_init_element (pop_init_level (1, braced_init_obstack),
+                             true, braced_init_obstack);
+      else
+       break;
+    }
+
+  /* In the case of [LO ... HI] = VALUE, only evaluate VALUE once.  */
+  if (constructor_range_stack)
+    {
+      /* If value is a compound literal and we'll be just using its
+        content, don't put it into a SAVE_EXPR.  */
+      if (TREE_CODE (value.value) != COMPOUND_LITERAL_EXPR
+         || !require_constant_value
+         || flag_isoc99)
+       {
+         tree semantic_type = NULL_TREE;
+         if (TREE_CODE (value.value) == EXCESS_PRECISION_EXPR)
+           {
+             semantic_type = TREE_TYPE (value.value);
+             value.value = TREE_OPERAND (value.value, 0);
+           }
+         value.value = c_save_expr (value.value);
+         if (semantic_type)
+           value.value = build1 (EXCESS_PRECISION_EXPR, semantic_type,
+                                 value.value);
+       }
+    }
+
+  while (1)
+    {
+      if (TREE_CODE (constructor_type) == RECORD_TYPE)
+       {
+         tree fieldtype;
+         enum tree_code fieldcode;
+
+         if (constructor_fields == 0)
+           {
+             pedwarn_init (input_location, 0,
+                           "excess elements in struct initializer");
+             break;
+           }
+
+         fieldtype = TREE_TYPE (constructor_fields);
+         if (fieldtype != error_mark_node)
+           fieldtype = TYPE_MAIN_VARIANT (fieldtype);
+         fieldcode = TREE_CODE (fieldtype);
+
+         /* Error for non-static initialization of a flexible array member.  */
+         if (fieldcode == ARRAY_TYPE
+             && !require_constant_value
+             && TYPE_SIZE (fieldtype) == NULL_TREE
+             && DECL_CHAIN (constructor_fields) == NULL_TREE)
+           {
+             error_init ("non-static initialization of a flexible array member");
+             break;
+           }
+
+         /* Accept a string constant to initialize a subarray.  */
+         if (value.value != 0
+             && fieldcode == ARRAY_TYPE
+             && INTEGRAL_TYPE_P (TREE_TYPE (fieldtype))
+             && string_flag)
+           value.value = orig_value;
+         /* Otherwise, if we have come to a subaggregate,
+            and we don't have an element of its type, push into it.  */
+         else if (value.value != 0
+                  && value.value != error_mark_node
+                  && TYPE_MAIN_VARIANT (TREE_TYPE (value.value)) != fieldtype
+                  && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE
+                      || fieldcode == UNION_TYPE || fieldcode == VECTOR_TYPE))
+           {
+             push_init_level (1, braced_init_obstack);
+             continue;
+           }
+
+         if (value.value)
+           {
+             push_member_name (constructor_fields);
+             output_init_element (value.value, value.original_type,
+                                  strict_string, fieldtype,
+                                  constructor_fields, 1, implicit,
+                                  braced_init_obstack);
+             RESTORE_SPELLING_DEPTH (constructor_depth);
+           }
+         else
+           /* Do the bookkeeping for an element that was
+              directly output as a constructor.  */
+           {
+             /* For a record, keep track of end position of last field.  */
+             if (DECL_SIZE (constructor_fields))
+               constructor_bit_index
+                 = size_binop_loc (input_location, PLUS_EXPR,
+                                   bit_position (constructor_fields),
+                                   DECL_SIZE (constructor_fields));
+
+             /* If the current field was the first one not yet written out,
+                it isn't now, so update.  */
+             if (constructor_unfilled_fields == constructor_fields)
+               {
+                 constructor_unfilled_fields = DECL_CHAIN (constructor_fields);
+                 /* Skip any nameless bit fields.  */
+                 while (constructor_unfilled_fields != 0
+                        && DECL_C_BIT_FIELD (constructor_unfilled_fields)
+                        && DECL_NAME (constructor_unfilled_fields) == 0)
+                   constructor_unfilled_fields =
+                     DECL_CHAIN (constructor_unfilled_fields);
+               }
+           }
+
+         constructor_fields = DECL_CHAIN (constructor_fields);
+         /* Skip any nameless bit fields at the beginning.  */
+         while (constructor_fields != 0
+                && DECL_C_BIT_FIELD (constructor_fields)
+                && DECL_NAME (constructor_fields) == 0)
+           constructor_fields = DECL_CHAIN (constructor_fields);
+       }
+      else if (TREE_CODE (constructor_type) == UNION_TYPE)
+       {
+         tree fieldtype;
+         enum tree_code fieldcode;
+
+         if (constructor_fields == 0)
+           {
+             pedwarn_init (input_location, 0,
+                           "excess elements in union initializer");
+             break;
+           }
+
+         fieldtype = TREE_TYPE (constructor_fields);
+         if (fieldtype != error_mark_node)
+           fieldtype = TYPE_MAIN_VARIANT (fieldtype);
+         fieldcode = TREE_CODE (fieldtype);
+
+         /* Warn that traditional C rejects initialization of unions.
+            We skip the warning if the value is zero.  This is done
+            under the assumption that the zero initializer in user
+            code appears conditioned on e.g. __STDC__ to avoid
+            "missing initializer" warnings and relies on default
+            initialization to zero in the traditional C case.
+            We also skip the warning if the initializer is designated,
+            again on the assumption that this must be conditional on
+            __STDC__ anyway (and we've already complained about the
+            member-designator already).  */
+         if (!in_system_header && !constructor_designated
+             && !(value.value && (integer_zerop (value.value)
+                                  || real_zerop (value.value))))
+           warning (OPT_Wtraditional, "traditional C rejects initialization "
+                    "of unions");
+
+         /* Accept a string constant to initialize a subarray.  */
+         if (value.value != 0
+             && fieldcode == ARRAY_TYPE
+             && INTEGRAL_TYPE_P (TREE_TYPE (fieldtype))
+             && string_flag)
+           value.value = orig_value;
+         /* Otherwise, if we have come to a subaggregate,
+            and we don't have an element of its type, push into it.  */
+         else if (value.value != 0
+                  && value.value != error_mark_node
+                  && TYPE_MAIN_VARIANT (TREE_TYPE (value.value)) != fieldtype
+                  && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE
+                      || fieldcode == UNION_TYPE || fieldcode == VECTOR_TYPE))
+           {
+             push_init_level (1, braced_init_obstack);
+             continue;
+           }
+
+         if (value.value)
+           {
+             push_member_name (constructor_fields);
+             output_init_element (value.value, value.original_type,
+                                  strict_string, fieldtype,
+                                  constructor_fields, 1, implicit,
+                                  braced_init_obstack);
+             RESTORE_SPELLING_DEPTH (constructor_depth);
+           }
+         else
+           /* Do the bookkeeping for an element that was
+              directly output as a constructor.  */
+           {
+             constructor_bit_index = DECL_SIZE (constructor_fields);
+             constructor_unfilled_fields = DECL_CHAIN (constructor_fields);
+           }
+
+         constructor_fields = 0;
+       }
+      else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
+       {
+         tree elttype = TYPE_MAIN_VARIANT (TREE_TYPE (constructor_type));
+         enum tree_code eltcode = TREE_CODE (elttype);
+
+         /* Accept a string constant to initialize a subarray.  */
+         if (value.value != 0
+             && eltcode == ARRAY_TYPE
+             && INTEGRAL_TYPE_P (TREE_TYPE (elttype))
+             && string_flag)
+           value.value = orig_value;
+         /* Otherwise, if we have come to a subaggregate,
+            and we don't have an element of its type, push into it.  */
+         else if (value.value != 0
+                  && value.value != error_mark_node
+                  && TYPE_MAIN_VARIANT (TREE_TYPE (value.value)) != elttype
+                  && (eltcode == RECORD_TYPE || eltcode == ARRAY_TYPE
+                      || eltcode == UNION_TYPE || eltcode == VECTOR_TYPE))
+           {
+             push_init_level (1, braced_init_obstack);
+             continue;
+           }
+
+         if (constructor_max_index != 0
+             && (tree_int_cst_lt (constructor_max_index, constructor_index)
+                 || integer_all_onesp (constructor_max_index)))
+           {
+             pedwarn_init (input_location, 0,
+                           "excess elements in array initializer");
+             break;
+           }
+
+         /* Now output the actual element.  */
+         if (value.value)
+           {
+             push_array_bounds (tree_low_cst (constructor_index, 1));
+             output_init_element (value.value, value.original_type,
+                                  strict_string, elttype,
+                                  constructor_index, 1, implicit,
+                                  braced_init_obstack);
+             RESTORE_SPELLING_DEPTH (constructor_depth);
+           }
+
+         constructor_index
+           = size_binop_loc (input_location, PLUS_EXPR,
+                             constructor_index, bitsize_one_node);
+
+         if (!value.value)
+           /* If we are doing the bookkeeping for an element that was
+              directly output as a constructor, we must update
+              constructor_unfilled_index.  */
+           constructor_unfilled_index = constructor_index;
+       }
+      else if (TREE_CODE (constructor_type) == VECTOR_TYPE)
+       {
+         tree elttype = TYPE_MAIN_VARIANT (TREE_TYPE (constructor_type));
+
+        /* Do a basic check of initializer size.  Note that vectors
+           always have a fixed size derived from their type.  */
+         if (tree_int_cst_lt (constructor_max_index, constructor_index))
+           {
+             pedwarn_init (input_location, 0,
+                           "excess elements in vector initializer");
+             break;
+           }
+
+         /* Now output the actual element.  */
+         if (value.value)
+           {
+             if (TREE_CODE (value.value) == VECTOR_CST)
+               elttype = TYPE_MAIN_VARIANT (constructor_type);
+             output_init_element (value.value, value.original_type,
+                                  strict_string, elttype,
+                                  constructor_index, 1, implicit,
+                                  braced_init_obstack);
+           }
+
+         constructor_index
+           = size_binop_loc (input_location,
+                             PLUS_EXPR, constructor_index, bitsize_one_node);
+
+         if (!value.value)
+           /* If we are doing the bookkeeping for an element that was
+              directly output as a constructor, we must update
+              constructor_unfilled_index.  */
+           constructor_unfilled_index = constructor_index;
+       }
+
+      /* Handle the sole element allowed in a braced initializer
+        for a scalar variable.  */
+      else if (constructor_type != error_mark_node
+              && constructor_fields == 0)
+       {
+         pedwarn_init (input_location, 0,
+                       "excess elements in scalar initializer");
+         break;
+       }
+      else
+       {
+         if (value.value)
+           output_init_element (value.value, value.original_type,
+                                strict_string, constructor_type,
+                                NULL_TREE, 1, implicit,
+                                braced_init_obstack);
+         constructor_fields = 0;
+       }
+
+      /* Handle range initializers either at this level or anywhere higher
+        in the designator stack.  */
+      if (constructor_range_stack)
+       {
+         struct constructor_range_stack *p, *range_stack;
+         int finish = 0;
+
+         range_stack = constructor_range_stack;
+         constructor_range_stack = 0;
+         while (constructor_stack != range_stack->stack)
+           {
+             gcc_assert (constructor_stack->implicit);
+             process_init_element (pop_init_level (1,
+                                                   braced_init_obstack),
+                                   true, braced_init_obstack);
+           }
+         for (p = range_stack;
+              !p->range_end || tree_int_cst_equal (p->index, p->range_end);
+              p = p->prev)
+           {
+             gcc_assert (constructor_stack->implicit);
+             process_init_element (pop_init_level (1, braced_init_obstack),
+                                   true, braced_init_obstack);
+           }
+
+         p->index = size_binop_loc (input_location,
+                                    PLUS_EXPR, p->index, bitsize_one_node);
+         if (tree_int_cst_equal (p->index, p->range_end) && !p->prev)
+           finish = 1;
+
+         while (1)
+           {
+             constructor_index = p->index;
+             constructor_fields = p->fields;
+             if (finish && p->range_end && p->index == p->range_start)
+               {
+                 finish = 0;
+                 p->prev = 0;
+               }
+             p = p->next;
+             if (!p)
+               break;
+             push_init_level (2, braced_init_obstack);
+             p->stack = constructor_stack;
+             if (p->range_end && tree_int_cst_equal (p->index, p->range_end))
+               p->index = p->range_start;
+           }
+
+         if (!finish)
+           constructor_range_stack = range_stack;
+         continue;
+       }
+
+      break;
+    }
+
+  constructor_range_stack = 0;
+}
+\f
+/* Build a complete asm-statement, whose components are a CV_QUALIFIER
+   (guaranteed to be 'volatile' or null) and ARGS (represented using
+   an ASM_EXPR node).  */
+tree
+build_asm_stmt (tree cv_qualifier, tree args)
+{
+  if (!ASM_VOLATILE_P (args) && cv_qualifier)
+    ASM_VOLATILE_P (args) = 1;
+  return add_stmt (args);
+}
+
+/* Build an asm-expr, whose components are a STRING, some OUTPUTS,
+   some INPUTS, and some CLOBBERS.  The latter three may be NULL.
+   SIMPLE indicates whether there was anything at all after the
+   string in the asm expression -- asm("blah") and asm("blah" : )
+   are subtly different.  We use a ASM_EXPR node to represent this.  */
+tree
+build_asm_expr (location_t loc, tree string, tree outputs, tree inputs,
+               tree clobbers, tree labels, bool simple)
+{
+  tree tail;
+  tree args;
+  int i;
+  const char *constraint;
+  const char **oconstraints;
+  bool allows_mem, allows_reg, is_inout;
+  int ninputs, noutputs;
+
+  ninputs = list_length (inputs);
+  noutputs = list_length (outputs);
+  oconstraints = (const char **) alloca (noutputs * sizeof (const char *));
+
+  string = resolve_asm_operand_names (string, outputs, inputs, labels);
+
+  /* Remove output conversions that change the type but not the mode.  */
+  for (i = 0, tail = outputs; tail; ++i, tail = TREE_CHAIN (tail))
+    {
+      tree output = TREE_VALUE (tail);
+
+      /* ??? Really, this should not be here.  Users should be using a
+        proper lvalue, dammit.  But there's a long history of using casts
+        in the output operands.  In cases like longlong.h, this becomes a
+        primitive form of typechecking -- if the cast can be removed, then
+        the output operand had a type of the proper width; otherwise we'll
+        get an error.  Gross, but ...  */
+      STRIP_NOPS (output);
+
+      if (!lvalue_or_else (loc, output, lv_asm))
+       output = error_mark_node;
+
+      if (output != error_mark_node
+         && (TREE_READONLY (output)
+             || TYPE_READONLY (TREE_TYPE (output))
+             || ((TREE_CODE (TREE_TYPE (output)) == RECORD_TYPE
+                  || TREE_CODE (TREE_TYPE (output)) == UNION_TYPE)
+                 && C_TYPE_FIELDS_READONLY (TREE_TYPE (output)))))
+       readonly_error (output, lv_asm);
+
+      constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (tail)));
+      oconstraints[i] = constraint;
+
+      if (parse_output_constraint (&constraint, i, ninputs, noutputs,
+                                  &allows_mem, &allows_reg, &is_inout))
+       {
+         /* If the operand is going to end up in memory,
+            mark it addressable.  */
+         if (!allows_reg && !c_mark_addressable (output))
+           output = error_mark_node;
+         if (!(!allows_reg && allows_mem)
+             && output != error_mark_node
+             && VOID_TYPE_P (TREE_TYPE (output)))
+           {
+             error_at (loc, "invalid use of void expression");
+             output = error_mark_node;
+           }
+       }
+      else
+       output = error_mark_node;
+
+      TREE_VALUE (tail) = output;
+    }
+
+  for (i = 0, tail = inputs; tail; ++i, tail = TREE_CHAIN (tail))
+    {
+      tree input;
+
+      constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (tail)));
+      input = TREE_VALUE (tail);
+
+      if (parse_input_constraint (&constraint, i, ninputs, noutputs, 0,
+                                 oconstraints, &allows_mem, &allows_reg))
+       {
+         /* If the operand is going to end up in memory,
+            mark it addressable.  */
+         if (!allows_reg && allows_mem)
+           {
+             /* Strip the nops as we allow this case.  FIXME, this really
+                should be rejected or made deprecated.  */
+             STRIP_NOPS (input);
+             if (!c_mark_addressable (input))
+               input = error_mark_node;
+           }
+         else if (input != error_mark_node && VOID_TYPE_P (TREE_TYPE (input)))
+           {
+             error_at (loc, "invalid use of void expression");
+             input = error_mark_node;
+           }
+       }
+      else
+       input = error_mark_node;
+
+      TREE_VALUE (tail) = input;
+    }
+
+  /* ASMs with labels cannot have outputs.  This should have been
+     enforced by the parser.  */
+  gcc_assert (outputs == NULL || labels == NULL);
+
+  args = build_stmt (loc, ASM_EXPR, string, outputs, inputs, clobbers, labels);
+
+  /* asm statements without outputs, including simple ones, are treated
+     as volatile.  */
+  ASM_INPUT_P (args) = simple;
+  ASM_VOLATILE_P (args) = (noutputs == 0);
+
+  return args;
+}
+\f
+/* Generate a goto statement to LABEL.  LOC is the location of the
+   GOTO.  */
+
+tree
+c_finish_goto_label (location_t loc, tree label)
+{
+  tree decl = lookup_label_for_goto (loc, label);
+  if (!decl)
+    return NULL_TREE;
+  TREE_USED (decl) = 1;
+  {
+    tree t = build1 (GOTO_EXPR, void_type_node, decl);
+    SET_EXPR_LOCATION (t, loc);
+    return add_stmt (t);
+  }
+}
+
+/* Generate a computed goto statement to EXPR.  LOC is the location of
+   the GOTO.  */
+
+tree
+c_finish_goto_ptr (location_t loc, tree expr)
+{
+  tree t;
+  pedwarn (loc, OPT_Wpedantic, "ISO C forbids %<goto *expr;%>");
+  expr = c_fully_fold (expr, false, NULL);
+  expr = convert (ptr_type_node, expr);
+  t = build1 (GOTO_EXPR, void_type_node, expr);
+  SET_EXPR_LOCATION (t, loc);
+  return add_stmt (t);
+}
+
+/* Generate a C `return' statement.  RETVAL is the expression for what
+   to return, or a null pointer for `return;' with no value.  LOC is
+   the location of the return statement.  If ORIGTYPE is not NULL_TREE, it
+   is the original type of RETVAL.  */
+
+tree
+c_finish_return (location_t loc, tree retval, tree origtype)
+{
+  tree valtype = TREE_TYPE (TREE_TYPE (current_function_decl)), ret_stmt;
+  bool no_warning = false;
+  bool npc = false;
+
+  if (TREE_THIS_VOLATILE (current_function_decl))
+    warning_at (loc, 0,
+               "function declared %<noreturn%> has a %<return%> statement");
+
+  if (retval)
+    {
+      tree semantic_type = NULL_TREE;
+      npc = null_pointer_constant_p (retval);
+      if (TREE_CODE (retval) == EXCESS_PRECISION_EXPR)
+       {
+         semantic_type = TREE_TYPE (retval);
+         retval = TREE_OPERAND (retval, 0);
+       }
+      retval = c_fully_fold (retval, false, NULL);
+      if (semantic_type)
+       retval = build1 (EXCESS_PRECISION_EXPR, semantic_type, retval);
+    }
+
+  if (!retval)
+    {
+      current_function_returns_null = 1;
+      if ((warn_return_type || flag_isoc99)
+         && valtype != 0 && TREE_CODE (valtype) != VOID_TYPE)
+       {
+         pedwarn_c99 (loc, flag_isoc99 ? 0 : OPT_Wreturn_type,
+                      "%<return%> with no value, in "
+                      "function returning non-void");
+         no_warning = true;
+       }
+    }
+  else if (valtype == 0 || TREE_CODE (valtype) == VOID_TYPE)
+    {
+      current_function_returns_null = 1;
+      if (TREE_CODE (TREE_TYPE (retval)) != VOID_TYPE)
+       pedwarn (loc, 0,
+                "%<return%> with a value, in function returning void");
+      else
+       pedwarn (loc, OPT_Wpedantic, "ISO C forbids "
+                "%<return%> with expression, in function returning void");
+    }
+  else
+    {
+      tree t = convert_for_assignment (loc, valtype, retval, origtype,
+                                      ic_return,
+                                      npc, NULL_TREE, NULL_TREE, 0);
+      tree res = DECL_RESULT (current_function_decl);
+      tree inner;
+
+      current_function_returns_value = 1;
+      if (t == error_mark_node)
+       return NULL_TREE;
+
+      inner = t = convert (TREE_TYPE (res), t);
+
+      /* Strip any conversions, additions, and subtractions, and see if
+        we are returning the address of a local variable.  Warn if so.  */
+      while (1)
+       {
+         switch (TREE_CODE (inner))
+           {
+           CASE_CONVERT:
+           case NON_LVALUE_EXPR:
+           case PLUS_EXPR:
+           case POINTER_PLUS_EXPR:
+             inner = TREE_OPERAND (inner, 0);
+             continue;
+
+           case MINUS_EXPR:
+             /* If the second operand of the MINUS_EXPR has a pointer
+                type (or is converted from it), this may be valid, so
+                don't give a warning.  */
+             {
+               tree op1 = TREE_OPERAND (inner, 1);
+
+               while (!POINTER_TYPE_P (TREE_TYPE (op1))
+                      && (CONVERT_EXPR_P (op1)
+                          || TREE_CODE (op1) == NON_LVALUE_EXPR))
+                 op1 = TREE_OPERAND (op1, 0);
+
+               if (POINTER_TYPE_P (TREE_TYPE (op1)))
+                 break;
+
+               inner = TREE_OPERAND (inner, 0);
+               continue;
+             }
+
+           case ADDR_EXPR:
+             inner = TREE_OPERAND (inner, 0);
+
+             while (REFERENCE_CLASS_P (inner)
+                    && TREE_CODE (inner) != INDIRECT_REF)
+               inner = TREE_OPERAND (inner, 0);
+
+             if (DECL_P (inner)
+                 && !DECL_EXTERNAL (inner)
+                 && !TREE_STATIC (inner)
+                 && DECL_CONTEXT (inner) == current_function_decl)
+               warning_at (loc,
+                           0, "function returns address of local variable");
+             break;
+
+           default:
+             break;
+           }
+
+         break;
+       }
+
+      retval = build2 (MODIFY_EXPR, TREE_TYPE (res), res, t);
+      SET_EXPR_LOCATION (retval, loc);
+
+      if (warn_sequence_point)
+       verify_sequence_points (retval);
+    }
+
+  ret_stmt = build_stmt (loc, RETURN_EXPR, retval);
+  TREE_NO_WARNING (ret_stmt) |= no_warning;
+  return add_stmt (ret_stmt);
+}
+\f
+struct c_switch {
+  /* The SWITCH_EXPR being built.  */
+  tree switch_expr;
+
+  /* The original type of the testing expression, i.e. before the
+     default conversion is applied.  */
+  tree orig_type;
+
+  /* A splay-tree mapping the low element of a case range to the high
+     element, or NULL_TREE if there is no high element.  Used to
+     determine whether or not a new case label duplicates an old case
+     label.  We need a tree, rather than simply a hash table, because
+     of the GNU case range extension.  */
+  splay_tree cases;
+
+  /* The bindings at the point of the switch.  This is used for
+     warnings crossing decls when branching to a case label.  */
+  struct c_spot_bindings *bindings;
+
+  /* The next node on the stack.  */
+  struct c_switch *next;
+};
+
+/* A stack of the currently active switch statements.  The innermost
+   switch statement is on the top of the stack.  There is no need to
+   mark the stack for garbage collection because it is only active
+   during the processing of the body of a function, and we never
+   collect at that point.  */
+
+struct c_switch *c_switch_stack;
+
+/* Start a C switch statement, testing expression EXP.  Return the new
+   SWITCH_EXPR.  SWITCH_LOC is the location of the `switch'.
+   SWITCH_COND_LOC is the location of the switch's condition.  */
+
+tree
+c_start_case (location_t switch_loc,
+             location_t switch_cond_loc,
+             tree exp)
+{
+  tree orig_type = error_mark_node;
+  struct c_switch *cs;
+
+  if (exp != error_mark_node)
+    {
+      orig_type = TREE_TYPE (exp);
+
+      if (!INTEGRAL_TYPE_P (orig_type))
+       {
+         if (orig_type != error_mark_node)
+           {
+             error_at (switch_cond_loc, "switch quantity not an integer");
+             orig_type = error_mark_node;
+           }
+         exp = integer_zero_node;
+       }
+      else
+       {
+         tree type = TYPE_MAIN_VARIANT (orig_type);
+
+         if (!in_system_header
+             && (type == long_integer_type_node
+                 || type == long_unsigned_type_node))
+           warning_at (switch_cond_loc,
+                       OPT_Wtraditional, "%<long%> switch expression not "
+                       "converted to %<int%> in ISO C");
+
+         exp = c_fully_fold (exp, false, NULL);
+         exp = default_conversion (exp);
+
+         if (warn_sequence_point)
+           verify_sequence_points (exp);
+       }
+    }
+
+  /* Add this new SWITCH_EXPR to the stack.  */
+  cs = XNEW (struct c_switch);
+  cs->switch_expr = build3 (SWITCH_EXPR, orig_type, exp, NULL_TREE, NULL_TREE);
+  SET_EXPR_LOCATION (cs->switch_expr, switch_loc);
+  cs->orig_type = orig_type;
+  cs->cases = splay_tree_new (case_compare, NULL, NULL);
+  cs->bindings = c_get_switch_bindings ();
+  cs->next = c_switch_stack;
+  c_switch_stack = cs;
+
+  return add_stmt (cs->switch_expr);
+}
+
+/* Process a case label at location LOC.  */
+
+tree
+do_case (location_t loc, tree low_value, tree high_value)
+{
+  tree label = NULL_TREE;
+
+  if (low_value && TREE_CODE (low_value) != INTEGER_CST)
+    {
+      low_value = c_fully_fold (low_value, false, NULL);
+      if (TREE_CODE (low_value) == INTEGER_CST)
+       pedwarn (input_location, OPT_Wpedantic,
+                "case label is not an integer constant expression");
+    }
+
+  if (high_value && TREE_CODE (high_value) != INTEGER_CST)
+    {
+      high_value = c_fully_fold (high_value, false, NULL);
+      if (TREE_CODE (high_value) == INTEGER_CST)
+       pedwarn (input_location, OPT_Wpedantic,
+                "case label is not an integer constant expression");
+    }
+
+  if (c_switch_stack == NULL)
+    {
+      if (low_value)
+       error_at (loc, "case label not within a switch statement");
+      else
+       error_at (loc, "%<default%> label not within a switch statement");
+      return NULL_TREE;
+    }
+
+  if (c_check_switch_jump_warnings (c_switch_stack->bindings,
+                                   EXPR_LOCATION (c_switch_stack->switch_expr),
+                                   loc))
+    return NULL_TREE;
+
+  label = c_add_case_label (loc, c_switch_stack->cases,
+                           SWITCH_COND (c_switch_stack->switch_expr),
+                           c_switch_stack->orig_type,
+                           low_value, high_value);
+  if (label == error_mark_node)
+    label = NULL_TREE;
+  return label;
+}
+
+/* Finish the switch statement.  */
+
+void
+c_finish_case (tree body)
+{
+  struct c_switch *cs = c_switch_stack;
+  location_t switch_location;
+
+  SWITCH_BODY (cs->switch_expr) = body;
+
+  /* Emit warnings as needed.  */
+  switch_location = EXPR_LOCATION (cs->switch_expr);
+  c_do_switch_warnings (cs->cases, switch_location,
+                       TREE_TYPE (cs->switch_expr),
+                       SWITCH_COND (cs->switch_expr));
+
+  /* Pop the stack.  */
+  c_switch_stack = cs->next;
+  splay_tree_delete (cs->cases);
+  c_release_switch_bindings (cs->bindings);
+  XDELETE (cs);
+}
+\f
+/* Emit an if statement.  IF_LOCUS is the location of the 'if'.  COND,
+   THEN_BLOCK and ELSE_BLOCK are expressions to be used; ELSE_BLOCK
+   may be null.  NESTED_IF is true if THEN_BLOCK contains another IF
+   statement, and was not surrounded with parenthesis.  */
+
+void
+c_finish_if_stmt (location_t if_locus, tree cond, tree then_block,
+                 tree else_block, bool nested_if)
+{
+  tree stmt;
+
+  /* Diagnose an ambiguous else if if-then-else is nested inside if-then.  */
+  if (warn_parentheses && nested_if && else_block == NULL)
+    {
+      tree inner_if = then_block;
+
+      /* We know from the grammar productions that there is an IF nested
+        within THEN_BLOCK.  Due to labels and c99 conditional declarations,
+        it might not be exactly THEN_BLOCK, but should be the last
+        non-container statement within.  */
+      while (1)
+       switch (TREE_CODE (inner_if))
+         {
+         case COND_EXPR:
+           goto found;
+         case BIND_EXPR:
+           inner_if = BIND_EXPR_BODY (inner_if);
+           break;
+         case STATEMENT_LIST:
+           inner_if = expr_last (then_block);
+           break;
+         case TRY_FINALLY_EXPR:
+         case TRY_CATCH_EXPR:
+           inner_if = TREE_OPERAND (inner_if, 0);
+           break;
+         default:
+           gcc_unreachable ();
+         }
+    found:
+
+      if (COND_EXPR_ELSE (inner_if))
+        warning_at (if_locus, OPT_Wparentheses,
+                    "suggest explicit braces to avoid ambiguous %<else%>");
+    }
+
+  stmt = build3 (COND_EXPR, void_type_node, cond, then_block, else_block);
+  SET_EXPR_LOCATION (stmt, if_locus);
+  add_stmt (stmt);
+}
+
+/* Emit a general-purpose loop construct.  START_LOCUS is the location of
+   the beginning of the loop.  COND is the loop condition.  COND_IS_FIRST
+   is false for DO loops.  INCR is the FOR increment expression.  BODY is
+   the statement controlled by the loop.  BLAB is the break label.  CLAB is
+   the continue label.  Everything is allowed to be NULL.  */
+
+void
+c_finish_loop (location_t start_locus, tree cond, tree incr, tree body,
+              tree blab, tree clab, bool cond_is_first)
+{
+  tree entry = NULL, exit = NULL, t;
+
+  /* If the condition is zero don't generate a loop construct.  */
+  if (cond && integer_zerop (cond))
+    {
+      if (cond_is_first)
+       {
+         t = build_and_jump (&blab);
+         SET_EXPR_LOCATION (t, start_locus);
+         add_stmt (t);
+       }
+    }
+  else
+    {
+      tree top = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
+
+      /* If we have an exit condition, then we build an IF with gotos either
+        out of the loop, or to the top of it.  If there's no exit condition,
+        then we just build a jump back to the top.  */
+      exit = build_and_jump (&LABEL_EXPR_LABEL (top));
+
+      if (cond && !integer_nonzerop (cond))
+       {
+         /* Canonicalize the loop condition to the end.  This means
+            generating a branch to the loop condition.  Reuse the
+            continue label, if possible.  */
+         if (cond_is_first)
+           {
+             if (incr || !clab)
+               {
+                 entry = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
+                 t = build_and_jump (&LABEL_EXPR_LABEL (entry));
+               }
+             else
+               t = build1 (GOTO_EXPR, void_type_node, clab);
+             SET_EXPR_LOCATION (t, start_locus);
+             add_stmt (t);
+           }
+
+         t = build_and_jump (&blab);
+         if (cond_is_first)
+           exit = fold_build3_loc (start_locus,
+                               COND_EXPR, void_type_node, cond, exit, t);
+         else
+           exit = fold_build3_loc (input_location,
+                               COND_EXPR, void_type_node, cond, exit, t);
+       }
+
+      add_stmt (top);
+    }
+
+  if (body)
+    add_stmt (body);
+  if (clab)
+    add_stmt (build1 (LABEL_EXPR, void_type_node, clab));
+  if (incr)
+    add_stmt (incr);
+  if (entry)
+    add_stmt (entry);
+  if (exit)
+    add_stmt (exit);
+  if (blab)
+    add_stmt (build1 (LABEL_EXPR, void_type_node, blab));
+}
+
+tree
+c_finish_bc_stmt (location_t loc, tree *label_p, bool is_break)
+{
+  bool skip;
+  tree label = *label_p;
+
+  /* In switch statements break is sometimes stylistically used after
+     a return statement.  This can lead to spurious warnings about
+     control reaching the end of a non-void function when it is
+     inlined.  Note that we are calling block_may_fallthru with
+     language specific tree nodes; this works because
+     block_may_fallthru returns true when given something it does not
+     understand.  */
+  skip = !block_may_fallthru (cur_stmt_list);
+
+  if (!label)
+    {
+      if (!skip)
+       *label_p = label = create_artificial_label (loc);
+    }
+  else if (TREE_CODE (label) == LABEL_DECL)
+    ;
+  else switch (TREE_INT_CST_LOW (label))
+    {
+    case 0:
+      if (is_break)
+       error_at (loc, "break statement not within loop or switch");
+      else
+       error_at (loc, "continue statement not within a loop");
+      return NULL_TREE;
+
+    case 1:
+      gcc_assert (is_break);
+      error_at (loc, "break statement used with OpenMP for loop");
+      return NULL_TREE;
+
+    default:
+      gcc_unreachable ();
+    }
+
+  if (skip)
+    return NULL_TREE;
+
+  if (!is_break)
+    add_stmt (build_predict_expr (PRED_CONTINUE, NOT_TAKEN));
+
+  return add_stmt (build1 (GOTO_EXPR, void_type_node, label));
+}
+
+/* A helper routine for c_process_expr_stmt and c_finish_stmt_expr.  */
+
+static void
+emit_side_effect_warnings (location_t loc, tree expr)
+{
+  if (expr == error_mark_node)
+    ;
+  else if (!TREE_SIDE_EFFECTS (expr))
+    {
+      if (!VOID_TYPE_P (TREE_TYPE (expr)) && !TREE_NO_WARNING (expr))
+       warning_at (loc, OPT_Wunused_value, "statement with no effect");
+    }
+  else
+    warn_if_unused_value (expr, loc);
+}
+
+/* Process an expression as if it were a complete statement.  Emit
+   diagnostics, but do not call ADD_STMT.  LOC is the location of the
+   statement.  */
+
+tree
+c_process_expr_stmt (location_t loc, tree expr)
+{
+  tree exprv;
+
+  if (!expr)
+    return NULL_TREE;
+
+  expr = c_fully_fold (expr, false, NULL);
+
+  if (warn_sequence_point)
+    verify_sequence_points (expr);
+
+  if (TREE_TYPE (expr) != error_mark_node
+      && !COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (expr))
+      && TREE_CODE (TREE_TYPE (expr)) != ARRAY_TYPE)
+    error_at (loc, "expression statement has incomplete type");
+
+  /* If we're not processing a statement expression, warn about unused values.
+     Warnings for statement expressions will be emitted later, once we figure
+     out which is the result.  */
+  if (!STATEMENT_LIST_STMT_EXPR (cur_stmt_list)
+      && warn_unused_value)
+    emit_side_effect_warnings (loc, expr);
+
+  exprv = expr;
+  while (TREE_CODE (exprv) == COMPOUND_EXPR)
+    exprv = TREE_OPERAND (exprv, 1);
+  while (CONVERT_EXPR_P (exprv))
+    exprv = TREE_OPERAND (exprv, 0);
+  if (DECL_P (exprv)
+      || handled_component_p (exprv)
+      || TREE_CODE (exprv) == ADDR_EXPR)
+    mark_exp_read (exprv);
+
+  /* If the expression is not of a type to which we cannot assign a line
+     number, wrap the thing in a no-op NOP_EXPR.  */
+  if (DECL_P (expr) || CONSTANT_CLASS_P (expr))
+    {
+      expr = build1 (NOP_EXPR, TREE_TYPE (expr), expr);
+      SET_EXPR_LOCATION (expr, loc);
+    }
+
+  return expr;
+}
+
+/* Emit an expression as a statement.  LOC is the location of the
+   expression.  */
+
+tree
+c_finish_expr_stmt (location_t loc, tree expr)
+{
+  if (expr)
+    return add_stmt (c_process_expr_stmt (loc, expr));
+  else
+    return NULL;
+}
+
+/* Do the opposite and emit a statement as an expression.  To begin,
+   create a new binding level and return it.  */
+
+tree
+c_begin_stmt_expr (void)
+{
+  tree ret;
+
+  /* We must force a BLOCK for this level so that, if it is not expanded
+     later, there is a way to turn off the entire subtree of blocks that
+     are contained in it.  */
+  keep_next_level ();
+  ret = c_begin_compound_stmt (true);
+
+  c_bindings_start_stmt_expr (c_switch_stack == NULL
+                             ? NULL
+                             : c_switch_stack->bindings);
+
+  /* Mark the current statement list as belonging to a statement list.  */
+  STATEMENT_LIST_STMT_EXPR (ret) = 1;
+
+  return ret;
+}
+
+/* LOC is the location of the compound statement to which this body
+   belongs.  */
+
+tree
+c_finish_stmt_expr (location_t loc, tree body)
+{
+  tree last, type, tmp, val;
+  tree *last_p;
+
+  body = c_end_compound_stmt (loc, body, true);
+
+  c_bindings_end_stmt_expr (c_switch_stack == NULL
+                           ? NULL
+                           : c_switch_stack->bindings);
+
+  /* Locate the last statement in BODY.  See c_end_compound_stmt
+     about always returning a BIND_EXPR.  */
+  last_p = &BIND_EXPR_BODY (body);
+  last = BIND_EXPR_BODY (body);
+
+ continue_searching:
+  if (TREE_CODE (last) == STATEMENT_LIST)
+    {
+      tree_stmt_iterator i;
+
+      /* This can happen with degenerate cases like ({ }).  No value.  */
+      if (!TREE_SIDE_EFFECTS (last))
+       return body;
+
+      /* If we're supposed to generate side effects warnings, process
+        all of the statements except the last.  */
+      if (warn_unused_value)
+       {
+         for (i = tsi_start (last); !tsi_one_before_end_p (i); tsi_next (&i))
+           {
+             location_t tloc;
+             tree t = tsi_stmt (i);
+
+             tloc = EXPR_HAS_LOCATION (t) ? EXPR_LOCATION (t) : loc;
+             emit_side_effect_warnings (tloc, t);
+           }
+       }
+      else
+       i = tsi_last (last);
+      last_p = tsi_stmt_ptr (i);
+      last = *last_p;
+    }
+
+  /* If the end of the list is exception related, then the list was split
+     by a call to push_cleanup.  Continue searching.  */
+  if (TREE_CODE (last) == TRY_FINALLY_EXPR
+      || TREE_CODE (last) == TRY_CATCH_EXPR)
+    {
+      last_p = &TREE_OPERAND (last, 0);
+      last = *last_p;
+      goto continue_searching;
+    }
+
+  if (last == error_mark_node)
+    return last;
+
+  /* In the case that the BIND_EXPR is not necessary, return the
+     expression out from inside it.  */
+  if (last == BIND_EXPR_BODY (body)
+      && BIND_EXPR_VARS (body) == NULL)
+    {
+      /* Even if this looks constant, do not allow it in a constant
+        expression.  */
+      last = c_wrap_maybe_const (last, true);
+      /* Do not warn if the return value of a statement expression is
+        unused.  */
+      TREE_NO_WARNING (last) = 1;
+      return last;
+    }
+
+  /* Extract the type of said expression.  */
+  type = TREE_TYPE (last);
+
+  /* If we're not returning a value at all, then the BIND_EXPR that
+     we already have is a fine expression to return.  */
+  if (!type || VOID_TYPE_P (type))
+    return body;
+
+  /* Now that we've located the expression containing the value, it seems
+     silly to make voidify_wrapper_expr repeat the process.  Create a
+     temporary of the appropriate type and stick it in a TARGET_EXPR.  */
+  tmp = create_tmp_var_raw (type, NULL);
+
+  /* Unwrap a no-op NOP_EXPR as added by c_finish_expr_stmt.  This avoids
+     tree_expr_nonnegative_p giving up immediately.  */
+  val = last;
+  if (TREE_CODE (val) == NOP_EXPR
+      && TREE_TYPE (val) == TREE_TYPE (TREE_OPERAND (val, 0)))
+    val = TREE_OPERAND (val, 0);
+
+  *last_p = build2 (MODIFY_EXPR, void_type_node, tmp, val);
+  SET_EXPR_LOCATION (*last_p, EXPR_LOCATION (last));
+
+  {
+    tree t = build4 (TARGET_EXPR, type, tmp, body, NULL_TREE, NULL_TREE);
+    SET_EXPR_LOCATION (t, loc);
+    return t;
+  }
+}
+\f
+/* Begin and end compound statements.  This is as simple as pushing
+   and popping new statement lists from the tree.  */
+
+tree
+c_begin_compound_stmt (bool do_scope)
+{
+  tree stmt = push_stmt_list ();
+  if (do_scope)
+    push_scope ();
+  return stmt;
+}
+
+/* End a compound statement.  STMT is the statement.  LOC is the
+   location of the compound statement-- this is usually the location
+   of the opening brace.  */
+
+tree
+c_end_compound_stmt (location_t loc, tree stmt, bool do_scope)
+{
+  tree block = NULL;
+
+  if (do_scope)
+    {
+      if (c_dialect_objc ())
+       objc_clear_super_receiver ();
+      block = pop_scope ();
+    }
+
+  stmt = pop_stmt_list (stmt);
+  stmt = c_build_bind_expr (loc, block, stmt);
+
+  /* If this compound statement is nested immediately inside a statement
+     expression, then force a BIND_EXPR to be created.  Otherwise we'll
+     do the wrong thing for ({ { 1; } }) or ({ 1; { } }).  In particular,
+     STATEMENT_LISTs merge, and thus we can lose track of what statement
+     was really last.  */
+  if (building_stmt_list_p ()
+      && STATEMENT_LIST_STMT_EXPR (cur_stmt_list)
+      && TREE_CODE (stmt) != BIND_EXPR)
+    {
+      stmt = build3 (BIND_EXPR, void_type_node, NULL, stmt, NULL);
+      TREE_SIDE_EFFECTS (stmt) = 1;
+      SET_EXPR_LOCATION (stmt, loc);
+    }
+
+  return stmt;
+}
+
+/* Queue a cleanup.  CLEANUP is an expression/statement to be executed
+   when the current scope is exited.  EH_ONLY is true when this is not
+   meant to apply to normal control flow transfer.  */
+
+void
+push_cleanup (tree decl, tree cleanup, bool eh_only)
+{
+  enum tree_code code;
+  tree stmt, list;
+  bool stmt_expr;
+
+  code = eh_only ? TRY_CATCH_EXPR : TRY_FINALLY_EXPR;
+  stmt = build_stmt (DECL_SOURCE_LOCATION (decl), code, NULL, cleanup);
+  add_stmt (stmt);
+  stmt_expr = STATEMENT_LIST_STMT_EXPR (cur_stmt_list);
+  list = push_stmt_list ();
+  TREE_OPERAND (stmt, 0) = list;
+  STATEMENT_LIST_STMT_EXPR (list) = stmt_expr;
+}
+
+/* Convert scalar to vector for the range of operations.  */
+static enum stv_conv
+scalar_to_vector (location_t loc, enum tree_code code, tree op0, tree op1)
+{
+  tree type0 = TREE_TYPE (op0);
+  tree type1 = TREE_TYPE (op1);
+  bool integer_only_op = false;
+  enum stv_conv ret = stv_firstarg;
+
+  gcc_assert (TREE_CODE (type0) == VECTOR_TYPE
+             || TREE_CODE (type1) == VECTOR_TYPE);
+  switch (code)
+    {
+      case RSHIFT_EXPR:
+      case LSHIFT_EXPR:
+       if (TREE_CODE (type0) == INTEGER_TYPE
+           && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE)
+         {
+           if (unsafe_conversion_p (TREE_TYPE (type1), op0, false))
+             {
+               error_at (loc, "conversion of scalar to vector "
+                              "involves truncation");
+               return stv_error;
+             }
+           else
+             return stv_firstarg;
+         }
+       break;
+
+      case BIT_IOR_EXPR:
+      case BIT_XOR_EXPR:
+      case BIT_AND_EXPR:
+       integer_only_op = true;
+       /* ... fall through ...  */
+
+      case PLUS_EXPR:
+      case MINUS_EXPR:
+      case MULT_EXPR:
+      case TRUNC_DIV_EXPR:
+      case TRUNC_MOD_EXPR:
+      case RDIV_EXPR:
+       if (TREE_CODE (type0) == VECTOR_TYPE)
+         {
+           tree tmp;
+           ret = stv_secondarg;
+           /* Swap TYPE0 with TYPE1 and OP0 with OP1  */
+           tmp = type0; type0 = type1; type1 = tmp;
+           tmp = op0; op0 = op1; op1 = tmp;
+         }
+
+       if (TREE_CODE (type0) == INTEGER_TYPE
+           && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE)
+         {
+           if (unsafe_conversion_p (TREE_TYPE (type1), op0, false))
+             {
+               error_at (loc, "conversion of scalar to vector "
+                              "involves truncation");
+               return stv_error;
+             }
+           return ret;
+         }
+       else if (!integer_only_op
+                   /* Allow integer --> real conversion if safe.  */
+                && (TREE_CODE (type0) == REAL_TYPE
+                    || TREE_CODE (type0) == INTEGER_TYPE)
+                && SCALAR_FLOAT_TYPE_P (TREE_TYPE (type1)))
+         {
+           if (unsafe_conversion_p (TREE_TYPE (type1), op0, false))
+             {
+               error_at (loc, "conversion of scalar to vector "
+                              "involves truncation");
+               return stv_error;
+             }
+           return ret;
+         }
+      default:
+       break;
+    }
+
+  return stv_nothing;
+}
+\f
+/* Build a binary-operation expression without default conversions.
+   CODE is the kind of expression to build.
+   LOCATION is the operator's location.
+   This function differs from `build' in several ways:
+   the data type of the result is computed and recorded in it,
+   warnings are generated if arg data types are invalid,
+   special handling for addition and subtraction of pointers is known,
+   and some optimization is done (operations on narrow ints
+   are done in the narrower type when that gives the same result).
+   Constant folding is also done before the result is returned.
+
+   Note that the operands will never have enumeral types, or function
+   or array types, because either they will have the default conversions
+   performed or they have both just been converted to some other type in which
+   the arithmetic is to be done.  */
+
+tree
+build_binary_op (location_t location, enum tree_code code,
+                tree orig_op0, tree orig_op1, int convert_p)
+{
+  tree type0, type1, orig_type0, orig_type1;
+  tree eptype;
+  enum tree_code code0, code1;
+  tree op0, op1;
+  tree ret = error_mark_node;
+  const char *invalid_op_diag;
+  bool op0_int_operands, op1_int_operands;
+  bool int_const, int_const_or_overflow, int_operands;
+
+  /* Expression code to give to the expression when it is built.
+     Normally this is CODE, which is what the caller asked for,
+     but in some special cases we change it.  */
+  enum tree_code resultcode = code;
+
+  /* Data type in which the computation is to be performed.
+     In the simplest cases this is the common type of the arguments.  */
+  tree result_type = NULL;
+
+  /* When the computation is in excess precision, the type of the
+     final EXCESS_PRECISION_EXPR.  */
+  tree semantic_result_type = NULL;
+
+  /* Nonzero means operands have already been type-converted
+     in whatever way is necessary.
+     Zero means they need to be converted to RESULT_TYPE.  */
+  int converted = 0;
+
+  /* Nonzero means create the expression with this type, rather than
+     RESULT_TYPE.  */
+  tree build_type = 0;
+
+  /* Nonzero means after finally constructing the expression
+     convert it to this type.  */
+  tree final_type = 0;
+
+  /* Nonzero if this is an operation like MIN or MAX which can
+     safely be computed in short if both args are promoted shorts.
+     Also implies COMMON.
+     -1 indicates a bitwise operation; this makes a difference
+     in the exact conditions for when it is safe to do the operation
+     in a narrower mode.  */
+  int shorten = 0;
+
+  /* Nonzero if this is a comparison operation;
+     if both args are promoted shorts, compare the original shorts.
+     Also implies COMMON.  */
+  int short_compare = 0;
+
+  /* Nonzero if this is a right-shift operation, which can be computed on the
+     original short and then promoted if the operand is a promoted short.  */
+  int short_shift = 0;
+
+  /* Nonzero means set RESULT_TYPE to the common type of the args.  */
+  int common = 0;
+
+  /* True means types are compatible as far as ObjC is concerned.  */
+  bool objc_ok;
+
+  /* True means this is an arithmetic operation that may need excess
+     precision.  */
+  bool may_need_excess_precision;
+
+  /* True means this is a boolean operation that converts both its
+     operands to truth-values.  */
+  bool boolean_op = false;
+
+  if (location == UNKNOWN_LOCATION)
+    location = input_location;
+
+  op0 = orig_op0;
+  op1 = orig_op1;
+
+  op0_int_operands = EXPR_INT_CONST_OPERANDS (orig_op0);
+  if (op0_int_operands)
+    op0 = remove_c_maybe_const_expr (op0);
+  op1_int_operands = EXPR_INT_CONST_OPERANDS (orig_op1);
+  if (op1_int_operands)
+    op1 = remove_c_maybe_const_expr (op1);
+  int_operands = (op0_int_operands && op1_int_operands);
+  if (int_operands)
+    {
+      int_const_or_overflow = (TREE_CODE (orig_op0) == INTEGER_CST
+                              && TREE_CODE (orig_op1) == INTEGER_CST);
+      int_const = (int_const_or_overflow
+                  && !TREE_OVERFLOW (orig_op0)
+                  && !TREE_OVERFLOW (orig_op1));
+    }
+  else
+    int_const = int_const_or_overflow = false;
+
+  /* Do not apply default conversion in mixed vector/scalar expression.  */
+  if (convert_p
+      && !((TREE_CODE (TREE_TYPE (op0)) == VECTOR_TYPE)
+          != (TREE_CODE (TREE_TYPE (op1)) == VECTOR_TYPE)))
+    {
+      op0 = default_conversion (op0);
+      op1 = default_conversion (op1);
+    }
+
+  orig_type0 = type0 = TREE_TYPE (op0);
+  orig_type1 = type1 = TREE_TYPE (op1);
+
+  /* The expression codes of the data types of the arguments tell us
+     whether the arguments are integers, floating, pointers, etc.  */
+  code0 = TREE_CODE (type0);
+  code1 = TREE_CODE (type1);
+
+  /* Strip NON_LVALUE_EXPRs, etc., since we aren't using as an lvalue.  */
+  STRIP_TYPE_NOPS (op0);
+  STRIP_TYPE_NOPS (op1);
+
+  /* If an error was already reported for one of the arguments,
+     avoid reporting another error.  */
+
+  if (code0 == ERROR_MARK || code1 == ERROR_MARK)
+    return error_mark_node;
+
+  if ((invalid_op_diag
+       = targetm.invalid_binary_op (code, type0, type1)))
+    {
+      error_at (location, invalid_op_diag);
+      return error_mark_node;
+    }
+
+  switch (code)
+    {
+    case PLUS_EXPR:
+    case MINUS_EXPR:
+    case MULT_EXPR:
+    case TRUNC_DIV_EXPR:
+    case CEIL_DIV_EXPR:
+    case FLOOR_DIV_EXPR:
+    case ROUND_DIV_EXPR:
+    case EXACT_DIV_EXPR:
+      may_need_excess_precision = true;
+      break;
+    default:
+      may_need_excess_precision = false;
+      break;
+    }
+  if (TREE_CODE (op0) == EXCESS_PRECISION_EXPR)
+    {
+      op0 = TREE_OPERAND (op0, 0);
+      type0 = TREE_TYPE (op0);
+    }
+  else if (may_need_excess_precision
+          && (eptype = excess_precision_type (type0)) != NULL_TREE)
+    {
+      type0 = eptype;
+      op0 = convert (eptype, op0);
+    }
+  if (TREE_CODE (op1) == EXCESS_PRECISION_EXPR)
+    {
+      op1 = TREE_OPERAND (op1, 0);
+      type1 = TREE_TYPE (op1);
+    }
+  else if (may_need_excess_precision
+          && (eptype = excess_precision_type (type1)) != NULL_TREE)
+    {
+      type1 = eptype;
+      op1 = convert (eptype, op1);
+    }
+
+  objc_ok = objc_compare_types (type0, type1, -3, NULL_TREE);
+
+  /* In case when one of the operands of the binary operation is
+     a vector and another is a scalar -- convert scalar to vector.  */
+  if ((code0 == VECTOR_TYPE) != (code1 == VECTOR_TYPE))
+    {
+      enum stv_conv convert_flag = scalar_to_vector (location, code, op0, op1);
+
+      switch (convert_flag)
+       {
+         case stv_error:
+           return error_mark_node;
+         case stv_firstarg:
+           {
+              bool maybe_const = true;
+              tree sc;
+              sc = c_fully_fold (op0, false, &maybe_const);
+              sc = save_expr (sc);
+              sc = convert (TREE_TYPE (type1), sc);
+              op0 = build_vector_from_val (type1, sc);
+              if (!maybe_const)
+                op0 = c_wrap_maybe_const (op0, true);
+              orig_type0 = type0 = TREE_TYPE (op0);
+              code0 = TREE_CODE (type0);
+              converted = 1;
+              break;
+           }
+         case stv_secondarg:
+           {
+             bool maybe_const = true;
+             tree sc;
+             sc = c_fully_fold (op1, false, &maybe_const);
+             sc = save_expr (sc);
+             sc = convert (TREE_TYPE (type0), sc);
+             op1 = build_vector_from_val (type0, sc);
+             if (!maybe_const)
+               op1 = c_wrap_maybe_const (op1, true);
+             orig_type1 = type1 = TREE_TYPE (op1);
+             code1 = TREE_CODE (type1);
+             converted = 1;
+             break;
+           }
+         default:
+           break;
+       }
+    }
+
+  switch (code)
+    {
+    case PLUS_EXPR:
+      /* Handle the pointer + int case.  */
+      if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
+       {
+         ret = pointer_int_sum (location, PLUS_EXPR, op0, op1);
+         goto return_build_binary_op;
+       }
+      else if (code1 == POINTER_TYPE && code0 == INTEGER_TYPE)
+       {
+         ret = pointer_int_sum (location, PLUS_EXPR, op1, op0);
+         goto return_build_binary_op;
+       }
+      else
+       common = 1;
+      break;
+
+    case MINUS_EXPR:
+      /* Subtraction of two similar pointers.
+        We must subtract them as integers, then divide by object size.  */
+      if (code0 == POINTER_TYPE && code1 == POINTER_TYPE
+         && comp_target_types (location, type0, type1))
+       {
+         ret = pointer_diff (location, op0, op1);
+         goto return_build_binary_op;
+       }
+      /* Handle pointer minus int.  Just like pointer plus int.  */
+      else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
+       {
+         ret = pointer_int_sum (location, MINUS_EXPR, op0, op1);
+         goto return_build_binary_op;
+       }
+      else
+       common = 1;
+      break;
+
+    case MULT_EXPR:
+      common = 1;
+      break;
+
+    case TRUNC_DIV_EXPR:
+    case CEIL_DIV_EXPR:
+    case FLOOR_DIV_EXPR:
+    case ROUND_DIV_EXPR:
+    case EXACT_DIV_EXPR:
+      warn_for_div_by_zero (location, op1);
+
+      if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
+          || code0 == FIXED_POINT_TYPE
+          || code0 == COMPLEX_TYPE || code0 == VECTOR_TYPE)
+         && (code1 == INTEGER_TYPE || code1 == REAL_TYPE
+             || code1 == FIXED_POINT_TYPE
+             || code1 == COMPLEX_TYPE || code1 == VECTOR_TYPE))
+       {
+         enum tree_code tcode0 = code0, tcode1 = code1;
+
+         if (code0 == COMPLEX_TYPE || code0 == VECTOR_TYPE)
+           tcode0 = TREE_CODE (TREE_TYPE (TREE_TYPE (op0)));
+         if (code1 == COMPLEX_TYPE || code1 == VECTOR_TYPE)
+           tcode1 = TREE_CODE (TREE_TYPE (TREE_TYPE (op1)));
+
+         if (!((tcode0 == INTEGER_TYPE && tcode1 == INTEGER_TYPE)
+             || (tcode0 == FIXED_POINT_TYPE && tcode1 == FIXED_POINT_TYPE)))
+           resultcode = RDIV_EXPR;
+         else
+           /* Although it would be tempting to shorten always here, that
+              loses on some targets, since the modulo instruction is
+              undefined if the quotient can't be represented in the
+              computation mode.  We shorten only if unsigned or if
+              dividing by something we know != -1.  */
+           shorten = (TYPE_UNSIGNED (TREE_TYPE (orig_op0))
+                      || (TREE_CODE (op1) == INTEGER_CST
+                          && !integer_all_onesp (op1)));
+         common = 1;
+       }
+      break;
+
+    case BIT_AND_EXPR:
+    case BIT_IOR_EXPR:
+    case BIT_XOR_EXPR:
+      if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
+       shorten = -1;
+      /* Allow vector types which are not floating point types.   */
+      else if (code0 == VECTOR_TYPE
+              && code1 == VECTOR_TYPE
+              && !VECTOR_FLOAT_TYPE_P (type0)
+              && !VECTOR_FLOAT_TYPE_P (type1))
+       common = 1;
+      break;
+
+    case TRUNC_MOD_EXPR:
+    case FLOOR_MOD_EXPR:
+      warn_for_div_by_zero (location, op1);
+
+      if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE
+         && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE
+         && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE)
+       common = 1;
+      else if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
+       {
+         /* Although it would be tempting to shorten always here, that loses
+            on some targets, since the modulo instruction is undefined if the
+            quotient can't be represented in the computation mode.  We shorten
+            only if unsigned or if dividing by something we know != -1.  */
+         shorten = (TYPE_UNSIGNED (TREE_TYPE (orig_op0))
+                    || (TREE_CODE (op1) == INTEGER_CST
+                        && !integer_all_onesp (op1)));
+         common = 1;
+       }
+      break;
+
+    case TRUTH_ANDIF_EXPR:
+    case TRUTH_ORIF_EXPR:
+    case TRUTH_AND_EXPR:
+    case TRUTH_OR_EXPR:
+    case TRUTH_XOR_EXPR:
+      if ((code0 == INTEGER_TYPE || code0 == POINTER_TYPE
+          || code0 == REAL_TYPE || code0 == COMPLEX_TYPE
+          || code0 == FIXED_POINT_TYPE)
+         && (code1 == INTEGER_TYPE || code1 == POINTER_TYPE
+             || code1 == REAL_TYPE || code1 == COMPLEX_TYPE
+             || code1 == FIXED_POINT_TYPE))
+       {
+         /* Result of these operations is always an int,
+            but that does not mean the operands should be
+            converted to ints!  */
+         result_type = integer_type_node;
+         op0 = c_common_truthvalue_conversion (location, op0);
+         op1 = c_common_truthvalue_conversion (location, op1);
+         converted = 1;
+         boolean_op = true;
+       }
+      if (code == TRUTH_ANDIF_EXPR)
+       {
+         int_const_or_overflow = (int_operands
+                                  && TREE_CODE (orig_op0) == INTEGER_CST
+                                  && (op0 == truthvalue_false_node
+                                      || TREE_CODE (orig_op1) == INTEGER_CST));
+         int_const = (int_const_or_overflow
+                      && !TREE_OVERFLOW (orig_op0)
+                      && (op0 == truthvalue_false_node
+                          || !TREE_OVERFLOW (orig_op1)));
+       }
+      else if (code == TRUTH_ORIF_EXPR)
+       {
+         int_const_or_overflow = (int_operands
+                                  && TREE_CODE (orig_op0) == INTEGER_CST
+                                  && (op0 == truthvalue_true_node
+                                      || TREE_CODE (orig_op1) == INTEGER_CST));
+         int_const = (int_const_or_overflow
+                      && !TREE_OVERFLOW (orig_op0)
+                      && (op0 == truthvalue_true_node
+                          || !TREE_OVERFLOW (orig_op1)));
+       }
+      break;
+
+      /* Shift operations: result has same type as first operand;
+        always convert second operand to int.
+        Also set SHORT_SHIFT if shifting rightward.  */
+
+    case RSHIFT_EXPR:
+      if (code0 == VECTOR_TYPE && code1 == INTEGER_TYPE
+          && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE)
+        {
+          result_type = type0;
+          converted = 1;
+        }
+      else if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE
+         && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE
+          && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE
+          && TYPE_VECTOR_SUBPARTS (type0) == TYPE_VECTOR_SUBPARTS (type1))
+       {
+         result_type = type0;
+         converted = 1;
+       }
+      else if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
+         && code1 == INTEGER_TYPE)
+       {
+         if (TREE_CODE (op1) == INTEGER_CST)
+           {
+             if (tree_int_cst_sgn (op1) < 0)
+               {
+                 int_const = false;
+                 if (c_inhibit_evaluation_warnings == 0)
+                   warning (0, "right shift count is negative");
+               }
+             else
+               {
+                 if (!integer_zerop (op1))
+                   short_shift = 1;
+
+                 if (compare_tree_int (op1, TYPE_PRECISION (type0)) >= 0)
+                   {
+                     int_const = false;
+                     if (c_inhibit_evaluation_warnings == 0)
+                       warning (0, "right shift count >= width of type");
+                   }
+               }
+           }
+
+         /* Use the type of the value to be shifted.  */
+         result_type = type0;
+         /* Convert the non vector shift-count to an integer, regardless
+            of size of value being shifted.  */
+         if (TREE_CODE (TREE_TYPE (op1)) != VECTOR_TYPE
+             && TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
+           op1 = convert (integer_type_node, op1);
+         /* Avoid converting op1 to result_type later.  */
+         converted = 1;
+       }
+      break;
+
+    case LSHIFT_EXPR:
+      if (code0 == VECTOR_TYPE && code1 == INTEGER_TYPE
+          && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE)
+        {
+          result_type = type0;
+          converted = 1;
+        }
+      else if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE
+         && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE
+          && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE
+          && TYPE_VECTOR_SUBPARTS (type0) == TYPE_VECTOR_SUBPARTS (type1))
+       {
+         result_type = type0;
+         converted = 1;
+       }
+      else if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
+         && code1 == INTEGER_TYPE)
+       {
+         if (TREE_CODE (op1) == INTEGER_CST)
+           {
+             if (tree_int_cst_sgn (op1) < 0)
+               {
+                 int_const = false;
+                 if (c_inhibit_evaluation_warnings == 0)
+                   warning (0, "left shift count is negative");
+               }
+
+             else if (compare_tree_int (op1, TYPE_PRECISION (type0)) >= 0)
+               {
+                 int_const = false;
+                 if (c_inhibit_evaluation_warnings == 0)
+                   warning (0, "left shift count >= width of type");
+               }
+           }
+
+         /* Use the type of the value to be shifted.  */
+         result_type = type0;
+         /* Convert the non vector shift-count to an integer, regardless
+            of size of value being shifted.  */
+         if (TREE_CODE (TREE_TYPE (op1)) != VECTOR_TYPE
+             && TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
+           op1 = convert (integer_type_node, op1);
+         /* Avoid converting op1 to result_type later.  */
+         converted = 1;
+       }
+      break;
+
+    case EQ_EXPR:
+    case NE_EXPR:
+      if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE)
+        {
+          tree intt;
+          if (TREE_TYPE (type0) != TREE_TYPE (type1))
+            {
+              error_at (location, "comparing vectors with different "
+                                  "element types");
+              return error_mark_node;
+            }
+
+          if (TYPE_VECTOR_SUBPARTS (type0) != TYPE_VECTOR_SUBPARTS (type1))
+            {
+              error_at (location, "comparing vectors with different "
+                                  "number of elements");
+              return error_mark_node;
+            }
+
+          /* Always construct signed integer vector type.  */
+          intt = c_common_type_for_size (GET_MODE_BITSIZE
+                                          (TYPE_MODE (TREE_TYPE (type0))), 0);
+          result_type = build_opaque_vector_type (intt,
+                                                 TYPE_VECTOR_SUBPARTS (type0));
+          converted = 1;
+          break;
+        }
+      if (FLOAT_TYPE_P (type0) || FLOAT_TYPE_P (type1))
+       warning_at (location,
+                   OPT_Wfloat_equal,
+                   "comparing floating point with == or != is unsafe");
+      /* Result of comparison is always int,
+        but don't convert the args to int!  */
+      build_type = integer_type_node;
+      if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
+          || code0 == FIXED_POINT_TYPE || code0 == COMPLEX_TYPE)
+         && (code1 == INTEGER_TYPE || code1 == REAL_TYPE
+             || code1 == FIXED_POINT_TYPE || code1 == COMPLEX_TYPE))
+       short_compare = 1;
+      else if (code0 == POINTER_TYPE && null_pointer_constant_p (orig_op1))
+       {
+         if (TREE_CODE (op0) == ADDR_EXPR
+             && decl_with_nonnull_addr_p (TREE_OPERAND (op0, 0)))
+           {
+             if (code == EQ_EXPR)
+               warning_at (location,
+                           OPT_Waddress,
+                           "the comparison will always evaluate as %<false%> "
+                           "for the address of %qD will never be NULL",
+                           TREE_OPERAND (op0, 0));
+             else
+               warning_at (location,
+                           OPT_Waddress,
+                           "the comparison will always evaluate as %<true%> "
+                           "for the address of %qD will never be NULL",
+                           TREE_OPERAND (op0, 0));
+           }
+         result_type = type0;
+       }
+      else if (code1 == POINTER_TYPE && null_pointer_constant_p (orig_op0))
+       {
+         if (TREE_CODE (op1) == ADDR_EXPR
+             && decl_with_nonnull_addr_p (TREE_OPERAND (op1, 0)))
+           {
+             if (code == EQ_EXPR)
+               warning_at (location,
+                           OPT_Waddress,
+                           "the comparison will always evaluate as %<false%> "
+                           "for the address of %qD will never be NULL",
+                           TREE_OPERAND (op1, 0));
+             else
+               warning_at (location,
+                           OPT_Waddress,
+                           "the comparison will always evaluate as %<true%> "
+                           "for the address of %qD will never be NULL",
+                           TREE_OPERAND (op1, 0));
+           }
+         result_type = type1;
+       }
+      else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
+       {
+         tree tt0 = TREE_TYPE (type0);
+         tree tt1 = TREE_TYPE (type1);
+         addr_space_t as0 = TYPE_ADDR_SPACE (tt0);
+         addr_space_t as1 = TYPE_ADDR_SPACE (tt1);
+         addr_space_t as_common = ADDR_SPACE_GENERIC;
+
+         /* Anything compares with void *.  void * compares with anything.
+            Otherwise, the targets must be compatible
+            and both must be object or both incomplete.  */
+         if (comp_target_types (location, type0, type1))
+           result_type = common_pointer_type (type0, type1);
+         else if (!addr_space_superset (as0, as1, &as_common))
+           {
+             error_at (location, "comparison of pointers to "
+                       "disjoint address spaces");
+             return error_mark_node;
+           }
+         else if (VOID_TYPE_P (tt0))
+           {
+             if (pedantic && TREE_CODE (tt1) == FUNCTION_TYPE)
+               pedwarn (location, OPT_Wpedantic, "ISO C forbids "
+                        "comparison of %<void *%> with function pointer");
+           }
+         else if (VOID_TYPE_P (tt1))
+           {
+             if (pedantic && TREE_CODE (tt0) == FUNCTION_TYPE)
+               pedwarn (location, OPT_Wpedantic, "ISO C forbids "
+                        "comparison of %<void *%> with function pointer");
+           }
+         else
+           /* Avoid warning about the volatile ObjC EH puts on decls.  */
+           if (!objc_ok)
+             pedwarn (location, 0,
+                      "comparison of distinct pointer types lacks a cast");
+
+         if (result_type == NULL_TREE)
+           {
+             int qual = ENCODE_QUAL_ADDR_SPACE (as_common);
+             result_type = build_pointer_type
+                             (build_qualified_type (void_type_node, qual));
+           }
+       }
+      else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
+       {
+         result_type = type0;
+         pedwarn (location, 0, "comparison between pointer and integer");
+       }
+      else if (code0 == INTEGER_TYPE && code1 == POINTER_TYPE)
+       {
+         result_type = type1;
+         pedwarn (location, 0, "comparison between pointer and integer");
+       }
+      break;
+
+    case LE_EXPR:
+    case GE_EXPR:
+    case LT_EXPR:
+    case GT_EXPR:
+      if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE)
+        {
+          tree intt;
+          if (TREE_TYPE (type0) != TREE_TYPE (type1))
+            {
+              error_at (location, "comparing vectors with different "
+                                  "element types");
+              return error_mark_node;
+            }
+
+          if (TYPE_VECTOR_SUBPARTS (type0) != TYPE_VECTOR_SUBPARTS (type1))
+            {
+              error_at (location, "comparing vectors with different "
+                                  "number of elements");
+              return error_mark_node;
+            }
+
+          /* Always construct signed integer vector type.  */
+          intt = c_common_type_for_size (GET_MODE_BITSIZE
+                                          (TYPE_MODE (TREE_TYPE (type0))), 0);
+          result_type = build_opaque_vector_type (intt,
+                                                 TYPE_VECTOR_SUBPARTS (type0));
+          converted = 1;
+          break;
+        }
+      build_type = integer_type_node;
+      if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
+          || code0 == FIXED_POINT_TYPE)
+         && (code1 == INTEGER_TYPE || code1 == REAL_TYPE
+             || code1 == FIXED_POINT_TYPE))
+       short_compare = 1;
+      else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
+       {
+         addr_space_t as0 = TYPE_ADDR_SPACE (TREE_TYPE (type0));
+         addr_space_t as1 = TYPE_ADDR_SPACE (TREE_TYPE (type1));
+         addr_space_t as_common;
+
+         if (comp_target_types (location, type0, type1))
+           {
+             result_type = common_pointer_type (type0, type1);
+             if (!COMPLETE_TYPE_P (TREE_TYPE (type0))
+                 != !COMPLETE_TYPE_P (TREE_TYPE (type1)))
+               pedwarn (location, 0,
+                        "comparison of complete and incomplete pointers");
+             else if (TREE_CODE (TREE_TYPE (type0)) == FUNCTION_TYPE)
+               pedwarn (location, OPT_Wpedantic, "ISO C forbids "
+                        "ordered comparisons of pointers to functions");
+             else if (null_pointer_constant_p (orig_op0)
+                      || null_pointer_constant_p (orig_op1))
+               warning_at (location, OPT_Wextra,
+                           "ordered comparison of pointer with null pointer");
+
+           }
+         else if (!addr_space_superset (as0, as1, &as_common))
+           {
+             error_at (location, "comparison of pointers to "
+                       "disjoint address spaces");
+             return error_mark_node;
+           }
+         else
+           {
+             int qual = ENCODE_QUAL_ADDR_SPACE (as_common);
+             result_type = build_pointer_type
+                             (build_qualified_type (void_type_node, qual));
+             pedwarn (location, 0,
+                      "comparison of distinct pointer types lacks a cast");
+           }
+       }
+      else if (code0 == POINTER_TYPE && null_pointer_constant_p (orig_op1))
+       {
+         result_type = type0;
+         if (pedantic)
+           pedwarn (location, OPT_Wpedantic,
+                    "ordered comparison of pointer with integer zero");
+         else if (extra_warnings)
+           warning_at (location, OPT_Wextra,
+                       "ordered comparison of pointer with integer zero");
+       }
+      else if (code1 == POINTER_TYPE && null_pointer_constant_p (orig_op0))
+       {
+         result_type = type1;
+         if (pedantic)
+           pedwarn (location, OPT_Wpedantic,
+                    "ordered comparison of pointer with integer zero");
+         else if (extra_warnings)
+           warning_at (location, OPT_Wextra,
+                       "ordered comparison of pointer with integer zero");
+       }
+      else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
+       {
+         result_type = type0;
+         pedwarn (location, 0, "comparison between pointer and integer");
+       }
+      else if (code0 == INTEGER_TYPE && code1 == POINTER_TYPE)
+       {
+         result_type = type1;
+         pedwarn (location, 0, "comparison between pointer and integer");
+       }
+      break;
+
+    default:
+      gcc_unreachable ();
+    }
+
+  if (code0 == ERROR_MARK || code1 == ERROR_MARK)
+    return error_mark_node;
+
+  if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE
+      && (!tree_int_cst_equal (TYPE_SIZE (type0), TYPE_SIZE (type1))
+         || !same_scalar_type_ignoring_signedness (TREE_TYPE (type0),
+                                                   TREE_TYPE (type1))))
+    {
+      binary_op_error (location, code, type0, type1);
+      return error_mark_node;
+    }
+
+  if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE || code0 == COMPLEX_TYPE
+       || code0 == FIXED_POINT_TYPE || code0 == VECTOR_TYPE)
+      &&
+      (code1 == INTEGER_TYPE || code1 == REAL_TYPE || code1 == COMPLEX_TYPE
+       || code1 == FIXED_POINT_TYPE || code1 == VECTOR_TYPE))
+    {
+      bool first_complex = (code0 == COMPLEX_TYPE);
+      bool second_complex = (code1 == COMPLEX_TYPE);
+      int none_complex = (!first_complex && !second_complex);
+
+      if (shorten || common || short_compare)
+       {
+         result_type = c_common_type (type0, type1);
+         do_warn_double_promotion (result_type, type0, type1,
+                                   "implicit conversion from %qT to %qT "
+                                   "to match other operand of binary "
+                                   "expression",
+                                   location);
+         if (result_type == error_mark_node)
+           return error_mark_node;
+       }
+
+      if (first_complex != second_complex
+         && (code == PLUS_EXPR
+             || code == MINUS_EXPR
+             || code == MULT_EXPR
+             || (code == TRUNC_DIV_EXPR && first_complex))
+         && TREE_CODE (TREE_TYPE (result_type)) == REAL_TYPE
+         && flag_signed_zeros)
+       {
+         /* An operation on mixed real/complex operands must be
+            handled specially, but the language-independent code can
+            more easily optimize the plain complex arithmetic if
+            -fno-signed-zeros.  */
+         tree real_type = TREE_TYPE (result_type);
+         tree real, imag;
+         if (type0 != orig_type0 || type1 != orig_type1)
+           {
+             gcc_assert (may_need_excess_precision && common);
+             semantic_result_type = c_common_type (orig_type0, orig_type1);
+           }
+         if (first_complex)
+           {
+             if (TREE_TYPE (op0) != result_type)
+               op0 = convert_and_check (result_type, op0);
+             if (TREE_TYPE (op1) != real_type)
+               op1 = convert_and_check (real_type, op1);
+           }
+         else
+           {
+             if (TREE_TYPE (op0) != real_type)
+               op0 = convert_and_check (real_type, op0);
+             if (TREE_TYPE (op1) != result_type)
+               op1 = convert_and_check (result_type, op1);
+           }
+         if (TREE_CODE (op0) == ERROR_MARK || TREE_CODE (op1) == ERROR_MARK)
+           return error_mark_node;
+         if (first_complex)
+           {
+             op0 = c_save_expr (op0);
+             real = build_unary_op (EXPR_LOCATION (orig_op0), REALPART_EXPR,
+                                    op0, 1);
+             imag = build_unary_op (EXPR_LOCATION (orig_op0), IMAGPART_EXPR,
+                                    op0, 1);
+             switch (code)
+               {
+               case MULT_EXPR:
+               case TRUNC_DIV_EXPR:
+                 op1 = c_save_expr (op1);
+                 imag = build2 (resultcode, real_type, imag, op1);
+                 /* Fall through.  */
+               case PLUS_EXPR:
+               case MINUS_EXPR:
+                 real = build2 (resultcode, real_type, real, op1);
+                 break;
+               default:
+                 gcc_unreachable();
+               }
+           }
+         else
+           {
+             op1 = c_save_expr (op1);
+             real = build_unary_op (EXPR_LOCATION (orig_op1), REALPART_EXPR,
+                                    op1, 1);
+             imag = build_unary_op (EXPR_LOCATION (orig_op1), IMAGPART_EXPR,
+                                    op1, 1);
+             switch (code)
+               {
+               case MULT_EXPR:
+                 op0 = c_save_expr (op0);
+                 imag = build2 (resultcode, real_type, op0, imag);
+                 /* Fall through.  */
+               case PLUS_EXPR:
+                 real = build2 (resultcode, real_type, op0, real);
+                 break;
+               case MINUS_EXPR:
+                 real = build2 (resultcode, real_type, op0, real);
+                 imag = build1 (NEGATE_EXPR, real_type, imag);
+                 break;
+               default:
+                 gcc_unreachable();
+               }
+           }
+         ret = build2 (COMPLEX_EXPR, result_type, real, imag);
+         goto return_build_binary_op;
+       }
+
+      /* For certain operations (which identify themselves by shorten != 0)
+        if both args were extended from the same smaller type,
+        do the arithmetic in that type and then extend.
+
+        shorten !=0 and !=1 indicates a bitwise operation.
+        For them, this optimization is safe only if
+        both args are zero-extended or both are sign-extended.
+        Otherwise, we might change the result.
+        Eg, (short)-1 | (unsigned short)-1 is (int)-1
+        but calculated in (unsigned short) it would be (unsigned short)-1.  */
+
+      if (shorten && none_complex)
+       {
+         final_type = result_type;
+         result_type = shorten_binary_op (result_type, op0, op1,
+                                          shorten == -1);
+       }
+
+      /* Shifts can be shortened if shifting right.  */
+
+      if (short_shift)
+       {
+         int unsigned_arg;
+         tree arg0 = get_narrower (op0, &unsigned_arg);
+
+         final_type = result_type;
+
+         if (arg0 == op0 && final_type == TREE_TYPE (op0))
+           unsigned_arg = TYPE_UNSIGNED (TREE_TYPE (op0));
+
+         if (TYPE_PRECISION (TREE_TYPE (arg0)) < TYPE_PRECISION (result_type)
+             && tree_int_cst_sgn (op1) > 0
+             /* We can shorten only if the shift count is less than the
+                number of bits in the smaller type size.  */
+             && compare_tree_int (op1, TYPE_PRECISION (TREE_TYPE (arg0))) < 0
+             /* We cannot drop an unsigned shift after sign-extension.  */
+             && (!TYPE_UNSIGNED (final_type) || unsigned_arg))
+           {
+             /* Do an unsigned shift if the operand was zero-extended.  */
+             result_type
+               = c_common_signed_or_unsigned_type (unsigned_arg,
+                                                   TREE_TYPE (arg0));
+             /* Convert value-to-be-shifted to that type.  */
+             if (TREE_TYPE (op0) != result_type)
+               op0 = convert (result_type, op0);
+             converted = 1;
+           }
+       }
+
+      /* Comparison operations are shortened too but differently.
+        They identify themselves by setting short_compare = 1.  */
+
+      if (short_compare)
+       {
+         /* Don't write &op0, etc., because that would prevent op0
+            from being kept in a register.
+            Instead, make copies of the our local variables and
+            pass the copies by reference, then copy them back afterward.  */
+         tree xop0 = op0, xop1 = op1, xresult_type = result_type;
+         enum tree_code xresultcode = resultcode;
+         tree val
+           = shorten_compare (&xop0, &xop1, &xresult_type, &xresultcode);
+
+         if (val != 0)
+           {
+             ret = val;
+             goto return_build_binary_op;
+           }
+
+         op0 = xop0, op1 = xop1;
+         converted = 1;
+         resultcode = xresultcode;
+
+         if (c_inhibit_evaluation_warnings == 0)
+           {
+             bool op0_maybe_const = true;
+             bool op1_maybe_const = true;
+             tree orig_op0_folded, orig_op1_folded;
+
+             if (in_late_binary_op)
+               {
+                 orig_op0_folded = orig_op0;
+                 orig_op1_folded = orig_op1;
+               }
+             else
+               {
+                 /* Fold for the sake of possible warnings, as in
+                    build_conditional_expr.  This requires the
+                    "original" values to be folded, not just op0 and
+                    op1.  */
+                 c_inhibit_evaluation_warnings++;
+                 op0 = c_fully_fold (op0, require_constant_value,
+                                     &op0_maybe_const);
+                 op1 = c_fully_fold (op1, require_constant_value,
+                                     &op1_maybe_const);
+                 c_inhibit_evaluation_warnings--;
+                 orig_op0_folded = c_fully_fold (orig_op0,
+                                                 require_constant_value,
+                                                 NULL);
+                 orig_op1_folded = c_fully_fold (orig_op1,
+                                                 require_constant_value,
+                                                 NULL);
+               }
+
+             if (warn_sign_compare)
+               warn_for_sign_compare (location, orig_op0_folded,
+                                      orig_op1_folded, op0, op1,
+                                      result_type, resultcode);
+             if (!in_late_binary_op && !int_operands)
+               {
+                 if (!op0_maybe_const || TREE_CODE (op0) != INTEGER_CST)
+                   op0 = c_wrap_maybe_const (op0, !op0_maybe_const);
+                 if (!op1_maybe_const || TREE_CODE (op1) != INTEGER_CST)
+                   op1 = c_wrap_maybe_const (op1, !op1_maybe_const);
+               }
+           }
+       }
+    }
+
+  /* At this point, RESULT_TYPE must be nonzero to avoid an error message.
+     If CONVERTED is zero, both args will be converted to type RESULT_TYPE.
+     Then the expression will be built.
+     It will be given type FINAL_TYPE if that is nonzero;
+     otherwise, it will be given type RESULT_TYPE.  */
+
+  if (!result_type)
+    {
+      binary_op_error (location, code, TREE_TYPE (op0), TREE_TYPE (op1));
+      return error_mark_node;
+    }
+
+  if (build_type == NULL_TREE)
+    {
+      build_type = result_type;
+      if ((type0 != orig_type0 || type1 != orig_type1)
+         && !boolean_op)
+       {
+         gcc_assert (may_need_excess_precision && common);
+         semantic_result_type = c_common_type (orig_type0, orig_type1);
+       }
+    }
+
+  if (!converted)
+    {
+      op0 = ep_convert_and_check (result_type, op0, semantic_result_type);
+      op1 = ep_convert_and_check (result_type, op1, semantic_result_type);
+
+      /* This can happen if one operand has a vector type, and the other
+        has a different type.  */
+      if (TREE_CODE (op0) == ERROR_MARK || TREE_CODE (op1) == ERROR_MARK)
+       return error_mark_node;
+    }
+
+  /* Treat expressions in initializers specially as they can't trap.  */
+  if (int_const_or_overflow)
+    ret = (require_constant_value
+          ? fold_build2_initializer_loc (location, resultcode, build_type,
+                                         op0, op1)
+          : fold_build2_loc (location, resultcode, build_type, op0, op1));
+  else
+    ret = build2 (resultcode, build_type, op0, op1);
+  if (final_type != 0)
+    ret = convert (final_type, ret);
+
+ return_build_binary_op:
+  gcc_assert (ret != error_mark_node);
+  if (TREE_CODE (ret) == INTEGER_CST && !TREE_OVERFLOW (ret) && !int_const)
+    ret = (int_operands
+          ? note_integer_operands (ret)
+          : build1 (NOP_EXPR, TREE_TYPE (ret), ret));
+  else if (TREE_CODE (ret) != INTEGER_CST && int_operands
+          && !in_late_binary_op)
+    ret = note_integer_operands (ret);
+  if (semantic_result_type)
+    ret = build1 (EXCESS_PRECISION_EXPR, semantic_result_type, ret);
+  protected_set_expr_location (ret, location);
+  return ret;
+}
+
+
+/* Convert EXPR to be a truth-value, validating its type for this
+   purpose.  LOCATION is the source location for the expression.  */
+
+tree
+c_objc_common_truthvalue_conversion (location_t location, tree expr)
+{
+  bool int_const, int_operands;
+
+  switch (TREE_CODE (TREE_TYPE (expr)))
+    {
+    case ARRAY_TYPE:
+      error_at (location, "used array that cannot be converted to pointer where scalar is required");
+      return error_mark_node;
+
+    case RECORD_TYPE:
+      error_at (location, "used struct type value where scalar is required");
+      return error_mark_node;
+
+    case UNION_TYPE:
+      error_at (location, "used union type value where scalar is required");
+      return error_mark_node;
+
+    case VOID_TYPE:
+      error_at (location, "void value not ignored as it ought to be");
+      return error_mark_node;
+
+    case FUNCTION_TYPE:
+      gcc_unreachable ();
+
+    case VECTOR_TYPE:
+      error_at (location, "used vector type where scalar is required");
+      return error_mark_node;
+
+    default:
+      break;
+    }
+
+  int_const = (TREE_CODE (expr) == INTEGER_CST && !TREE_OVERFLOW (expr));
+  int_operands = EXPR_INT_CONST_OPERANDS (expr);
+  if (int_operands)
+    expr = remove_c_maybe_const_expr (expr);
+
+  /* ??? Should we also give an error for vectors rather than leaving
+     those to give errors later?  */
+  expr = c_common_truthvalue_conversion (location, expr);
+
+  if (TREE_CODE (expr) == INTEGER_CST && int_operands && !int_const)
+    {
+      if (TREE_OVERFLOW (expr))
+       return expr;
+      else
+       return note_integer_operands (expr);
+    }
+  if (TREE_CODE (expr) == INTEGER_CST && !int_const)
+    return build1 (NOP_EXPR, TREE_TYPE (expr), expr);
+  return expr;
+}
+\f
+
+/* Convert EXPR to a contained DECL, updating *TC, *TI and *SE as
+   required.  */
+
+tree
+c_expr_to_decl (tree expr, bool *tc ATTRIBUTE_UNUSED, bool *se)
+{
+  if (TREE_CODE (expr) == COMPOUND_LITERAL_EXPR)
+    {
+      tree decl = COMPOUND_LITERAL_EXPR_DECL (expr);
+      /* Executing a compound literal inside a function reinitializes
+        it.  */
+      if (!TREE_STATIC (decl))
+       *se = true;
+      return decl;
+    }
+  else
+    return expr;
+}
+\f
+/* Like c_begin_compound_stmt, except force the retention of the BLOCK.  */
+
+tree
+c_begin_omp_parallel (void)
+{
+  tree block;
+
+  keep_next_level ();
+  block = c_begin_compound_stmt (true);
+
+  return block;
+}
+
+/* Generate OMP_PARALLEL, with CLAUSES and BLOCK as its compound
+   statement.  LOC is the location of the OMP_PARALLEL.  */
+
+tree
+c_finish_omp_parallel (location_t loc, tree clauses, tree block)
+{
+  tree stmt;
+
+  block = c_end_compound_stmt (loc, block, true);
+
+  stmt = make_node (OMP_PARALLEL);
+  TREE_TYPE (stmt) = void_type_node;
+  OMP_PARALLEL_CLAUSES (stmt) = clauses;
+  OMP_PARALLEL_BODY (stmt) = block;
+  SET_EXPR_LOCATION (stmt, loc);
+
+  return add_stmt (stmt);
+}
+
+/* Like c_begin_compound_stmt, except force the retention of the BLOCK.  */
+
+tree
+c_begin_omp_task (void)
+{
+  tree block;
+
+  keep_next_level ();
+  block = c_begin_compound_stmt (true);
+
+  return block;
+}
+
+/* Generate OMP_TASK, with CLAUSES and BLOCK as its compound
+   statement.  LOC is the location of the #pragma.  */
+
+tree
+c_finish_omp_task (location_t loc, tree clauses, tree block)
+{
+  tree stmt;
+
+  block = c_end_compound_stmt (loc, block, true);
+
+  stmt = make_node (OMP_TASK);
+  TREE_TYPE (stmt) = void_type_node;
+  OMP_TASK_CLAUSES (stmt) = clauses;
+  OMP_TASK_BODY (stmt) = block;
+  SET_EXPR_LOCATION (stmt, loc);
+
+  return add_stmt (stmt);
+}
+
+/* For all elements of CLAUSES, validate them vs OpenMP constraints.
+   Remove any elements from the list that are invalid.  */
+
+tree
+c_finish_omp_clauses (tree clauses)
+{
+  bitmap_head generic_head, firstprivate_head, lastprivate_head;
+  tree c, t, *pc = &clauses;
+  const char *name;
+
+  bitmap_obstack_initialize (NULL);
+  bitmap_initialize (&generic_head, &bitmap_default_obstack);
+  bitmap_initialize (&firstprivate_head, &bitmap_default_obstack);
+  bitmap_initialize (&lastprivate_head, &bitmap_default_obstack);
+
+  for (pc = &clauses, c = clauses; c ; c = *pc)
+    {
+      bool remove = false;
+      bool need_complete = false;
+      bool need_implicitly_determined = false;
+
+      switch (OMP_CLAUSE_CODE (c))
+       {
+       case OMP_CLAUSE_SHARED:
+         name = "shared";
+         need_implicitly_determined = true;
+         goto check_dup_generic;
+
+       case OMP_CLAUSE_PRIVATE:
+         name = "private";
+         need_complete = true;
+         need_implicitly_determined = true;
+         goto check_dup_generic;
+
+       case OMP_CLAUSE_REDUCTION:
+         name = "reduction";
+         need_implicitly_determined = true;
+         t = OMP_CLAUSE_DECL (c);
+         if (AGGREGATE_TYPE_P (TREE_TYPE (t))
+             || POINTER_TYPE_P (TREE_TYPE (t)))
+           {
+             error_at (OMP_CLAUSE_LOCATION (c),
+                       "%qE has invalid type for %<reduction%>", t);
+             remove = true;
+           }
+         else if (FLOAT_TYPE_P (TREE_TYPE (t)))
+           {
+             enum tree_code r_code = OMP_CLAUSE_REDUCTION_CODE (c);
+             const char *r_name = NULL;
+
+             switch (r_code)
+               {
+               case PLUS_EXPR:
+               case MULT_EXPR:
+               case MINUS_EXPR:
+               case MIN_EXPR:
+               case MAX_EXPR:
+                 break;
+               case BIT_AND_EXPR:
+                 r_name = "&";
+                 break;
+               case BIT_XOR_EXPR:
+                 r_name = "^";
+                 break;
+               case BIT_IOR_EXPR:
+                 r_name = "|";
+                 break;
+               case TRUTH_ANDIF_EXPR:
+                 r_name = "&&";
+                 break;
+               case TRUTH_ORIF_EXPR:
+                 r_name = "||";
+                 break;
+               default:
+                 gcc_unreachable ();
+               }
+             if (r_name)
+               {
+                 error_at (OMP_CLAUSE_LOCATION (c),
+                           "%qE has invalid type for %<reduction(%s)%>",
+                           t, r_name);
+                 remove = true;
+               }
+           }
+         goto check_dup_generic;
+
+       case OMP_CLAUSE_COPYPRIVATE:
+         name = "copyprivate";
+         goto check_dup_generic;
+
+       case OMP_CLAUSE_COPYIN:
+         name = "copyin";
+         t = OMP_CLAUSE_DECL (c);
+         if (TREE_CODE (t) != VAR_DECL || !DECL_THREAD_LOCAL_P (t))
+           {
+             error_at (OMP_CLAUSE_LOCATION (c),
+                       "%qE must be %<threadprivate%> for %<copyin%>", t);
+             remove = true;
+           }
+         goto check_dup_generic;
+
+       check_dup_generic:
+         t = OMP_CLAUSE_DECL (c);
+         if (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL)
+           {
+             error_at (OMP_CLAUSE_LOCATION (c),
+                       "%qE is not a variable in clause %qs", t, name);
+             remove = true;
+           }
+         else if (bitmap_bit_p (&generic_head, DECL_UID (t))
+                  || bitmap_bit_p (&firstprivate_head, DECL_UID (t))
+                  || bitmap_bit_p (&lastprivate_head, DECL_UID (t)))
+           {
+             error_at (OMP_CLAUSE_LOCATION (c),
+                       "%qE appears more than once in data clauses", t);
+             remove = true;
+           }
+         else
+           bitmap_set_bit (&generic_head, DECL_UID (t));
+         break;
+
+       case OMP_CLAUSE_FIRSTPRIVATE:
+         name = "firstprivate";
+         t = OMP_CLAUSE_DECL (c);
+         need_complete = true;
+         need_implicitly_determined = true;
+         if (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL)
+           {
+             error_at (OMP_CLAUSE_LOCATION (c),
+                       "%qE is not a variable in clause %<firstprivate%>", t);
+             remove = true;
+           }
+         else if (bitmap_bit_p (&generic_head, DECL_UID (t))
+                  || bitmap_bit_p (&firstprivate_head, DECL_UID (t)))
+           {
+             error_at (OMP_CLAUSE_LOCATION (c),
+                       "%qE appears more than once in data clauses", t);
+             remove = true;
+           }
+         else
+           bitmap_set_bit (&firstprivate_head, DECL_UID (t));
+         break;
+
+       case OMP_CLAUSE_LASTPRIVATE:
+         name = "lastprivate";
+         t = OMP_CLAUSE_DECL (c);
+         need_complete = true;
+         need_implicitly_determined = true;
+         if (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL)
+           {
+             error_at (OMP_CLAUSE_LOCATION (c),
+                       "%qE is not a variable in clause %<lastprivate%>", t);
+             remove = true;
+           }
+         else if (bitmap_bit_p (&generic_head, DECL_UID (t))
+                  || bitmap_bit_p (&lastprivate_head, DECL_UID (t)))
+           {
+             error_at (OMP_CLAUSE_LOCATION (c),
+                    "%qE appears more than once in data clauses", t);
+             remove = true;
+           }
+         else
+           bitmap_set_bit (&lastprivate_head, DECL_UID (t));
+         break;
+
+       case OMP_CLAUSE_IF:
+       case OMP_CLAUSE_NUM_THREADS:
+       case OMP_CLAUSE_SCHEDULE:
+       case OMP_CLAUSE_NOWAIT:
+       case OMP_CLAUSE_ORDERED:
+       case OMP_CLAUSE_DEFAULT:
+       case OMP_CLAUSE_UNTIED:
+       case OMP_CLAUSE_COLLAPSE:
+       case OMP_CLAUSE_FINAL:
+       case OMP_CLAUSE_MERGEABLE:
+         pc = &OMP_CLAUSE_CHAIN (c);
+         continue;
+
+       default:
+         gcc_unreachable ();
+       }
+
+      if (!remove)
+       {
+         t = OMP_CLAUSE_DECL (c);
+
+         if (need_complete)
+           {
+             t = require_complete_type (t);
+             if (t == error_mark_node)
+               remove = true;
+           }
+
+         if (need_implicitly_determined)
+           {
+             const char *share_name = NULL;
+
+             if (TREE_CODE (t) == VAR_DECL && DECL_THREAD_LOCAL_P (t))
+               share_name = "threadprivate";
+             else switch (c_omp_predetermined_sharing (t))
+               {
+               case OMP_CLAUSE_DEFAULT_UNSPECIFIED:
+                 break;
+               case OMP_CLAUSE_DEFAULT_SHARED:
+                 /* const vars may be specified in firstprivate clause.  */
+                 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
+                     && TREE_READONLY (t))
+                   break;
+                 share_name = "shared";
+                 break;
+               case OMP_CLAUSE_DEFAULT_PRIVATE:
+                 share_name = "private";
+                 break;
+               default:
+                 gcc_unreachable ();
+               }
+             if (share_name)
+               {
+                 error_at (OMP_CLAUSE_LOCATION (c),
+                           "%qE is predetermined %qs for %qs",
+                           t, share_name, name);
+                 remove = true;
+               }
+           }
+       }
+
+      if (remove)
+       *pc = OMP_CLAUSE_CHAIN (c);
+      else
+       pc = &OMP_CLAUSE_CHAIN (c);
+    }
+
+  bitmap_obstack_release (NULL);
+  return clauses;
+}
+
+/* Create a transaction node.  */
+
+tree
+c_finish_transaction (location_t loc, tree block, int flags)
+{
+  tree stmt = build_stmt (loc, TRANSACTION_EXPR, block);
+  if (flags & TM_STMT_ATTR_OUTER)
+    TRANSACTION_EXPR_OUTER (stmt) = 1;
+  if (flags & TM_STMT_ATTR_RELAXED)
+    TRANSACTION_EXPR_RELAXED (stmt) = 1;
+  return add_stmt (stmt);
+}
+
+/* Make a variant type in the proper way for C/C++, propagating qualifiers
+   down to the element type of an array.  */
+
+tree
+c_build_qualified_type (tree type, int type_quals)
+{
+  if (type == error_mark_node)
+    return type;
+
+  if (TREE_CODE (type) == ARRAY_TYPE)
+    {
+      tree t;
+      tree element_type = c_build_qualified_type (TREE_TYPE (type),
+                                                 type_quals);
+
+      /* See if we already have an identically qualified type.  */
+      for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
+       {
+         if (TYPE_QUALS (strip_array_types (t)) == type_quals
+             && TYPE_NAME (t) == TYPE_NAME (type)
+             && TYPE_CONTEXT (t) == TYPE_CONTEXT (type)
+             && attribute_list_equal (TYPE_ATTRIBUTES (t),
+                                      TYPE_ATTRIBUTES (type)))
+           break;
+       }
+      if (!t)
+       {
+          tree domain = TYPE_DOMAIN (type);
+
+         t = build_variant_type_copy (type);
+         TREE_TYPE (t) = element_type;
+
+          if (TYPE_STRUCTURAL_EQUALITY_P (element_type)
+              || (domain && TYPE_STRUCTURAL_EQUALITY_P (domain)))
+            SET_TYPE_STRUCTURAL_EQUALITY (t);
+          else if (TYPE_CANONICAL (element_type) != element_type
+                   || (domain && TYPE_CANONICAL (domain) != domain))
+            {
+              tree unqualified_canon
+                = build_array_type (TYPE_CANONICAL (element_type),
+                                    domain? TYPE_CANONICAL (domain)
+                                          : NULL_TREE);
+              TYPE_CANONICAL (t)
+                = c_build_qualified_type (unqualified_canon, type_quals);
+            }
+          else
+            TYPE_CANONICAL (t) = t;
+       }
+      return t;
+    }
+
+  /* A restrict-qualified pointer type must be a pointer to object or
+     incomplete type.  Note that the use of POINTER_TYPE_P also allows
+     REFERENCE_TYPEs, which is appropriate for C++.  */
+  if ((type_quals & TYPE_QUAL_RESTRICT)
+      && (!POINTER_TYPE_P (type)
+         || !C_TYPE_OBJECT_OR_INCOMPLETE_P (TREE_TYPE (type))))
+    {
+      error ("invalid use of %<restrict%>");
+      type_quals &= ~TYPE_QUAL_RESTRICT;
+    }
+
+  return build_qualified_type (type, type_quals);
+}
+
+/* Build a VA_ARG_EXPR for the C parser.  */
+
+tree
+c_build_va_arg (location_t loc, tree expr, tree type)
+{
+  if (warn_cxx_compat && TREE_CODE (type) == ENUMERAL_TYPE)
+    warning_at (loc, OPT_Wc___compat,
+               "C++ requires promoted type, not enum type, in %<va_arg%>");
+  return build_va_arg (loc, expr, type);
+}
diff --git a/gcc/c/config-lang.in b/gcc/c/config-lang.in
new file mode 100644 (file)
index 0000000..46c7e47
--- /dev/null
@@ -0,0 +1,34 @@
+# Top level configure fragment for GNU C - C language.
+# Copyright (C) 1994, 1995, 1997, 1998, 2000, 2001, 2002, 2005, 2007,
+# 2010, 2012
+# 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/>.
+
+# Configure looks for the existence of this file to auto-config each language.
+# We define several parameters used by configure:
+#
+# language     - name of language as it would appear in $(LANGUAGES)
+# compilers    - value to add to $(COMPILERS)
+
+language="c"
+
+compilers="cc1\$(exeext)"
+
+target_libs=
+
+gtfiles="\$(srcdir)/c/c-lang.c \$(srcdir)/c/c-tree.h \$(srcdir)/c/c-decl.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-objc.h \$(srcdir)/c-family/c-cppbuiltin.c \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c \$(srcdir)/c/c-objc-common.c \$(srcdir)/c/c-parser.c \$(srcdir)/c/c-lang.h"
diff --git a/gcc/c/gccspec.c b/gcc/c/gccspec.c
new file mode 100644 (file)
index 0000000..e161359
--- /dev/null
@@ -0,0 +1,108 @@
+/* Specific flags and argument handling of the C front-end.
+   Copyright (C) 1999, 2001, 2003, 2007, 2010 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/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "gcc.h"
+#include "opts.h"
+
+/* Filter command line before processing by the gcc driver proper.  */
+void
+lang_specific_driver (struct cl_decoded_option **in_decoded_options ATTRIBUTE_UNUSED,
+                     unsigned int *in_decoded_options_count ATTRIBUTE_UNUSED,
+                     int *in_added_libraries ATTRIBUTE_UNUSED)
+{
+  /* Systems which use the NeXT runtime by default should arrange
+     for the shared libgcc to be used when -fgnu-runtime is passed
+     through specs.  */
+#if defined(ENABLE_SHARED_LIBGCC) && ! NEXT_OBJC_RUNTIME
+  unsigned int i;
+
+  /* The new argument list will be contained in this.  */
+  struct cl_decoded_option *new_decoded_options;
+
+  /* True if we should add -shared-libgcc to the command-line.  */
+  int shared_libgcc = 0;
+
+  /* The total number of arguments with the new stuff.  */
+  unsigned int argc;
+
+  /* The argument list.  */
+  struct cl_decoded_option *decoded_options;
+
+  argc = *in_decoded_options_count;
+  decoded_options = *in_decoded_options;
+
+  for (i = 1; i < argc; i++)
+    {
+      switch (decoded_options[i].opt_index)
+       {
+       case OPT_static_libgcc:
+       case OPT_static:
+         return;
+
+       case OPT_SPECIAL_input_file:
+         {
+           const char *file = decoded_options[i].arg;
+           int len;
+
+           /* If the filename ends in .m or .mi, we are compiling
+              ObjC and want to pass -shared-libgcc.  */
+           len = strlen (file);
+           if ((len > 2 && file[len - 2] == '.' && file[len - 1] == 'm')
+               ||  (len > 3 && file[len - 3] == '.' && file[len - 2] == 'm'
+                    && file[len - 1] == 'i'))
+             shared_libgcc = 1;
+         }
+         break;
+       }
+    }
+
+  if  (shared_libgcc)
+    {
+      new_decoded_options = XNEWVEC (struct cl_decoded_option, argc + 1);
+
+      i = 0;
+      do
+       {
+         new_decoded_options[i] = decoded_options[i];
+         i++;
+       }
+      while (i < argc);
+
+      generate_option (OPT_shared_libgcc, NULL, 1, CL_DRIVER,
+                      &new_decoded_options[i++]);
+
+      *in_decoded_options_count = i;
+      *in_decoded_options = new_decoded_options;
+    }
+#endif
+}
+
+/* Called before linking.  Returns 0 on success and -1 on failure.  */
+int
+lang_specific_pre_link (void)
+{
+  return 0;  /* Not used for C.  */
+}
+
+/* Number of extra output files that lang_specific_pre_link may generate.  */
+int lang_specific_extra_outfiles = 0;  /* Not used for C.  */
index 09172b261abc21f6211836352f5faf02e43b265e..733932336a9fb6cff6b0647e82b7aee937884f91 100644 (file)
@@ -27,7 +27,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree.h"
 #include "c-family/c-pragma.h"
 #include "c-family/c-common.h"
-#include "c-tree.h"
+#include "c/c-tree.h"
 #include "toplev.h"
 #include "ggc.h"
 #include "tm_p.h"
index 1fdf0af80ca4c7d411f25a8a91811211616e2e4b..0bdbece6ae865b4c79faddbd7418b9000c7b6214 100755 (executable)
@@ -26964,11 +26964,6 @@ $as_echo "#define ENABLE_LTO 1" >>confdefs.h
        esac
 done
 
-# Pick up gtfiles for c
-gtfiles=
-. ${srcdir}/c-config-lang.in
-all_gtfiles="$all_gtfiles [c] $gtfiles"
-
 check_languages=
 for language in $all_selected_languages
 do
index 22dab55a24a38fb932f3491c8c56cb9dbd3bd02c..7891fcc39dabca2a41c768cd2639d2586f7423cd 100644 (file)
@@ -4838,11 +4838,6 @@ changequote([,])dnl
        esac
 done
 
-# Pick up gtfiles for c
-gtfiles=
-. ${srcdir}/c-config-lang.in
-all_gtfiles="$all_gtfiles [[c]] $gtfiles"
-
 check_languages=
 for language in $all_selected_languages
 do
index 00e9ca07cf81536d5a1ac39c1f6c97657f6f8b67..9b5b7c163d60a50501ee5eb13dfb798006fd7fdc 100644 (file)
@@ -1,3 +1,7 @@
+2012-06-29  Steven Bosscher  <steven@gcc.gnu.org>
+
+       * Make-lang.in: Remove tree-mudflap.o from CXX_AND_OBJCXX_OBJS.
+
 2012-06-27  Jason Merrill  <jason@redhat.com>
 
        * parser.c (cp_parser_check_for_invalid_template_id): tag_type parm.
index af355f05079a5b5e15abfe7c047baf3613c935db..f09ff36a743a3044b37d675d62fd27338846303c 100644 (file)
@@ -82,7 +82,7 @@ CXX_AND_OBJCXX_OBJS = cp/call.o cp/decl.o cp/expr.o cp/pt.o cp/typeck2.o \
  cp/typeck.o cp/cvt.o cp/except.o cp/friend.o cp/init.o cp/method.o \
  cp/search.o cp/semantics.o cp/tree.o cp/repo.o cp/dump.o cp/optimize.o \
  cp/mangle.o cp/cp-objcp-common.o cp/name-lookup.o cp/cxx-pretty-print.o \
- cp/cp-gimplify.o tree-mudflap.o $(CXX_C_OBJS)
+ cp/cp-gimplify.o $(CXX_C_OBJS)
 
 # Language-specific object files for C++.
 CXX_OBJS = cp/cp-lang.o c-family/stub-objc.o $(CXX_AND_OBJCXX_OBJS)
@@ -237,6 +237,7 @@ c++.mostlyclean:
 c++.clean:
 c++.distclean:
        -rm -f cp/config.status cp/Makefile
+       -rm -f cxxmain.c
 c++.maintainer-clean:
 #\f
 # Stage hooks:
diff --git a/gcc/cppspec.c b/gcc/cppspec.c
deleted file mode 100644 (file)
index c9ff70e..0000000
+++ /dev/null
@@ -1,198 +0,0 @@
-/* Specific flags and argument handling of the C preprocessor.
-   Copyright (C) 1999, 2007, 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/>.  */
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "tm.h"
-#include "gcc.h"
-#include "opts.h"
-
-/* The `cpp' executable installed in $(bindir) and $(cpp_install_dir)
-   is a customized version of the gcc driver.  It forces -E; -S and -c
-   are errors.  It defaults to -x c for files with unrecognized
-   extensions, unless -x options appear in argv, in which case we
-   assume the user knows what they're doing.  If no explicit input is
-   mentioned, it will read stdin.  */
-
-/* Suffixes for known sorts of input files.  Note that we do not list
-   files which are normally considered to have been preprocessed already,
-   since the user's expectation is that `cpp' always preprocesses.  */
-static const char *const known_suffixes[] =
-{
-  ".c",  ".C",   ".S",   ".m",
-  ".cc", ".cxx", ".cpp", ".cp",  ".c++",
-  ".sx",
-  NULL
-};
-
-/* Filter the command line before processing by the gcc driver proper.  */
-void
-lang_specific_driver (struct cl_decoded_option **in_decoded_options,
-                     unsigned int *in_decoded_options_count,
-                     int *in_added_libraries ATTRIBUTE_UNUSED)
-{
-  struct cl_decoded_option *decoded_options = *in_decoded_options;
-  unsigned int argc = *in_decoded_options_count;
-
-  /* Do we need to read stdin? */
-  int read_stdin = 1;
-
-  /* Do we need to insert -E? */
-  int need_E = 1;
-
-  /* Have we seen an input file? */
-  int seen_input = 0;
-
-  /* Positions to insert -xc, -xassembler-with-cpp, and -o, if necessary.
-     0 means unnecessary.  */
-  unsigned int lang_c_here = 0;
-  unsigned int lang_S_here = 0;
-  unsigned int o_here = 0;
-
-  /* Do we need to fix up an input file with an unrecognized suffix? */
-  int need_fixups = 1;
-
-  unsigned int i, j;
-  struct cl_decoded_option *new_decoded_options;
-  unsigned int new_argc;
-  extern int is_cpp_driver;
-
-  is_cpp_driver = 1;
-
-  /* First pass.  If we see an -S or -c, barf.  If we see an input file,
-     turn off read_stdin.  If we see a second input file, it is actually
-     the output file.  If we see a third input file, barf.  */
-  for (i = 1; i < argc; i++)
-    {
-      switch (decoded_options[i].opt_index)
-       {
-       case OPT_E:
-         need_E = 0;
-         break;
-
-       case OPT_S:
-       case OPT_c:
-         fatal_error ("%qs is not a valid option to the preprocessor",
-                      decoded_options[i].orig_option_with_args_text);
-         return;
-
-       case OPT_x:
-         need_fixups = 0;
-         break;
-
-       case OPT_SPECIAL_input_file:
-         {
-           const char *file = decoded_options[i].arg;
-
-           if (strcmp (file, "-") == 0)
-             read_stdin = 0;
-           else
-             {
-               seen_input++;
-               if (seen_input == 3)
-                 {
-                   fatal_error ("too many input files");
-                   return;
-                 }
-               else if (seen_input == 2)
-                 {
-                   o_here = i;
-                 }
-               else
-                 {
-                   read_stdin = 0;
-                   if (need_fixups)
-                     {
-                       int l = strlen (file);
-                       int known = 0;
-                       const char *const *suff;
-
-                       for (suff = known_suffixes; *suff; suff++)
-                         if (!strcmp (*suff, &file[l - strlen(*suff)]))
-                           {
-                             known = 1;
-                             break;
-                           }
-
-                       if (! known)
-                         {
-                           /* .s files are a special case; we have to
-                              treat them like .S files so
-                              -D__ASSEMBLER__ will be in effect.  */
-                           if (!strcmp (".s", &file[l - 2]))
-                             lang_S_here = i;
-                           else
-                             lang_c_here = i;
-                         }
-                     }
-                 }
-             }
-         }
-         break;
-       }
-    }
-
-  /* If we don't need to edit the command line, we can bail early.  */
-
-  new_argc = argc + need_E + read_stdin + !!lang_c_here + !!lang_S_here;
-
-  if (new_argc == argc && !o_here)
-    return;
-
-  new_decoded_options = XNEWVEC (struct cl_decoded_option, new_argc);
-
-  new_decoded_options[0] = decoded_options[0];
-  j = 1;
-
-  if (need_E)
-    generate_option (OPT_E, NULL, 1, CL_DRIVER, &new_decoded_options[j++]);
-
-  for (i = 1; i < argc; i++, j++)
-    {
-      if (i == lang_c_here)
-       generate_option (OPT_x, "c", 1, CL_DRIVER, &new_decoded_options[j++]);
-      else if (i == lang_S_here)
-       generate_option (OPT_x, "assembler-with-cpp", 1, CL_DRIVER,
-                        &new_decoded_options[j++]);
-      else if (i == o_here)
-       {
-         generate_option (OPT_o, decoded_options[i].arg, 1, CL_DRIVER,
-                          &new_decoded_options[j]);
-         continue;
-       }
-
-      new_decoded_options[j] = decoded_options[i];
-    }
-
-  if (read_stdin)
-    generate_option_input_file ("-", &new_decoded_options[j++]);
-
-  *in_decoded_options_count = new_argc;
-  *in_decoded_options = new_decoded_options;
-}
-
-/* Called before linking.  Returns 0 on success and -1 on failure.  */
-int lang_specific_pre_link (void)
-{
-  return 0;  /* Not used for cpp.  */
-}
-
-/* Number of extra output files that lang_specific_pre_link may generate.  */
-int lang_specific_extra_outfiles = 0;  /* Not used for cpp.  */
index 03bcbf813cd1485efd54d31052ca012a5e759bdc..cff3ffdfc5dc2dc8378df785453a786cf6ea5d92 100644 (file)
@@ -491,7 +491,7 @@ For files shared by all front ends, add the filename to the
 @item
 For files that are part of one front end, add the filename to the
 @code{gtfiles} variable defined in the appropriate
-@file{config-lang.in}.  For C, the file is @file{c-config-lang.in}.
+@file{config-lang.in}.
 Headers should appear before non-headers in this list.
 
 @item
index dc5cc47c33acb8fdf68668257ae38356db1af770..84fcc23e55a6eb480f28cd5e4672d661d2a6d336 100644 (file)
@@ -168,10 +168,11 @@ The @file{gcc} directory contains the following subdirectories:
 @item @var{language}
 Subdirectories for various languages.  Directories containing a file
 @file{config-lang.in} are language subdirectories.  The contents of
-the subdirectories @file{cp} (for C++), @file{lto} (for LTO),
-@file{objc} (for Objective-C) and @file{objcp} (for Objective-C++) are
-documented in this manual (@pxref{Passes, , Passes and Files of the
-Compiler}); those for other languages are not.  @xref{Front End, ,
+the subdirectories @file{c} (for C), @file{cp} (for C++),
+@file{objc} (for Objective-C), @file{objcp} (for Objective-C++),
+and @file{lto} (for LTO) are documented in this
+manual (@pxref{Passes, , Passes and Files of the Compiler});
+those for other languages are not.  @xref{Front End, ,
 Anatomy of a Language Front End}, for details of the files in these
 directories.
 
@@ -483,7 +484,7 @@ why isn't this part of this manual or of the GCC Coding Conventions?
 @end table
 
 FIXME: document such files in subdirectories, at least @file{config},
-@file{cp}, @file{objc}, @file{testsuite}.
+@file{c}, @file{cp}, @file{objc}, @file{testsuite}.
 
 @node Front End
 @subsection Anatomy of a Language Front End
@@ -615,10 +616,9 @@ codes.
 @node Front End Config
 @subsubsection The Front End @file{config-lang.in} File
 
-Each language subdirectory contains a @file{config-lang.in} file.  In
-addition the main directory contains @file{c-config-lang.in}, which
-contains limited information for the C language.  This file is a shell
-script that may define some variables describing the language:
+Each language subdirectory contains a @file{config-lang.in} file.
+This file is a shell script that may define some variables describing
+the language:
 
 @table @code
 @item language
diff --git a/gcc/gccspec.c b/gcc/gccspec.c
deleted file mode 100644 (file)
index e161359..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-/* Specific flags and argument handling of the C front-end.
-   Copyright (C) 1999, 2001, 2003, 2007, 2010 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/>.  */
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "tm.h"
-#include "gcc.h"
-#include "opts.h"
-
-/* Filter command line before processing by the gcc driver proper.  */
-void
-lang_specific_driver (struct cl_decoded_option **in_decoded_options ATTRIBUTE_UNUSED,
-                     unsigned int *in_decoded_options_count ATTRIBUTE_UNUSED,
-                     int *in_added_libraries ATTRIBUTE_UNUSED)
-{
-  /* Systems which use the NeXT runtime by default should arrange
-     for the shared libgcc to be used when -fgnu-runtime is passed
-     through specs.  */
-#if defined(ENABLE_SHARED_LIBGCC) && ! NEXT_OBJC_RUNTIME
-  unsigned int i;
-
-  /* The new argument list will be contained in this.  */
-  struct cl_decoded_option *new_decoded_options;
-
-  /* True if we should add -shared-libgcc to the command-line.  */
-  int shared_libgcc = 0;
-
-  /* The total number of arguments with the new stuff.  */
-  unsigned int argc;
-
-  /* The argument list.  */
-  struct cl_decoded_option *decoded_options;
-
-  argc = *in_decoded_options_count;
-  decoded_options = *in_decoded_options;
-
-  for (i = 1; i < argc; i++)
-    {
-      switch (decoded_options[i].opt_index)
-       {
-       case OPT_static_libgcc:
-       case OPT_static:
-         return;
-
-       case OPT_SPECIAL_input_file:
-         {
-           const char *file = decoded_options[i].arg;
-           int len;
-
-           /* If the filename ends in .m or .mi, we are compiling
-              ObjC and want to pass -shared-libgcc.  */
-           len = strlen (file);
-           if ((len > 2 && file[len - 2] == '.' && file[len - 1] == 'm')
-               ||  (len > 3 && file[len - 3] == '.' && file[len - 2] == 'm'
-                    && file[len - 1] == 'i'))
-             shared_libgcc = 1;
-         }
-         break;
-       }
-    }
-
-  if  (shared_libgcc)
-    {
-      new_decoded_options = XNEWVEC (struct cl_decoded_option, argc + 1);
-
-      i = 0;
-      do
-       {
-         new_decoded_options[i] = decoded_options[i];
-         i++;
-       }
-      while (i < argc);
-
-      generate_option (OPT_shared_libgcc, NULL, 1, CL_DRIVER,
-                      &new_decoded_options[i++]);
-
-      *in_decoded_options_count = i;
-      *in_decoded_options = new_decoded_options;
-    }
-#endif
-}
-
-/* Called before linking.  Returns 0 on success and -1 on failure.  */
-int
-lang_specific_pre_link (void)
-{
-  return 0;  /* Not used for C.  */
-}
-
-/* Number of extra output files that lang_specific_pre_link may generate.  */
-int lang_specific_extra_outfiles = 0;  /* Not used for C.  */
index cd1a32c27e717b1b476d949495eea1f79f72f7ad..96c75b3ebb255661a023ca1d975cbd05a238e69b 100644 (file)
@@ -1786,12 +1786,12 @@ struct file_rule_st files_rules[] = {
     REG_EXTENDED, NULL_REGEX,
     "gt-c-family-$3.h", "c-family/$3.h", NULL_FRULACT},
 
-  /* Both c-lang.h & c-tree.h gives gt-c-decl.h for c-decl.c !  */
-  { DIR_PREFIX_REGEX "c-lang\\.h$",
-    REG_EXTENDED, NULL_REGEX, "gt-c-decl.h", "c-decl.c", NULL_FRULACT},
+  /* Both c-lang.h & c-tree.h gives gt-c-c-decl.h for c-decl.c !  */
+  { DIR_PREFIX_REGEX "c/c-lang\\.h$",
+    REG_EXTENDED, NULL_REGEX, "gt-c-c-decl.h", "c/c-decl.c", NULL_FRULACT},
 
-  { DIR_PREFIX_REGEX "c-tree\\.h$",
-    REG_EXTENDED, NULL_REGEX, "gt-c-decl.h", "c-decl.c", NULL_FRULACT},
+  { DIR_PREFIX_REGEX "c/c-tree\\.h$",
+    REG_EXTENDED, NULL_REGEX, "gt-c-c-decl.h", "c/c-decl.c", NULL_FRULACT},
 
   /* cp/cp-tree.h gives gt-cp-tree.h for cp/tree.c !  */
   { DIR_PREFIX_REGEX "cp/cp-tree\\.h$",
index 5ca44c36dfdaf5306159773cc8b66bfef73a1b21..e8ef7bb347d8646112b2e3b63c4d90535e24777d 100644 (file)
@@ -1,3 +1,16 @@
+2012-06-29  Steven Bosscher  <steven@gcc.gnu.org>
+
+       * Make-ang.in: Adjust for move of C front-end files.
+       * config-lang.in: Likewise.
+       * objc-encoding.c: Look for cp-tree.h in cp/, and for c-tree.h
+       and c-lang.h in c/.
+       * objc-runtime-shared-support.c: Likewise.
+       * objc-next-runtime-abi-01.c: Likewise.
+       * objc-next-runtime-abi-02.c: Likewise.
+       * objc-gnu-runtime-abi-01.c: Likewise.
+       * objc-act.c: Likewise.
+       * objc-lang.c: Likewise.
+
 2012-06-19  Steven Bosscher  <steven@gcc.gnu.org>
 
        * objc-next-runtime-abi-01.c: Do not include tm.h and output.h.
index 94a462b00aada85e3094e090c9d900136b651592..05ddec639ff21fcd1a36d235e9c978879525e1fa 100644 (file)
@@ -44,7 +44,7 @@ objc: cc1obj$(exeext)
 .PHONY: objc
 
 START_HDRS = $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(C_TREE_H) \
-  c-lang.h langhooks.h c-family/c-objc.h objc/objc-act.h
+  c/c-lang.h langhooks.h c-family/c-objc.h objc/objc-act.h
 
 # Use maximal warnings for this front end.
 objc-warn = $(STRICT_WARN)
@@ -83,7 +83,7 @@ objc/objc-lang.o : objc/objc-lang.c \
    $(START_HDRS) \
    $(GGC_H) \
    $(LANGHOOKS_DEF_H) $(C_COMMON_H) gtype-objc.h \
-   c-objc-common.h
+   c/c-objc-common.h
 
 objc/objc-runtime-shared-support.o : objc/objc-runtime-shared-support.c \
    gt-objc-objc-runtime-shared-support.h \
index 48f8582d74c143b03e423d019333c1cc53b3335c..9a4ede653182e1ea74da2033088db0707904bdab 100644 (file)
@@ -36,4 +36,4 @@ lang_requires="c"
 # Order is important.  If you change this list, make sure you test
 # building without C++ as well; that is, remove the gcc/cp directory,
 # and build with --enable-languages=c,objc.
-gtfiles="\$(srcdir)/objc/objc-map.h \$(srcdir)/c-family/c-objc.h \$(srcdir)/objc/objc-act.h \$(srcdir)/objc/objc-act.c \$(srcdir)/objc/objc-runtime-shared-support.c \$(srcdir)/objc/objc-gnu-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-02.c \$(srcdir)/c-parser.c \$(srcdir)/c-tree.h \$(srcdir)/c-decl.c \$(srcdir)/c-lang.h \$(srcdir)/c-objc-common.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-cppbuiltin.c \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c"
+gtfiles="\$(srcdir)/objc/objc-map.h \$(srcdir)/c-family/c-objc.h \$(srcdir)/objc/objc-act.h \$(srcdir)/objc/objc-act.c \$(srcdir)/objc/objc-runtime-shared-support.c \$(srcdir)/objc/objc-gnu-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-02.c \$(srcdir)/c/c-parser.c \$(srcdir)/c/c-tree.h \$(srcdir)/c/c-decl.c \$(srcdir)/c/c-lang.h \$(srcdir)/c/c-objc-common.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-cppbuiltin.c \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c"
index 14e1d5f0599bb6d32ccf4b160f379f83ad13128a..5c924bf736cfa5435e55d9674060eae332c951ce 100644 (file)
@@ -27,10 +27,10 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree.h"
 
 #ifdef OBJCPLUS
-#include "cp-tree.h"
+#include "cp/cp-tree.h"
 #else
-#include "c-tree.h"
-#include "c-lang.h"
+#include "c/c-tree.h"
+#include "c/c-lang.h"
 #endif
 
 #include "c-family/c-common.h"
index 10171fdd2c59214c7e78e5eb1b284714fcbda417..8d4a9c758b76ad24940158f312ad8c04b40c5d60 100644 (file)
@@ -25,10 +25,10 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree.h"
 
 #ifdef OBJCPLUS
-#include "cp-tree.h"
+#include "cp/cp-tree.h"
 #else
-#include "c-tree.h"
-#include "c-lang.h"
+#include "c/c-tree.h"
+#include "c/c-lang.h"
 #endif
 
 #include "c-family/c-common.h"
index 63a8c5b2e31b421f6c2e9f91475ffdc06f8b58f4..6bdffac10e764ec1894a0073d3fdd9be3c9373f0 100644 (file)
@@ -24,10 +24,10 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree.h"
 
 #ifdef OBJCPLUS
-#include "cp-tree.h"
+#include "cp/cp-tree.h"
 #else
-#include "c-tree.h"
-#include "c-lang.h"
+#include "c/c-tree.h"
+#include "c/c-lang.h"
 #endif
 
 #include "langhooks.h"
index b1bbb9e1fc0a8cc2293a22c8885375d9c79f5653..9aa9bb3731cf067a91943132d168aab7df5c652b 100644 (file)
@@ -25,15 +25,15 @@ along with GCC; see the file COPYING3.  If not see
 #include "coretypes.h"
 #include "tm.h"
 #include "tree.h"
-#include "c-tree.h"
+#include "c/c-tree.h"
 #include "c-family/c-common.h"
 #include "c-family/c-objc.h"
 #include "ggc.h"
 #include "objc-act.h"
 #include "langhooks.h"
 #include "langhooks-def.h"
-#include "c-objc-common.h"
-#include "c-lang.h"
+#include "c/c-objc-common.h"
+#include "c/c-lang.h"
 
 enum c_language_kind c_language = clk_objc;
 
index b60bd468000ca2c0734157d4097c6f350601050e..cf245911b9018fb4e4dd75cea4341cefc345b9e5 100644 (file)
@@ -29,10 +29,10 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree.h"
 
 #ifdef OBJCPLUS
-#include "cp-tree.h"
+#include "cp/cp-tree.h"
 #else
-#include "c-tree.h"
-#include "c-lang.h"
+#include "c/c-tree.h"
+#include "c/c-lang.h"
 #endif
 #include "langhooks.h"
 #include "c-family/c-objc.h"
index ee6a0a3fbf739f6958b0a86e45de05a1a4b31d0c..4f47a5790876ae65e436a62a80a0fbe964d7aa3e 100644 (file)
@@ -32,10 +32,10 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree.h"
 
 #ifdef OBJCPLUS
-#include "cp-tree.h"
+#include "cp/cp-tree.h"
 #else
-#include "c-tree.h"
-#include "c-lang.h"
+#include "c/c-tree.h"
+#include "c/c-lang.h"
 #endif
 #include "langhooks.h"
 #include "c-family/c-objc.h"
index 7d478d97beafc84778b8951ac47548198acd7e4c..0b6f93716b82362d92a62dea88f38c09e6ea7b1c 100644 (file)
@@ -25,10 +25,10 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree.h"
 
 #ifdef OBJCPLUS
-#include "cp-tree.h"
+#include "cp/cp-tree.h"
 #else
-#include "c-tree.h"
-#include "c-lang.h"
+#include "c/c-tree.h"
+#include "c/c-lang.h"
 #endif
 #include "langhooks.h"
 #include "c-family/c-objc.h"