diff options
Diffstat (limited to 'gcc-4.8.1/gcc/c')
-rw-r--r-- | gcc-4.8.1/gcc/c/ChangeLog | 203 | ||||
-rw-r--r-- | gcc-4.8.1/gcc/c/Make-lang.in | 194 | ||||
-rw-r--r-- | gcc-4.8.1/gcc/c/c-aux-info.c | 566 | ||||
-rw-r--r-- | gcc-4.8.1/gcc/c/c-convert.c | 183 | ||||
-rw-r--r-- | gcc-4.8.1/gcc/c/c-decl.c | 10157 | ||||
-rw-r--r-- | gcc-4.8.1/gcc/c/c-errors.c | 64 | ||||
-rw-r--r-- | gcc-4.8.1/gcc/c/c-lang.c | 50 | ||||
-rw-r--r-- | gcc-4.8.1/gcc/c/c-lang.h | 59 | ||||
-rw-r--r-- | gcc-4.8.1/gcc/c/c-objc-common.c | 213 | ||||
-rw-r--r-- | gcc-4.8.1/gcc/c/c-objc-common.h | 108 | ||||
-rw-r--r-- | gcc-4.8.1/gcc/c/c-parser.c | 10884 | ||||
-rw-r--r-- | gcc-4.8.1/gcc/c/c-tree.h | 671 | ||||
-rw-r--r-- | gcc-4.8.1/gcc/c/c-typeck.c | 10899 | ||||
-rw-r--r-- | gcc-4.8.1/gcc/c/config-lang.in | 32 | ||||
-rw-r--r-- | gcc-4.8.1/gcc/c/gccspec.c | 108 |
15 files changed, 0 insertions, 34391 deletions
diff --git a/gcc-4.8.1/gcc/c/ChangeLog b/gcc-4.8.1/gcc/c/ChangeLog deleted file mode 100644 index 32410a3c3..000000000 --- a/gcc-4.8.1/gcc/c/ChangeLog +++ /dev/null @@ -1,203 +0,0 @@ -2013-05-31 Release Manager - - * GCC 4.8.1 released. - -2013-03-22 Release Manager - - * GCC 4.8.0 released. - -2013-02-12 Marek Polacek <polacek@redhat.com> - - PR c/44938 - * c-parser.c (c_parser_postfix_expression_after_primary): Initialize - origtypes to NULL. - -2013-01-24 Jakub Jelinek <jakub@redhat.com> - - PR c/56078 - * c-typeck.c (set_nonincremental_init_from_string): If - constructor_max_index is NULL, treat it as if tree_int_cst_lt - returned false. - (process_init_element): Likewise. - -2012-12-20 Jakub Jelinek <jakub@redhat.com> - - PR c++/55619 - * c-parser.c (c_parser_asm_operands): Remove CONVERT_P - argument, don't call default_function_array_conversion - nor c_fully_fold here. - (c_parser_asm_statement): Adjust callers. - * c-typeck.c (build_asm_expr): Call c_fully_fold on inputs - and outputs here, and call default_function_array_conversion - on inputs that don't need to be addressable. - -2012-12-18 Jakub Jelinek <jakub@redhat.com> - - PR c/39464 - * c-typeck.c (convert_for_assignment): For -Wpointer-sign - warning require that both c_common_unsigned_type as well as - c_common_signed_type is the same for both mvl and mvr types. - -2012-11-16 Diego Novillo <dnovillo@google.com> - - Adjust for new vec API (http://gcc.gnu.org/wiki/cxx-conversion/cxx-vec) - - * c-common.c: Use new vec API in vec.h. - * c-common.h: Likewise. - * c-gimplify.c: Likewise. - * c-pragma.c: Likewise. - * c-pretty-print.c: Likewise. - * c-pretty-print.h: Likewise. - * c-semantics.c: Likewise. - * c-decl.c: Likewise. - * c-parser.c: Likewise. - * c-tree.h: Likewise. - * c-typeck.c: Likewise. - -2012-10-29 Jonathan Wakely <jwakely.gcc@gmail.com> - - PR c++/54930 - * c-typeck.c (c_finish_return): Use OPT_Wreturn_local_addr. - -2012-10-29 Manuel López-Ibáñez <manu@gcc.gnu.org> - - PR c/53066 - * c-decl.c (warn_if_shadowing): Do not warn if a variable - shadows a function, unless the variable is a function or a - pointer-to-function. - -2012-10-12 Jakub Jelinek <jakub@redhat.com> - - PR c/54381 - * c-parser.c (struct c_tree_loc_pair): Removed. - (c_parser_expr_list): Remove struct c_tree_loc_pair * argument, - add location_t * and tree * arguments, fill in array of 3 - sizeof_arg trees and corresponding locs. - (c_parser_attributes, c_parser_objc_keywordexpr): Adjust - c_parser_expr_list callers. - (c_parser_postfix_expression_after_primary): Likewise. Pass - array of 3 sizeof_arg trees and locs (corresponding to first - 3 arguments) to sizeof_pointer_memaccess_warning. - -2012-10-09 Lawrence Crowl <crowl@google.com> - - * Make-lang.in (c-decl.o): Add dependence on hash-table.h. - * c-decl.c (detect_field_duplicates_hash): Change to new type-safe - hash table. - -2012-10-09 Paolo Carlini <paolo.carlini@oracle.com> - - PR c++/54194 - * c-typeck.c (parser_build_binary_op): Update warn_about_parentheses - call. - -2012-10-09 Marc Glisse <marc.glisse@inria.fr> - - PR c++/54427 - * c-typeck.c: Include c-common.h. - (enum stv_conv): Moved to c-common.h. - (scalar_to_vector): Moved to c-common.c. - (build_binary_op): Adapt to scalar_to_vector's new prototype. - * Make-lang.in: c-typeck.c depends on c-common.h. - -2012-10-04 Arnaud Charlet <charlet@adacore.com> - - * c-decl.c (c_write_global_declarations): Fix handling of - -fdump-ada-spec*. - -2012-09-30 Sharad Singhai <singhai@google.com> - - * c-decl.c (c_write_global_declarations): Use a different method - to determine if the dump has ben initialized. - -2012-09-14 Joseph Myers <joseph@codesourcery.com> - - PR c/54552 - * c-typeck.c (c_cast_expr): When casting to a type requiring - C_MAYBE_CONST_EXPR to be created, pass the inner expression to - c_fully_fold first. - -2012-09-14 Joseph Myers <joseph@codesourcery.com> - - PR c/54103 - * c-typeck.c (build_unary_op): Pass original argument of - TRUTH_NOT_EXPR to c_objc_common_truthvalue_conversion, then remove - any C_MAYBE_CONST_EXPR, if it has integer operands. - (build_binary_op): Pass original arguments of TRUTH_ANDIF_EXPR, - TRUTH_ORIF_EXPR, TRUTH_AND_EXPR, TRUTH_OR_EXPR and TRUTH_XOR_EXPR - to c_objc_common_truthvalue_conversion, then remove any - C_MAYBE_CONST_EXPR, if they have integer operands. Use - c_objc_common_truthvalue_conversion not - c_common_truthvalue_conversion. - (c_objc_common_truthvalue_conversion): Build NE_EXPR directly and - call note_integer_operands for arguments with integer operands - that are not integer constants. - -2012-09-13 Jakub Jelinek <jakub@redhat.com> - - PR c/54559 - * c-typeck.c (c_finish_return): Do convert to BOOLEAN_TYPE or - COMPLEX_TYPE with in_late_binary_op set temporarily to true. - -2012-08-31 Jakub Jelinek <jakub@redhat.com> - - PR c/54428 - * c-convert.c (convert): Don't call fold_convert_loc if - TYPE_MAIN_VARIANT of a COMPLEX_TYPE is the same, unless e - is a COMPLEX_EXPR. Remove TYPE_MAIN_VARIANT check from - COMPLEX_TYPE -> COMPLEX_TYPE conversion. - -2012-08-24 Jakub Jelinek <jakub@redhat.com> - - PR c/54355 - * c-decl.c (c_parser_label): Pass true as nested and fix up comments - for nested and empty_ok arguments in the call to - c_parser_declaration_or_fndef. - -2012-08-17 Jakub Jelinek <jakub@redhat.com> - - * c-tree.h (c_last_sizeof_arg): Declare. - * c-parser.c (struct c_tree_loc_pair): New type. - (c_parser_expr_list): Add sizeof_arg argument. Fill it in if - non-NULL. - (c_parser_attributes, c_parser_objc_keywordexpr): Adjust callers. - (c_parser_postfix_expression_after_primary): Likewise. Call - sizeof_pointer_memaccess_warning if needed. - (sizeof_ptr_memacc_comptypes): New function. - * c-typeck.c (c_last_sizeof_arg): New global variable. - (c_expr_sizeof_expr, c_expr_sizeof_type): Initialize it. - -2012-07-24 Uros Bizjak <ubizjak@gmail.com> - - * c-lang.h (lang_decl): Add variable_size GTY option. - -2012-07-16 Steven Bosscher <steven@gcc.gnu.org> - - * c-decl.c: Include dumpfile.h instead of tree-dump.h. - * Make-lang.in: Fix dependencies. - -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. - -Copyright (C) 2012-2013 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-4.8.1/gcc/c/Make-lang.in b/gcc-4.8.1/gcc/c/Make-lang.in deleted file mode 100644 index 8310e0ab7..000000000 --- a/gcc-4.8.1/gcc/c/Make-lang.in +++ /dev/null @@ -1,194 +0,0 @@ -# Top level -*- makefile -*- fragment for GNU C - C language. -# Copyright (C) 1994-2013 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. - -# -# 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) -# -# 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 - -# -# Install hooks: -# cc1 is installed elsewhere as part of $(COMPILERS). - -c.install-common: -c.install-man: -c.install-plugin: -c.uninstall: - -# -# 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: -# -# 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 - -# -# .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) \ - $(HASH_TABLE_H) $(LANGHOOKS_DEF_H) \ - dumpfile.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 c-family/c-common.h - diff --git a/gcc-4.8.1/gcc/c/c-aux-info.c b/gcc-4.8.1/gcc/c/c-aux-info.c deleted file mode 100644 index dd9c7685b..000000000 --- a/gcc-4.8.1/gcc/c/c-aux-info.c +++ /dev/null @@ -1,566 +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-2013 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); - -/* 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-4.8.1/gcc/c/c-convert.c b/gcc-4.8.1/gcc/c/c-convert.c deleted file mode 100644 index 3951ef549..000000000 --- a/gcc-4.8.1/gcc/c/c-convert.c +++ /dev/null @@ -1,183 +0,0 @@ -/* Language-level data type conversion for GNU C. - Copyright (C) 1987-2013 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. */ - -/* Subroutines of `convert'. */ - - - -/* 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)) - && (TREE_CODE (TREE_TYPE (expr)) != COMPLEX_TYPE - || TREE_CODE (e) == COMPLEX_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) - { - if (TREE_CODE (e) != COMPLEX_EXPR) - { - tree subtype = TREE_TYPE (type); - tree elt_type = TREE_TYPE (TREE_TYPE (e)); - - if (in_late_binary_op) - e = save_expr (e); - else - e = c_save_expr (e); - ret - = fold_build2_loc (loc, 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-4.8.1/gcc/c/c-decl.c b/gcc-4.8.1/gcc/c/c-decl.c deleted file mode 100644 index d9bbf5c25..000000000 --- a/gcc-4.8.1/gcc/c/c-decl.c +++ /dev/null @@ -1,10157 +0,0 @@ -/* Process declarations and variables for C compiler. - Copyright (C) 1988-2013 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 "dumpfile.h" -#include "cgraph.h" -#include "hash-table.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 -}; - - -/* 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; - - -/* 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; - -/* 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, va_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, va_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 vector of pointers to c_binding structures. */ - -typedef struct c_binding *c_binding_ptr; - -/* 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> 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> fields; - /* If warn_cxx_compat, a list of typedef names used when defining - fields in this struct. */ - vec<tree> 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); - -/* 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; -} - -/* 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); -} - - -/* 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; -} - - -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; -} - -/* 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); - } - } -} - -/* 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; -} - -/* 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; -} - -/* 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(label_vars->decls_in_scope, b1->decl); - } - } - } - - /* Update the bindings of any goto statements associated - with this label. */ - FOR_EACH_VEC_SAFE_ELT (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 (); -} - -/* 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_SAFE_ELT (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_SAFE_ELT (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); - } -} - -/* 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"); - } - } -} - -/* 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 = ¤t_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; -} - - -/* 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)) - { - /* Do not warn if a variable shadows a function, unless - the variable is a function or a pointer-to-function. */ - if (TREE_CODE (old_decl) == FUNCTION_DECL - && TREE_CODE (new_decl) != FUNCTION_DECL - && !FUNCTION_POINTER_TYPE_P (TREE_TYPE (new_decl))) - continue; - - warning_at (DECL_SOURCE_LOCATION (new_decl), OPT_Wshadow, - "declaration of %qD 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; -} - -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); -} - -/* 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 = NULL; - *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 (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_SAFE_ELT (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_SAFE_ELT (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_safe_truncate (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; -} - -/* 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; -} - -/* 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; -} - - -/* 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; -} - -/* 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; -} - -/* 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"); - } -} - - -/* 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_safe_is_empty (CONSTRUCTOR_ELTS (init))) - return; - - elt = CONSTRUCTOR_ELTS (init)->last ().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)); - } -} - -/* 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, va_gc> *v; - - /* Build "cleanup(&decl)" for the destructor. */ - cleanup = build_unary_op (input_location, ADDR_EXPR, decl, 0); - vec_alloc (v, 1); - v->quick_push (cleanup); - cleanup = build_function_call_vec (DECL_SOURCE_LOCATION (decl), - cleanup_decl, v, NULL); - vec_free (v); - - /* 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; -} - -/* 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++"); -} - -/* 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; - } -} - -/* 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); - } -} - - - -/* 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_SAFE_ELT_REVERSE (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; - } -} - -/* 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, va_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.id = b->id; - tag.type = decl; - vec_safe_push (tags, tag); - 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; -} - -/* 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; -} - -/* 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.create (0); - struct_parse_info->fields.create (0); - struct_parse_info->typedefs_seen.create (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) - { - struct_parse_info->fields.safe_push (b); - b->in_struct = 1; - } - } - } - - return value; -} - -/* 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, - hash_table <pointer_hash <tree_node> > htab) -{ - tree x, y; - tree_node **slot; - - for (x = fieldlist; x ; x = DECL_CHAIN (x)) - if ((y = DECL_NAME (x)) != 0) - { - slot = htab.find_slot (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 (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 - { - hash_table <pointer_hash <tree_node> > htab; - htab.create (37); - - detect_field_duplicates_hash (fieldlist, htab); - htab.dispose (); - } -} - -/* 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 (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 (!struct_parse_info->typedefs_seen.is_empty () - && 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 (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 (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); - - struct_parse_info->struct_types.release (); - struct_parse_info->fields.release (); - struct_parse_info->typedefs_seen.release (); - 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) - struct_parse_info->struct_types.safe_push (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); -} - -/* 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) - struct_parse_info->struct_types.safe_push (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); -} - - -/* 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; -} - -/* 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_SAFE_ELT_REVERSE (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); -} - - -/* 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; -} - -/* 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; -} - -/* 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_safe_copy (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) - struct_parse_info->typedefs_seen.safe_push (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 (*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 (*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 (flag_dump_ada_spec || flag_dump_ada_spec_slim) - { - /* Build a table of files to generate specs for */ - if (flag_dump_ada_spec_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 (*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 (*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-4.8.1/gcc/c/c-errors.c b/gcc-4.8.1/gcc/c/c-errors.c deleted file mode 100644 index 0d2754084..000000000 --- a/gcc-4.8.1/gcc/c/c-errors.c +++ /dev/null @@ -1,64 +0,0 @@ -/* Various diagnostic subroutines for the GNU C language. - Copyright (C) 2000-2013 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-4.8.1/gcc/c/c-lang.c b/gcc-4.8.1/gcc/c/c-lang.c deleted file mode 100644 index 614c46d15..000000000 --- a/gcc-4.8.1/gcc/c/c-lang.c +++ /dev/null @@ -1,50 +0,0 @@ -/* Language-specific hook definitions for C front end. - Copyright (C) 1991-2013 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-4.8.1/gcc/c/c-lang.h b/gcc-4.8.1/gcc/c/c-lang.h deleted file mode 100644 index 5ff7cd542..000000000 --- a/gcc-4.8.1/gcc/c/c-lang.h +++ /dev/null @@ -1,59 +0,0 @@ -/* Definitions for C language specific types. - Copyright (C) 2009-2013 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((variable_size)) 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-4.8.1/gcc/c/c-objc-common.c b/gcc-4.8.1/gcc/c/c-objc-common.c deleted file mode 100644 index 6020c028d..000000000 --- a/gcc-4.8.1/gcc/c/c-objc-common.c +++ /dev/null @@ -1,213 +0,0 @@ -/* Some code common to C and ObjC front ends. - Copyright (C) 2001-2013 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-4.8.1/gcc/c/c-objc-common.h b/gcc-4.8.1/gcc/c/c-objc-common.h deleted file mode 100644 index e1448248c..000000000 --- a/gcc-4.8.1/gcc/c/c-objc-common.h +++ /dev/null @@ -1,108 +0,0 @@ -/* Language hooks common to C and ObjC front ends. - Copyright (C) 2004-2013 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-4.8.1/gcc/c/c-parser.c b/gcc-4.8.1/gcc/c/c-parser.c deleted file mode 100644 index 2ae46220a..000000000 --- a/gcc-4.8.1/gcc/c/c-parser.c +++ /dev/null @@ -1,10884 +0,0 @@ -/* Parser for C and Objective-C. - Copyright (C) 1987-2013 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" - - -/* 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; - } -} - -/* 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 *); -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, va_gc> *c_parser_expr_list (c_parser *, bool, bool, - vec<tree, va_gc> **, location_t *, - tree *); -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, va_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, NULL, 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, NULL, 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, - /*empty_ok*/ true, /*nested*/ true, - /*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); - break; - case 1: - inputs = c_parser_asm_operands (parser); - 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. - - 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) -{ - tree list = NULL_TREE; - 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; - } - expr = c_parser_expression (parser); - mark_exp_read (expr.value); - 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, va_gc> **ret_cexpr_list) -{ - location_t loc = c_parser_peek_token (parser)->location; - vec<c_expr_t, va_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); - vec_alloc (cexpr_list, 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, va_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_safe_length (cexpr_list) != 3) - { - error_at (loc, "wrong number of arguments to " - "%<__builtin_choose_expr%>"); - expr.value = error_mark_node; - break; - } - - e1_p = &(*cexpr_list)[0]; - e2_p = &(*cexpr_list)[1]; - e3_p = &(*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, va_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_safe_length (cexpr_list) != 2) - { - error_at (loc, "wrong number of arguments to " - "%<__builtin_complex%>"); - expr.value = error_mark_node; - break; - } - - e1_p = &(*cexpr_list)[0]; - e2_p = &(*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, va_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_SAFE_ELT (cexpr_list, i, p) - mark_exp_read (p->value); - - if (vec_safe_length (cexpr_list) == 2) - expr.value = - c_build_vec_perm_expr - (loc, (*cexpr_list)[0].value, - NULL_TREE, (*cexpr_list)[1].value); - - else if (vec_safe_length (cexpr_list) == 3) - expr.value = - c_build_vec_perm_expr - (loc, (*cexpr_list)[0].value, - (*cexpr_list)[1].value, - (*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); -} - -/* Callback function for sizeof_pointer_memaccess_warning to compare - types. */ - -static bool -sizeof_ptr_memacc_comptypes (tree type1, tree type2) -{ - return comptypes (type1, type2) == 1; -} - -/* 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; - location_t sizeof_arg_loc[3]; - tree sizeof_arg[3]; - unsigned int i; - vec<tree, va_gc> *exprlist; - vec<tree, va_gc> *origtypes = NULL; - 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); - for (i = 0; i < 3; i++) - { - sizeof_arg[i] = NULL_TREE; - sizeof_arg_loc[i] = UNKNOWN_LOCATION; - } - if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) - exprlist = NULL; - else - exprlist = c_parser_expr_list (parser, true, false, &origtypes, - sizeof_arg_loc, sizeof_arg); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, - "expected %<)%>"); - orig_expr = expr; - mark_exp_read (expr.value); - if (warn_sizeof_pointer_memaccess) - sizeof_pointer_memaccess_warning (sizeof_arg_loc, - expr.value, exprlist, - sizeof_arg, - sizeof_ptr_memacc_comptypes); - /* 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) - { - 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, va_gc> * -c_parser_expr_list (c_parser *parser, bool convert_p, bool fold_p, - vec<tree, va_gc> **p_orig_types, - location_t *sizeof_arg_loc, tree *sizeof_arg) -{ - vec<tree, va_gc> *ret; - vec<tree, va_gc> *orig_types; - struct c_expr expr; - location_t loc = c_parser_peek_token (parser)->location; - location_t cur_sizeof_arg_loc = UNKNOWN_LOCATION; - unsigned int idx = 0; - - ret = make_tree_vector (); - if (p_orig_types == NULL) - orig_types = NULL; - else - orig_types = make_tree_vector (); - - if (sizeof_arg != NULL - && c_parser_next_token_is_keyword (parser, RID_SIZEOF)) - cur_sizeof_arg_loc = c_parser_peek_2nd_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); - ret->quick_push (expr.value); - if (orig_types) - orig_types->quick_push (expr.original_type); - if (sizeof_arg != NULL - && cur_sizeof_arg_loc != UNKNOWN_LOCATION - && expr.original_code == SIZEOF_EXPR) - { - sizeof_arg[0] = c_last_sizeof_arg; - sizeof_arg_loc[0] = cur_sizeof_arg_loc; - } - while (c_parser_next_token_is (parser, CPP_COMMA)) - { - c_parser_consume_token (parser); - loc = c_parser_peek_token (parser)->location; - if (sizeof_arg != NULL - && c_parser_next_token_is_keyword (parser, RID_SIZEOF)) - cur_sizeof_arg_loc = c_parser_peek_2nd_token (parser)->location; - else - cur_sizeof_arg_loc = UNKNOWN_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 (ret, expr.value); - if (orig_types) - vec_safe_push (orig_types, expr.original_type); - if (++idx < 3 - && sizeof_arg != NULL - && cur_sizeof_arg_loc != UNKNOWN_LOCATION - && expr.original_code == SIZEOF_EXPR) - { - sizeof_arg[idx] = c_last_sizeof_arg; - sizeof_arg_loc[idx] = cur_sizeof_arg_loc; - } - } - if (orig_types) - *p_orig_types = orig_types; - return ret; -} - -/* 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, va_gc> *expr_list = c_parser_expr_list (parser, true, true, - NULL, NULL, NULL); - if (vec_safe_length (expr_list) == 1) - { - /* Just return the expression, remove a level of - indirection. */ - ret = (*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); -} - - -/* 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)); -} - -/* 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, va_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 (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 (!for_block->is_empty ()) - { - /* 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, for_block->pop (), 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); -} - -/* 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-4.8.1/gcc/c/c-tree.h b/gcc-4.8.1/gcc/c/c-tree.h deleted file mode 100644 index d1a871daa..000000000 --- a/gcc-4.8.1/gcc/c/c-tree.h +++ /dev/null @@ -1,671 +0,0 @@ -/* Definitions for C parsing and type checking. - Copyright (C) 1987-2013 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. */ - -/* Append a new c_expr_t element to V. */ -#define C_EXPR_APPEND(V, ELEM) \ - do { \ - c_expr_t __elem = (ELEM); \ - vec_safe_push (V, __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; - - -/* 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, va_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 -}; - - -/* 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 tree c_last_sizeof_arg; - -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-4.8.1/gcc/c/c-typeck.c b/gcc-4.8.1/gcc/c/c-typeck.c deleted file mode 100644 index ddb6d3977..000000000 --- a/gcc-4.8.1/gcc/c/c-typeck.c +++ /dev/null @@ -1,10899 +0,0 @@ -/* Build expressions with type checking for C compiler. - Copyright (C) 1987-2013 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" -#include "c-family/c-common.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 -}; - -/* 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; - -/* The argument of last parsed sizeof expression, only to be tested - if expr.original_code == SIZEOF_EXPR. */ -tree c_last_sizeof_arg; - -/* 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, va_gc> *, vec<tree, va_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 *); - -/* 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; -} - -/* 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; -} - -/* 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; -} - -/* 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; -} - -/* 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; -} - -/* 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); - } -} - -/* 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)); -} - -/* 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; -} - -/* 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; -} - -/* 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); - } -} - -/* 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)); - c_last_sizeof_arg = expr.value; - ret.original_code = SIZEOF_EXPR; - 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); - c_last_sizeof_arg = type; - ret.original_code = SIZEOF_EXPR; - 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, va_gc> *v; - tree ret; - - vec_alloc (v, list_length (params)); - for (; params; params = TREE_CHAIN (params)) - v->quick_push (TREE_VALUE (params)); - ret = build_function_call_vec (loc, function, v, NULL); - vec_free (v); - 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, va_gc> *params, - vec<tree, va_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 (params && !params->is_empty ()) - function = objc_rewrite_function_call (function, (*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, (*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, - NULL), - false); - else - rhs = build_zero_cst (return_type); - - return require_complete_type (build2 (COMPOUND_EXPR, return_type, - trap, rhs)); - } - } - - argarray = vec_safe_address (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); -} - -/* 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, va_gc> *values, - vec<tree, va_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; - values && values->iterate (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_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); - - (*values)[parmnum] = parmval; - if (parmval == error_mark_node) - error_args = true; - - if (typetail) - typetail = TREE_CHAIN (typetail); - } - - gcc_assert (parmnum == vec_safe_length (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; -} - -/* 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 (input_location, 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; -} - -/* 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); -} - -/* 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; - } - if (int_operands) - { - arg = c_objc_common_truthvalue_conversion (location, xarg); - arg = remove_c_maybe_const_expr (arg); - } - else - 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; - } -} - -/* 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; -} - -/* 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; - } -} - -/* 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; -} - -/* 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) - { - bool inner_expr_const = true; - ret = c_fully_fold (ret, require_constant_value, &inner_expr_const); - ret = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (ret), type_expr, ret); - C_MAYBE_CONST_EXPR_NON_CONST (ret) = !(type_expr_const - && inner_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; -} - -/* 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; -} - -/* 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)) - && c_common_signed_type (mvl) - == c_common_signed_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; -} - -/* 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; -} - -/* 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)); - } - } - } -} - -/* 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); -} - -/* 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; -} - -/* 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, va_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; - - -/* 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, va_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, va_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; - -/* 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); -} - -/* 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 = NULL; - 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; - } -} - -/* 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 = NULL; - 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_safe_is_empty (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_safe_length (constructor_elements) == 1 - && integer_zerop ((*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_safe_is_empty (constructor_elements)) - { - if (!constructor_erroneous) - error_init ("empty scalar initializer"); - ret.value = error_mark_node; - } - else if (vec_safe_length (constructor_elements) != 1) - { - error_init ("extra elements in scalar initializer"); - ret.value = (*constructor_elements)[0].value; - } - else - ret.value = (*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); -} - -/* 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 = NULL; - 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 - && !(constructor_max_index - && 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_safe_is_empty (constructor_elements) - && (constructor_elements->last ().index == field)) - return constructor_elements->last ().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; - 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_safe_is_empty (constructor_elements)) - { - if (!implicit) - { - if (TREE_SIDE_EFFECTS (constructor_elements->last ().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 = NULL; - } - - /* Otherwise, output this element either to - constructor_elements or to the assembler file. */ - - constructor_elt celt = {field, value}; - vec_safe_push (constructor_elements, celt); - - /* 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; -} - -/* 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 - && 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; -} - -/* 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); - - output = c_fully_fold (output, false, NULL); - - /* ??? 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) - { - input = c_fully_fold (input, false, NULL); - - /* 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 - { - struct c_expr expr; - memset (&expr, 0, sizeof (expr)); - expr.value = input; - expr = default_function_array_conversion (loc, expr); - input = c_fully_fold (expr.value, false, NULL); - - 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; -} - -/* 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; - bool save; - - current_function_returns_value = 1; - if (t == error_mark_node) - return NULL_TREE; - - save = in_late_binary_op; - if (TREE_CODE (TREE_TYPE (res)) == BOOLEAN_TYPE - || TREE_CODE (TREE_TYPE (res)) == COMPLEX_TYPE) - in_late_binary_op = true; - inner = t = convert (TREE_TYPE (res), t); - in_late_binary_op = save; - - /* 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, - OPT_Wreturn_local_addr, "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); -} - -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); -} - -/* 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; - } -} - -/* 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; -} - -/* 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, - true); - - 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; - if (op0_int_operands) - { - op0 = c_objc_common_truthvalue_conversion (location, orig_op0); - op0 = remove_c_maybe_const_expr (op0); - } - else - op0 = c_objc_common_truthvalue_conversion (location, op0); - if (op1_int_operands) - { - op1 = c_objc_common_truthvalue_conversion (location, orig_op1); - op1 = remove_c_maybe_const_expr (op1); - } - else - op1 = c_objc_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 && TREE_CODE (expr) != INTEGER_CST) - { - expr = remove_c_maybe_const_expr (expr); - expr = build2 (NE_EXPR, integer_type_node, expr, - convert (TREE_TYPE (expr), integer_zero_node)); - expr = note_integer_operands (expr); - } - else - /* ??? 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; -} - - -/* 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; -} - -/* 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-4.8.1/gcc/c/config-lang.in b/gcc-4.8.1/gcc/c/config-lang.in deleted file mode 100644 index 86c7850a1..000000000 --- a/gcc-4.8.1/gcc/c/config-lang.in +++ /dev/null @@ -1,32 +0,0 @@ -# Top level configure fragment for GNU C - C language. -# Copyright (C) 1994-2013 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-4.8.1/gcc/c/gccspec.c b/gcc-4.8.1/gcc/c/gccspec.c deleted file mode 100644 index 44fc71dfa..000000000 --- a/gcc-4.8.1/gcc/c/gccspec.c +++ /dev/null @@ -1,108 +0,0 @@ -/* Specific flags and argument handling of the C front-end. - Copyright (C) 1999-2013 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. */ |