summaryrefslogtreecommitdiff
path: root/gcc/fortran
diff options
context:
space:
mode:
authorhjl <hjl@138bc75d-0d04-0410-961f-82ee72b054a4>2010-07-01 22:22:57 +0000
committerhjl <hjl@138bc75d-0d04-0410-961f-82ee72b054a4>2010-07-01 22:22:57 +0000
commit9e169c4bf36a38689550c059570c57efbf00a6fb (patch)
tree95e6800f7ac2a49ff7f799d96f04172320e70ac0 /gcc/fortran
parent6170dfb6edfb7b19f8ae5209b8f948fe0076a4ad (diff)
downloadgcc-vect256.tar.gz
Merged trunk at revision 161680 into branch.vect256
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/vect256@161681 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/fortran')
-rw-r--r--gcc/fortran/ChangeLog479
-rw-r--r--gcc/fortran/Make-lang.in2
-rw-r--r--gcc/fortran/array.c2
-rw-r--r--gcc/fortran/check.c166
-rw-r--r--gcc/fortran/cpp.c124
-rw-r--r--gcc/fortran/cpp.h6
-rw-r--r--gcc/fortran/decl.c360
-rw-r--r--gcc/fortran/dependency.c1
-rw-r--r--gcc/fortran/dependency.h1
-rw-r--r--gcc/fortran/dump-parse-tree.c32
-rw-r--r--gcc/fortran/error.c2
-rw-r--r--gcc/fortran/expr.c102
-rw-r--r--gcc/fortran/f95-lang.c10
-rw-r--r--gcc/fortran/gfc-internals.texi4
-rw-r--r--gcc/fortran/gfortran.h57
-rw-r--r--gcc/fortran/gfortran.texi37
-rw-r--r--gcc/fortran/gfortranspec.c33
-rw-r--r--gcc/fortran/interface.c88
-rw-r--r--gcc/fortran/intrinsic.c124
-rw-r--r--gcc/fortran/intrinsic.h8
-rw-r--r--gcc/fortran/intrinsic.texi88
-rw-r--r--gcc/fortran/invoke.texi8
-rw-r--r--gcc/fortran/io.c2
-rw-r--r--gcc/fortran/lang-specs.h2
-rw-r--r--gcc/fortran/lang.opt38
-rw-r--r--gcc/fortran/libgfortran.h19
-rw-r--r--gcc/fortran/match.c150
-rw-r--r--gcc/fortran/match.h2
-rw-r--r--gcc/fortran/mathbuiltins.def17
-rw-r--r--gcc/fortran/module.c14
-rw-r--r--gcc/fortran/openmp.c38
-rw-r--r--gcc/fortran/options.c19
-rw-r--r--gcc/fortran/parse.c120
-rw-r--r--gcc/fortran/parse.h2
-rw-r--r--gcc/fortran/primary.c6
-rw-r--r--gcc/fortran/resolve.c406
-rw-r--r--gcc/fortran/scanner.c39
-rw-r--r--gcc/fortran/simplify.c46
-rw-r--r--gcc/fortran/st.c15
-rw-r--r--gcc/fortran/symbol.c29
-rw-r--r--gcc/fortran/trans-array.c67
-rw-r--r--gcc/fortran/trans-decl.c24
-rw-r--r--gcc/fortran/trans-expr.c98
-rw-r--r--gcc/fortran/trans-intrinsic.c512
-rw-r--r--gcc/fortran/trans-openmp.c52
-rw-r--r--gcc/fortran/trans-stmt.c51
-rw-r--r--gcc/fortran/trans-types.c35
-rw-r--r--gcc/fortran/trans.h15
48 files changed, 2593 insertions, 959 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index 0db8ce51016..18509132034 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,482 @@
+2010-06-29 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/44718
+ * resolve.c (is_external_proc): Prevent procedure pointers from being
+ regarded as external procedures.
+
+2010-06-29 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/44696
+ * trans-intrinsic.c (gfc_conv_associated): Handle polymorphic variables
+ passed as second argument of ASSOCIATED.
+
+2010-06-29 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/44582
+ * trans-expr.c (arrayfunc_assign_needs_temporary): New function
+ to determine if a function assignment can be made without a
+ temporary.
+ (gfc_trans_arrayfunc_assign): Move all the conditions that
+ suppress the direct function call to the above new functon and
+ call it.
+
+2010-06-28 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/40158
+ * interface.c (argument_rank_mismatch): New function.
+ (compare_parameter): Call new function instead of generating
+ the error directly.
+
+2010-06-28 Nathan Froyd <froydnj@codesourcery.com>
+
+ * trans-openmp.c (dovar_init): Define. Define VECs containing it.
+ (gfc_trans_omp_do): Use a VEC to accumulate variables and their
+ initializers.
+
+2010-06-28 Steven Bosscher <steven@gcc.gnu.org>
+
+ * Make-lang.in: Update dependencies.
+
+2010-06-27 Nathan Froyd <froydnj@codesourcery.com>
+
+ * gfortran.h (gfc_code): Split backend_decl field into cycle_label
+ and exit_label fields.
+ * trans-openmp.c (gfc_trans_omp_do): Assign to new fields
+ individually.
+ * trans-stmt.c (gfc_trans_simple_do): Likewise.
+ (gfc_trans_do): Likewise.
+ (gfc_trans_do_while): Likewise.
+ (gfc_trans_cycle): Use cycle_label directly.
+ (gfc_trans_exit): Use exit_label directly.
+
+2010-06-27 Daniel Kraft <d@domob.eu>
+
+ * dump-parse-tree.c (show_symbol): Dump target-expression for
+ associate names.
+ (show_code_node): Make distinction between BLOCK and ASSOCIATE.
+ (show_namespace): Use show_level for correct indentation of
+ "inner namespaces" (contained procedures or BLOCK).
+
+2010-06-27 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/44678
+ * dump-parse-tree.c (show_code_node): Show namespace for
+ EXEC_BLOCK.
+
+2010-06-26 Tobias Burnus <burnus@net-b.de>
+
+ * decl.c (gfc_match_decl_type_spec): Support
+ TYPE(intrinsic-type-spec).
+
+2010-06-25 Tobias Burnus <burnus@net-b.de>
+
+ * intrinsic.h (gfc_check_selected_real_kind,
+ gfc_simplify_selected_real_kind): Update prototypes.
+ * intrinsic.c (add_functions): Add radix support to
+ selected_real_kind.
+ * check.c (gfc_check_selected_real_kind): Ditto.
+ * simplify.c (gfc_simplify_selected_real_kind): Ditto.
+ * trans-decl.c (gfc_build_intrinsic_function_decls):
+ Change call from selected_real_kind to selected_real_kind2008.
+ * intrinsic.texi (SELECTED_REAL_KIND): Update for radix.
+ (PRECISION, RANGE, RADIX): Add cross @refs.
+
+2010-06-25 Tobias Burnus <burnus@net-b.de>
+
+ * decl.c (gfc_match_entry): Mark ENTRY as GFC_STD_F2008_OBS.
+ * gfortran.texi (_gfortran_set_options): Update for
+ GFC_STD_F2008_OBS addition.
+ * libgfortran.h: Add GFC_STD_F2008_OBS.
+ * options.c (set_default_std_flags, gfc_handle_option): Handle
+ GFC_STD_F2008_OBS.
+ io.c (check_format): Fix allow_std check.
+
+2010-06-25 Tobias Burnus <burnus@net-b.de>
+
+ * decl.c (gfc_match_entry): Allow END besides
+ END SUBROUTINE/END FUNCTION for contained procedures.
+
+2010-06-25 Tobias Burnus <burnus@net-b.de>
+
+ * parse.c (next_free, next_fixed): Allow ";" as first character.
+
+2010-06-24 Tobias Burnus <burnus@net-b.de>
+
+ PR fortran/44614
+ * decl.c (variable_decl): Fix IMPORT diagnostic for CLASS.
+
+2010-06-22 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/44616
+ * resolve.c (resolve_fl_derived): Avoid checking for abstract on class
+ containers.
+
+2010-06-21 Tobias Burnus <burnus@net-b.de>
+
+ PR fortran/40632
+ * interface.c (compare_parameter): Add gfc_is_simply_contiguous
+ checks.
+ * symbol.c (gfc_add_contiguous): New function.
+ (gfc_copy_attr, check_conflict): Handle contiguous attribute.
+ * decl.c (match_attr_spec): Ditto.
+ (gfc_match_contiguous): New function.
+ * resolve.c (resolve_fl_derived, resolve_symbol): Handle
+ contiguous.
+ * gfortran.h (symbol_attribute): Add contiguous.
+ (gfc_is_simply_contiguous): Add prototype.
+ (gfc_add_contiguous): Add prototype.
+ * match.h (gfc_match_contiguous): Add prototype.
+ * parse.c (decode_specification_statement,
+ decode_statement): Handle contiguous attribute.
+ * expr.c (gfc_is_simply_contiguous): New function.
+ * dump-parse-tree.c (show_attr): Handle contiguous.
+ * module.c (ab_attribute, attr_bits, mio_symbol_attribute):
+ Ditto.
+ * trans-expr.c (gfc_add_interface_mapping): Copy
+ attr.contiguous.
+ * trans-array.c (gfc_conv_descriptor_stride_get,
+ gfc_conv_array_parameter): Handle contiguous arrays.
+ * trans-types.c (gfc_build_array_type, gfc_build_array_type,
+ gfc_sym_type, gfc_get_derived_type, gfc_get_array_descr_info):
+ Ditto.
+ * trans.h (gfc_array_kind): Ditto.
+ * trans-decl.c (gfc_get_symbol_decl): Ditto.
+
+2010-06-20 Joseph Myers <joseph@codesourcery.com>
+
+ * options.c (gfc_handle_option): Don't handle N_OPTS.
+
+2010-06-19 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/44584
+ * resolve.c (resolve_fl_derived): Reverse ordering of conditions
+ to avoid ICE.
+
+2010-06-18 Tobias Burnus <burnus@net-b.de>
+
+ PR fortran/44556
+ * resolve.c (resolve_allocate_deallocate): Properly check
+ part-refs in stat=/errmsg= for invalid use.
+
+2010-06-17 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/44558
+ * resolve.c (resolve_typebound_function,resolve_typebound_subroutine):
+ Return directly in case of an error.
+
+2010-06-16 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/44549
+ * gfortran.h (gfc_get_typebound_proc): Modified Prototype.
+ * decl.c (match_procedure_in_type): Give a unique gfc_typebound_proc
+ structure to each procedure in a procedure list.
+ * module.c (mio_typebound_proc): Add NULL argument to
+ 'gfc_get_typebound_proc'.
+ * symbol.c (gfc_get_typebound_proc): Add a new argument, which is used
+ to initialize the new structure.
+
+2010-06-15 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/43388
+ * gfortran.h (gfc_expr): Add new member 'mold'.
+ * match.c (gfc_match_allocate): Implement the MOLD tag.
+ * resolve.c (resolve_allocate_expr): Ditto.
+ * trans-stmt.c (gfc_trans_allocate): Ditto.
+
+2010-06-15 Jakub Jelinek <jakub@redhat.com>
+
+ PR fortran/44536
+ * trans-openmp.c (gfc_omp_predetermined_sharing): Don't return
+ OMP_CLAUSE_DEFAULT_SHARED for artificial vars with
+ GFC_DECL_SAVED_DESCRIPTOR set.
+ (gfc_omp_report_decl): New function.
+ * trans.h (gfc_omp_report_decl): New prototype.
+ * f95-lang.c (LANG_HOOKS_OMP_REPORT_DECL): Redefine.
+
+2010-06-13 Daniel Franke <franke.daniel@gmail.com>
+
+ PR fortran/31588
+ PR fortran/43954
+ * gfortranspec.c (lang_specific_driver): Removed deprecation
+ warning for -M.
+ * lang.opt: Add options -M, -MM, -MD, -MMD, -MF, -MG, -MP, -MT, -MQ.
+ * lang-specs.h (CPP_FORWARD_OPTIONS): Add -M* options.
+ * cpp.h (gfc_cpp_makedep): New.
+ (gfc_cpp_add_dep): New.
+ (gfc_cpp_add_target): New.
+ * cpp.c (gfc_cpp_option): Add deps* members.
+ (gfc_cpp_makedep): New.
+ (gfc_cpp_add_dep): New.
+ (gfc_cpp_add_target): New.
+ (gfc_cpp_init_options): Initialize new options.
+ (gfc_cpp_handle_option): Handle new options.
+ (gfc_cpp_post_options): Map new options to libcpp-options.
+ (gfc_cpp_init): Handle deferred -MQ and -MT options.
+ (gfc_cpp_done): If requested, write dependencies to file.
+ * module.c (gfc_dump_module): Add a module filename as target.
+ * scanner.c (open_included_file): New parameter system; add the
+ included file as dependency.
+ (gfc_open_included_file): Add the included file as dependency.
+ (gfc_open_intrinsic_module): Likewise.
+ * invoke.texi: Removed deprecation warning for -M.
+ * gfortran.texi: Removed Makefile-dependencies project.
+
+2010-06-12 Daniel Franke <franke.daniel@gmail.com>
+
+ * resolve.c (resolve_global_procedure): Improved checking if an
+ explicit interface is required.
+
+2010-06-12 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
+
+ * trans-decl.c (gfc_build_intrinsic_function_decls): Fix
+ return type.
+ * trans-intrinsic.c (gfc_conv_intrinsic_fdate): Fix argument type.
+ (gfc_conv_intrinsic_ttynam): Likewise.
+ (gfc_conv_intrinsic_trim): Likewise.
+
+2010-06-12 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/40117
+ * decl.c (match_procedure_in_type): Allow procedure lists (F08).
+
+2010-06-11 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
+
+ * trans-intrinsic.c (gfc_build_intrinsic_lib_fndecls): Fix comment.
+
+2010-06-11 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
+
+ * mathbuiltins.def: Add builtins that do not directly correspond
+ to a Fortran intrinsic, with new macro OTHER_BUILTIN.
+ * f95-lang.c (gfc_init_builtin_functions): Define OTHER_BUILTIN.
+ * trans-intrinsic.c (gfc_intrinsic_map_t): Remove
+ code_{r,c}{4,8,10,16} fields. Add
+ {,complex}{float,double,long_double}_built_in fields.
+ (gfc_intrinsic_map): Adjust definitions of DEFINE_MATH_BUILTIN,
+ DEFINE_MATH_BUILTIN_C and LIB_FUNCTION accordingly. Add
+ definition of OTHER_BUILTIN.
+ (real_compnt_info): Remove unused struct.
+ (builtin_decl_for_precision, builtin_decl_for_float_kind): New
+ functions.
+ (build_round_expr): Call builtin_decl_for_precision instead of
+ series of if-else.
+ (gfc_conv_intrinsic_aint): Call builtin_decl_for_float_kind
+ instead of a switch.
+ (gfc_build_intrinsic_lib_fndecls): Match
+ {real,complex}{4,8,10,16}decl into the C-style built_in_decls.
+ (gfc_get_intrinsic_lib_fndecl): Do not hardcode floating-point
+ kinds.
+ (gfc_conv_intrinsic_lib_function): Go through all the extended
+ gfc_intrinsic_map.
+ (gfc_trans_same_strlen_check): Call builtin_decl_for_float_kind
+ instead of a switch.
+ (gfc_conv_intrinsic_abs): Likewise.
+ (gfc_conv_intrinsic_mod): Likewise.
+ (gfc_conv_intrinsic_sign): Likewise.
+ (gfc_conv_intrinsic_fraction): Likewise.
+ (gfc_conv_intrinsic_nearest): Likewise.
+ (gfc_conv_intrinsic_spacing): Likewise.
+ (gfc_conv_intrinsic_rrspacing): Likewise.
+ (gfc_conv_intrinsic_scale): Likewise.
+ (gfc_conv_intrinsic_set_exponent): Likewise.
+
+2010-06-11 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/42051
+ PR fortran/43896
+ * trans-expr.c (gfc_conv_derived_to_class): Handle array-valued
+ functions with CLASS formal arguments.
+
+2010-06-10 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/44207
+ * resolve.c (conformable_arrays): Handle allocatable components.
+
+2010-06-10 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
+
+ PR fortran/38273
+ * gfortran.texi: Document that Cray pointers cannot be function
+ results.
+
+2010-06-10 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
+
+ PR fortran/36234
+ * gfortran.texi: Document lack of support for syntax
+ "complex FUNCTION name*16()", and existence of alternative
+ legacy syntax "complex*16 FUNCTION name()".
+
+2010-06-10 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
+
+ PR fortran/43032
+ * intrinsic.texi (FLUSH): Note the difference between FLUSH and
+ POSIX's fsync(), and how to call the latter from Fortran code.
+
+2010-06-10 Daniel Franke <franke.daniel@gmail.com>
+
+ PR fortran/44457
+ * interface.c (compare_actual_formal): Reject actual arguments with
+ array subscript passed to ASYNCHRONOUS dummys.
+
+2010-06-10 Daniel Kraft <d@domob.eu>
+
+ PR fortran/38936
+ * gfortran.h (enum gfc_statement): Add ST_ASSOCIATE, ST_END_ASSOCIATE.
+ (struct gfc_symbol): New field `assoc'.
+ (struct gfc_association_list): New struct.
+ (struct gfc_code): New struct `block' in union, move `ns' there
+ and add association list.
+ (gfc_free_association_list): New method.
+ (gfc_has_vector_subscript): Made public;
+ * match.h (gfc_match_associate): New method.
+ * parse.h (enum gfc_compile_state): Add COMP_ASSOCIATE.
+ * decl.c (gfc_match_end): Handle ST_END_ASSOCIATE.
+ * interface.c (gfc_has_vector_subscript): Made public.
+ (compare_actual_formal): Rename `has_vector_subscript' accordingly.
+ * match.c (gfc_match_associate): New method.
+ (gfc_match_select_type): Change reference to gfc_code's `ns' field.
+ * primary.c (match_variable): Don't allow names associated to expr here.
+ * parse.c (decode_statement): Try matching ASSOCIATE statement.
+ (case_exec_markers, case_end): Add ASSOCIATE statement.
+ (gfc_ascii_statement): Hande ST_ASSOCIATE and ST_END_ASSOCIATE.
+ (parse_associate): New method.
+ (parse_executable): Handle ST_ASSOCIATE.
+ (parse_block_construct): Change reference to gfc_code's `ns' field.
+ * resolve.c (resolve_select_type): Ditto.
+ (resolve_code): Ditto.
+ (resolve_block_construct): Ditto and add comment.
+ (resolve_select_type): Set association list in generated BLOCK to NULL.
+ (resolve_symbol): Resolve associate names.
+ * st.c (gfc_free_statement): Change reference to gfc_code's `ns' field
+ and free association list.
+ (gfc_free_association_list): New method.
+ * symbol.c (gfc_new_symbol): NULL new field `assoc'.
+ * trans-stmt.c (gfc_trans_block_construct): Change reference to
+ gfc_code's `ns' field.
+
+2010-06-10 Kai Tietz <kai.tietz@onevision.com>
+
+ * error.c (error_print): Pre-initialize loc by NULL.
+ * openmp.c (resolve_omp_clauses): Add explicit
+ braces to avoid ambigous else.
+ * array.c (match_subscript): Pre-initialize m to MATCH_ERROR.
+
+2010-06-10 Gerald Pfeifer <gerald@pfeifer.com>
+
+ * gfc-internals.texi: Move to GFDL 1.3.
+ * gfortran.texi: Ditto.
+ * intrinsic.texi: Ditto.
+ * invoke.texi: Ditto.
+
+2010-06-09 Daniel Franke <franke.daniel@gmail.com>
+
+ PR fortran/44347
+ * check.c (gfc_check_selected_real_kind): Verify that the
+ actual arguments are scalar.
+
+2010-06-09 Daniel Franke <franke.daniel@gmail.com>
+
+ PR fortran/44359
+ * intrinsic.c (gfc_convert_type_warn): Further improve -Wconversion.
+
+2010-06-09 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/44430
+ * dump-parse-tree.c (show_symbol): Avoid infinite loop.
+
+2010-06-09 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ * fortran/symbol.c (check_conflict): Remove an invalid conflict check.
+
+2010-06-09 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ * fortran/intrinsic.c (add_functions): Change gfc_check_btest,
+ gfc_check_ibclr, and gfc_check_ibset to gfc_check_bitfcn.
+ * fortran/intrinsic.h: Remove prototypes for gfc_check_btest,
+ gfc_check_ibclr, and gfc_check_ibset. Add prototype for
+ gfc_check_bitfcn.
+ * fortran/check.c (nonnegative_check, less_than_bitsize1,
+ less_than_bitsize2): New functions.
+ (gfc_check_btest): Renamed to gfc_check_bitfcn. Use
+ nonnegative_check and less_than_bitsize1.
+ (gfc_check_ibclr, gfc_check_ibset): Removed.
+ (gfc_check_ibits,gfc_check_mvbits): Use nonnegative_check and
+ less_than_bitsize1.
+
+2010-06-09 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/44211
+ * resolve.c (resolve_typebound_function,resolve_typebound_subroutine):
+ Resolve references.
+
+2010-06-09 Kai Tietz <kai.tietz@onevision.com>
+
+ * resolve.c (resolve_deallocate_expr): Avoid warning
+ about possible use of iunitialized sym.
+ (resolve_allocate_expr): Pre-initialize sym by NULL.
+
+2010-06-09 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
+
+ PR fortran/43040
+ * f95-lang.c (gfc_init_builtin_functions): Remove comment.
+
+2010-06-08 Laurynas Biveinis <laurynas.biveinis@gmail.com>
+
+ * trans-types.c (gfc_get_nodesc_array_type): Use typed GC
+ allocation.
+ (gfc_get_array_type_bounds): Likewise.
+
+ * trans-decl.c (gfc_allocate_lang_decl): Likewise.
+ (gfc_find_module): Likewise.
+
+ * f95-lang.c (pushlevel): Likewise.
+
+ * trans.h (struct lang_type): Add variable_size GTY option.
+ (struct lang_decl): Likewise.
+
+2010-06-08 Tobias Burnus <burnus@net-b.de>
+
+ PR fortran/44446
+ * symbol.c (check_conflict): Move protected--external/procedure check ...
+ * resolve.c (resolve_select_type): ... to the resolution stage.
+
+2010-06-07 Tobias Burnus <burnus@net-b.de>
+
+ * options.c (gfc_handle_option): Fix -fno-recursive.
+
+2010-06-07 Tobias Burnus <burnus@net-b.de>
+
+ * gfc-internals.texi (copyrights-gfortran): Fix copyright year format.
+ * gfortran.texi (copyrights-gfortran): Ditto.
+
+2010-06-07 Joseph Myers <joseph@codesourcery.com>
+
+ * lang.opt (fshort-enums): Define using Var and VarExists.
+ * options.c (gfc_handle_option): Don't set flag_short_enums here.
+
+2010-06-05 Paul Thomas <pault@gcc.gnu.org>
+ Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/43945
+ * resolve.c (get_declared_from_expr): Move to before
+ resolve_typebound_generic_call. Make new_ref and class_ref
+ ignorable if set to NULL.
+ (resolve_typebound_generic_call): Once we have resolved the
+ generic call, check that the specific instance is that which
+ is bound to the declared type.
+ (resolve_typebound_function,resolve_typebound_subroutine): Avoid
+ freeing 'class_ref->next' twice.
+
+2010-06-05 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/43895
+ * trans-array.c (structure_alloc_comps): Dereference scalar
+ 'decl' if it is a REFERENCE_TYPE. Tidy expressions containing
+ TREE_TYPE (decl).
+
+2010-06-04 Joseph Myers <joseph@codesourcery.com>
+
+ * gfortranspec.c (append_arg, lang_specific_driver): Use
+ GCC-specific formats in diagnostics.
+
2010-06-02 Tobias Burnus <burnus@net-b.de>
PR fortran/44360
diff --git a/gcc/fortran/Make-lang.in b/gcc/fortran/Make-lang.in
index b74f9e99d0b..2a8c791c445 100644
--- a/gcc/fortran/Make-lang.in
+++ b/gcc/fortran/Make-lang.in
@@ -336,7 +336,7 @@ GFORTRAN_TRANS_DEPS = fortran/gfortran.h fortran/libgfortran.h \
fortran/f95-lang.o: $(GFORTRAN_TRANS_DEPS) fortran/mathbuiltins.def \
gt-fortran-f95-lang.h gtype-fortran.h $(CGRAPH_H) $(TARGET_H) fortran/cpp.h \
$(BUILTINS_DEF) fortran/types.def \
- libfuncs.h expr.h except.h
+ libfuncs.h expr.h
fortran/scanner.o: toplev.h fortran/cpp.h
fortran/convert.o: $(GFORTRAN_TRANS_DEPS)
fortran/trans.o: $(GFORTRAN_TRANS_DEPS) tree-iterator.h
diff --git a/gcc/fortran/array.c b/gcc/fortran/array.c
index 3ffc39714da..64816f28abb 100644
--- a/gcc/fortran/array.c
+++ b/gcc/fortran/array.c
@@ -64,7 +64,7 @@ gfc_copy_array_ref (gfc_array_ref *src)
static match
match_subscript (gfc_array_ref *ar, int init, bool match_star)
{
- match m;
+ match m = MATCH_ERROR;
bool star = false;
int i;
diff --git a/gcc/fortran/check.c b/gcc/fortran/check.c
index 3a68c29b543..34527172431 100644
--- a/gcc/fortran/check.c
+++ b/gcc/fortran/check.c
@@ -241,6 +241,80 @@ array_check (gfc_expr *e, int n)
}
+/* If expr is a constant, then check to ensure that it is greater than
+ of equal to zero. */
+
+static gfc_try
+nonnegative_check (const char *arg, gfc_expr *expr)
+{
+ int i;
+
+ if (expr->expr_type == EXPR_CONSTANT)
+ {
+ gfc_extract_int (expr, &i);
+ if (i < 0)
+ {
+ gfc_error ("'%s' at %L must be nonnegative", arg, &expr->where);
+ return FAILURE;
+ }
+ }
+
+ return SUCCESS;
+}
+
+
+/* If expr2 is constant, then check that the value is less than
+ bit_size(expr1). */
+
+static gfc_try
+less_than_bitsize1 (const char *arg1, gfc_expr *expr1, const char *arg2,
+ gfc_expr *expr2)
+{
+ int i2, i3;
+
+ if (expr2->expr_type == EXPR_CONSTANT)
+ {
+ gfc_extract_int (expr2, &i2);
+ i3 = gfc_validate_kind (BT_INTEGER, expr1->ts.kind, false);
+ if (i2 >= gfc_integer_kinds[i3].bit_size)
+ {
+ gfc_error ("'%s' at %L must be less than BIT_SIZE('%s')",
+ arg2, &expr2->where, arg1);
+ return FAILURE;
+ }
+ }
+
+ return SUCCESS;
+}
+
+
+/* If expr2 and expr3 are constants, then check that the value is less than
+ or equal to bit_size(expr1). */
+
+static gfc_try
+less_than_bitsize2 (const char *arg1, gfc_expr *expr1, const char *arg2,
+ gfc_expr *expr2, const char *arg3, gfc_expr *expr3)
+{
+ int i2, i3;
+
+ if (expr2->expr_type == EXPR_CONSTANT && expr3->expr_type == EXPR_CONSTANT)
+ {
+ gfc_extract_int (expr2, &i2);
+ gfc_extract_int (expr3, &i3);
+ i2 += i3;
+ i3 = gfc_validate_kind (BT_INTEGER, expr1->ts.kind, false);
+ if (i2 > gfc_integer_kinds[i3].bit_size)
+ {
+ gfc_error ("'%s + %s' at %L must be less than or equal "
+ "to BIT_SIZE('%s')",
+ arg2, arg3, &expr2->where, arg1);
+ return FAILURE;
+ }
+ }
+
+ return SUCCESS;
+}
+
/* Make sure two expressions have the same type. */
static gfc_try
@@ -766,13 +840,20 @@ gfc_check_besn (gfc_expr *n, gfc_expr *x)
gfc_try
-gfc_check_btest (gfc_expr *i, gfc_expr *pos)
+gfc_check_bitfcn (gfc_expr *i, gfc_expr *pos)
{
if (type_check (i, 0, BT_INTEGER) == FAILURE)
return FAILURE;
+
if (type_check (pos, 1, BT_INTEGER) == FAILURE)
return FAILURE;
+ if (nonnegative_check ("pos", pos) == FAILURE)
+ return FAILURE;
+
+ if (less_than_bitsize1 ("i", i, "pos", pos) == FAILURE)
+ return FAILURE;
+
return SUCCESS;
}
@@ -1389,19 +1470,6 @@ gfc_check_iand (gfc_expr *i, gfc_expr *j)
gfc_try
-gfc_check_ibclr (gfc_expr *i, gfc_expr *pos)
-{
- if (type_check (i, 0, BT_INTEGER) == FAILURE)
- return FAILURE;
-
- if (type_check (pos, 1, BT_INTEGER) == FAILURE)
- return FAILURE;
-
- return SUCCESS;
-}
-
-
-gfc_try
gfc_check_ibits (gfc_expr *i, gfc_expr *pos, gfc_expr *len)
{
if (type_check (i, 0, BT_INTEGER) == FAILURE)
@@ -1413,17 +1481,13 @@ gfc_check_ibits (gfc_expr *i, gfc_expr *pos, gfc_expr *len)
if (type_check (len, 2, BT_INTEGER) == FAILURE)
return FAILURE;
- return SUCCESS;
-}
-
+ if (nonnegative_check ("pos", pos) == FAILURE)
+ return FAILURE;
-gfc_try
-gfc_check_ibset (gfc_expr *i, gfc_expr *pos)
-{
- if (type_check (i, 0, BT_INTEGER) == FAILURE)
+ if (nonnegative_check ("len", len) == FAILURE)
return FAILURE;
- if (type_check (pos, 1, BT_INTEGER) == FAILURE)
+ if (less_than_bitsize2 ("i", i, "pos", pos, "len", len) == FAILURE)
return FAILURE;
return SUCCESS;
@@ -2856,21 +2920,45 @@ gfc_check_selected_int_kind (gfc_expr *r)
gfc_try
-gfc_check_selected_real_kind (gfc_expr *p, gfc_expr *r)
+gfc_check_selected_real_kind (gfc_expr *p, gfc_expr *r, gfc_expr *radix)
{
- if (p == NULL && r == NULL)
+ if (p == NULL && r == NULL
+ && gfc_notify_std (GFC_STD_F2008, "Fortran 2008: SELECTED_REAL_KIND with"
+ " neither 'P' nor 'R' argument at %L",
+ gfc_current_intrinsic_where) == FAILURE)
+ return FAILURE;
+
+ if (p)
{
- gfc_error ("Missing arguments to %s intrinsic at %L",
- gfc_current_intrinsic, gfc_current_intrinsic_where);
+ if (type_check (p, 0, BT_INTEGER) == FAILURE)
+ return FAILURE;
- return FAILURE;
+ if (scalar_check (p, 0) == FAILURE)
+ return FAILURE;
}
- if (p != NULL && type_check (p, 0, BT_INTEGER) == FAILURE)
- return FAILURE;
+ if (r)
+ {
+ if (type_check (r, 1, BT_INTEGER) == FAILURE)
+ return FAILURE;
- if (r != NULL && type_check (r, 1, BT_INTEGER) == FAILURE)
- return FAILURE;
+ if (scalar_check (r, 1) == FAILURE)
+ return FAILURE;
+ }
+
+ if (radix)
+ {
+ if (type_check (radix, 1, BT_INTEGER) == FAILURE)
+ return FAILURE;
+
+ if (scalar_check (radix, 1) == FAILURE)
+ return FAILURE;
+
+ if (gfc_notify_std (GFC_STD_F2008, "Fortran 2008: '%s' intrinsic with "
+ "RADIX argument at %L", gfc_current_intrinsic,
+ &radix->where) == FAILURE)
+ return FAILURE;
+ }
return SUCCESS;
}
@@ -3646,6 +3734,22 @@ gfc_check_mvbits (gfc_expr *from, gfc_expr *frompos, gfc_expr *len,
if (type_check (topos, 4, BT_INTEGER) == FAILURE)
return FAILURE;
+ if (nonnegative_check ("frompos", frompos) == FAILURE)
+ return FAILURE;
+
+ if (nonnegative_check ("topos", topos) == FAILURE)
+ return FAILURE;
+
+ if (nonnegative_check ("len", len) == FAILURE)
+ return FAILURE;
+
+ if (less_than_bitsize2 ("from", from, "frompos", frompos, "len", len)
+ == FAILURE)
+ return FAILURE;
+
+ if (less_than_bitsize2 ("to", to, "topos", topos, "len", len) == FAILURE)
+ return FAILURE;
+
return SUCCESS;
}
diff --git a/gcc/fortran/cpp.c b/gcc/fortran/cpp.c
index 8dbd157deaa..7f960f5e557 100644
--- a/gcc/fortran/cpp.c
+++ b/gcc/fortran/cpp.c
@@ -35,6 +35,7 @@ along with GCC; see the file COPYING3. If not see
#include "../../libcpp/internal.h"
#include "cpp.h"
#include "incpath.h"
+#include "mkdeps.h"
#ifndef TARGET_OS_CPP_BUILTINS
# define TARGET_OS_CPP_BUILTINS()
@@ -84,6 +85,12 @@ struct gfc_cpp_option_data
int no_predefined; /* -undef */
int standard_include_paths; /* -nostdinc */
int verbose; /* -v */
+ int deps; /* -M */
+ int deps_skip_system; /* -MM */
+ const char *deps_filename; /* -M[M]D */
+ const char *deps_filename_user; /* -MF <arg> */
+ int deps_missing_are_generated; /* -MG */
+ int deps_phony; /* -MP */
const char *multilib; /* -imultilib <dir> */
const char *prefix; /* -iprefix <dir> */
@@ -270,6 +277,26 @@ gfc_cpp_preprocess_only (void)
return gfc_cpp_option.preprocess_only;
}
+bool
+gfc_cpp_makedep (void)
+{
+ return gfc_cpp_option.deps;
+}
+
+void
+gfc_cpp_add_dep (const char *name, bool system)
+{
+ if (!gfc_cpp_option.deps_skip_system || !system)
+ deps_add_dep (cpp_get_deps (cpp_in), name);
+}
+
+void
+gfc_cpp_add_target (const char *name)
+{
+ deps_add_target (cpp_get_deps (cpp_in), name, 0);
+}
+
+
const char *
gfc_cpp_temporary_file (void)
{
@@ -299,6 +326,12 @@ gfc_cpp_init_options (unsigned int argc,
gfc_cpp_option.no_predefined = 0;
gfc_cpp_option.standard_include_paths = 1;
gfc_cpp_option.verbose = 0;
+ gfc_cpp_option.deps = 0;
+ gfc_cpp_option.deps_skip_system = 0;
+ gfc_cpp_option.deps_phony = 0;
+ gfc_cpp_option.deps_missing_are_generated = 0;
+ gfc_cpp_option.deps_filename = NULL;
+ gfc_cpp_option.deps_filename_user = NULL;
gfc_cpp_option.multilib = NULL;
gfc_cpp_option.prefix = NULL;
@@ -414,6 +447,43 @@ gfc_cpp_handle_option (size_t scode, const char *arg, int value ATTRIBUTE_UNUSED
gfc_cpp_option.print_include_names = 1;
break;
+ case OPT_MM:
+ gfc_cpp_option.deps_skip_system = 1;
+ /* fall through */
+
+ case OPT_M:
+ gfc_cpp_option.deps = 1;
+ break;
+
+ case OPT_MMD:
+ gfc_cpp_option.deps_skip_system = 1;
+ /* fall through */
+
+ case OPT_MD:
+ gfc_cpp_option.deps = 1;
+ gfc_cpp_option.deps_filename = arg;
+ break;
+
+ case OPT_MF:
+ /* If specified multiple times, last one wins. */
+ gfc_cpp_option.deps_filename_user = arg;
+ break;
+
+ case OPT_MG:
+ gfc_cpp_option.deps_missing_are_generated = 1;
+ break;
+
+ case OPT_MP:
+ gfc_cpp_option.deps_phony = 1;
+ break;
+
+ case OPT_MQ:
+ case OPT_MT:
+ gfc_cpp_option.deferred_opt[gfc_cpp_option.deferred_opt_count].code = code;
+ gfc_cpp_option.deferred_opt[gfc_cpp_option.deferred_opt_count].arg = arg;
+ gfc_cpp_option.deferred_opt_count++;
+ break;
+
case OPT_P:
gfc_cpp_option.no_line_commands = 1;
break;
@@ -430,16 +500,17 @@ gfc_cpp_post_options (void)
an error. */
if (!gfc_cpp_enabled ()
&& (gfc_cpp_preprocess_only ()
- || !gfc_cpp_option.discard_comments
- || !gfc_cpp_option.discard_comments_in_macro_exp
- || gfc_cpp_option.print_include_names
- || gfc_cpp_option.no_line_commands
- || gfc_cpp_option.dump_macros
- || gfc_cpp_option.dump_includes))
+ || gfc_cpp_makedep ()
+ || !gfc_cpp_option.discard_comments
+ || !gfc_cpp_option.discard_comments_in_macro_exp
+ || gfc_cpp_option.print_include_names
+ || gfc_cpp_option.no_line_commands
+ || gfc_cpp_option.dump_macros
+ || gfc_cpp_option.dump_includes))
gfc_fatal_error("To enable preprocessing, use -cpp");
cpp_in = cpp_create_reader (CLK_GNUC89, NULL, line_table);
- if (!gfc_cpp_enabled())
+ if (!gfc_cpp_enabled ())
return;
gcc_assert (cpp_in);
@@ -462,6 +533,17 @@ gfc_cpp_post_options (void)
cpp_option->print_include_names = gfc_cpp_option.print_include_names;
cpp_option->preprocessed = gfc_option.flag_preprocessed;
+ if (gfc_cpp_makedep ())
+ {
+ cpp_option->deps.style = DEPS_USER;
+ cpp_option->deps.phony_targets = gfc_cpp_option.deps_phony;
+ cpp_option->deps.missing_files = gfc_cpp_option.deps_missing_are_generated;
+
+ /* -MF <arg> overrides -M[M]D. */
+ if (gfc_cpp_option.deps_filename_user)
+ gfc_cpp_option.deps_filename = gfc_cpp_option.deps_filename_user;
+ }
+
if (gfc_cpp_option.working_directory == -1)
gfc_cpp_option.working_directory = (debug_info_level != DINFO_LEVEL_NONE);
@@ -572,6 +654,9 @@ gfc_cpp_init (void)
else
cpp_assert (cpp_in, opt->arg);
}
+ else if (opt->code == OPT_MT || opt->code == OPT_MQ)
+ deps_add_target (cpp_get_deps (cpp_in),
+ opt->arg, opt->code == OPT_MQ);
}
if (gfc_cpp_option.working_directory
@@ -615,14 +700,27 @@ gfc_cpp_done (void)
if (!gfc_cpp_enabled ())
return;
- /* TODO: if dependency tracking was enabled, call
- cpp_finish() here to write dependencies.
+ gcc_assert (cpp_in);
- Use cpp_get_deps() to access the current source's
- dependencies during parsing. Add dependencies using
- the mkdeps-interface (defined in libcpp). */
+ if (gfc_cpp_makedep ())
+ {
+ if (gfc_cpp_option.deps_filename)
+ {
+ FILE *f = fopen (gfc_cpp_option.deps_filename, "w");
+ if (f)
+ {
+ cpp_finish (cpp_in, f);
+ fclose (f);
+ }
+ else
+ gfc_fatal_error ("opening output file %s: %s",
+ gfc_cpp_option.deps_filename,
+ xstrerror (errno));
+ }
+ else
+ cpp_finish (cpp_in, stdout);
+ }
- gcc_assert (cpp_in);
cpp_undef_all (cpp_in);
cpp_clear_file_cache (cpp_in);
}
diff --git a/gcc/fortran/cpp.h b/gcc/fortran/cpp.h
index 54a899f6a8e..556eecbc099 100644
--- a/gcc/fortran/cpp.h
+++ b/gcc/fortran/cpp.h
@@ -24,6 +24,12 @@ bool gfc_cpp_enabled (void);
bool gfc_cpp_preprocess_only (void);
+bool gfc_cpp_makedep (void);
+
+void gfc_cpp_add_dep (const char *name, bool system);
+
+void gfc_cpp_add_target (const char *name);
+
const char *gfc_cpp_temporary_file (void);
diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c
index 9786a860bae..07c3acb9467 100644
--- a/gcc/fortran/decl.c
+++ b/gcc/fortran/decl.c
@@ -1764,7 +1764,7 @@ variable_decl (int elem)
specified in the procedure definition, except that the interface
may specify a procedure that is not pure if the procedure is
defined to be pure(12.3.2). */
- if (current_ts.type == BT_DERIVED
+ if ((current_ts.type == BT_DERIVED || current_ts.type == BT_CLASS)
&& gfc_current_ns->proc_name
&& gfc_current_ns->proc_name->attr.if_source == IFSRC_IFBODY
&& current_ts.u.derived->ns != gfc_current_ns)
@@ -2342,7 +2342,7 @@ gfc_match_decl_type_spec (gfc_typespec *ts, int implicit_flag)
gfc_symbol *sym;
match m;
char c;
- bool seen_deferred_kind;
+ bool seen_deferred_kind, matched_type;
/* A belt and braces check that the typespec is correctly being treated
as a deferred characteristic association. */
@@ -2374,47 +2374,88 @@ gfc_match_decl_type_spec (gfc_typespec *ts, int implicit_flag)
return MATCH_YES;
}
- if (gfc_match (" integer") == MATCH_YES)
+
+ m = gfc_match (" type ( %n", name);
+ matched_type = (m == MATCH_YES);
+
+ if ((matched_type && strcmp ("integer", name) == 0)
+ || (!matched_type && gfc_match (" integer") == MATCH_YES))
{
ts->type = BT_INTEGER;
ts->kind = gfc_default_integer_kind;
goto get_kind;
}
- if (gfc_match (" character") == MATCH_YES)
+ if ((matched_type && strcmp ("character", name) == 0)
+ || (!matched_type && gfc_match (" character") == MATCH_YES))
{
+ if (matched_type
+ && gfc_notify_std (GFC_STD_F2008, "Fortran 2008: TYPE with "
+ "intrinsic-type-spec at %C") == FAILURE)
+ return MATCH_ERROR;
+
ts->type = BT_CHARACTER;
if (implicit_flag == 0)
- return gfc_match_char_spec (ts);
+ m = gfc_match_char_spec (ts);
else
- return MATCH_YES;
+ m = MATCH_YES;
+
+ if (matched_type && m == MATCH_YES && gfc_match_char (')') != MATCH_YES)
+ m = MATCH_ERROR;
+
+ return m;
}
- if (gfc_match (" real") == MATCH_YES)
+ if ((matched_type && strcmp ("real", name) == 0)
+ || (!matched_type && gfc_match (" real") == MATCH_YES))
{
ts->type = BT_REAL;
ts->kind = gfc_default_real_kind;
goto get_kind;
}
- if (gfc_match (" double precision") == MATCH_YES)
+ if ((matched_type
+ && (strcmp ("doubleprecision", name) == 0
+ || (strcmp ("double", name) == 0
+ && gfc_match (" precision") == MATCH_YES)))
+ || (!matched_type && gfc_match (" double precision") == MATCH_YES))
{
+ if (matched_type
+ && gfc_notify_std (GFC_STD_F2008, "Fortran 2008: TYPE with "
+ "intrinsic-type-spec at %C") == FAILURE)
+ return MATCH_ERROR;
+ if (matched_type && gfc_match_char (')') != MATCH_YES)
+ return MATCH_ERROR;
+
ts->type = BT_REAL;
ts->kind = gfc_default_double_kind;
return MATCH_YES;
}
- if (gfc_match (" complex") == MATCH_YES)
+ if ((matched_type && strcmp ("complex", name) == 0)
+ || (!matched_type && gfc_match (" complex") == MATCH_YES))
{
ts->type = BT_COMPLEX;
ts->kind = gfc_default_complex_kind;
goto get_kind;
}
- if (gfc_match (" double complex") == MATCH_YES)
+ if ((matched_type
+ && (strcmp ("doublecomplex", name) == 0
+ || (strcmp ("double", name) == 0
+ && gfc_match (" complex") == MATCH_YES)))
+ || (!matched_type && gfc_match (" double complex") == MATCH_YES))
{
- if (gfc_notify_std (GFC_STD_GNU, "DOUBLE COMPLEX at %C does not "
- "conform to the Fortran 95 standard") == FAILURE)
+ if (gfc_notify_std (GFC_STD_GNU, "Extension: DOUBLE COMPLEX at %C")
+ == FAILURE)
+ return MATCH_ERROR;
+
+ if (matched_type
+ && gfc_notify_std (GFC_STD_F2008, "Fortran 2008: TYPE with "
+ "intrinsic-type-spec at %C") == FAILURE)
+ return MATCH_ERROR;
+
+ if (matched_type && gfc_match_char (')') != MATCH_YES)
return MATCH_ERROR;
ts->type = BT_COMPLEX;
@@ -2422,14 +2463,17 @@ gfc_match_decl_type_spec (gfc_typespec *ts, int implicit_flag)
return MATCH_YES;
}
- if (gfc_match (" logical") == MATCH_YES)
+ if ((matched_type && strcmp ("logical", name) == 0)
+ || (!matched_type && gfc_match (" logical") == MATCH_YES))
{
ts->type = BT_LOGICAL;
ts->kind = gfc_default_logical_kind;
goto get_kind;
}
- m = gfc_match (" type ( %n )", name);
+ if (matched_type)
+ m = gfc_match_char (')');
+
if (m == MATCH_YES)
ts->type = BT_DERIVED;
else
@@ -2490,23 +2534,43 @@ gfc_match_decl_type_spec (gfc_typespec *ts, int implicit_flag)
return MATCH_YES;
get_kind:
+ if (matched_type
+ && gfc_notify_std (GFC_STD_F2008, "Fortran 2008: TYPE with "
+ "intrinsic-type-spec at %C") == FAILURE)
+ return MATCH_ERROR;
+
/* For all types except double, derived and character, look for an
optional kind specifier. MATCH_NO is actually OK at this point. */
if (implicit_flag == 1)
- return MATCH_YES;
+ {
+ if (matched_type && gfc_match_char (')') != MATCH_YES)
+ return MATCH_ERROR;
+
+ return MATCH_YES;
+ }
if (gfc_current_form == FORM_FREE)
{
c = gfc_peek_ascii_char ();
if (!gfc_is_whitespace (c) && c != '*' && c != '('
&& c != ':' && c != ',')
- return MATCH_NO;
+ {
+ if (matched_type && c == ')')
+ {
+ gfc_next_ascii_char ();
+ return MATCH_YES;
+ }
+ return MATCH_NO;
+ }
}
m = gfc_match_kind_spec (ts, false);
if (m == MATCH_NO && ts->type != BT_CHARACTER)
m = gfc_match_old_kind_spec (ts);
+ if (matched_type && gfc_match_char (')') != MATCH_YES)
+ return MATCH_ERROR;
+
/* Defer association of the KIND expression of function results
until after USE and IMPORT statements. */
if ((gfc_current_state () == COMP_NONE && gfc_error_flag_test ())
@@ -2875,8 +2939,8 @@ match_attr_spec (void)
DECL_IN, DECL_OUT, DECL_INOUT, DECL_INTRINSIC, DECL_OPTIONAL,
DECL_PARAMETER, DECL_POINTER, DECL_PROTECTED, DECL_PRIVATE,
DECL_PUBLIC, DECL_SAVE, DECL_TARGET, DECL_VALUE, DECL_VOLATILE,
- DECL_IS_BIND_C, DECL_CODIMENSION, DECL_ASYNCHRONOUS, DECL_NONE,
- GFC_DECL_END /* Sentinel */
+ DECL_IS_BIND_C, DECL_CODIMENSION, DECL_ASYNCHRONOUS, DECL_CONTIGUOUS,
+ DECL_NONE, GFC_DECL_END /* Sentinel */
}
decl_types;
@@ -2939,6 +3003,7 @@ match_attr_spec (void)
}
break;
}
+ break;
case 'b':
/* Try and match the bind(c). */
@@ -2950,8 +3015,24 @@ match_attr_spec (void)
break;
case 'c':
- if (match_string_p ("codimension"))
- d = DECL_CODIMENSION;
+ gfc_next_ascii_char ();
+ if ('o' != gfc_next_ascii_char ())
+ break;
+ switch (gfc_next_ascii_char ())
+ {
+ case 'd':
+ if (match_string_p ("imension"))
+ {
+ d = DECL_CODIMENSION;
+ break;
+ }
+ case 'n':
+ if (match_string_p ("tiguous"))
+ {
+ d = DECL_CONTIGUOUS;
+ break;
+ }
+ }
break;
case 'd':
@@ -3144,6 +3225,9 @@ match_attr_spec (void)
case DECL_CODIMENSION:
attr = "CODIMENSION";
break;
+ case DECL_CONTIGUOUS:
+ attr = "CONTIGUOUS";
+ break;
case DECL_DIMENSION:
attr = "DIMENSION";
break;
@@ -3214,7 +3298,7 @@ match_attr_spec (void)
if (gfc_current_state () == COMP_DERIVED
&& d != DECL_DIMENSION && d != DECL_CODIMENSION
&& d != DECL_POINTER && d != DECL_PRIVATE
- && d != DECL_PUBLIC && d != DECL_NONE)
+ && d != DECL_PUBLIC && d != DECL_CONTIGUOUS && d != DECL_NONE)
{
if (d == DECL_ALLOCATABLE)
{
@@ -3283,6 +3367,15 @@ match_attr_spec (void)
t = gfc_add_codimension (&current_attr, NULL, &seen_at[d]);
break;
+ case DECL_CONTIGUOUS:
+ if (gfc_notify_std (GFC_STD_F2008,
+ "Fortran 2008: CONTIGUOUS attribute at %C")
+ == FAILURE)
+ t = FAILURE;
+ else
+ t = gfc_add_contiguous (&current_attr, NULL, &seen_at[d]);
+ break;
+
case DECL_DIMENSION:
t = gfc_add_dimension (&current_attr, NULL, &seen_at[d]);
break;
@@ -4934,6 +5027,10 @@ gfc_match_entry (void)
if (m != MATCH_YES)
return m;
+ if (gfc_notify_std (GFC_STD_F2008_OBS, "Fortran 2008 obsolescent feature: "
+ "ENTRY statement at %C") == FAILURE)
+ return MATCH_ERROR;
+
state = gfc_current_state ();
if (state != COMP_SUBROUTINE && state != COMP_FUNCTION)
{
@@ -5483,14 +5580,23 @@ gfc_match_end (gfc_statement *st)
block_name = gfc_current_block () == NULL
? NULL : gfc_current_block ()->name;
- if (state == COMP_BLOCK && !strcmp (block_name, "block@"))
- block_name = NULL;
-
- if (state == COMP_CONTAINS || state == COMP_DERIVED_CONTAINS)
+ switch (state)
{
+ case COMP_ASSOCIATE:
+ case COMP_BLOCK:
+ if (!strcmp (block_name, "block@"))
+ block_name = NULL;
+ break;
+
+ case COMP_CONTAINS:
+ case COMP_DERIVED_CONTAINS:
state = gfc_state_stack->previous->state;
block_name = gfc_state_stack->previous->sym == NULL
? NULL : gfc_state_stack->previous->sym->name;
+ break;
+
+ default:
+ break;
}
switch (state)
@@ -5539,6 +5645,12 @@ gfc_match_end (gfc_statement *st)
eos_ok = 0;
break;
+ case COMP_ASSOCIATE:
+ *st = ST_END_ASSOCIATE;
+ target = " associate";
+ eos_ok = 0;
+ break;
+
case COMP_BLOCK:
*st = ST_END_BLOCK;
target = " block";
@@ -5598,7 +5710,14 @@ gfc_match_end (gfc_statement *st)
if (gfc_match_eos () == MATCH_YES)
{
- if (!eos_ok)
+ if (!eos_ok && (*st == ST_END_SUBROUTINE || *st == ST_END_FUNCTION))
+ {
+ if (gfc_notify_std (GFC_STD_F2008, "Fortran 2008: END statement "
+ "instead of %s statement at %L",
+ gfc_ascii_statement (*st), &old_loc) == FAILURE)
+ goto cleanup;
+ }
+ else if (!eos_ok)
{
/* We would have required END [something]. */
gfc_error ("%s statement expected at %L",
@@ -5622,7 +5741,7 @@ gfc_match_end (gfc_statement *st)
if (*st != ST_ENDDO && *st != ST_ENDIF && *st != ST_END_SELECT
&& *st != ST_END_FORALL && *st != ST_END_WHERE && *st != ST_END_BLOCK
- && *st != ST_END_CRITICAL)
+ && *st != ST_END_ASSOCIATE && *st != ST_END_CRITICAL)
return MATCH_YES;
if (!block_name)
@@ -6106,6 +6225,20 @@ gfc_match_codimension (void)
match
+gfc_match_contiguous (void)
+{
+ if (gfc_notify_std (GFC_STD_F2008, "Fortran 2008: CONTIGUOUS statement at %C")
+ == FAILURE)
+ return MATCH_ERROR;
+
+ gfc_clear_attr (&current_attr);
+ current_attr.contiguous = 1;
+
+ return attr_decl ();
+}
+
+
+match
gfc_match_dimension (void)
{
gfc_clear_attr (&current_attr);
@@ -7527,14 +7660,15 @@ match_procedure_in_type (void)
{
char name[GFC_MAX_SYMBOL_LEN + 1];
char target_buf[GFC_MAX_SYMBOL_LEN + 1];
- char* target = NULL;
- gfc_typebound_proc* tb;
+ char* target = NULL, *ifc = NULL;
+ gfc_typebound_proc tb;
bool seen_colons;
bool seen_attrs;
match m;
gfc_symtree* stree;
gfc_namespace* ns;
gfc_symbol* block;
+ int num;
/* Check current state. */
gcc_assert (gfc_state_stack->state == COMP_DERIVED_CONTAINS);
@@ -7559,28 +7693,26 @@ match_procedure_in_type (void)
return MATCH_ERROR;
}
- target = target_buf;
+ ifc = target_buf;
}
/* Construct the data structure. */
- tb = gfc_get_typebound_proc ();
- tb->where = gfc_current_locus;
- tb->is_generic = 0;
+ tb.where = gfc_current_locus;
+ tb.is_generic = 0;
/* Match binding attributes. */
- m = match_binding_attributes (tb, false, false);
+ m = match_binding_attributes (&tb, false, false);
if (m == MATCH_ERROR)
return m;
seen_attrs = (m == MATCH_YES);
- /* Check that attribute DEFERRED is given iff an interface is specified, which
- means target != NULL. */
- if (tb->deferred && !target)
+ /* Check that attribute DEFERRED is given if an interface is specified. */
+ if (tb.deferred && !ifc)
{
gfc_error ("Interface must be specified for DEFERRED binding at %C");
return MATCH_ERROR;
}
- if (target && !tb->deferred)
+ if (ifc && !tb.deferred)
{
gfc_error ("PROCEDURE(interface) at %C should be declared DEFERRED");
return MATCH_ERROR;
@@ -7597,97 +7729,103 @@ match_procedure_in_type (void)
return MATCH_ERROR;
}
- /* Match the binding name. */
- m = gfc_match_name (name);
- if (m == MATCH_ERROR)
- return m;
- if (m == MATCH_NO)
- {
- gfc_error ("Expected binding name at %C");
- return MATCH_ERROR;
- }
-
- /* Try to match the '=> target', if it's there. */
- m = gfc_match (" =>");
- if (m == MATCH_ERROR)
- return m;
- if (m == MATCH_YES)
+ /* Match the binding names. */
+ for(num=1;;num++)
{
- if (tb->deferred)
+ m = gfc_match_name (name);
+ if (m == MATCH_ERROR)
+ return m;
+ if (m == MATCH_NO)
{
- gfc_error ("'=> target' is invalid for DEFERRED binding at %C");
+ gfc_error ("Expected binding name at %C");
return MATCH_ERROR;
}
- if (!seen_colons)
- {
- gfc_error ("'::' needed in PROCEDURE binding with explicit target"
- " at %C");
- return MATCH_ERROR;
- }
+ if (num>1 && gfc_notify_std (GFC_STD_F2008, "Fortran 2008: PROCEDURE list"
+ " at %C") == FAILURE)
+ return MATCH_ERROR;
- m = gfc_match_name (target_buf);
+ /* Try to match the '=> target', if it's there. */
+ target = ifc;
+ m = gfc_match (" =>");
if (m == MATCH_ERROR)
return m;
- if (m == MATCH_NO)
+ if (m == MATCH_YES)
{
- gfc_error ("Expected binding target after '=>' at %C");
- return MATCH_ERROR;
+ if (tb.deferred)
+ {
+ gfc_error ("'=> target' is invalid for DEFERRED binding at %C");
+ return MATCH_ERROR;
+ }
+
+ if (!seen_colons)
+ {
+ gfc_error ("'::' needed in PROCEDURE binding with explicit target"
+ " at %C");
+ return MATCH_ERROR;
+ }
+
+ m = gfc_match_name (target_buf);
+ if (m == MATCH_ERROR)
+ return m;
+ if (m == MATCH_NO)
+ {
+ gfc_error ("Expected binding target after '=>' at %C");
+ return MATCH_ERROR;
+ }
+ target = target_buf;
}
- target = target_buf;
- }
- /* Now we should have the end. */
- m = gfc_match_eos ();
- if (m == MATCH_ERROR)
- return m;
- if (m == MATCH_NO)
- {
- gfc_error ("Junk after PROCEDURE declaration at %C");
- return MATCH_ERROR;
- }
+ /* If no target was found, it has the same name as the binding. */
+ if (!target)
+ target = name;
- /* If no target was found, it has the same name as the binding. */
- if (!target)
- target = name;
+ /* Get the namespace to insert the symbols into. */
+ ns = block->f2k_derived;
+ gcc_assert (ns);
- /* Get the namespace to insert the symbols into. */
- ns = block->f2k_derived;
- gcc_assert (ns);
+ /* If the binding is DEFERRED, check that the containing type is ABSTRACT. */
+ if (tb.deferred && !block->attr.abstract)
+ {
+ gfc_error ("Type '%s' containing DEFERRED binding at %C "
+ "is not ABSTRACT", block->name);
+ return MATCH_ERROR;
+ }
- /* If the binding is DEFERRED, check that the containing type is ABSTRACT. */
- if (tb->deferred && !block->attr.abstract)
- {
- gfc_error ("Type '%s' containing DEFERRED binding at %C is not ABSTRACT",
- block->name);
- return MATCH_ERROR;
- }
+ /* See if we already have a binding with this name in the symtree which
+ would be an error. If a GENERIC already targetted this binding, it may
+ be already there but then typebound is still NULL. */
+ stree = gfc_find_symtree (ns->tb_sym_root, name);
+ if (stree && stree->n.tb)
+ {
+ gfc_error ("There is already a procedure with binding name '%s' for "
+ "the derived type '%s' at %C", name, block->name);
+ return MATCH_ERROR;
+ }
- /* See if we already have a binding with this name in the symtree which would
- be an error. If a GENERIC already targetted this binding, it may be
- already there but then typebound is still NULL. */
- stree = gfc_find_symtree (ns->tb_sym_root, name);
- if (stree && stree->n.tb)
- {
- gfc_error ("There's already a procedure with binding name '%s' for the"
- " derived type '%s' at %C", name, block->name);
- return MATCH_ERROR;
- }
+ /* Insert it and set attributes. */
- /* Insert it and set attributes. */
+ if (!stree)
+ {
+ stree = gfc_new_symtree (&ns->tb_sym_root, name);
+ gcc_assert (stree);
+ }
+ stree->n.tb = gfc_get_typebound_proc (&tb);
- if (!stree)
- {
- stree = gfc_new_symtree (&ns->tb_sym_root, name);
- gcc_assert (stree);
+ if (gfc_get_sym_tree (target, gfc_current_ns, &stree->n.tb->u.specific,
+ false))
+ return MATCH_ERROR;
+ gfc_set_sym_referenced (stree->n.tb->u.specific->n.sym);
+
+ if (gfc_match_eos () == MATCH_YES)
+ return MATCH_YES;
+ if (gfc_match_char (',') != MATCH_YES)
+ goto syntax;
}
- stree->n.tb = tb;
-
- if (gfc_get_sym_tree (target, gfc_current_ns, &tb->u.specific, false))
- return MATCH_ERROR;
- gfc_set_sym_referenced (tb->u.specific->n.sym);
- return MATCH_YES;
+syntax:
+ gfc_error ("Syntax error in PROCEDURE statement at %C");
+ return MATCH_ERROR;
}
@@ -7821,7 +7959,7 @@ gfc_match_generic (void)
}
else
{
- tb = gfc_get_typebound_proc ();
+ tb = gfc_get_typebound_proc (NULL);
tb->where = gfc_current_locus;
tb->access = tbattr.access;
tb->is_generic = 1;
diff --git a/gcc/fortran/dependency.c b/gcc/fortran/dependency.c
index 87f60df8e2a..fcf5b25d350 100644
--- a/gcc/fortran/dependency.c
+++ b/gcc/fortran/dependency.c
@@ -1588,4 +1588,3 @@ gfc_dep_resolver (gfc_ref *lref, gfc_ref *rref)
return fin_dep == GFC_DEP_OVERLAP;
}
-
diff --git a/gcc/fortran/dependency.h b/gcc/fortran/dependency.h
index 6fa0416e2a7..dd786bedaba 100644
--- a/gcc/fortran/dependency.h
+++ b/gcc/fortran/dependency.h
@@ -43,3 +43,4 @@ int gfc_expr_is_one (gfc_expr *, int);
int gfc_dep_resolver(gfc_ref *, gfc_ref *);
int gfc_are_equivalenced_arrays (gfc_expr *, gfc_expr *);
+
diff --git a/gcc/fortran/dump-parse-tree.c b/gcc/fortran/dump-parse-tree.c
index e90b0941885..1a649106f15 100644
--- a/gcc/fortran/dump-parse-tree.c
+++ b/gcc/fortran/dump-parse-tree.c
@@ -598,6 +598,8 @@ show_attr (symbol_attribute *attr)
fputs (" CODIMENSION", dumpfile);
if (attr->dimension)
fputs (" DIMENSION", dumpfile);
+ if (attr->contiguous)
+ fputs (" CONTIGUOUS", dumpfile);
if (attr->external)
fputs (" EXTERNAL", dumpfile);
if (attr->intrinsic)
@@ -794,6 +796,15 @@ show_symbol (gfc_symbol *sym)
fprintf (dumpfile, "symbol %s ", sym->name);
show_typespec (&sym->ts);
+
+ /* If this symbol is an associate-name, show its target expression. */
+ if (sym->assoc)
+ {
+ fputs (" => ", dumpfile);
+ show_expr (sym->assoc->target);
+ fputs (" ", dumpfile);
+ }
+
show_attr (&sym->attr);
if (sym->value)
@@ -853,7 +864,7 @@ show_symbol (gfc_symbol *sym)
}
}
- if (sym->formal_ns)
+ if (sym->formal_ns && (sym->formal_ns->proc_name != sym))
{
show_indent ();
fputs ("Formal namespace", dumpfile);
@@ -1175,6 +1186,7 @@ show_code_node (int level, gfc_code *c)
gfc_filepos *fp;
gfc_inquire *i;
gfc_dt *dt;
+ gfc_namespace *ns;
code_indent (level, c->here);
@@ -1374,6 +1386,22 @@ show_code_node (int level, gfc_code *c)
fputs ("ENDIF", dumpfile);
break;
+ case EXEC_BLOCK:
+ {
+ const char* blocktype;
+ if (c->ext.block.assoc)
+ blocktype = "ASSOCIATE";
+ else
+ blocktype = "BLOCK";
+ show_indent ();
+ fprintf (dumpfile, "%s ", blocktype);
+ ns = c->ext.block.ns;
+ show_namespace (ns);
+ show_indent ();
+ fprintf (dumpfile, "END %s ", blocktype);
+ break;
+ }
+
case EXEC_SELECT:
d = c->block;
fputs ("SELECT CASE ", dumpfile);
@@ -2144,7 +2172,7 @@ show_namespace (gfc_namespace *ns)
fputc ('\n', dumpfile);
fputc ('\n', dumpfile);
- show_code (0, ns->code);
+ show_code (show_level, ns->code);
for (ns = ns->contained; ns; ns = ns->sibling)
{
diff --git a/gcc/fortran/error.c b/gcc/fortran/error.c
index b05e669c370..30928286c98 100644
--- a/gcc/fortran/error.c
+++ b/gcc/fortran/error.c
@@ -471,7 +471,7 @@ error_print (const char *type, const char *format0, va_list argp)
locus *l1, *l2, *loc;
const char *format;
- l1 = l2 = NULL;
+ loc = l1 = l2 = NULL;
have_l1 = 0;
pos = -1;
diff --git a/gcc/fortran/expr.c b/gcc/fortran/expr.c
index b6452054b11..c876fdd7740 100644
--- a/gcc/fortran/expr.c
+++ b/gcc/fortran/expr.c
@@ -4080,3 +4080,105 @@ gfc_has_ultimate_pointer (gfc_expr *e)
else
return false;
}
+
+
+/* Check whether an expression is "simply contiguous", cf. F2008, 6.5.4.
+ Note: A scalar is not regarded as "simply contiguous" by the standard.
+ if bool is not strict, some futher checks are done - for instance,
+ a "(::1)" is accepted. */
+
+bool
+gfc_is_simply_contiguous (gfc_expr *expr, bool strict)
+{
+ bool colon;
+ int i;
+ gfc_array_ref *ar = NULL;
+ gfc_ref *ref, *part_ref = NULL;
+
+ if (expr->expr_type == EXPR_FUNCTION)
+ return expr->value.function.esym
+ ? expr->value.function.esym->result->attr.contiguous : false;
+ else if (expr->expr_type != EXPR_VARIABLE)
+ return false;
+
+ if (expr->rank == 0)
+ return false;
+
+ for (ref = expr->ref; ref; ref = ref->next)
+ {
+ if (ar)
+ return false; /* Array shall be last part-ref. */
+
+ if (ref->type == REF_COMPONENT)
+ part_ref = ref;
+ else if (ref->type == REF_SUBSTRING)
+ return false;
+ else if (ref->u.ar.type != AR_ELEMENT)
+ ar = &ref->u.ar;
+ }
+
+ if ((part_ref && !part_ref->u.c.component->attr.contiguous
+ && part_ref->u.c.component->attr.pointer)
+ || (!part_ref && !expr->symtree->n.sym->attr.contiguous
+ && (expr->symtree->n.sym->attr.pointer
+ || expr->symtree->n.sym->as->type == AS_ASSUMED_SHAPE)))
+ return false;
+
+ if (!ar || ar->type == AR_FULL)
+ return true;
+
+ gcc_assert (ar->type == AR_SECTION);
+
+ /* Check for simply contiguous array */
+ colon = true;
+ for (i = 0; i < ar->dimen; i++)
+ {
+ if (ar->dimen_type[i] == DIMEN_VECTOR)
+ return false;
+
+ if (ar->dimen_type[i] == DIMEN_ELEMENT)
+ {
+ colon = false;
+ continue;
+ }
+
+ gcc_assert (ar->dimen_type[i] == DIMEN_RANGE);
+
+
+ /* If the previous section was not contiguous, that's an error,
+ unless we have effective only one element and checking is not
+ strict. */
+ if (!colon && (strict || !ar->start[i] || !ar->end[i]
+ || ar->start[i]->expr_type != EXPR_CONSTANT
+ || ar->end[i]->expr_type != EXPR_CONSTANT
+ || mpz_cmp (ar->start[i]->value.integer,
+ ar->end[i]->value.integer) != 0))
+ return false;
+
+ /* Following the standard, "(::1)" or - if known at compile time -
+ "(lbound:ubound)" are not simply contigous; if strict
+ is false, they are regarded as simply contiguous. */
+ if (ar->stride[i] && (strict || ar->stride[i]->expr_type != EXPR_CONSTANT
+ || ar->stride[i]->ts.type != BT_INTEGER
+ || mpz_cmp_si (ar->stride[i]->value.integer, 1) != 0))
+ return false;
+
+ if (ar->start[i]
+ && (strict || ar->start[i]->expr_type != EXPR_CONSTANT
+ || !ar->as->lower[i]
+ || ar->as->lower[i]->expr_type != EXPR_CONSTANT
+ || mpz_cmp (ar->start[i]->value.integer,
+ ar->as->lower[i]->value.integer) != 0))
+ colon = false;
+
+ if (ar->end[i]
+ && (strict || ar->end[i]->expr_type != EXPR_CONSTANT
+ || !ar->as->upper[i]
+ || ar->as->upper[i]->expr_type != EXPR_CONSTANT
+ || mpz_cmp (ar->end[i]->value.integer,
+ ar->as->upper[i]->value.integer) != 0))
+ colon = false;
+ }
+
+ return true;
+}
diff --git a/gcc/fortran/f95-lang.c b/gcc/fortran/f95-lang.c
index 14525dc2552..c6af0026ba8 100644
--- a/gcc/fortran/f95-lang.c
+++ b/gcc/fortran/f95-lang.c
@@ -111,6 +111,7 @@ static void gfc_init_ts (void);
#undef LANG_HOOKS_INIT_TS
#undef LANG_HOOKS_OMP_PRIVATIZE_BY_REFERENCE
#undef LANG_HOOKS_OMP_PREDETERMINED_SHARING
+#undef LANG_HOOKS_OMP_REPORT_DECL
#undef LANG_HOOKS_OMP_CLAUSE_DEFAULT_CTOR
#undef LANG_HOOKS_OMP_CLAUSE_COPY_CTOR
#undef LANG_HOOKS_OMP_CLAUSE_ASSIGN_OP
@@ -137,6 +138,7 @@ static void gfc_init_ts (void);
#define LANG_HOOKS_INIT_TS gfc_init_ts
#define LANG_HOOKS_OMP_PRIVATIZE_BY_REFERENCE gfc_omp_privatize_by_reference
#define LANG_HOOKS_OMP_PREDETERMINED_SHARING gfc_omp_predetermined_sharing
+#define LANG_HOOKS_OMP_REPORT_DECL gfc_omp_report_decl
#define LANG_HOOKS_OMP_CLAUSE_DEFAULT_CTOR gfc_omp_clause_default_ctor
#define LANG_HOOKS_OMP_CLAUSE_COPY_CTOR gfc_omp_clause_copy_ctor
#define LANG_HOOKS_OMP_CLAUSE_ASSIGN_OP gfc_omp_clause_assign_op
@@ -350,8 +352,7 @@ getdecls (void)
void
pushlevel (int ignore ATTRIBUTE_UNUSED)
{
- struct binding_level *newlevel
- = (struct binding_level *) ggc_alloc (sizeof (struct binding_level));
+ struct binding_level *newlevel = ggc_alloc_binding_level ();
*newlevel = clear_binding_level;
@@ -754,10 +755,11 @@ gfc_init_builtin_functions (void)
func_longdouble_longdoublep_longdoublep =
build_function_type_list (void_type_node, ptype, ptype, NULL_TREE);
+/* Non-math builtins are defined manually, so they're not included here. */
+#define OTHER_BUILTIN(ID,NAME,TYPE)
+
#include "mathbuiltins.def"
- /* We define these separately as the fortran versions have different
- semantics (they return an integer type) */
gfc_define_builtin ("__builtin_roundl", mfunc_longdouble[0],
BUILT_IN_ROUNDL, "roundl", true);
gfc_define_builtin ("__builtin_round", mfunc_double[0],
diff --git a/gcc/fortran/gfc-internals.texi b/gcc/fortran/gfc-internals.texi
index f01393e3d68..90f90fdac5d 100644
--- a/gcc/fortran/gfc-internals.texi
+++ b/gcc/fortran/gfc-internals.texi
@@ -1,7 +1,7 @@
\input texinfo @c -*-texinfo-*-
@c %**start of header
@setfilename gfc-internals.info
-@set copyrights-gfortran 2007-2010
+@set copyrights-gfortran 2007, 2008, 2009, 2010
@include gcc-common.texi
@@ -35,7 +35,7 @@ Copyright @copyright{} @value{copyrights-gfortran} Free Software Foundation,
Inc.
Permission is granted to copy, distribute and/or modify this document
-under the terms of the GNU Free Documentation License, Version 1.2 or
+under the terms of the GNU Free Documentation License, Version 1.3 or
any later version published by the Free Software Foundation; with the
Invariant Sections being ``Funding Free Software'', the Front-Cover
Texts being (a) (see below), and with the Back-Cover Texts being (b)
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index 9762cddfaa8..0c96bf40e6e 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -205,11 +205,12 @@ arith;
/* Statements. */
typedef enum
{
- ST_ARITHMETIC_IF, ST_ALLOCATE, ST_ATTR_DECL, ST_BACKSPACE,
- ST_BLOCK, ST_BLOCK_DATA,
+ ST_ARITHMETIC_IF, ST_ALLOCATE, ST_ATTR_DECL, ST_ASSOCIATE,
+ ST_BACKSPACE, ST_BLOCK, ST_BLOCK_DATA,
ST_CALL, ST_CASE, ST_CLOSE, ST_COMMON, ST_CONTINUE, ST_CONTAINS, ST_CYCLE,
ST_DATA, ST_DATA_DECL, ST_DEALLOCATE, ST_DO, ST_ELSE, ST_ELSEIF,
- ST_ELSEWHERE, ST_END_BLOCK, ST_END_BLOCK_DATA, ST_ENDDO, ST_IMPLIED_ENDDO,
+ ST_ELSEWHERE, ST_END_ASSOCIATE, ST_END_BLOCK, ST_END_BLOCK_DATA,
+ ST_ENDDO, ST_IMPLIED_ENDDO,
ST_END_FILE, ST_FINAL, ST_FLUSH, ST_END_FORALL, ST_END_FUNCTION, ST_ENDIF,
ST_END_INTERFACE, ST_END_MODULE, ST_END_PROGRAM, ST_END_SELECT,
ST_END_SUBROUTINE, ST_END_WHERE, ST_END_TYPE, ST_ENTRY, ST_EQUIVALENCE,
@@ -664,7 +665,8 @@ typedef struct
unsigned allocatable:1, dimension:1, codimension:1, external:1, intrinsic:1,
optional:1, pointer:1, target:1, value:1, volatile_:1, temporary:1,
dummy:1, result:1, assign:1, threadprivate:1, not_always_present:1,
- implied_index:1, subref_array_pointer:1, proc_pointer:1, asynchronous:1;
+ implied_index:1, subref_array_pointer:1, proc_pointer:1, asynchronous:1,
+ contiguous:1;
/* For CLASS containers, the pointer attribute is sometimes set internally
even though it was not directly specified. In this case, keep the
@@ -1201,6 +1203,9 @@ typedef struct gfc_symbol
char binding_label[GFC_MAX_BINDING_LABEL_LEN + 1];
/* Store a reference to the common_block, if this symbol is in one. */
struct gfc_common_head *common_block;
+
+ /* Link to corresponding association-list if this is an associate name. */
+ struct gfc_association_list *assoc;
}
gfc_symbol;
@@ -1665,10 +1670,13 @@ typedef struct gfc_expr
it from recurring. */
unsigned int error : 1;
- /* Mark and expression where a user operator has been substituted by
+ /* Mark an expression where a user operator has been substituted by
a function call in interface.c(gfc_extend_expr). */
unsigned int user_operator : 1;
+ /* Mark an expression as being a MOLD argument of ALLOCATE. */
+ unsigned int mold : 1;
+
/* If an expression comes from a Hollerith constant or compile-time
evaluation of a transfer statement, it may have a prescribed target-
memory representation, and these cannot always be backformed from
@@ -1974,6 +1982,25 @@ typedef struct gfc_forall_iterator
gfc_forall_iterator;
+/* Linked list to store associations in an ASSOCIATE statement. */
+
+typedef struct gfc_association_list
+{
+ struct gfc_association_list *next;
+
+ /* Whether this is association to a variable that can be changed; otherwise,
+ it's association to an expression and the name may not be used as
+ lvalue. */
+ unsigned variable:1;
+
+ char name[GFC_MAX_SYMBOL_LEN + 1];
+ gfc_symtree *st; /* Symtree corresponding to name. */
+ gfc_expr *target;
+}
+gfc_association_list;
+#define gfc_get_association_list() XCNEW (gfc_association_list)
+
+
/* Executable statements that fill gfc_code structures. */
typedef enum
{
@@ -2026,6 +2053,13 @@ typedef struct gfc_code
}
alloc;
+ struct
+ {
+ gfc_namespace *ns;
+ gfc_association_list *assoc;
+ }
+ block;
+
gfc_open *open;
gfc_close *close;
gfc_filepos *filepos;
@@ -2040,13 +2074,12 @@ typedef struct gfc_code
const char *omp_name;
gfc_namelist *omp_namelist;
bool omp_bool;
- gfc_namespace *ns;
}
ext; /* Points to additional structures required by statement */
- /* Backend_decl is used for cycle and break labels in do loops, and
- probably for other constructs as well, once we translate them. */
- tree backend_decl;
+ /* Cycle and break labels in do loops. */
+ tree cycle_label;
+ tree exit_label;
}
gfc_code;
@@ -2405,6 +2438,7 @@ gfc_try gfc_add_attribute (symbol_attribute *, locus *);
gfc_try gfc_add_ext_attribute (symbol_attribute *, ext_attr_id_t, locus *);
gfc_try gfc_add_allocatable (symbol_attribute *, locus *);
gfc_try gfc_add_codimension (symbol_attribute *, const char *, locus *);
+gfc_try gfc_add_contiguous (symbol_attribute *, const char *, locus *);
gfc_try gfc_add_dimension (symbol_attribute *, const char *, locus *);
gfc_try gfc_add_external (symbol_attribute *, locus *);
gfc_try gfc_add_intrinsic (symbol_attribute *, locus *);
@@ -2513,7 +2547,7 @@ void gfc_free_dt_list (void);
gfc_gsymbol *gfc_get_gsymbol (const char *);
gfc_gsymbol *gfc_find_gsymbol (gfc_gsymbol *, const char *);
-gfc_typebound_proc* gfc_get_typebound_proc (void);
+gfc_typebound_proc* gfc_get_typebound_proc (gfc_typebound_proc*);
gfc_symbol* gfc_get_derived_super_type (gfc_symbol*);
gfc_symbol* gfc_get_ultimate_derived_super_type (gfc_symbol*);
bool gfc_type_is_extension_of (gfc_symbol *, gfc_symbol *);
@@ -2582,6 +2616,7 @@ void gfc_free_actual_arglist (gfc_actual_arglist *);
gfc_actual_arglist *gfc_copy_actual_arglist (gfc_actual_arglist *);
const char *gfc_extract_int (gfc_expr *, int *);
bool is_subref_array (gfc_expr *);
+bool gfc_is_simply_contiguous (gfc_expr *, bool);
gfc_expr *gfc_build_conversion (gfc_expr *);
void gfc_free_ref_list (gfc_ref *);
@@ -2647,6 +2682,7 @@ gfc_code *gfc_get_code (void);
gfc_code *gfc_append_code (gfc_code *, gfc_code *);
void gfc_free_statement (gfc_code *);
void gfc_free_statements (gfc_code *);
+void gfc_free_association_list (gfc_association_list *);
/* resolve.c */
gfc_try gfc_resolve_expr (gfc_expr *);
@@ -2719,6 +2755,7 @@ void gfc_set_current_interface_head (gfc_interface *);
gfc_symtree* gfc_find_sym_in_symtree (gfc_symbol*);
bool gfc_arglist_matches_symbol (gfc_actual_arglist**, gfc_symbol*);
bool gfc_check_operator_interface (gfc_symbol*, gfc_intrinsic_op, locus);
+int gfc_has_vector_subscript (gfc_expr*);
/* io.c */
extern gfc_st_label format_asterisk;
diff --git a/gcc/fortran/gfortran.texi b/gcc/fortran/gfortran.texi
index a7f6fbac220..8d43c8bf8a4 100644
--- a/gcc/fortran/gfortran.texi
+++ b/gcc/fortran/gfortran.texi
@@ -1,7 +1,7 @@
\input texinfo @c -*-texinfo-*-
@c %**start of header
@setfilename gfortran.info
-@set copyrights-gfortran 1999-2010
+@set copyrights-gfortran 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
@include gcc-common.texi
@@ -80,7 +80,7 @@
Copyright @copyright{} @value{copyrights-gfortran} Free Software Foundation, Inc.
Permission is granted to copy, distribute and/or modify this document
-under the terms of the GNU Free Documentation License, Version 1.2 or
+under the terms of the GNU Free Documentation License, Version 1.3 or
any later version published by the Free Software Foundation; with the
Invariant Sections being ``Funding Free Software'', the Front-Cover
Texts being (a) (see below), and with the Back-Cover Texts being (b)
@@ -1515,10 +1515,10 @@ to Cray pointers and pointees. Pointees may not have the
@code{ALLOCATABLE}, @code{INTENT}, @code{OPTIONAL}, @code{DUMMY},
@code{TARGET}, @code{INTRINSIC}, or @code{POINTER} attributes. Pointers
may not have the @code{DIMENSION}, @code{POINTER}, @code{TARGET},
-@code{ALLOCATABLE}, @code{EXTERNAL}, or @code{INTRINSIC} attributes.
-Pointees may not occur in more than one pointer statement. A pointee
-cannot be a pointer. Pointees cannot occur in equivalence, common, or
-data statements.
+@code{ALLOCATABLE}, @code{EXTERNAL}, or @code{INTRINSIC} attributes, nor
+may they be function results. Pointees may not occur in more than one
+pointer statement. A pointee cannot be a pointer. Pointees cannot occur
+in equivalence, common, or data statements.
A Cray pointer may also point to a function or a subroutine. For
example, the following excerpt is valid:
@@ -1719,7 +1719,8 @@ code that uses them running with the GNU Fortran compiler.
@c * TYPE and ACCEPT I/O Statements::
@c * .XOR. operator::
@c * CARRIAGECONTROL, DEFAULTFILE, DISPOSE and RECORDTYPE I/O specifiers::
-@c * Omitted arguments in procedure call:
+@c * Omitted arguments in procedure call::
+* Alternate complex function syntax::
@end menu
@@ -1894,6 +1895,18 @@ c
@end smallexample
+@node Alternate complex function syntax
+@subsection Alternate complex function syntax
+@cindex Complex function
+
+Some Fortran compilers, including @command{g77}, let the user declare
+complex functions with the syntax @code{COMPLEX FUNCTION name*16()}, as
+well as @code{COMPLEX*16 FUNCTION name()}. Both are non-standard, legacy
+extensions. @command{gfortran} accepts the latter form, which is more
+common, but not the former.
+
+
+
@c ---------------------------------------------------------------------
@c Mixed-Language Programming
@c ---------------------------------------------------------------------
@@ -2322,9 +2335,10 @@ if e.g. an input-output edit descriptor is invalid in a given standard.
Possible values are (bitwise or-ed) @code{GFC_STD_F77} (1),
@code{GFC_STD_F95_OBS} (2), @code{GFC_STD_F95_DEL} (4), @code{GFC_STD_F95}
(8), @code{GFC_STD_F2003} (16), @code{GFC_STD_GNU} (32),
-@code{GFC_STD_LEGACY} (64), and @code{GFC_STD_F2008} (128).
-Default: @code{GFC_STD_F95_OBS | GFC_STD_F95_DEL | GFC_STD_F2003
-| GFC_STD_F2008 | GFC_STD_F95 | GFC_STD_F77 | GFC_STD_GNU | GFC_STD_LEGACY}.
+@code{GFC_STD_LEGACY} (64), @code{GFC_STD_F2008} (128), and
+@code{GFC_STD_F2008_OBS} (256). Default: @code{GFC_STD_F95_OBS
+| GFC_STD_F95_DEL | GFC_STD_F95 | GFC_STD_F2003 | GFC_STD_F2008
+| GFC_STD_F2008_OBS | GFC_STD_F77 | GFC_STD_GNU | GFC_STD_LEGACY}.
@item @var{option}[1] @tab Standard-warning flag; prints a warning to
standard error. Default: @code{GFC_STD_F95_DEL | GFC_STD_LEGACY}.
@item @var{option}[2] @tab If non zero, enable pedantic checking.
@@ -2639,9 +2653,6 @@ J3 Fortran 95 standard.
User-specified alignment rules for structures.
@item
-Flag to generate @code{Makefile} info.
-
-@item
Automatically extend single precision constants to double.
@item
diff --git a/gcc/fortran/gfortranspec.c b/gcc/fortran/gfortranspec.c
index 1f67acc1513..61f1547c87c 100644
--- a/gcc/fortran/gfortranspec.c
+++ b/gcc/fortran/gfortranspec.c
@@ -244,7 +244,7 @@ append_arg (const char *arg)
}
if (g77_newargc == newargsize)
- fatal_error ("overflowed output arg list for '%s'", arg);
+ fatal_error ("overflowed output arg list for %qs", arg);
g77_newargv[g77_newargc++] = arg;
}
@@ -402,7 +402,7 @@ For more information about these matters, see the file named COPYING\n\n"));
if (i + skip < argc)
i += skip;
else
- fatal_error ("argument to '%s' missing", argv[i]);
+ fatal_error ("argument to %qs missing", argv[i]);
}
if ((n_outfiles != 0) && (n_infiles == 0))
@@ -424,35 +424,6 @@ For more information about these matters, see the file named COPYING\n\n"));
continue;
}
- if ((argv[i][0] == '-') && (argv[i][1] == 'M'))
- {
- char *p;
-
- warning (0, "using -M <directory> is deprecated, use -J instead");
- if (argv[i][2] == '\0')
- {
- if (i+1 < argc)
- {
- p = XNEWVEC (char, strlen (argv[i + 1]) + 3);
- p[0] = '-';
- p[1] = 'J';
- strcpy (&p[2], argv[i + 1]);
- i++;
- }
- else
- fatal_error ("argument to '%s' missing", argv[i]);
- }
- else
- {
- p = XNEWVEC (char, strlen (argv[i]) + 1);
- p[0] = '-';
- p[1] = 'J';
- strcpy (&p[2], argv[i] + 2);
- }
- append_arg (p);
- continue;
- }
-
if ((argv[i][0] == '-') && (argv[i][1] != 'l'))
{
/* Not a filename or library. */
diff --git a/gcc/fortran/interface.c b/gcc/fortran/interface.c
index 99ade9d273d..587b09cdf8c 100644
--- a/gcc/fortran/interface.c
+++ b/gcc/fortran/interface.c
@@ -1376,6 +1376,30 @@ compare_pointer (gfc_symbol *formal, gfc_expr *actual)
}
+/* Emit clear error messages for rank mismatch. */
+
+static void
+argument_rank_mismatch (const char *name, locus *where,
+ int rank1, int rank2)
+{
+ if (rank1 == 0)
+ {
+ gfc_error ("Rank mismatch in argument '%s' at %L "
+ "(scalar and rank-%d)", name, where, rank2);
+ }
+ else if (rank2 == 0)
+ {
+ gfc_error ("Rank mismatch in argument '%s' at %L "
+ "(rank-%d and scalar)", name, where, rank1);
+ }
+ else
+ {
+ gfc_error ("Rank mismatch in argument '%s' at %L "
+ "(rank-%d and rank-%d)", name, where, rank1, rank2);
+ }
+}
+
+
/* Given a symbol of a formal argument list and an expression, see if
the two are compatible as arguments. Returns nonzero if
compatible, zero if not compatible. */
@@ -1435,6 +1459,16 @@ compare_parameter (gfc_symbol *formal, gfc_expr *actual,
return 1;
}
+ /* F2008, C1241. */
+ if (formal->attr.pointer && formal->attr.contiguous
+ && !gfc_is_simply_contiguous (actual, true))
+ {
+ if (where)
+ gfc_error ("Actual argument to contiguous pointer dummy '%s' at %L "
+ "must be simply contigous", formal->name, &actual->where);
+ return 0;
+ }
+
if ((actual->expr_type != EXPR_NULL || actual->ts.type != BT_UNKNOWN)
&& !gfc_compare_types (&formal->ts, &actual->ts))
{
@@ -1502,6 +1536,34 @@ compare_parameter (gfc_symbol *formal, gfc_expr *actual,
: actual->symtree->n.sym->as->corank);
return 0;
}
+
+ /* F2008, 12.5.2.8. */
+ if (formal->attr.dimension
+ && (formal->attr.contiguous || formal->as->type != AS_ASSUMED_SHAPE)
+ && !gfc_is_simply_contiguous (actual, true))
+ {
+ if (where)
+ gfc_error ("Actual argument to '%s' at %L must be simply "
+ "contiguous", formal->name, &actual->where);
+ return 0;
+ }
+ }
+
+ /* F2008, C1239/C1240. */
+ if (actual->expr_type == EXPR_VARIABLE
+ && (actual->symtree->n.sym->attr.asynchronous
+ || actual->symtree->n.sym->attr.volatile_)
+ && (formal->attr.asynchronous || formal->attr.volatile_)
+ && actual->rank && !gfc_is_simply_contiguous (actual, true)
+ && ((formal->as->type != AS_ASSUMED_SHAPE && !formal->attr.pointer)
+ || formal->attr.contiguous))
+ {
+ if (where)
+ gfc_error ("Dummy argument '%s' has to be a pointer or assumed-shape "
+ "array without CONTIGUOUS attribute - as actual argument at"
+ " %L is not simply contiguous and both are ASYNCHRONOUS "
+ "or VOLATILE", formal->name, &actual->where);
+ return 0;
}
if (symbol_rank (formal) == actual->rank)
@@ -1521,9 +1583,8 @@ compare_parameter (gfc_symbol *formal, gfc_expr *actual,
&& gfc_is_coindexed (actual)))
{
if (where)
- gfc_error ("Rank mismatch in argument '%s' at %L (%d and %d)",
- formal->name, &actual->where, symbol_rank (formal),
- actual->rank);
+ argument_rank_mismatch (formal->name, &actual->where,
+ symbol_rank (formal), actual->rank);
return 0;
}
else if (actual->rank != 0 && (is_elemental || formal->attr.dimension))
@@ -1562,9 +1623,8 @@ compare_parameter (gfc_symbol *formal, gfc_expr *actual,
else if (ref == NULL && actual->expr_type != EXPR_NULL)
{
if (where)
- gfc_error ("Rank mismatch in argument '%s' at %L (%d and %d)",
- formal->name, &actual->where, symbol_rank (formal),
- actual->rank);
+ argument_rank_mismatch (formal->name, &actual->where,
+ symbol_rank (formal), actual->rank);
return 0;
}
@@ -1821,8 +1881,8 @@ get_expr_storage_size (gfc_expr *e)
which has a vector subscript. If it has, one is returned,
otherwise zero. */
-static int
-has_vector_subscript (gfc_expr *e)
+int
+gfc_has_vector_subscript (gfc_expr *e)
{
int i;
gfc_ref *ref;
@@ -2133,13 +2193,15 @@ compare_actual_formal (gfc_actual_arglist **ap, gfc_formal_arglist *formal,
if ((f->sym->attr.intent == INTENT_OUT
|| f->sym->attr.intent == INTENT_INOUT
- || f->sym->attr.volatile_)
- && has_vector_subscript (a->expr))
+ || f->sym->attr.volatile_
+ || f->sym->attr.asynchronous)
+ && gfc_has_vector_subscript (a->expr))
{
if (where)
- gfc_error ("Array-section actual argument with vector subscripts "
- "at %L is incompatible with INTENT(OUT), INTENT(INOUT) "
- "or VOLATILE attribute of the dummy argument '%s'",
+ gfc_error ("Array-section actual argument with vector "
+ "subscripts at %L is incompatible with INTENT(OUT), "
+ "INTENT(INOUT), VOLATILE or ASYNCHRONOUS attribute "
+ "of the dummy argument '%s'",
&a->expr->where, f->sym->name);
return 0;
}
diff --git a/gcc/fortran/intrinsic.c b/gcc/fortran/intrinsic.c
index a92b5b54519..833fd30beb1 100644
--- a/gcc/fortran/intrinsic.c
+++ b/gcc/fortran/intrinsic.c
@@ -1354,7 +1354,7 @@ add_functions (void)
make_generic ("bit_size", GFC_ISYM_BIT_SIZE, GFC_STD_F95);
add_sym_2 ("btest", GFC_ISYM_BTEST, CLASS_ELEMENTAL, ACTUAL_NO, BT_LOGICAL, dl, GFC_STD_F95,
- gfc_check_btest, gfc_simplify_btest, gfc_resolve_btest,
+ gfc_check_bitfcn, gfc_simplify_btest, gfc_resolve_btest,
i, BT_INTEGER, di, REQUIRED, pos, BT_INTEGER, di, REQUIRED);
make_generic ("btest", GFC_ISYM_BTEST, GFC_STD_F95);
@@ -1738,7 +1738,7 @@ add_functions (void)
make_generic ("iargc", GFC_ISYM_IARGC, GFC_STD_GNU);
add_sym_2 ("ibclr", GFC_ISYM_IBCLR, CLASS_ELEMENTAL, ACTUAL_NO, BT_INTEGER, di, GFC_STD_F95,
- gfc_check_ibclr, gfc_simplify_ibclr, gfc_resolve_ibclr,
+ gfc_check_bitfcn, gfc_simplify_ibclr, gfc_resolve_ibclr,
i, BT_INTEGER, di, REQUIRED, pos, BT_INTEGER, di, REQUIRED);
make_generic ("ibclr", GFC_ISYM_IBCLR, GFC_STD_F95);
@@ -1751,7 +1751,7 @@ add_functions (void)
make_generic ("ibits", GFC_ISYM_IBITS, GFC_STD_F95);
add_sym_2 ("ibset", GFC_ISYM_IBSET, CLASS_ELEMENTAL, ACTUAL_NO, BT_INTEGER, di, GFC_STD_F95,
- gfc_check_ibset, gfc_simplify_ibset, gfc_resolve_ibset,
+ gfc_check_bitfcn, gfc_simplify_ibset, gfc_resolve_ibset,
i, BT_INTEGER, di, REQUIRED, pos, BT_INTEGER, di, REQUIRED);
make_generic ("ibset", GFC_ISYM_IBSET, GFC_STD_F95);
@@ -2375,10 +2375,11 @@ add_functions (void)
make_generic ("selected_int_kind", GFC_ISYM_SI_KIND, GFC_STD_F95);
- add_sym_2 ("selected_real_kind", GFC_ISYM_SR_KIND, CLASS_TRANSFORMATIONAL, ACTUAL_NO, BT_INTEGER, di,
+ add_sym_3 ("selected_real_kind", GFC_ISYM_SR_KIND, CLASS_TRANSFORMATIONAL, ACTUAL_NO, BT_INTEGER, di,
GFC_STD_F95, gfc_check_selected_real_kind,
gfc_simplify_selected_real_kind, NULL,
- p, BT_INTEGER, di, OPTIONAL, r, BT_INTEGER, di, OPTIONAL);
+ p, BT_INTEGER, di, OPTIONAL, r, BT_INTEGER, di, OPTIONAL,
+ "radix", BT_INTEGER, di, OPTIONAL);
make_generic ("selected_real_kind", GFC_ISYM_SR_KIND, GFC_STD_F95);
@@ -4022,58 +4023,67 @@ gfc_convert_type_warn (gfc_expr *expr, gfc_typespec *ts, int eflag, int wflag)
}
else if (wflag)
{
- /* Two modes of warning:
- - gfc_option.warn_conversion tries to be more intelligent
- about the warnings raised and omits those where smaller
- kinds are promoted to larger ones without change in the
- value
- - gfc_option.warn_conversion_extra does not take the kinds
- into account and also warns for coversions like
- REAL(4) -> REAL(8)
-
- NOTE: Possible enhancement for warn_conversion
- If converting from a smaller to a larger kind, check if the
- value is constant and if yes, whether the value still fits
- in the smaller kind. If yes, omit the warning.
- */
-
- /* If the types are the same (but not LOGICAL), and if from-kind
- is larger than to-kind, this may indicate a loss of precision.
- The same holds for conversions from REAL to COMPLEX. */
- if (((from_ts.type == ts->type && from_ts.type != BT_LOGICAL)
- && ((gfc_option.warn_conversion && from_ts.kind > ts->kind)
- || gfc_option.warn_conversion_extra))
- || ((from_ts.type == BT_REAL && ts->type == BT_COMPLEX)
- && ((gfc_option.warn_conversion && from_ts.kind > ts->kind)
- || gfc_option.warn_conversion_extra)))
- gfc_warning_now ("Possible change of value in conversion "
- "from %s to %s at %L", gfc_typename (&from_ts),
- gfc_typename (ts), &expr->where);
-
- /* If INTEGER is converted to REAL/COMPLEX, this is generally ok if
- the kind of the INTEGER value is less or equal to the kind of the
- REAL/COMPLEX one. Otherwise the value may not fit.
- Assignment of an overly large integer constant also generates
- an overflow error with range checking. */
- else if (from_ts.type == BT_INTEGER
- && (ts->type == BT_REAL || ts->type == BT_COMPLEX)
- && ((gfc_option.warn_conversion && from_ts.kind > ts->kind)
- || gfc_option.warn_conversion_extra))
- gfc_warning_now ("Possible change of value in conversion "
- "from %s to %s at %L", gfc_typename (&from_ts),
- gfc_typename (ts), &expr->where);
-
- /* If REAL/COMPLEX is converted to INTEGER, or COMPLEX is converted
- to REAL we almost certainly have a loss of digits, regardless of
- the respective kinds. */
- else if ((((from_ts.type == BT_REAL || from_ts.type == BT_COMPLEX)
- && ts->type == BT_INTEGER)
- || (from_ts.type == BT_COMPLEX && ts->type == BT_REAL))
- && (gfc_option.warn_conversion
- || gfc_option.warn_conversion_extra))
- gfc_warning_now ("Possible change of value in conversion from "
- "%s to %s at %L", gfc_typename (&from_ts),
- gfc_typename (ts), &expr->where);
+ if (gfc_option.flag_range_check
+ && expr->expr_type == EXPR_CONSTANT
+ && from_ts.type == ts->type)
+ {
+ /* Do nothing. Constants of the same type are range-checked
+ elsewhere. If a value too large for the target type is
+ assigned, an error is generated. Not checking here avoids
+ duplications of warnings/errors.
+ If range checking was disabled, but -Wconversion enabled,
+ a non range checked warning is generated below. */
+ }
+ else if (from_ts.type == BT_LOGICAL || ts->type == BT_LOGICAL)
+ {
+ /* Do nothing. This block exists only to simplify the other
+ else-if expressions.
+ LOGICAL <> LOGICAL no warning, independent of kind values
+ LOGICAL <> INTEGER extension, warned elsewhere
+ LOGICAL <> REAL invalid, error generated elsewhere
+ LOGICAL <> COMPLEX invalid, error generated elsewhere */
+ }
+ else if (from_ts.type == ts->type
+ || (from_ts.type == BT_INTEGER && ts->type == BT_REAL)
+ || (from_ts.type == BT_INTEGER && ts->type == BT_COMPLEX)
+ || (from_ts.type == BT_REAL && ts->type == BT_COMPLEX))
+ {
+ /* Larger kinds can hold values of smaller kinds without problems.
+ Hence, only warn if target kind is smaller than the source
+ kind - or if -Wconversion-extra is specified. */
+ if (gfc_option.warn_conversion_extra)
+ gfc_warning_now ("Conversion from %s to %s at %L",
+ gfc_typename (&from_ts), gfc_typename (ts),
+ &expr->where);
+ else if (gfc_option.warn_conversion
+ && from_ts.kind > ts->kind)
+ gfc_warning_now ("Possible change of value in conversion "
+ "from %s to %s at %L", gfc_typename (&from_ts),
+ gfc_typename (ts), &expr->where);
+ }
+ else if ((from_ts.type == BT_REAL && ts->type == BT_INTEGER)
+ || (from_ts.type == BT_COMPLEX && ts->type == BT_INTEGER)
+ || (from_ts.type == BT_COMPLEX && ts->type == BT_REAL))
+ {
+ /* Conversion from REAL/COMPLEX to INTEGER or COMPLEX to REAL
+ usually comes with a loss of information, regardless of kinds. */
+ if (gfc_option.warn_conversion_extra
+ || gfc_option.warn_conversion)
+ gfc_warning_now ("Possible change of value in conversion "
+ "from %s to %s at %L", gfc_typename (&from_ts),
+ gfc_typename (ts), &expr->where);
+ }
+ else if (from_ts.type == BT_HOLLERITH || ts->type == BT_HOLLERITH)
+ {
+ /* If HOLLERITH is involved, all bets are off. */
+ if (gfc_option.warn_conversion_extra
+ || gfc_option.warn_conversion)
+ gfc_warning_now ("Conversion from %s to %s at %L",
+ gfc_typename (&from_ts), gfc_typename (ts),
+ &expr->where);
+ }
+ else
+ gcc_unreachable ();
}
/* Insert a pre-resolved function call to the right function. */
diff --git a/gcc/fortran/intrinsic.h b/gcc/fortran/intrinsic.h
index 2e1b95eb375..919f09e90b4 100644
--- a/gcc/fortran/intrinsic.h
+++ b/gcc/fortran/intrinsic.h
@@ -40,7 +40,7 @@ gfc_try gfc_check_associated (gfc_expr *, gfc_expr *);
gfc_try gfc_check_atan_2 (gfc_expr *, gfc_expr *);
gfc_try gfc_check_atan2 (gfc_expr *, gfc_expr *);
gfc_try gfc_check_besn (gfc_expr *, gfc_expr *);
-gfc_try gfc_check_btest (gfc_expr *, gfc_expr *);
+gfc_try gfc_check_bitfcn (gfc_expr *, gfc_expr *);
gfc_try gfc_check_char (gfc_expr *, gfc_expr *);
gfc_try gfc_check_chdir (gfc_expr *);
gfc_try gfc_check_chmod (gfc_expr *, gfc_expr *);
@@ -74,9 +74,7 @@ gfc_try gfc_check_hypot (gfc_expr *, gfc_expr *);
gfc_try gfc_check_i (gfc_expr *);
gfc_try gfc_check_iand (gfc_expr *, gfc_expr *);
gfc_try gfc_check_and (gfc_expr *, gfc_expr *);
-gfc_try gfc_check_ibclr (gfc_expr *, gfc_expr *);
gfc_try gfc_check_ibits (gfc_expr *, gfc_expr *, gfc_expr *);
-gfc_try gfc_check_ibset (gfc_expr *, gfc_expr *);
gfc_try gfc_check_ichar_iachar (gfc_expr *, gfc_expr *);
gfc_try gfc_check_idnint (gfc_expr *);
gfc_try gfc_check_ieor (gfc_expr *, gfc_expr *);
@@ -128,7 +126,7 @@ gfc_try gfc_check_second_sub (gfc_expr *);
gfc_try gfc_check_secnds (gfc_expr *);
gfc_try gfc_check_selected_char_kind (gfc_expr *);
gfc_try gfc_check_selected_int_kind (gfc_expr *);
-gfc_try gfc_check_selected_real_kind (gfc_expr *, gfc_expr *);
+gfc_try gfc_check_selected_real_kind (gfc_expr *, gfc_expr *, gfc_expr *);
gfc_try gfc_check_set_exponent (gfc_expr *, gfc_expr *);
gfc_try gfc_check_shape (gfc_expr *);
gfc_try gfc_check_size (gfc_expr *, gfc_expr *, gfc_expr *);
@@ -324,7 +322,7 @@ gfc_expr *gfc_simplify_scale (gfc_expr *, gfc_expr *);
gfc_expr *gfc_simplify_scan (gfc_expr *, gfc_expr *, gfc_expr *, gfc_expr *);
gfc_expr *gfc_simplify_selected_char_kind (gfc_expr *);
gfc_expr *gfc_simplify_selected_int_kind (gfc_expr *);
-gfc_expr *gfc_simplify_selected_real_kind (gfc_expr *, gfc_expr *);
+gfc_expr *gfc_simplify_selected_real_kind (gfc_expr *, gfc_expr *, gfc_expr *);
gfc_expr *gfc_simplify_set_exponent (gfc_expr *, gfc_expr *);
gfc_expr *gfc_simplify_sign (gfc_expr *, gfc_expr *);
gfc_expr *gfc_simplify_shape (gfc_expr *);
diff --git a/gcc/fortran/intrinsic.texi b/gcc/fortran/intrinsic.texi
index bc0ea8dce3a..06c6793b2c4 100644
--- a/gcc/fortran/intrinsic.texi
+++ b/gcc/fortran/intrinsic.texi
@@ -5,7 +5,7 @@ This is part of the GNU Fortran manual.
For copying conditions, see the file gfortran.texi.
Permission is granted to copy, distribute and/or modify this document
-under the terms of the GNU Free Documentation License, Version 1.2 or
+under the terms of the GNU Free Documentation License, Version 1.3 or
any later version published by the Free Software Foundation; with the
Invariant Sections being ``Funding Free Software'', the Front-Cover
Texts being (a) (see below), and with the Back-Cover Texts being (b)
@@ -4185,6 +4185,44 @@ Subroutine
Beginning with the Fortran 2003 standard, there is a @code{FLUSH}
statement that should be preferred over the @code{FLUSH} intrinsic.
+The @code{FLUSH} intrinsic and the Fortran 2003 @code{FLUSH} statement
+have identical effect: they flush the runtime library's I/O buffer so
+that the data becomes visible to other processes. This does not guarantee
+that the data is committed to disk.
+
+On POSIX systems, you can request that all data is transferred to the
+storage device by calling the @code{fsync} function, with the POSIX file
+descriptor of the I/O unit as argument (retrieved with GNU intrinsic
+@code{FNUM}). The following example shows how:
+
+@smallexample
+ ! Declare the interface for POSIX fsync function
+ interface
+ function fsync (fd) bind(c,name="fsync")
+ use iso_c_binding, only: c_int
+ integer(c_int), value :: fd
+ integer(c_int) :: fsync
+ end function fsync
+ end interface
+
+ ! Variable declaration
+ integer :: ret
+
+ ! Opening unit 10
+ open (10,file="foo")
+
+ ! ...
+ ! Perform I/O on unit 10
+ ! ...
+
+ ! Flush and sync
+ flush(10)
+ ret = fsync(fnum(10))
+
+ ! Handle possible error
+ if (ret /= 0) stop "Error calling FSYNC"
+@end smallexample
+
@end table
@@ -8678,6 +8716,9 @@ Inquiry function
The return value is of type @code{INTEGER} and of the default integer
kind.
+@item @emph{See also}:
+@ref{SELECTED_REAL_KIND}, @ref{RANGE}
+
@item @emph{Example}:
@smallexample
program prec_and_range
@@ -8823,6 +8864,9 @@ Inquiry function
The return value is a scalar of type @code{INTEGER} and of the default
integer kind.
+@item @emph{See also}:
+@ref{SELECTED_REAL_KIND}
+
@item @emph{Example}:
@smallexample
program test_radix
@@ -9060,6 +9104,9 @@ or @code{COMPLEX}.
The return value is of type @code{INTEGER} and of the default integer
kind.
+@item @emph{See also}:
+@ref{SELECTED_REAL_KIND}, @ref{PRECISION}
+
@item @emph{Example}:
See @code{PRECISION} for an example.
@end table
@@ -9638,45 +9685,58 @@ end program large_integers
@fnindex SELECTED_REAL_KIND
@cindex real kind
@cindex kind, real
+@cindex radix, real
@table @asis
@item @emph{Description}:
@code{SELECTED_REAL_KIND(P,R)} returns the kind value of a real data type
-with decimal precision of at least @code{P} digits and exponent
-range greater at least @code{R}.
+with decimal precision of at least @code{P} digits, exponent range of
+at least @code{R}, and with a radix of @code{RADIX}.
@item @emph{Standard}:
-Fortran 95 and later
+Fortran 95 and later, with @code{RADIX} Fortran 2008 or later
@item @emph{Class}:
Transformational function
@item @emph{Syntax}:
-@code{RESULT = SELECTED_REAL_KIND([P, R])}
+@code{RESULT = SELECTED_REAL_KIND([P, R, RADIX])}
@item @emph{Arguments}:
@multitable @columnfractions .15 .70
@item @var{P} @tab (Optional) shall be a scalar and of type @code{INTEGER}.
@item @var{R} @tab (Optional) shall be a scalar and of type @code{INTEGER}.
+@item @var{RADIX} @tab (Optional) shall be a scalar and of type @code{INTEGER}.
@end multitable
-At least one argument shall be present.
+Before Fortran 2008, at least one of the arguments @var{R} or @var{P} shall
+be present; since Fortran 2008, they are assumed to be zero if absent.
@item @emph{Return value}:
@code{SELECTED_REAL_KIND} returns the value of the kind type parameter of
-a real data type with decimal precision of at least @code{P} digits and a
-decimal exponent range of at least @code{R}. If more than one real data
-type meet the criteria, the kind of the data type with the smallest
-decimal precision is returned. If no real data type matches the criteria,
-the result is
+a real data type with decimal precision of at least @code{P} digits, a
+decimal exponent range of at least @code{R}, and with the requested
+@code{RADIX}. If the @code{RADIX} parameter is absent, real kinds with
+any radix can be returned. If more than one real data type meet the
+criteria, the kind of the data type with the smallest decimal precision
+is returned. If no real data type matches the criteria, the result is
@table @asis
@item -1 if the processor does not support a real data type with a
-precision greater than or equal to @code{P}
+precision greater than or equal to @code{P}, but the @code{R} and
+@code{RADIX} requirements can be fulfilled
@item -2 if the processor does not support a real type with an exponent
-range greater than or equal to @code{R}
-@item -3 if neither is supported.
+range greater than or equal to @code{R}, but @code{P} and @code{RADIX}
+are fulfillable
+@item -3 if @code{RADIX} but not @code{P} and @code{R} requirements
+are fulfillable
+@item -4 if @code{RADIX} and either @code{P} or @code{R} requirements
+are fulfillable
+@item -5 if there is no real type with the given @code{RADIX}
@end table
+@item @emph{See also}:
+@ref{PRECISION}, @ref{RANGE}, @ref{RADIX}
+
@item @emph{Example}:
@smallexample
program real_kinds
diff --git a/gcc/fortran/invoke.texi b/gcc/fortran/invoke.texi
index 78c1c436561..1dfd3bdd920 100644
--- a/gcc/fortran/invoke.texi
+++ b/gcc/fortran/invoke.texi
@@ -9,7 +9,7 @@ Copyright @copyright{} 2004, 2005, 2006, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
Permission is granted to copy, distribute and/or modify this document
-under the terms of the GNU Free Documentation License, Version 1.2 or
+under the terms of the GNU Free Documentation License, Version 1.3 or
any later version published by the Free Software Foundation; with the
Invariant Sections being ``Funding Free Software'', the Front-Cover
Texts being (a) (see below), and with the Back-Cover Texts being (b)
@@ -148,8 +148,7 @@ and warnings}.
@item Directory Options
@xref{Directory Options,,Options for directory search}.
-@gccoptlist{-I@var{dir} -J@var{dir} -M@var{dir} @gol
--fintrinsic-modules-path @var{dir}}
+@gccoptlist{-I@var{dir} -J@var{dir} -fintrinsic-modules-path @var{dir}}
@item Link Options
@xref{Link Options,,Options for influencing the linking step}.
@@ -964,7 +963,6 @@ gcc,Using the GNU Compiler Collection (GCC)}, for information on the
@option{-I} option.
@item -J@var{dir}
-@item -M@var{dir}
@opindex @code{J}@var{dir}
@opindex @code{M}@var{dir}
@cindex paths, search
@@ -975,8 +973,6 @@ statement.
The default is the current directory.
-@option{-M} is deprecated to avoid conflicts with existing GCC options.
-
@item -fintrinsic-modules-path @var{dir}
@opindex @code{fintrinsic-modules-path} @var{dir}
@cindex paths, search
diff --git a/gcc/fortran/io.c b/gcc/fortran/io.c
index dc20bc2ffb6..f9a6d7b1240 100644
--- a/gcc/fortran/io.c
+++ b/gcc/fortran/io.c
@@ -730,7 +730,7 @@ data_desc:
t = format_lex ();
if (t == FMT_ERROR)
goto fail;
- if (gfc_option.allow_std < GFC_STD_F2003 && t != FMT_COMMA
+ if (!(gfc_option.allow_std & GFC_STD_F2003) && t != FMT_COMMA
&& t != FMT_F && t != FMT_E && t != FMT_EN && t != FMT_ES
&& t != FMT_D && t != FMT_G && t != FMT_RPAREN && t != FMT_SLASH)
{
diff --git a/gcc/fortran/lang-specs.h b/gcc/fortran/lang-specs.h
index a622dcb1a6a..4fe24de1927 100644
--- a/gcc/fortran/lang-specs.h
+++ b/gcc/fortran/lang-specs.h
@@ -28,7 +28,7 @@
%{O*} %{undef}"
/* Options that f951 should know about, even if not preprocessing. */
-#define CPP_FORWARD_OPTIONS "%{i*} %{I*}"
+#define CPP_FORWARD_OPTIONS "%{i*} %{I*} %{M*}"
#define F951_CPP_OPTIONS "%{!nocpp: -cpp %g.f90 %{E} %(cpp_unique_options) \
%{E|M|MM:%(cpp_debug_options) " CPP_ONLY_OPTIONS \
diff --git a/gcc/fortran/lang.opt b/gcc/fortran/lang.opt
index c1a86ddab08..1f3ef9d0574 100644
--- a/gcc/fortran/lang.opt
+++ b/gcc/fortran/lang.opt
@@ -56,6 +56,42 @@ J
Fortran Joined Separate
-J<directory> Put MODULE files in 'directory'
+M
+Fortran
+; Documented in C
+
+MD
+Fortran Separate
+; Documented in C
+
+MF
+Fortran Joined Separate
+; Documented in C
+
+MG
+Fortran
+; Documented in C
+
+MM
+Fortran
+; Documented in C
+
+MMD
+Fortran Separate
+; Documented in C
+
+MP
+Fortran
+; Documented in C
+
+MT
+Fortran Joined Separate
+; Documented in C
+
+MQ
+Fortran Joined Separate
+; Documented in C
+
P
Fortran
; Documented in C
@@ -369,7 +405,7 @@ Fortran
Append a second underscore if the name already contains an underscore
fshort-enums
-Fortran
+Fortran Var(flag_short_enums) VarExists
; Documented in C
fsign-zero
diff --git a/gcc/fortran/libgfortran.h b/gcc/fortran/libgfortran.h
index 85bd43df98c..d9216d30149 100644
--- a/gcc/fortran/libgfortran.h
+++ b/gcc/fortran/libgfortran.h
@@ -23,15 +23,16 @@ along with GCC; see the file COPYING3. If not see
Note that no features were obsoleted nor deleted in F2003.
Please remember to keep those definitions in sync with
gfortran.texi. */
-#define GFC_STD_F2008 (1<<7) /* New in F2008. */
-#define GFC_STD_LEGACY (1<<6) /* Backward compatibility. */
-#define GFC_STD_GNU (1<<5) /* GNU Fortran extension. */
-#define GFC_STD_F2003 (1<<4) /* New in F2003. */
-#define GFC_STD_F95 (1<<3) /* New in F95. */
-#define GFC_STD_F95_DEL (1<<2) /* Deleted in F95. */
-#define GFC_STD_F95_OBS (1<<1) /* Obsolescent in F95. */
-#define GFC_STD_F77 (1<<0) /* Included in F77, but not deleted or
- obsolescent in later standards. */
+#define GFC_STD_F2008_OBS (1<<8) /* Obsolescent in F2008. */
+#define GFC_STD_F2008 (1<<7) /* New in F2008. */
+#define GFC_STD_LEGACY (1<<6) /* Backward compatibility. */
+#define GFC_STD_GNU (1<<5) /* GNU Fortran extension. */
+#define GFC_STD_F2003 (1<<4) /* New in F2003. */
+#define GFC_STD_F95 (1<<3) /* New in F95. */
+#define GFC_STD_F95_DEL (1<<2) /* Deleted in F95. */
+#define GFC_STD_F95_OBS (1<<1) /* Obsolescent in F95. */
+#define GFC_STD_F77 (1<<0) /* Included in F77, but not deleted or
+ obsolescent in later standards. */
/* Bitmasks for the various FPE that can be enabled. */
diff --git a/gcc/fortran/match.c b/gcc/fortran/match.c
index 2cbac0200fd..92c4da0a4b5 100644
--- a/gcc/fortran/match.c
+++ b/gcc/fortran/match.c
@@ -1797,6 +1797,98 @@ gfc_match_block (void)
}
+/* Match an ASSOCIATE statement. */
+
+match
+gfc_match_associate (void)
+{
+ if (gfc_match_label () == MATCH_ERROR)
+ return MATCH_ERROR;
+
+ if (gfc_match (" associate") != MATCH_YES)
+ return MATCH_NO;
+
+ /* Match the association list. */
+ if (gfc_match_char ('(') != MATCH_YES)
+ {
+ gfc_error ("Expected association list at %C");
+ return MATCH_ERROR;
+ }
+ new_st.ext.block.assoc = NULL;
+ while (true)
+ {
+ gfc_association_list* newAssoc = gfc_get_association_list ();
+ gfc_association_list* a;
+
+ /* Match the next association. */
+ if (gfc_match (" %n => %e", newAssoc->name, &newAssoc->target)
+ != MATCH_YES)
+ {
+ gfc_error ("Expected association at %C");
+ goto assocListError;
+ }
+
+ /* Check that the current name is not yet in the list. */
+ for (a = new_st.ext.block.assoc; a; a = a->next)
+ if (!strcmp (a->name, newAssoc->name))
+ {
+ gfc_error ("Duplicate name '%s' in association at %C",
+ newAssoc->name);
+ goto assocListError;
+ }
+
+ /* The target expression must not be coindexed. */
+ if (gfc_is_coindexed (newAssoc->target))
+ {
+ gfc_error ("Association target at %C must not be coindexed");
+ goto assocListError;
+ }
+
+ /* The target is a variable (and may be used as lvalue) if it's an
+ EXPR_VARIABLE and does not have vector-subscripts. */
+ newAssoc->variable = (newAssoc->target->expr_type == EXPR_VARIABLE
+ && !gfc_has_vector_subscript (newAssoc->target));
+
+ /* Put it into the list. */
+ newAssoc->next = new_st.ext.block.assoc;
+ new_st.ext.block.assoc = newAssoc;
+
+ /* Try next one or end if closing parenthesis is found. */
+ gfc_gobble_whitespace ();
+ if (gfc_peek_char () == ')')
+ break;
+ if (gfc_match_char (',') != MATCH_YES)
+ {
+ gfc_error ("Expected ')' or ',' at %C");
+ return MATCH_ERROR;
+ }
+
+ continue;
+
+assocListError:
+ gfc_free (newAssoc);
+ goto error;
+ }
+ if (gfc_match_char (')') != MATCH_YES)
+ {
+ /* This should never happen as we peek above. */
+ gcc_unreachable ();
+ }
+
+ if (gfc_match_eos () != MATCH_YES)
+ {
+ gfc_error ("Junk after ASSOCIATE statement at %C");
+ goto error;
+ }
+
+ return MATCH_YES;
+
+error:
+ gfc_free_association_list (new_st.ext.block.assoc);
+ return MATCH_ERROR;
+}
+
+
/* Match a DO statement. */
match
@@ -2693,16 +2785,16 @@ match
gfc_match_allocate (void)
{
gfc_alloc *head, *tail;
- gfc_expr *stat, *errmsg, *tmp, *source;
+ gfc_expr *stat, *errmsg, *tmp, *source, *mold;
gfc_typespec ts;
gfc_symbol *sym;
match m;
locus old_locus;
- bool saw_stat, saw_errmsg, saw_source, b1, b2, b3;
+ bool saw_stat, saw_errmsg, saw_source, saw_mold, b1, b2, b3;
head = tail = NULL;
- stat = errmsg = source = tmp = NULL;
- saw_stat = saw_errmsg = saw_source = false;
+ stat = errmsg = source = mold = tmp = NULL;
+ saw_stat = saw_errmsg = saw_source = saw_mold = false;
if (gfc_match_char ('(') != MATCH_YES)
goto syntax;
@@ -2895,6 +2987,38 @@ alloc_opt_list:
goto alloc_opt_list;
}
+ m = gfc_match (" mold = %e", &tmp);
+ if (m == MATCH_ERROR)
+ goto cleanup;
+ if (m == MATCH_YES)
+ {
+ if (gfc_notify_std (GFC_STD_F2008, "Fortran 2008: MOLD tag at %L",
+ &tmp->where) == FAILURE)
+ goto cleanup;
+
+ /* Check F08:C636. */
+ if (saw_mold)
+ {
+ gfc_error ("Redundant MOLD tag found at %L ", &tmp->where);
+ goto cleanup;
+ }
+
+ /* Check F08:C637. */
+ if (ts.type != BT_UNKNOWN)
+ {
+ gfc_error ("MOLD tag at %L conflicts with the typespec at %L",
+ &tmp->where, &old_locus);
+ goto cleanup;
+ }
+
+ mold = tmp;
+ saw_mold = true;
+ mold->mold = 1;
+
+ if (gfc_match_char (',') == MATCH_YES)
+ goto alloc_opt_list;
+ }
+
gfc_gobble_whitespace ();
if (gfc_peek_char () == ')')
@@ -2905,10 +3029,21 @@ alloc_opt_list:
if (gfc_match (" )%t") != MATCH_YES)
goto syntax;
+ /* Check F08:C637. */
+ if (source && mold)
+ {
+ gfc_error ("MOLD tag at %L conflicts with SOURCE tag at %L",
+ &mold->where, &source->where);
+ goto cleanup;
+ }
+
new_st.op = EXEC_ALLOCATE;
new_st.expr1 = stat;
new_st.expr2 = errmsg;
- new_st.expr3 = source;
+ if (source)
+ new_st.expr3 = source;
+ else
+ new_st.expr3 = mold;
new_st.ext.alloc.list = head;
new_st.ext.alloc.ts = ts;
@@ -2921,7 +3056,8 @@ cleanup:
gfc_free_expr (errmsg);
gfc_free_expr (source);
gfc_free_expr (stat);
- gfc_free_expr (tmp);
+ gfc_free_expr (mold);
+ if (tmp && tmp->expr_type) gfc_free_expr (tmp);
gfc_free_alloc_list (head);
return MATCH_ERROR;
}
@@ -4361,7 +4497,7 @@ gfc_match_select_type (void)
new_st.op = EXEC_SELECT_TYPE;
new_st.expr1 = expr1;
new_st.expr2 = expr2;
- new_st.ext.ns = gfc_current_ns;
+ new_st.ext.block.ns = gfc_current_ns;
select_type_push (expr1->symtree->n.sym);
diff --git a/gcc/fortran/match.h b/gcc/fortran/match.h
index 049f3d3285c..501049e1220 100644
--- a/gcc/fortran/match.h
+++ b/gcc/fortran/match.h
@@ -69,6 +69,7 @@ match gfc_match_else (void);
match gfc_match_elseif (void);
match gfc_match_critical (void);
match gfc_match_block (void);
+match gfc_match_associate (void);
match gfc_match_do (void);
match gfc_match_cycle (void);
match gfc_match_exit (void);
@@ -167,6 +168,7 @@ void gfc_set_constant_character_len (int, gfc_expr *, int);
match gfc_match_allocatable (void);
match gfc_match_asynchronous (void);
match gfc_match_codimension (void);
+match gfc_match_contiguous (void);
match gfc_match_dimension (void);
match gfc_match_external (void);
match gfc_match_gcc_attributes (void);
diff --git a/gcc/fortran/mathbuiltins.def b/gcc/fortran/mathbuiltins.def
index 3bedc1a6ba5..2d6e9677d62 100644
--- a/gcc/fortran/mathbuiltins.def
+++ b/gcc/fortran/mathbuiltins.def
@@ -51,3 +51,20 @@ DEFINE_MATH_BUILTIN (ERFC, "erfc", 0)
DEFINE_MATH_BUILTIN (TGAMMA,"tgamma", 0)
DEFINE_MATH_BUILTIN (LGAMMA,"lgamma", 0)
DEFINE_MATH_BUILTIN (HYPOT, "hypot", 1)
+
+/* OTHER_BUILTIN (CODE, NAME, PROTOTYPE_TYPE)
+ For floating-point builtins that do not directly correspond to a
+ Fortran intrinsic. This is used to map the different variants (float,
+ double and long double) and to build the quad-precision decls. */
+OTHER_BUILTIN (CABS, "cabs", cabs)
+OTHER_BUILTIN (COPYSIGN, "copysign", 2)
+OTHER_BUILTIN (FABS, "fabs", 1)
+OTHER_BUILTIN (FMOD, "fmod", 2)
+OTHER_BUILTIN (FREXP, "frexp", frexp)
+OTHER_BUILTIN (HUGE_VAL, "huge_val", 0)
+OTHER_BUILTIN (LLROUND, "llround", llround)
+OTHER_BUILTIN (LROUND, "lround", lround)
+OTHER_BUILTIN (NEXTAFTER, "nextafter", 2)
+OTHER_BUILTIN (ROUND, "round", 1)
+OTHER_BUILTIN (SCALBN, "scalbn", scalbn)
+OTHER_BUILTIN (TRUNC, "trunc", 1)
diff --git a/gcc/fortran/module.c b/gcc/fortran/module.c
index 9bdee2a60f0..b42a9e8c1d1 100644
--- a/gcc/fortran/module.c
+++ b/gcc/fortran/module.c
@@ -74,6 +74,7 @@ along with GCC; see the file COPYING3. If not see
#include "parse.h" /* FIXME */
#include "md5.h"
#include "constructor.h"
+#include "cpp.h"
#define MODULE_EXTENSION ".mod"
@@ -1674,7 +1675,7 @@ typedef enum
AB_POINTER_COMP, AB_PRIVATE_COMP, AB_VALUE, AB_VOLATILE, AB_PROTECTED,
AB_IS_BIND_C, AB_IS_C_INTEROP, AB_IS_ISO_C, AB_ABSTRACT, AB_ZERO_COMP,
AB_IS_CLASS, AB_PROCEDURE, AB_PROC_POINTER, AB_ASYNCHRONOUS, AB_CODIMENSION,
- AB_COARRAY_COMP, AB_VTYPE, AB_VTAB
+ AB_COARRAY_COMP, AB_VTYPE, AB_VTAB, AB_CONTIGUOUS
}
ab_attribute;
@@ -1684,6 +1685,7 @@ static const mstring attr_bits[] =
minit ("ASYNCHRONOUS", AB_ASYNCHRONOUS),
minit ("DIMENSION", AB_DIMENSION),
minit ("CODIMENSION", AB_CODIMENSION),
+ minit ("CONTIGUOUS", AB_CONTIGUOUS),
minit ("EXTERNAL", AB_EXTERNAL),
minit ("INTRINSIC", AB_INTRINSIC),
minit ("OPTIONAL", AB_OPTIONAL),
@@ -1806,6 +1808,8 @@ mio_symbol_attribute (symbol_attribute *attr)
MIO_NAME (ab_attribute) (AB_DIMENSION, attr_bits);
if (attr->codimension)
MIO_NAME (ab_attribute) (AB_CODIMENSION, attr_bits);
+ if (attr->contiguous)
+ MIO_NAME (ab_attribute) (AB_CONTIGUOUS, attr_bits);
if (attr->external)
MIO_NAME (ab_attribute) (AB_EXTERNAL, attr_bits);
if (attr->intrinsic)
@@ -1914,6 +1918,9 @@ mio_symbol_attribute (symbol_attribute *attr)
case AB_CODIMENSION:
attr->codimension = 1;
break;
+ case AB_CONTIGUOUS:
+ attr->contiguous = 1;
+ break;
case AB_EXTERNAL:
attr->external = 1;
break;
@@ -3323,7 +3330,7 @@ mio_typebound_proc (gfc_typebound_proc** proc)
if (iomode == IO_INPUT)
{
- *proc = gfc_get_typebound_proc ();
+ *proc = gfc_get_typebound_proc (NULL);
(*proc)->where = gfc_current_locus;
}
gcc_assert (*proc);
@@ -5120,6 +5127,9 @@ gfc_dump_module (const char *name, int dump_flag)
return;
}
+ if (gfc_cpp_makedep ())
+ gfc_cpp_add_target (filename);
+
/* Write the module to the temporary file. */
module_fp = fopen (filename_tmp, "w");
if (module_fp == NULL)
diff --git a/gcc/fortran/openmp.c b/gcc/fortran/openmp.c
index 6a56515298e..0e25bf48cb3 100644
--- a/gcc/fortran/openmp.c
+++ b/gcc/fortran/openmp.c
@@ -845,11 +845,13 @@ resolve_omp_clauses (gfc_code *code)
for (list = 0; list < OMP_LIST_NUM; list++)
if (list != OMP_LIST_FIRSTPRIVATE && list != OMP_LIST_LASTPRIVATE)
for (n = omp_clauses->lists[list]; n; n = n->next)
- if (n->sym->mark)
- gfc_error ("Symbol '%s' present on multiple clauses at %L",
- n->sym->name, &code->loc);
- else
- n->sym->mark = 1;
+ {
+ if (n->sym->mark)
+ gfc_error ("Symbol '%s' present on multiple clauses at %L",
+ n->sym->name, &code->loc);
+ else
+ n->sym->mark = 1;
+ }
gcc_assert (OMP_LIST_LASTPRIVATE == OMP_LIST_FIRSTPRIVATE + 1);
for (list = OMP_LIST_FIRSTPRIVATE; list <= OMP_LIST_LASTPRIVATE; list++)
@@ -862,22 +864,24 @@ resolve_omp_clauses (gfc_code *code)
}
for (n = omp_clauses->lists[OMP_LIST_FIRSTPRIVATE]; n; n = n->next)
- if (n->sym->mark)
- gfc_error ("Symbol '%s' present on multiple clauses at %L",
- n->sym->name, &code->loc);
- else
- n->sym->mark = 1;
-
+ {
+ if (n->sym->mark)
+ gfc_error ("Symbol '%s' present on multiple clauses at %L",
+ n->sym->name, &code->loc);
+ else
+ n->sym->mark = 1;
+ }
for (n = omp_clauses->lists[OMP_LIST_LASTPRIVATE]; n; n = n->next)
n->sym->mark = 0;
for (n = omp_clauses->lists[OMP_LIST_LASTPRIVATE]; n; n = n->next)
- if (n->sym->mark)
- gfc_error ("Symbol '%s' present on multiple clauses at %L",
- n->sym->name, &code->loc);
- else
- n->sym->mark = 1;
-
+ {
+ if (n->sym->mark)
+ gfc_error ("Symbol '%s' present on multiple clauses at %L",
+ n->sym->name, &code->loc);
+ else
+ n->sym->mark = 1;
+ }
for (list = 0; list < OMP_LIST_NUM; list++)
if ((n = omp_clauses->lists[list]) != NULL)
{
diff --git a/gcc/fortran/options.c b/gcc/fortran/options.c
index 6c6ccb10461..af537a1e70e 100644
--- a/gcc/fortran/options.c
+++ b/gcc/fortran/options.c
@@ -48,7 +48,7 @@ set_default_std_flags (void)
{
gfc_option.allow_std = GFC_STD_F95_OBS | GFC_STD_F95_DEL
| GFC_STD_F2003 | GFC_STD_F2008 | GFC_STD_F95 | GFC_STD_F77
- | GFC_STD_GNU | GFC_STD_LEGACY;
+ | GFC_STD_F2008_OBS | GFC_STD_GNU | GFC_STD_LEGACY;
gfc_option.warn_std = GFC_STD_F95_DEL | GFC_STD_LEGACY;
}
@@ -541,10 +541,6 @@ gfc_handle_option (size_t scode, const char *arg, int value,
int result = 1;
enum opt_code code = (enum opt_code) scode;
- /* Ignore file names. */
- if (code == N_OPTS)
- return 1;
-
if (gfc_cpp_handle_option (scode, arg, value) == 1)
return 1;
@@ -861,7 +857,8 @@ gfc_handle_option (size_t scode, const char *arg, int value,
break;
case OPT_std_f95:
- gfc_option.allow_std = GFC_STD_F95_OBS | GFC_STD_F95 | GFC_STD_F77;
+ gfc_option.allow_std = GFC_STD_F95_OBS | GFC_STD_F95 | GFC_STD_F77
+ | GFC_STD_F2008_OBS;
gfc_option.warn_std = GFC_STD_F95_OBS;
gfc_option.max_continue_fixed = 19;
gfc_option.max_continue_free = 39;
@@ -872,7 +869,7 @@ gfc_handle_option (size_t scode, const char *arg, int value,
case OPT_std_f2003:
gfc_option.allow_std = GFC_STD_F95_OBS | GFC_STD_F77
- | GFC_STD_F2003 | GFC_STD_F95;
+ | GFC_STD_F2003 | GFC_STD_F95 | GFC_STD_F2008_OBS;
gfc_option.warn_std = GFC_STD_F95_OBS;
gfc_option.max_identifier_length = 63;
gfc_option.warn_ampersand = 1;
@@ -881,8 +878,8 @@ gfc_handle_option (size_t scode, const char *arg, int value,
case OPT_std_f2008:
gfc_option.allow_std = GFC_STD_F95_OBS | GFC_STD_F77
- | GFC_STD_F2003 | GFC_STD_F95 | GFC_STD_F2008;
- gfc_option.warn_std = GFC_STD_F95_OBS;
+ | GFC_STD_F2003 | GFC_STD_F95 | GFC_STD_F2008 | GFC_STD_F2008_OBS;
+ gfc_option.warn_std = GFC_STD_F95_OBS | GFC_STD_F2008_OBS;
gfc_option.max_identifier_length = 63;
gfc_option.warn_ampersand = 1;
gfc_option.warn_tabs = 0;
@@ -902,7 +899,7 @@ gfc_handle_option (size_t scode, const char *arg, int value,
break;
case OPT_fshort_enums:
- flag_short_enums = 1;
+ /* Handled in language-independent code. */
break;
case OPT_fconvert_little_endian:
@@ -938,7 +935,7 @@ gfc_handle_option (size_t scode, const char *arg, int value,
break;
case OPT_frecursive:
- gfc_option.flag_recursive = 1;
+ gfc_option.flag_recursive = value;
break;
case OPT_falign_commons:
diff --git a/gcc/fortran/parse.c b/gcc/fortran/parse.c
index 7fc35418bec..50f795723eb 100644
--- a/gcc/fortran/parse.c
+++ b/gcc/fortran/parse.c
@@ -139,6 +139,7 @@ decode_specification_statement (void)
case 'c':
match ("codimension", gfc_match_codimension, ST_ATTR_DECL);
+ match ("contiguous", gfc_match_contiguous, ST_ATTR_DECL);
break;
case 'd':
@@ -292,7 +293,7 @@ decode_statement (void)
gfc_undo_symbols ();
gfc_current_locus = old_locus;
- /* Check for the IF, DO, SELECT, WHERE, FORALL, CRITICAL, and BLOCK
+ /* Check for the IF, DO, SELECT, WHERE, FORALL, CRITICAL, BLOCK and ASSOCIATE
statements, which might begin with a block label. The match functions for
these statements are unusual in that their keyword is not seen before
the matcher is called. */
@@ -314,6 +315,7 @@ decode_statement (void)
match (NULL, gfc_match_do, ST_DO);
match (NULL, gfc_match_block, ST_BLOCK);
+ match (NULL, gfc_match_associate, ST_ASSOCIATE);
match (NULL, gfc_match_critical, ST_CRITICAL);
match (NULL, gfc_match_select, ST_SELECT_CASE);
match (NULL, gfc_match_select_type, ST_SELECT_TYPE);
@@ -345,6 +347,7 @@ decode_statement (void)
match ("call", gfc_match_call, ST_CALL);
match ("close", gfc_match_close, ST_CLOSE);
match ("continue", gfc_match_continue, ST_CONTINUE);
+ match ("contiguous", gfc_match_contiguous, ST_ATTR_DECL);
match ("cycle", gfc_match_cycle, ST_CYCLE);
match ("case", gfc_match_case, ST_CASE);
match ("common", gfc_match_common, ST_COMMON);
@@ -714,7 +717,9 @@ next_free (void)
if (at_bol && c == ';')
{
- gfc_error_now ("Semicolon at %C needs to be preceded by statement");
+ if (!(gfc_option.allow_std & GFC_STD_F2008))
+ gfc_error_now ("Fortran 2008: Semicolon at %C without preceding "
+ "statement");
gfc_next_ascii_char (); /* Eat up the semicolon. */
return ST_NONE;
}
@@ -850,7 +855,11 @@ next_fixed (void)
if (c == ';')
{
- gfc_error_now ("Semicolon at %C needs to be preceded by statement");
+ if (digit_flag)
+ gfc_error_now ("Semicolon at %C needs to be preceded by statement");
+ else if (!(gfc_option.allow_std & GFC_STD_F2008))
+ gfc_error_now ("Fortran 2008: Semicolon at %C without preceding "
+ "statement");
return ST_NONE;
}
@@ -949,7 +958,7 @@ next_statement (void)
/* Statements that mark other executable statements. */
#define case_exec_markers case ST_DO: case ST_FORALL_BLOCK: \
- case ST_IF_BLOCK: case ST_BLOCK: \
+ case ST_IF_BLOCK: case ST_BLOCK: case ST_ASSOCIATE: \
case ST_WHERE_BLOCK: case ST_SELECT_CASE: case ST_SELECT_TYPE: \
case ST_OMP_PARALLEL: \
case ST_OMP_PARALLEL_SECTIONS: case ST_OMP_SECTIONS: case ST_OMP_ORDERED: \
@@ -970,7 +979,7 @@ next_statement (void)
#define case_end case ST_END_BLOCK_DATA: case ST_END_FUNCTION: \
case ST_END_PROGRAM: case ST_END_SUBROUTINE: \
- case ST_END_BLOCK
+ case ST_END_BLOCK: case ST_END_ASSOCIATE
/* Push a new state onto the stack. */
@@ -1155,6 +1164,9 @@ gfc_ascii_statement (gfc_statement st)
case ST_ALLOCATE:
p = "ALLOCATE";
break;
+ case ST_ASSOCIATE:
+ p = "ASSOCIATE";
+ break;
case ST_ATTR_DECL:
p = _("attribute declaration");
break;
@@ -1215,6 +1227,9 @@ gfc_ascii_statement (gfc_statement st)
case ST_ELSEWHERE:
p = "ELSEWHERE";
break;
+ case ST_END_ASSOCIATE:
+ p = "END ASSOCIATE";
+ break;
case ST_END_BLOCK:
p = "END BLOCK";
break;
@@ -3160,7 +3175,8 @@ parse_block_construct (void)
my_ns = gfc_build_block_ns (gfc_current_ns);
new_st.op = EXEC_BLOCK;
- new_st.ext.ns = my_ns;
+ new_st.ext.block.ns = my_ns;
+ new_st.ext.block.assoc = NULL;
accept_statement (ST_BLOCK);
push_state (&s, COMP_BLOCK, my_ns->proc_name);
@@ -3173,6 +3189,92 @@ parse_block_construct (void)
}
+/* Parse an ASSOCIATE construct. This is essentially a BLOCK construct
+ behind the scenes with compiler-generated variables. */
+
+static void
+parse_associate (void)
+{
+ gfc_namespace* my_ns;
+ gfc_state_data s;
+ gfc_statement st;
+ gfc_association_list* a;
+ gfc_code* assignTail;
+
+ gfc_notify_std (GFC_STD_F2003, "Fortran 2003: ASSOCIATE construct at %C");
+
+ my_ns = gfc_build_block_ns (gfc_current_ns);
+
+ new_st.op = EXEC_BLOCK;
+ new_st.ext.block.ns = my_ns;
+ gcc_assert (new_st.ext.block.assoc);
+
+ /* Add all associations to expressions as BLOCK variables, and create
+ assignments to them giving their values. */
+ gfc_current_ns = my_ns;
+ assignTail = NULL;
+ for (a = new_st.ext.block.assoc; a; a = a->next)
+ if (!a->variable)
+ {
+ gfc_code* newAssign;
+
+ if (gfc_get_sym_tree (a->name, NULL, &a->st, false))
+ gcc_unreachable ();
+
+ /* Note that in certain cases, the target-expression's type is not yet
+ known and so we have to adapt the symbol's ts also during resolution
+ for these cases. */
+ a->st->n.sym->ts = a->target->ts;
+ a->st->n.sym->attr.flavor = FL_VARIABLE;
+ a->st->n.sym->assoc = a;
+ gfc_set_sym_referenced (a->st->n.sym);
+
+ /* Create the assignment to calculate the expression and set it. */
+ newAssign = gfc_get_code ();
+ newAssign->op = EXEC_ASSIGN;
+ newAssign->loc = gfc_current_locus;
+ newAssign->expr1 = gfc_get_variable_expr (a->st);
+ newAssign->expr2 = a->target;
+
+ /* Hang it in. */
+ if (assignTail)
+ assignTail->next = newAssign;
+ else
+ gfc_current_ns->code = newAssign;
+ assignTail = newAssign;
+ }
+ else
+ {
+ gfc_error ("Association to variables is not yet supported at %C");
+ return;
+ }
+ gcc_assert (assignTail);
+
+ accept_statement (ST_ASSOCIATE);
+ push_state (&s, COMP_ASSOCIATE, my_ns->proc_name);
+
+loop:
+ st = parse_executable (ST_NONE);
+ switch (st)
+ {
+ case ST_NONE:
+ unexpected_eof ();
+
+ case_end:
+ accept_statement (st);
+ assignTail->next = gfc_state_stack->head;
+ break;
+
+ default:
+ unexpected_statement (st);
+ goto loop;
+ }
+
+ gfc_current_ns = gfc_current_ns->parent;
+ pop_state ();
+}
+
+
/* Parse a DO loop. Note that the ST_CYCLE and ST_EXIT statements are
handled inside of parse_executable(), because they aren't really
loop statements. */
@@ -3542,8 +3644,6 @@ parse_executable (gfc_statement st)
case ST_END_SUBROUTINE:
case ST_DO:
- case ST_CRITICAL:
- case ST_BLOCK:
case ST_FORALL:
case ST_WHERE:
case ST_SELECT_CASE:
@@ -3573,6 +3673,10 @@ parse_executable (gfc_statement st)
parse_block_construct ();
break;
+ case ST_ASSOCIATE:
+ parse_associate ();
+ break;
+
case ST_IF_BLOCK:
parse_if_block ();
break;
diff --git a/gcc/fortran/parse.h b/gcc/fortran/parse.h
index faa813d88d0..65d1a7e604a 100644
--- a/gcc/fortran/parse.h
+++ b/gcc/fortran/parse.h
@@ -28,7 +28,7 @@ typedef enum
{
COMP_NONE, COMP_PROGRAM, COMP_MODULE, COMP_SUBROUTINE, COMP_FUNCTION,
COMP_BLOCK_DATA, COMP_INTERFACE, COMP_DERIVED, COMP_DERIVED_CONTAINS,
- COMP_BLOCK, COMP_IF,
+ COMP_BLOCK, COMP_ASSOCIATE, COMP_IF,
COMP_DO, COMP_SELECT, COMP_FORALL, COMP_WHERE, COMP_CONTAINS, COMP_ENUM,
COMP_SELECT_TYPE, COMP_OMP_STRUCTURED_BLOCK, COMP_CRITICAL
}
diff --git a/gcc/fortran/primary.c b/gcc/fortran/primary.c
index 68b6a437360..b6c08a9c406 100644
--- a/gcc/fortran/primary.c
+++ b/gcc/fortran/primary.c
@@ -2975,6 +2975,12 @@ match_variable (gfc_expr **result, int equiv_flag, int host_flag)
gfc_error ("Assigning to PROTECTED variable at %C");
return MATCH_ERROR;
}
+ if (sym->assoc && !sym->assoc->variable)
+ {
+ gfc_error ("'%s' associated to expression can't appear in a variable"
+ " definition context at %C", sym->name);
+ return MATCH_ERROR;
+ }
break;
case FL_UNKNOWN:
diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c
index 48bb6187c17..4e11fc6c311 100644
--- a/gcc/fortran/resolve.c
+++ b/gcc/fortran/resolve.c
@@ -1858,29 +1858,6 @@ resolve_global_procedure (gfc_symbol *sym, locus *where,
}
}
- if (gsym->ns->proc_name->attr.function
- && gsym->ns->proc_name->as
- && gsym->ns->proc_name->as->rank
- && (!sym->as || sym->as->rank != gsym->ns->proc_name->as->rank))
- gfc_error ("The reference to function '%s' at %L either needs an "
- "explicit INTERFACE or the rank is incorrect", sym->name,
- where);
-
- /* Non-assumed length character functions. */
- if (sym->attr.function && sym->ts.type == BT_CHARACTER
- && gsym->ns->proc_name->ts.u.cl->length != NULL)
- {
- gfc_charlen *cl = sym->ts.u.cl;
-
- if (!sym->attr.entry_master && sym->attr.if_source == IFSRC_UNKNOWN
- && cl && cl->length && cl->length->expr_type != EXPR_CONSTANT)
- {
- gfc_error ("Nonconstant character-length function '%s' at %L "
- "must have an explicit interface", sym->name,
- &sym->declared_at);
- }
- }
-
/* Differences in constant character lengths. */
if (sym->attr.function && sym->ts.type == BT_CHARACTER)
{
@@ -1911,26 +1888,108 @@ resolve_global_procedure (gfc_symbol *sym, locus *where,
sym->name, &sym->declared_at, gfc_typename (&sym->ts),
gfc_typename (&gsym->ns->proc_name->ts));
- /* Assumed shape arrays as dummy arguments. */
if (gsym->ns->proc_name->formal)
{
gfc_formal_arglist *arg = gsym->ns->proc_name->formal;
for ( ; arg; arg = arg->next)
- if (arg->sym && arg->sym->as
- && arg->sym->as->type == AS_ASSUMED_SHAPE)
+ if (!arg->sym)
+ continue;
+ /* F2003, 12.3.1.1 (2a); F2008, 12.4.2.2 (2a) */
+ else if (arg->sym->attr.allocatable
+ || arg->sym->attr.asynchronous
+ || arg->sym->attr.optional
+ || arg->sym->attr.pointer
+ || arg->sym->attr.target
+ || arg->sym->attr.value
+ || arg->sym->attr.volatile_)
+ {
+ gfc_error ("Dummy argument '%s' of procedure '%s' at %L "
+ "has an attribute that requires an explicit "
+ "interface for this procedure", arg->sym->name,
+ sym->name, &sym->declared_at);
+ break;
+ }
+ /* F2003, 12.3.1.1 (2b); F2008, 12.4.2.2 (2b) */
+ else if (arg->sym && arg->sym->as
+ && arg->sym->as->type == AS_ASSUMED_SHAPE)
{
gfc_error ("Procedure '%s' at %L with assumed-shape dummy "
- "'%s' argument must have an explicit interface",
+ "argument '%s' must have an explicit interface",
sym->name, &sym->declared_at, arg->sym->name);
break;
}
- else if (arg->sym && arg->sym->attr.optional)
+ /* F2008, 12.4.2.2 (2c) */
+ else if (arg->sym->attr.codimension)
{
- gfc_error ("Procedure '%s' at %L with optional dummy argument "
+ gfc_error ("Procedure '%s' at %L with coarray dummy argument "
"'%s' must have an explicit interface",
sym->name, &sym->declared_at, arg->sym->name);
break;
}
+ /* F2003, 12.3.1.1 (2c); F2008, 12.4.2.2 (2d) */
+ else if (false) /* TODO: is a parametrized derived type */
+ {
+ gfc_error ("Procedure '%s' at %L with parametrized derived "
+ "type argument '%s' must have an explicit "
+ "interface", sym->name, &sym->declared_at,
+ arg->sym->name);
+ break;
+ }
+ /* F2003, 12.3.1.1 (2d); F2008, 12.4.2.2 (2e) */
+ else if (arg->sym->ts.type == BT_CLASS)
+ {
+ gfc_error ("Procedure '%s' at %L with polymorphic dummy "
+ "argument '%s' must have an explicit interface",
+ sym->name, &sym->declared_at, arg->sym->name);
+ break;
+ }
+ }
+
+ if (gsym->ns->proc_name->attr.function)
+ {
+ /* F2003, 12.3.1.1 (3a); F2008, 12.4.2.2 (3a) */
+ if (gsym->ns->proc_name->as
+ && gsym->ns->proc_name->as->rank
+ && (!sym->as || sym->as->rank != gsym->ns->proc_name->as->rank))
+ gfc_error ("The reference to function '%s' at %L either needs an "
+ "explicit INTERFACE or the rank is incorrect", sym->name,
+ where);
+
+ /* F2003, 12.3.1.1 (3b); F2008, 12.4.2.2 (3b) */
+ if (gsym->ns->proc_name->result->attr.pointer
+ || gsym->ns->proc_name->result->attr.allocatable)
+ gfc_error ("Function '%s' at %L with a POINTER or ALLOCATABLE "
+ "result must have an explicit interface", sym->name,
+ where);
+
+ /* F2003, 12.3.1.1 (3c); F2008, 12.4.2.2 (3c) */
+ if (sym->ts.type == BT_CHARACTER
+ && gsym->ns->proc_name->ts.u.cl->length != NULL)
+ {
+ gfc_charlen *cl = sym->ts.u.cl;
+
+ if (!sym->attr.entry_master && sym->attr.if_source == IFSRC_UNKNOWN
+ && cl && cl->length && cl->length->expr_type != EXPR_CONSTANT)
+ {
+ gfc_error ("Nonconstant character-length function '%s' at %L "
+ "must have an explicit interface", sym->name,
+ &sym->declared_at);
+ }
+ }
+ }
+
+ /* F2003, 12.3.1.1 (4); F2008, 12.4.2.2 (4) */
+ if (gsym->ns->proc_name->attr.elemental)
+ {
+ gfc_error ("ELEMENTAL procedure '%s' at %L must have an explicit "
+ "interface", sym->name, &sym->declared_at);
+ }
+
+ /* F2003, 12.3.1.1 (5); F2008, 12.4.2.2 (5) */
+ if (gsym->ns->proc_name->attr.is_bind_c)
+ {
+ gfc_error ("Procedure '%s' at %L with BIND(C) attribute must have "
+ "an explicit interface", sym->name, &sym->declared_at);
}
if (gfc_option.flag_whole_file == 1
@@ -2200,6 +2259,7 @@ is_external_proc (gfc_symbol *sym)
&& !(sym->attr.intrinsic
|| gfc_is_intrinsic (sym, sym->attr.subroutine, sym->declared_at))
&& sym->attr.proc != PROC_ST_FUNCTION
+ && !sym->attr.proc_pointer
&& !sym->attr.use_assoc
&& sym->name)
return true;
@@ -3615,11 +3675,11 @@ resolve_operator (gfc_expr *e)
e->rank = op1->rank;
if (e->shape == NULL)
{
- t = compare_shapes(op1, op2);
+ t = compare_shapes (op1, op2);
if (t == FAILURE)
e->shape = NULL;
else
- e->shape = gfc_copy_shape (op1->shape, op1->rank);
+ e->shape = gfc_copy_shape (op1->shape, op1->rank);
}
}
else
@@ -5160,6 +5220,43 @@ resolve_typebound_static (gfc_expr* e, gfc_symtree** target,
}
+/* Get the ultimate declared type from an expression. In addition,
+ return the last class/derived type reference and the copy of the
+ reference list. */
+static gfc_symbol*
+get_declared_from_expr (gfc_ref **class_ref, gfc_ref **new_ref,
+ gfc_expr *e)
+{
+ gfc_symbol *declared;
+ gfc_ref *ref;
+
+ declared = NULL;
+ if (class_ref)
+ *class_ref = NULL;
+ if (new_ref)
+ *new_ref = gfc_copy_ref (e->ref);
+
+ for (ref = e->ref; ref; ref = ref->next)
+ {
+ if (ref->type != REF_COMPONENT)
+ continue;
+
+ if (ref->u.c.component->ts.type == BT_CLASS
+ || ref->u.c.component->ts.type == BT_DERIVED)
+ {
+ declared = ref->u.c.component->ts.u.derived;
+ if (class_ref)
+ *class_ref = ref;
+ }
+ }
+
+ if (declared == NULL)
+ declared = e->symtree->n.sym->ts.u.derived;
+
+ return declared;
+}
+
+
/* Given an EXPR_COMPCALL calling a GENERIC typebound procedure, figure out
which of the specific bindings (if any) matches the arglist and transform
the expression into a call of that binding. */
@@ -5169,6 +5266,8 @@ resolve_typebound_generic_call (gfc_expr* e, const char **name)
{
gfc_typebound_proc* genproc;
const char* genname;
+ gfc_symtree *st;
+ gfc_symbol *derived;
gcc_assert (e->expr_type == EXPR_COMPCALL);
genname = e->value.compcall.name;
@@ -5236,6 +5335,19 @@ resolve_typebound_generic_call (gfc_expr* e, const char **name)
return FAILURE;
success:
+ /* Make sure that we have the right specific instance for the name. */
+ genname = e->value.compcall.tbp->u.specific->name;
+
+ /* Is the symtree name a "unique name". */
+ if (*genname == '@')
+ genname = e->value.compcall.tbp->u.specific->n.sym->name;
+
+ derived = get_declared_from_expr (NULL, NULL, e);
+
+ st = gfc_find_typebound_proc (derived, NULL, genname, false, &e->where);
+ if (st)
+ e->value.compcall.tbp = st->n.tb;
+
return SUCCESS;
}
@@ -5343,38 +5455,6 @@ resolve_compcall (gfc_expr* e, const char **name)
}
-/* Get the ultimate declared type from an expression. In addition,
- return the last class/derived type reference and the copy of the
- reference list. */
-static gfc_symbol*
-get_declared_from_expr (gfc_ref **class_ref, gfc_ref **new_ref,
- gfc_expr *e)
-{
- gfc_symbol *declared;
- gfc_ref *ref;
-
- declared = NULL;
- *class_ref = NULL;
- *new_ref = gfc_copy_ref (e->ref);
- for (ref = *new_ref; ref; ref = ref->next)
- {
- if (ref->type != REF_COMPONENT)
- continue;
-
- if (ref->u.c.component->ts.type == BT_CLASS
- || ref->u.c.component->ts.type == BT_DERIVED)
- {
- declared = ref->u.c.component->ts.u.derived;
- *class_ref = ref;
- }
- }
-
- if (declared == NULL)
- declared = e->symtree->n.sym->ts.u.derived;
-
- return declared;
-}
-
/* Resolve a typebound function, or 'method'. First separate all
the non-CLASS references by calling resolve_compcall directly. */
@@ -5395,6 +5475,9 @@ resolve_typebound_function (gfc_expr* e)
if (st == NULL)
return resolve_compcall (e, NULL);
+ if (resolve_ref (e) == FAILURE)
+ return FAILURE;
+
/* Get the CLASS declared type. */
declared = get_declared_from_expr (&class_ref, &new_ref, e);
@@ -5416,18 +5499,16 @@ resolve_typebound_function (gfc_expr* e)
/* Treat the call as if it is a typebound procedure, in order to roll
out the correct name for the specific function. */
- resolve_compcall (e, &name);
+ if (resolve_compcall (e, &name) == FAILURE)
+ return FAILURE;
ts = e->ts;
/* Then convert the expression to a procedure pointer component call. */
e->value.function.esym = NULL;
e->symtree = st;
- if (class_ref)
- {
- gfc_free_ref_list (class_ref->next);
- e->ref = new_ref;
- }
+ if (new_ref)
+ e->ref = new_ref;
/* '$vptr' points to the vtab, which contains the procedure pointers. */
gfc_add_component_ref (e, "$vptr");
@@ -5470,6 +5551,9 @@ resolve_typebound_subroutine (gfc_code *code)
if (st == NULL)
return resolve_typebound_call (code, NULL);
+ if (resolve_ref (code->expr1) == FAILURE)
+ return FAILURE;
+
/* Get the CLASS declared type. */
declared = get_declared_from_expr (&class_ref, &new_ref, code->expr1);
@@ -5489,18 +5573,16 @@ resolve_typebound_subroutine (gfc_code *code)
if (code->expr1->value.compcall.tbp->is_generic)
genname = code->expr1->value.compcall.name;
- resolve_typebound_call (code, &name);
+ if (resolve_typebound_call (code, &name) == FAILURE)
+ return FAILURE;
ts = code->expr1->ts;
/* Then convert the expression to a procedure pointer component call. */
code->expr1->value.function.esym = NULL;
code->expr1->symtree = st;
- if (class_ref)
- {
- gfc_free_ref_list (class_ref->next);
- code->expr1->ref = new_ref;
- }
+ if (new_ref)
+ code->expr1->ref = new_ref;
/* '$vptr' points to the vtab, which contains the procedure pointers. */
gfc_add_component_ref (code->expr1, "$vptr");
@@ -6051,6 +6133,7 @@ resolve_deallocate_expr (gfc_expr *e)
bad:
gfc_error ("Allocate-object at %L must be ALLOCATABLE or a POINTER",
&e->where);
+ return FAILURE;
}
if (check_intent_in && sym->attr.intent == INTENT_IN)
@@ -6125,8 +6208,11 @@ gfc_expr_to_initialize (gfc_expr *e)
static gfc_try
conformable_arrays (gfc_expr *e1, gfc_expr *e2)
{
+ gfc_ref *tail;
+ for (tail = e2->ref; tail && tail->next; tail = tail->next);
+
/* First compare rank. */
- if (e2->ref && e1->rank != e2->ref->u.ar.as->rank)
+ if (tail && e1->rank != tail->u.ar.as->rank)
{
gfc_error ("Source-expr at %L must be scalar or have the "
"same rank as the allocate-object at %L",
@@ -6143,15 +6229,15 @@ conformable_arrays (gfc_expr *e1, gfc_expr *e2)
for (i = 0; i < e1->rank; i++)
{
- if (e2->ref->u.ar.end[i])
+ if (tail->u.ar.end[i])
{
- mpz_set (s, e2->ref->u.ar.end[i]->value.integer);
- mpz_sub (s, s, e2->ref->u.ar.start[i]->value.integer);
+ mpz_set (s, tail->u.ar.end[i]->value.integer);
+ mpz_sub (s, s, tail->u.ar.start[i]->value.integer);
mpz_add_ui (s, s, 1);
}
else
{
- mpz_set (s, e2->ref->u.ar.start[i]->value.integer);
+ mpz_set (s, tail->u.ar.start[i]->value.integer);
}
if (mpz_cmp (e1->shape[i], s) != 0)
@@ -6182,10 +6268,9 @@ resolve_allocate_expr (gfc_expr *e, gfc_code *code)
symbol_attribute attr;
gfc_ref *ref, *ref2;
gfc_array_ref *ar;
- gfc_symbol *sym;
+ gfc_symbol *sym = NULL;
gfc_alloc *a;
gfc_component *c;
- gfc_expr *init_e;
/* Check INTENT(IN), unless the object is a sub-component of a pointer. */
check_intent_in = 1;
@@ -6318,11 +6403,14 @@ resolve_allocate_expr (gfc_expr *e, gfc_code *code)
goto failure;
}
}
- else if (is_abstract&& code->ext.alloc.ts.type == BT_UNKNOWN)
+
+ /* Check F08:C629. */
+ if (is_abstract && code->ext.alloc.ts.type == BT_UNKNOWN
+ && !code->expr3)
{
gcc_assert (e->ts.type == BT_CLASS);
gfc_error ("Allocating %s of ABSTRACT base type at %L requires a "
- "type-spec or SOURCE=", sym->name, &e->where);
+ "type-spec or source-expr", sym->name, &e->where);
goto failure;
}
@@ -6333,25 +6421,26 @@ resolve_allocate_expr (gfc_expr *e, gfc_code *code)
goto failure;
}
- if (!code->expr3)
+ if (!code->expr3 || code->expr3->mold)
{
/* Add default initializer for those derived types that need them. */
- if (e->ts.type == BT_DERIVED
- && (init_e = gfc_default_initializer (&e->ts)))
- {
- gfc_code *init_st = gfc_get_code ();
- init_st->loc = code->loc;
- init_st->op = EXEC_INIT_ASSIGN;
- init_st->expr1 = gfc_expr_to_initialize (e);
- init_st->expr2 = init_e;
- init_st->next = code->next;
- code->next = init_st;
- }
- else if (e->ts.type == BT_CLASS
- && ((code->ext.alloc.ts.type == BT_UNKNOWN
- && (init_e = gfc_default_initializer (&CLASS_DATA (e)->ts)))
- || (code->ext.alloc.ts.type == BT_DERIVED
- && (init_e = gfc_default_initializer (&code->ext.alloc.ts)))))
+ gfc_expr *init_e = NULL;
+ gfc_typespec ts;
+
+ if (code->ext.alloc.ts.type == BT_DERIVED)
+ ts = code->ext.alloc.ts;
+ else if (code->expr3)
+ ts = code->expr3->ts;
+ else
+ ts = e->ts;
+
+ if (ts.type == BT_DERIVED)
+ init_e = gfc_default_initializer (&ts);
+ /* FIXME: Use default init of dynamic type (cf. PR 44541). */
+ else if (e->ts.type == BT_CLASS)
+ init_e = gfc_default_initializer (&ts.u.derived->components->ts);
+
+ if (init_e)
{
gfc_code *init_st = gfc_get_code ();
init_st->loc = code->loc;
@@ -6503,8 +6592,29 @@ resolve_allocate_deallocate (gfc_code *code, const char *fcn)
for (p = code->ext.alloc.list; p; p = p->next)
if (p->expr->symtree->n.sym->name == stat->symtree->n.sym->name)
- gfc_error ("Stat-variable at %L shall not be %sd within "
- "the same %s statement", &stat->where, fcn, fcn);
+ {
+ gfc_ref *ref1, *ref2;
+ bool found = true;
+
+ for (ref1 = p->expr->ref, ref2 = stat->ref; ref1 && ref2;
+ ref1 = ref1->next, ref2 = ref2->next)
+ {
+ if (ref1->type != REF_COMPONENT || ref2->type != REF_COMPONENT)
+ continue;
+ if (ref1->u.c.component->name != ref2->u.c.component->name)
+ {
+ found = false;
+ break;
+ }
+ }
+
+ if (found)
+ {
+ gfc_error ("Stat-variable at %L shall not be %sd within "
+ "the same %s statement", &stat->where, fcn, fcn);
+ break;
+ }
+ }
}
/* Check the errmsg variable. */
@@ -6532,8 +6642,29 @@ resolve_allocate_deallocate (gfc_code *code, const char *fcn)
for (p = code->ext.alloc.list; p; p = p->next)
if (p->expr->symtree->n.sym->name == errmsg->symtree->n.sym->name)
- gfc_error ("Errmsg-variable at %L shall not be %sd within "
- "the same %s statement", &errmsg->where, fcn, fcn);
+ {
+ gfc_ref *ref1, *ref2;
+ bool found = true;
+
+ for (ref1 = p->expr->ref, ref2 = errmsg->ref; ref1 && ref2;
+ ref1 = ref1->next, ref2 = ref2->next)
+ {
+ if (ref1->type != REF_COMPONENT || ref2->type != REF_COMPONENT)
+ continue;
+ if (ref1->u.c.component->name != ref2->u.c.component->name)
+ {
+ found = false;
+ break;
+ }
+ }
+
+ if (found)
+ {
+ gfc_error ("Errmsg-variable at %L shall not be %sd within "
+ "the same %s statement", &errmsg->where, fcn, fcn);
+ break;
+ }
+ }
}
/* Check that an allocate-object appears only once in the statement.
@@ -7137,7 +7268,7 @@ resolve_select_type (gfc_code *code)
gfc_namespace *ns;
int error = 0;
- ns = code->ext.ns;
+ ns = code->ext.block.ns;
gfc_resolve (ns);
/* Check for F03:C813. */
@@ -7224,6 +7355,7 @@ resolve_select_type (gfc_code *code)
else
ns->code->next = new_st;
code->op = EXEC_BLOCK;
+ code->ext.block.assoc = NULL;
code->expr1 = code->expr2 = NULL;
code->block = NULL;
@@ -7967,10 +8099,11 @@ gfc_resolve_forall (gfc_code *code, gfc_namespace *ns, int forall_save)
static void
resolve_block_construct (gfc_code* code)
{
- /* Eventually, we may want to do some checks here or handle special stuff.
- But so far the only thing we can do is resolving the local namespace. */
+ /* For an ASSOCIATE block, the associations (and their targets) are already
+ resolved during gfc_resolve_symbol. */
- gfc_resolve (code->ext.ns);
+ /* Resolve the BLOCK's namespace. */
+ gfc_resolve (code->ext.block.ns);
}
@@ -8291,7 +8424,7 @@ resolve_code (gfc_code *code, gfc_namespace *ns)
gfc_resolve_omp_do_blocks (code, ns);
break;
case EXEC_SELECT_TYPE:
- gfc_current_ns = code->ext.ns;
+ gfc_current_ns = code->ext.block.ns;
gfc_resolve_blocks (code->block, gfc_current_ns);
gfc_current_ns = ns;
break;
@@ -8455,7 +8588,7 @@ resolve_code (gfc_code *code, gfc_namespace *ns)
break;
case EXEC_BLOCK:
- gfc_resolve (code->ext.ns);
+ gfc_resolve (code->ext.block.ns);
break;
case EXEC_DO:
@@ -10694,6 +10827,14 @@ resolve_fl_derived (gfc_symbol *sym)
return FAILURE;
}
+ /* F2008, C448. */
+ if (c->attr.contiguous && (!c->attr.dimension || !c->attr.pointer))
+ {
+ gfc_error ("Component '%s' at %L has the CONTIGUOUS attribute but "
+ "is not an array pointer", c->name, &c->loc);
+ return FAILURE;
+ }
+
if (c->attr.proc_pointer && c->ts.interface)
{
if (c->ts.interface->attr.procedure && !sym->attr.vtype)
@@ -10760,7 +10901,7 @@ resolve_fl_derived (gfc_symbol *sym)
c->ts.u.cl = cl;
}
}
- else if (c->ts.interface->name[0] != '\0' && !sym->attr.vtype)
+ else if (!sym->attr.vtype && c->ts.interface->name[0] != '\0')
{
gfc_error ("Interface '%s' of procedure pointer component "
"'%s' at %L must be explicit", c->ts.interface->name,
@@ -11004,6 +11145,7 @@ resolve_fl_derived (gfc_symbol *sym)
/* If this is a non-ABSTRACT type extending an ABSTRACT one, ensure that
all DEFERRED bindings are overridden. */
if (super_type && super_type->attr.abstract && !sym->attr.abstract
+ && !sym->attr.is_class
&& ensure_not_abstract (sym, super_type) == FAILURE)
return FAILURE;
@@ -11265,6 +11407,7 @@ resolve_symbol (gfc_symbol *sym)
sym->attr.pure = ifc->attr.pure;
sym->attr.elemental = ifc->attr.elemental;
sym->attr.dimension = ifc->attr.dimension;
+ sym->attr.contiguous = ifc->attr.contiguous;
sym->attr.recursive = ifc->attr.recursive;
sym->attr.always_explicit = ifc->attr.always_explicit;
sym->attr.ext_attr |= ifc->attr.ext_attr;
@@ -11297,6 +11440,31 @@ resolve_symbol (gfc_symbol *sym)
}
}
+ if (sym->attr.is_protected && !sym->attr.proc_pointer
+ && (sym->attr.procedure || sym->attr.external))
+ {
+ if (sym->attr.external)
+ gfc_error ("PROTECTED attribute conflicts with EXTERNAL attribute "
+ "at %L", &sym->declared_at);
+ else
+ gfc_error ("PROCEDURE attribute conflicts with PROTECTED attribute "
+ "at %L", &sym->declared_at);
+
+ return;
+ }
+
+
+ /* F2008, C530. */
+ if (sym->attr.contiguous
+ && (!sym->attr.dimension || (sym->as->type != AS_ASSUMED_SHAPE
+ && !sym->attr.pointer)))
+ {
+ gfc_error ("'%s' at %L has the CONTIGUOUS attribute but is not an "
+ "array pointer or an assumed-shape array", sym->name,
+ &sym->declared_at);
+ return;
+ }
+
if (sym->attr.flavor == FL_DERIVED && resolve_fl_derived (sym) == FAILURE)
return;
@@ -11307,7 +11475,6 @@ resolve_symbol (gfc_symbol *sym)
can. */
mp_flag = (sym->result != NULL && sym->result != sym);
-
/* Make sure that the intrinsic is consistent with its internal
representation. This needs to be done before assigning a default
type to avoid spurious warnings. */
@@ -11315,6 +11482,18 @@ resolve_symbol (gfc_symbol *sym)
&& resolve_intrinsic (sym, &sym->declared_at) == FAILURE)
return;
+ /* For associate names, resolve corresponding expression and make sure
+ they get their type-spec set this way. */
+ if (sym->assoc)
+ {
+ gcc_assert (sym->attr.flavor == FL_VARIABLE);
+ if (gfc_resolve_expr (sym->assoc->target) != SUCCESS)
+ return;
+
+ sym->ts = sym->assoc->target->ts;
+ gcc_assert (sym->ts.type != BT_UNKNOWN);
+ }
+
/* Assign default type to symbols that need one and don't have one. */
if (sym->ts.type == BT_UNKNOWN)
{
@@ -11344,6 +11523,7 @@ resolve_symbol (gfc_symbol *sym)
sym->attr.dimension = sym->result->attr.dimension;
sym->attr.pointer = sym->result->attr.pointer;
sym->attr.allocatable = sym->result->attr.allocatable;
+ sym->attr.contiguous = sym->result->attr.contiguous;
}
}
}
diff --git a/gcc/fortran/scanner.c b/gcc/fortran/scanner.c
index 7b4ab244136..a8ab2353e85 100644
--- a/gcc/fortran/scanner.c
+++ b/gcc/fortran/scanner.c
@@ -390,7 +390,8 @@ gfc_release_include_path (void)
static FILE *
-open_included_file (const char *name, gfc_directorylist *list, bool module)
+open_included_file (const char *name, gfc_directorylist *list,
+ bool module, bool system)
{
char *fullname;
gfc_directorylist *p;
@@ -407,7 +408,12 @@ open_included_file (const char *name, gfc_directorylist *list, bool module)
f = gfc_open_file (fullname);
if (f != NULL)
- return f;
+ {
+ if (gfc_cpp_makedep ())
+ gfc_cpp_add_dep (fullname, system);
+
+ return f;
+ }
}
return NULL;
@@ -421,28 +427,37 @@ open_included_file (const char *name, gfc_directorylist *list, bool module)
FILE *
gfc_open_included_file (const char *name, bool include_cwd, bool module)
{
- FILE *f;
+ FILE *f = NULL;
- if (IS_ABSOLUTE_PATH (name))
- return gfc_open_file (name);
-
- if (include_cwd)
+ if (IS_ABSOLUTE_PATH (name) || include_cwd)
{
f = gfc_open_file (name);
- if (f != NULL)
- return f;
+ if (f && gfc_cpp_makedep ())
+ gfc_cpp_add_dep (name, false);
}
- return open_included_file (name, include_dirs, module);
+ if (!f)
+ f = open_included_file (name, include_dirs, module, false);
+
+ return f;
}
FILE *
gfc_open_intrinsic_module (const char *name)
{
+ FILE *f = NULL;
+
if (IS_ABSOLUTE_PATH (name))
- return gfc_open_file (name);
+ {
+ f = gfc_open_file (name);
+ if (f && gfc_cpp_makedep ())
+ gfc_cpp_add_dep (name, true);
+ }
+
+ if (!f)
+ f = open_included_file (name, intrinsic_modules_dirs, true, true);
- return open_included_file (name, intrinsic_modules_dirs, true);
+ return f;
}
diff --git a/gcc/fortran/simplify.c b/gcc/fortran/simplify.c
index 743c4632986..7356625cf41 100644
--- a/gcc/fortran/simplify.c
+++ b/gcc/fortran/simplify.c
@@ -4589,9 +4589,11 @@ gfc_simplify_selected_int_kind (gfc_expr *e)
gfc_expr *
-gfc_simplify_selected_real_kind (gfc_expr *p, gfc_expr *q)
+gfc_simplify_selected_real_kind (gfc_expr *p, gfc_expr *q, gfc_expr *rdx)
{
- int range, precision, i, kind, found_precision, found_range;
+ int range, precision, radix, i, kind, found_precision, found_range,
+ found_radix;
+ locus *loc = &gfc_current_locus;
if (p == NULL)
precision = 0;
@@ -4600,6 +4602,7 @@ gfc_simplify_selected_real_kind (gfc_expr *p, gfc_expr *q)
if (p->expr_type != EXPR_CONSTANT
|| gfc_extract_int (p, &precision) != NULL)
return NULL;
+ loc = &p->where;
}
if (q == NULL)
@@ -4609,11 +4612,27 @@ gfc_simplify_selected_real_kind (gfc_expr *p, gfc_expr *q)
if (q->expr_type != EXPR_CONSTANT
|| gfc_extract_int (q, &range) != NULL)
return NULL;
+
+ if (!loc)
+ loc = &q->where;
+ }
+
+ if (rdx == NULL)
+ radix = 0;
+ else
+ {
+ if (rdx->expr_type != EXPR_CONSTANT
+ || gfc_extract_int (rdx, &radix) != NULL)
+ return NULL;
+
+ if (!loc)
+ loc = &rdx->where;
}
kind = INT_MAX;
found_precision = 0;
found_range = 0;
+ found_radix = 0;
for (i = 0; gfc_real_kinds[i].kind != 0; i++)
{
@@ -4623,23 +4642,30 @@ gfc_simplify_selected_real_kind (gfc_expr *p, gfc_expr *q)
if (gfc_real_kinds[i].range >= range)
found_range = 1;
+ if (gfc_real_kinds[i].radix >= radix)
+ found_radix = 1;
+
if (gfc_real_kinds[i].precision >= precision
- && gfc_real_kinds[i].range >= range && gfc_real_kinds[i].kind < kind)
+ && gfc_real_kinds[i].range >= range
+ && gfc_real_kinds[i].radix >= radix && gfc_real_kinds[i].kind < kind)
kind = gfc_real_kinds[i].kind;
}
if (kind == INT_MAX)
{
- kind = 0;
-
- if (!found_precision)
+ if (found_radix && found_range && !found_precision)
kind = -1;
- if (!found_range)
- kind -= 2;
+ else if (found_radix && found_precision && !found_range)
+ kind = -2;
+ else if (found_radix && !found_precision && !found_range)
+ kind = -3;
+ else if (found_radix)
+ kind = -4;
+ else
+ kind = -5;
}
- return gfc_get_int_expr (gfc_default_integer_kind,
- p ? &p->where : &q->where, kind);
+ return gfc_get_int_expr (gfc_default_integer_kind, loc, kind);
}
diff --git a/gcc/fortran/st.c b/gcc/fortran/st.c
index ffef22d1140..f9ad5d82793 100644
--- a/gcc/fortran/st.c
+++ b/gcc/fortran/st.c
@@ -116,7 +116,8 @@ gfc_free_statement (gfc_code *p)
break;
case EXEC_BLOCK:
- gfc_free_namespace (p->ext.ns);
+ gfc_free_namespace (p->ext.block.ns);
+ gfc_free_association_list (p->ext.block.assoc);
break;
case EXEC_COMPCALL:
@@ -231,3 +232,15 @@ gfc_free_statements (gfc_code *p)
}
}
+
+/* Free an association list (of an ASSOCIATE statement). */
+
+void
+gfc_free_association_list (gfc_association_list* assoc)
+{
+ if (!assoc)
+ return;
+
+ gfc_free_association_list (assoc->next);
+ gfc_free (assoc);
+}
diff --git a/gcc/fortran/symbol.c b/gcc/fortran/symbol.c
index b436de5e2af..df6ada963c3 100644
--- a/gcc/fortran/symbol.c
+++ b/gcc/fortran/symbol.c
@@ -372,7 +372,8 @@ check_conflict (symbol_attribute *attr, const char *name, locus *where)
*cray_pointee = "CRAY POINTEE", *data = "DATA", *value = "VALUE",
*volatile_ = "VOLATILE", *is_protected = "PROTECTED",
*is_bind_c = "BIND(C)", *procedure = "PROCEDURE",
- *asynchronous = "ASYNCHRONOUS", *codimension = "CODIMENSION";
+ *asynchronous = "ASYNCHRONOUS", *codimension = "CODIMENSION",
+ *contiguous = "CONTIGUOUS";
static const char *threadprivate = "THREADPRIVATE";
const char *a1, *a2;
@@ -518,6 +519,7 @@ check_conflict (symbol_attribute *attr, const char *name, locus *where)
conf (cray_pointer, cray_pointee);
conf (cray_pointer, dimension);
conf (cray_pointer, codimension);
+ conf (cray_pointer, contiguous);
conf (cray_pointer, pointer);
conf (cray_pointer, target);
conf (cray_pointer, allocatable);
@@ -529,6 +531,7 @@ check_conflict (symbol_attribute *attr, const char *name, locus *where)
conf (cray_pointer, entry);
conf (cray_pointee, allocatable);
+ conf (cray_pointer, contiguous);
conf (cray_pointer, codimension);
conf (cray_pointee, intent);
conf (cray_pointee, optional);
@@ -545,7 +548,6 @@ check_conflict (symbol_attribute *attr, const char *name, locus *where)
conf (data, function);
conf (data, result);
conf (data, allocatable);
- conf (data, use_assoc);
conf (value, pointer)
conf (value, allocatable)
@@ -567,7 +569,6 @@ check_conflict (symbol_attribute *attr, const char *name, locus *where)
}
conf (is_protected, intrinsic)
- conf (is_protected, external)
conf (is_protected, in_common)
conf (asynchronous, intrinsic)
@@ -587,7 +588,6 @@ check_conflict (symbol_attribute *attr, const char *name, locus *where)
conf (procedure, dimension)
conf (procedure, codimension)
conf (procedure, intrinsic)
- conf (procedure, is_protected)
conf (procedure, target)
conf (procedure, value)
conf (procedure, volatile_)
@@ -616,6 +616,7 @@ check_conflict (symbol_attribute *attr, const char *name, locus *where)
conf2 (dummy);
conf2 (volatile_);
conf2 (asynchronous);
+ conf2 (contiguous);
conf2 (pointer);
conf2 (is_protected);
conf2 (target);
@@ -723,6 +724,7 @@ check_conflict (symbol_attribute *attr, const char *name, locus *where)
conf2 (function);
conf2 (subroutine);
conf2 (entry);
+ conf2 (contiguous);
conf2 (pointer);
conf2 (is_protected);
conf2 (target);
@@ -931,6 +933,18 @@ gfc_add_dimension (symbol_attribute *attr, const char *name, locus *where)
gfc_try
+gfc_add_contiguous (symbol_attribute *attr, const char *name, locus *where)
+{
+
+ if (check_used (attr, name, where))
+ return FAILURE;
+
+ attr->contiguous = 1;
+ return check_conflict (attr, name, where);
+}
+
+
+gfc_try
gfc_add_external (symbol_attribute *attr, locus *where)
{
@@ -1718,6 +1732,8 @@ gfc_copy_attr (symbol_attribute *dest, symbol_attribute *src, locus *where)
goto fail;
if (src->codimension && gfc_add_codimension (dest, NULL, where) == FAILURE)
goto fail;
+ if (src->contiguous && gfc_add_contiguous (dest, NULL, where) == FAILURE)
+ goto fail;
if (src->optional && gfc_add_optional (dest, where) == FAILURE)
goto fail;
if (src->pointer && gfc_add_pointer (dest, where) == FAILURE)
@@ -2515,6 +2531,7 @@ gfc_new_symbol (const char *name, gfc_namespace *ns)
/* Clear the ptrs we may need. */
p->common_block = NULL;
p->f2k_derived = NULL;
+ p->assoc = NULL;
return p;
}
@@ -4593,12 +4610,14 @@ gfc_check_symbol_typed (gfc_symbol* sym, gfc_namespace* ns,
list and marked `error' until symbols are committed. */
gfc_typebound_proc*
-gfc_get_typebound_proc (void)
+gfc_get_typebound_proc (gfc_typebound_proc *tb0)
{
gfc_typebound_proc *result;
tentative_tbp *list_node;
result = XCNEW (gfc_typebound_proc);
+ if (tb0)
+ *result = *tb0;
result->error = 1;
list_node = XCNEW (tentative_tbp);
diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c
index 7d7b3a36839..7eb8e755785 100644
--- a/gcc/fortran/trans-array.c
+++ b/gcc/fortran/trans-array.c
@@ -285,7 +285,9 @@ gfc_conv_descriptor_stride_get (tree desc, tree dim)
tree type = TREE_TYPE (desc);
gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
if (integer_zerop (dim)
- && GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE)
+ && (GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE
+ ||GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ASSUMED_SHAPE_CONT
+ ||GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER_CONT))
return gfc_index_one_node;
return gfc_conv_descriptor_stride (desc, dim);
@@ -5522,6 +5524,7 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, gfc_ss * ss, bool g77,
ultimate_ptr_comp = false;
ultimate_alloc_comp = false;
+
for (ref = expr->ref; ref; ref = ref->next)
{
if (ref->next == NULL)
@@ -5608,7 +5611,8 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, gfc_ss * ss, bool g77,
contiguous = g77 && !this_array_result && contiguous;
/* There is no need to pack and unpack the array, if it is contiguous
- and not deferred or assumed shape. */
+ and not a deferred- or assumed-shape array, or if it is simply
+ contiguous. */
no_pack = ((sym && sym->as
&& !sym->attr.pointer
&& sym->as->type != AS_DEFERRED
@@ -5616,7 +5620,9 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, gfc_ss * ss, bool g77,
||
(ref && ref->u.ar.as
&& ref->u.ar.as->type != AS_DEFERRED
- && ref->u.ar.as->type != AS_ASSUMED_SHAPE));
+ && ref->u.ar.as->type != AS_ASSUMED_SHAPE)
+ ||
+ gfc_is_simply_contiguous (expr, false));
no_pack = contiguous && no_pack;
@@ -5680,9 +5686,24 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, gfc_ss * ss, bool g77,
gfc_add_expr_to_block (&se->post, tmp);
}
- if (g77)
+ if (g77 || (fsym && fsym->attr.contiguous
+ && !gfc_is_simply_contiguous (expr, false)))
{
+ tree origptr = NULL_TREE;
+
desc = se->expr;
+
+ /* For contiguous arrays, save the original value of the descriptor. */
+ if (!g77)
+ {
+ origptr = gfc_create_var (pvoid_type_node, "origptr");
+ tmp = build_fold_indirect_ref_loc (input_location, desc);
+ tmp = gfc_conv_array_data (tmp);
+ tmp = fold_build2 (MODIFY_EXPR, TREE_TYPE (origptr), origptr,
+ fold_convert (TREE_TYPE (origptr), tmp));
+ gfc_add_expr_to_block (&se->pre, tmp);
+ }
+
/* Repack the array. */
if (gfc_option.warn_array_temp)
{
@@ -5706,7 +5727,15 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, gfc_ss * ss, bool g77,
ptr = gfc_evaluate_now (ptr, &se->pre);
- se->expr = ptr;
+ /* Use the packed data for the actual argument, except for contiguous arrays,
+ where the descriptor's data component is set. */
+ if (g77)
+ se->expr = ptr;
+ else
+ {
+ tmp = build_fold_indirect_ref_loc (input_location, desc);
+ gfc_conv_descriptor_data_set (&se->pre, tmp, ptr);
+ }
if (gfc_option.rtcheck & GFC_RTCHECK_ARRAY_TEMPS)
{
@@ -5768,6 +5797,14 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, gfc_ss * ss, bool g77,
gfc_add_block_to_block (&block, &se->post);
gfc_init_block (&se->post);
+
+ /* Reset the descriptor pointer. */
+ if (!g77)
+ {
+ tmp = build_fold_indirect_ref_loc (input_location, desc);
+ gfc_conv_descriptor_data_set (&se->post, tmp, origptr);
+ }
+
gfc_add_block_to_block (&se->post, &block);
}
}
@@ -5938,6 +5975,7 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl,
gfc_loopinfo loop;
stmtblock_t fnblock;
stmtblock_t loopbody;
+ tree decl_type;
tree tmp;
tree comp;
tree dcmp;
@@ -5951,21 +5989,28 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl,
gfc_init_block (&fnblock);
- if (POINTER_TYPE_P (TREE_TYPE (decl)) && rank != 0)
+ decl_type = TREE_TYPE (decl);
+
+ if ((POINTER_TYPE_P (decl_type) && rank != 0)
+ || (TREE_CODE (decl_type) == REFERENCE_TYPE && rank == 0))
+
decl = build_fold_indirect_ref_loc (input_location,
decl);
+ /* Just in case in gets dereferenced. */
+ decl_type = TREE_TYPE (decl);
+
/* If this an array of derived types with allocatable components
build a loop and recursively call this function. */
- if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
- || GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
+ if (TREE_CODE (decl_type) == ARRAY_TYPE
+ || GFC_DESCRIPTOR_TYPE_P (decl_type))
{
tmp = gfc_conv_array_data (decl);
var = build_fold_indirect_ref_loc (input_location,
tmp);
/* Get the number of elements - 1 and set the counter. */
- if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
+ if (GFC_DESCRIPTOR_TYPE_P (decl_type))
{
/* Use the descriptor for an allocatable array. Since this
is a full array reference, we only need the descriptor
@@ -5981,7 +6026,7 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl,
else
{
/* Otherwise use the TYPE_DOMAIN information. */
- tmp = array_type_nelts (TREE_TYPE (decl));
+ tmp = array_type_nelts (decl_type);
tmp = fold_convert (gfc_array_index_type, tmp);
}
@@ -5998,7 +6043,7 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl,
{
if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (dest)))
{
- tmp = gfc_duplicate_allocatable (dest, decl, TREE_TYPE(decl), rank);
+ tmp = gfc_duplicate_allocatable (dest, decl, decl_type, rank);
gfc_add_expr_to_block (&fnblock, tmp);
}
tmp = build_fold_indirect_ref_loc (input_location,
diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c
index 224474aeff2..1c7226c41e6 100644
--- a/gcc/fortran/trans-decl.c
+++ b/gcc/fortran/trans-decl.c
@@ -612,8 +612,8 @@ gfc_finish_var_decl (tree decl, gfc_symbol * sym)
void
gfc_allocate_lang_decl (tree decl)
{
- DECL_LANG_SPECIFIC (decl) = (struct lang_decl *)
- ggc_alloc_cleared (sizeof (struct lang_decl));
+ DECL_LANG_SPECIFIC (decl) = ggc_alloc_cleared_lang_decl(sizeof
+ (struct lang_decl));
}
/* Remember a symbol to generate initialization/cleanup code at function
@@ -1213,7 +1213,8 @@ gfc_get_symbol_decl (gfc_symbol * sym)
/* Create variables to hold the non-constant bits of array info. */
gfc_build_qualified_array (decl, sym);
- if ((sym->attr.allocatable || !sym->attr.dummy) && !sym->attr.pointer)
+ if (sym->attr.contiguous
+ || ((sym->attr.allocatable || !sym->attr.dummy) && !sym->attr.pointer))
GFC_DECL_PACKED_ARRAY (decl) = 1;
}
@@ -2424,26 +2425,26 @@ gfc_build_intrinsic_function_decls (void)
gfor_fndecl_string_len_trim =
gfc_build_library_function_decl (get_identifier (PREFIX("string_len_trim")),
- gfc_int4_type_node, 2,
+ gfc_charlen_type_node, 2,
gfc_charlen_type_node, pchar1_type_node);
gfor_fndecl_string_index =
gfc_build_library_function_decl (get_identifier (PREFIX("string_index")),
- gfc_int4_type_node, 5,
+ gfc_charlen_type_node, 5,
gfc_charlen_type_node, pchar1_type_node,
gfc_charlen_type_node, pchar1_type_node,
gfc_logical4_type_node);
gfor_fndecl_string_scan =
gfc_build_library_function_decl (get_identifier (PREFIX("string_scan")),
- gfc_int4_type_node, 5,
+ gfc_charlen_type_node, 5,
gfc_charlen_type_node, pchar1_type_node,
gfc_charlen_type_node, pchar1_type_node,
gfc_logical4_type_node);
gfor_fndecl_string_verify =
gfc_build_library_function_decl (get_identifier (PREFIX("string_verify")),
- gfc_int4_type_node, 5,
+ gfc_charlen_type_node, 5,
gfc_charlen_type_node, pchar1_type_node,
gfc_charlen_type_node, pchar1_type_node,
gfc_logical4_type_node);
@@ -2611,9 +2612,10 @@ gfc_build_intrinsic_function_decls (void)
gfor_fndecl_sr_kind =
gfc_build_library_function_decl (get_identifier
- (PREFIX("selected_real_kind")),
- gfc_int4_type_node, 2,
- pvoid_type_node, pvoid_type_node);
+ (PREFIX("selected_real_kind2008")),
+ gfc_int4_type_node, 3,
+ pvoid_type_node, pvoid_type_node,
+ pvoid_type_node);
/* Power functions. */
{
@@ -3410,7 +3412,7 @@ gfc_find_module (const char *name)
htab_hash_string (name), INSERT);
if (*slot == NULL)
{
- struct module_htab_entry *entry = GGC_CNEW (struct module_htab_entry);
+ struct module_htab_entry *entry = ggc_alloc_cleared_module_htab_entry ();
entry->name = gfc_get_string (name);
entry->decls = htab_create_ggc (10, module_htab_decls_hash,
diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c
index 6c5c3286eb8..692b3e2f846 100644
--- a/gcc/fortran/trans-expr.c
+++ b/gcc/fortran/trans-expr.c
@@ -1718,6 +1718,7 @@ gfc_add_interface_mapping (gfc_interface_mapping * mapping,
new_sym->as = gfc_copy_array_spec (sym->as);
new_sym->attr.referenced = 1;
new_sym->attr.dimension = sym->attr.dimension;
+ new_sym->attr.contiguous = sym->attr.contiguous;
new_sym->attr.codimension = sym->attr.codimension;
new_sym->attr.pointer = sym->attr.pointer;
new_sym->attr.allocatable = sym->attr.allocatable;
@@ -2492,12 +2493,14 @@ gfc_conv_derived_to_class (gfc_se *parmse, gfc_expr *e,
ss = gfc_walk_expr (e);
if (ss == gfc_ss_terminator)
{
+ parmse->ss = NULL;
gfc_conv_expr_reference (parmse, e);
tmp = fold_convert (TREE_TYPE (ctree), parmse->expr);
gfc_add_modify (&parmse->pre, ctree, tmp);
}
else
{
+ parmse->ss = ss;
gfc_conv_expr (parmse, e);
gfc_add_modify (&parmse->pre, ctree, parmse->expr);
}
@@ -4867,41 +4870,40 @@ gfc_trans_scalar_assign (gfc_se * lse, gfc_se * rse, gfc_typespec ts,
}
-/* Try to translate array(:) = func (...), where func is a transformational
- array function, without using a temporary. Returns NULL is this isn't the
- case. */
+/* There are quite a lot of restrictions on the optimisation in using an
+ array function assign without a temporary. */
-static tree
-gfc_trans_arrayfunc_assign (gfc_expr * expr1, gfc_expr * expr2)
+static bool
+arrayfunc_assign_needs_temporary (gfc_expr * expr1, gfc_expr * expr2)
{
- gfc_se se;
- gfc_ss *ss;
gfc_ref * ref;
bool seen_array_ref;
bool c = false;
- gfc_component *comp = NULL;
+ gfc_symbol *sym = expr1->symtree->n.sym;
/* The caller has already checked rank>0 and expr_type == EXPR_FUNCTION. */
if (expr2->value.function.isym && !gfc_is_intrinsic_libcall (expr2))
- return NULL;
+ return true;
- /* Elemental functions don't need a temporary anyway. */
+ /* Elemental functions are scalarized so that they don't need a
+ temporary in gfc_trans_assignment_1, so return a true. Otherwise,
+ they would need special treatment in gfc_trans_arrayfunc_assign. */
if (expr2->value.function.esym != NULL
&& expr2->value.function.esym->attr.elemental)
- return NULL;
+ return true;
- /* Fail if rhs is not FULL or a contiguous section. */
+ /* Need a temporary if rhs is not FULL or a contiguous section. */
if (expr1->ref && !(gfc_full_array_ref_p (expr1->ref, &c) || c))
- return NULL;
+ return true;
- /* Fail if EXPR1 can't be expressed as a descriptor. */
+ /* Need a temporary if EXPR1 can't be expressed as a descriptor. */
if (gfc_ref_needs_temporary_p (expr1->ref))
- return NULL;
+ return true;
/* Functions returning pointers need temporaries. */
if (expr2->symtree->n.sym->attr.pointer
|| expr2->symtree->n.sym->attr.allocatable)
- return NULL;
+ return true;
/* Character array functions need temporaries unless the
character lengths are the same. */
@@ -4909,15 +4911,15 @@ gfc_trans_arrayfunc_assign (gfc_expr * expr1, gfc_expr * expr2)
{
if (expr1->ts.u.cl->length == NULL
|| expr1->ts.u.cl->length->expr_type != EXPR_CONSTANT)
- return NULL;
+ return true;
if (expr2->ts.u.cl->length == NULL
|| expr2->ts.u.cl->length->expr_type != EXPR_CONSTANT)
- return NULL;
+ return true;
if (mpz_cmp (expr1->ts.u.cl->length->value.integer,
expr2->ts.u.cl->length->value.integer) != 0)
- return NULL;
+ return true;
}
/* Check that no LHS component references appear during an array
@@ -4931,7 +4933,7 @@ gfc_trans_arrayfunc_assign (gfc_expr * expr1, gfc_expr * expr2)
if (ref->type == REF_ARRAY)
seen_array_ref= true;
else if (ref->type == REF_COMPONENT && seen_array_ref)
- return NULL;
+ return true;
}
/* Check for a dependency. */
@@ -4939,6 +4941,62 @@ gfc_trans_arrayfunc_assign (gfc_expr * expr1, gfc_expr * expr2)
expr2->value.function.esym,
expr2->value.function.actual,
NOT_ELEMENTAL))
+ return true;
+
+ /* If we have reached here with an intrinsic function, we do not
+ need a temporary. */
+ if (expr2->value.function.isym)
+ return false;
+
+ /* If the LHS is a dummy, we need a temporary if it is not
+ INTENT(OUT). */
+ if (sym->attr.dummy && sym->attr.intent != INTENT_OUT)
+ return true;
+
+ /* A PURE function can unconditionally be called without a temporary. */
+ if (expr2->value.function.esym != NULL
+ && expr2->value.function.esym->attr.pure)
+ return false;
+
+ /* TODO a function that could correctly be declared PURE but is not
+ could do with returning false as well. */
+
+ if (!sym->attr.use_assoc
+ && !sym->attr.in_common
+ && !sym->attr.pointer
+ && !sym->attr.target
+ && expr2->value.function.esym)
+ {
+ /* A temporary is not needed if the function is not contained and
+ the variable is local or host associated and not a pointer or
+ a target. */
+ if (!expr2->value.function.esym->attr.contained)
+ return false;
+
+ /* A temporary is not needed if the variable is local and not
+ a pointer, a target or a result. */
+ if (sym->ns->parent
+ && expr2->value.function.esym->ns == sym->ns->parent)
+ return false;
+ }
+
+ /* Default to temporary use. */
+ return true;
+}
+
+
+/* Try to translate array(:) = func (...), where func is a transformational
+ array function, without using a temporary. Returns NULL if this isn't the
+ case. */
+
+static tree
+gfc_trans_arrayfunc_assign (gfc_expr * expr1, gfc_expr * expr2)
+{
+ gfc_se se;
+ gfc_ss *ss;
+ gfc_component *comp = NULL;
+
+ if (arrayfunc_assign_needs_temporary (expr1, expr2))
return NULL;
/* The frontend doesn't seem to bother filling in expr->symtree for intrinsic
diff --git a/gcc/fortran/trans-intrinsic.c b/gcc/fortran/trans-intrinsic.c
index 94dcc296dbf..06fd538d775 100644
--- a/gcc/fortran/trans-intrinsic.c
+++ b/gcc/fortran/trans-intrinsic.c
@@ -50,14 +50,12 @@ typedef struct GTY(()) gfc_intrinsic_map_t {
/* Enum value from the "language-independent", aka C-centric, part
of gcc, or END_BUILTINS of no such value set. */
- enum built_in_function code_r4;
- enum built_in_function code_r8;
- enum built_in_function code_r10;
- enum built_in_function code_r16;
- enum built_in_function code_c4;
- enum built_in_function code_c8;
- enum built_in_function code_c10;
- enum built_in_function code_c16;
+ enum built_in_function float_built_in;
+ enum built_in_function double_built_in;
+ enum built_in_function long_double_built_in;
+ enum built_in_function complex_float_built_in;
+ enum built_in_function complex_double_built_in;
+ enum built_in_function complex_long_double_built_in;
/* True if the naming pattern is to prepend "c" for complex and
append "f" for kind=4. False if the naming pattern is to
@@ -90,28 +88,33 @@ gfc_intrinsic_map_t;
except for atan2. */
#define DEFINE_MATH_BUILTIN(ID, NAME, ARGTYPE) \
{ GFC_ISYM_ ## ID, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
- BUILT_IN_ ## ID ## L, BUILT_IN_ ## ID ## L, (enum built_in_function) 0, \
- (enum built_in_function) 0, (enum built_in_function) 0, \
- (enum built_in_function) 0, true, false, true, NAME, NULL_TREE, \
- NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, \
- NULL_TREE},
+ BUILT_IN_ ## ID ## L, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
+ true, false, true, NAME, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, \
+ NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
#define DEFINE_MATH_BUILTIN_C(ID, NAME, ARGTYPE) \
{ GFC_ISYM_ ## ID, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
- BUILT_IN_ ## ID ## L, BUILT_IN_ ## ID ## L, BUILT_IN_C ## ID ## F, \
- BUILT_IN_C ## ID, BUILT_IN_C ## ID ## L, BUILT_IN_C ## ID ## L, true, \
- true, true, NAME, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, \
- NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
+ BUILT_IN_ ## ID ## L, BUILT_IN_C ## ID ## F, BUILT_IN_C ## ID, \
+ BUILT_IN_C ## ID ## L, true, true, true, NAME, NULL_TREE, NULL_TREE, \
+ NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
#define LIB_FUNCTION(ID, NAME, HAVE_COMPLEX) \
- { GFC_ISYM_ ## ID, END_BUILTINS, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
- END_BUILTINS, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
+ { GFC_ISYM_ ## ID, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
+ END_BUILTINS, END_BUILTINS, END_BUILTINS, \
false, HAVE_COMPLEX, true, NAME, NULL_TREE, NULL_TREE, NULL_TREE, \
NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE }
+#define OTHER_BUILTIN(ID, NAME, TYPE) \
+ { GFC_ISYM_NONE, BUILT_IN_ ## ID ## F, BUILT_IN_ ## ID, \
+ BUILT_IN_ ## ID ## L, END_BUILTINS, END_BUILTINS, END_BUILTINS, \
+ true, false, true, NAME, NULL_TREE, NULL_TREE, \
+ NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE},
+
static GTY(()) gfc_intrinsic_map_t gfc_intrinsic_map[] =
{
- /* Functions built into gcc itself. */
+ /* Functions built into gcc itself (DEFINE_MATH_BUILTIN and
+ DEFINE_MATH_BUILTIN_C), then the built-ins that don't correspond
+ to any GFC_ISYM id directly, which use the OTHER_BUILTIN macro. */
#include "mathbuiltins.def"
/* Functions in libgfortran. */
@@ -121,30 +124,45 @@ static GTY(()) gfc_intrinsic_map_t gfc_intrinsic_map[] =
LIB_FUNCTION (NONE, NULL, false)
};
+#undef OTHER_BUILTIN
#undef LIB_FUNCTION
#undef DEFINE_MATH_BUILTIN
#undef DEFINE_MATH_BUILTIN_C
-/* Structure for storing components of a floating number to be used by
- elemental functions to manipulate reals. */
-typedef struct
+
+enum rounding_mode { RND_ROUND, RND_TRUNC, RND_CEIL, RND_FLOOR };
+
+
+/* Find the correct variant of a given builtin from its argument. */
+static tree
+builtin_decl_for_precision (enum built_in_function base_built_in,
+ int precision)
{
- tree arg; /* Variable tree to view convert to integer. */
- tree expn; /* Variable tree to save exponent. */
- tree frac; /* Variable tree to save fraction. */
- tree smask; /* Constant tree of sign's mask. */
- tree emask; /* Constant tree of exponent's mask. */
- tree fmask; /* Constant tree of fraction's mask. */
- tree edigits; /* Constant tree of the number of exponent bits. */
- tree fdigits; /* Constant tree of the number of fraction bits. */
- tree f1; /* Constant tree of the f1 defined in the real model. */
- tree bias; /* Constant tree of the bias of exponent in the memory. */
- tree type; /* Type tree of arg1. */
- tree mtype; /* Type tree of integer type. Kind is that of arg1. */
+ int i = END_BUILTINS;
+
+ gfc_intrinsic_map_t *m;
+ for (m = gfc_intrinsic_map; m->double_built_in != base_built_in ; m++)
+ ;
+
+ if (precision == TYPE_PRECISION (float_type_node))
+ i = m->float_built_in;
+ else if (precision == TYPE_PRECISION (double_type_node))
+ i = m->double_built_in;
+ else if (precision == TYPE_PRECISION (long_double_type_node))
+ i = m->long_double_built_in;
+
+ return (i == END_BUILTINS ? NULL_TREE : built_in_decls[i]);
+}
+
+
+static tree
+builtin_decl_for_float_kind (enum built_in_function double_built_in, int kind)
+{
+ int i = gfc_validate_kind (BT_REAL, kind, false);
+ return builtin_decl_for_precision (double_built_in,
+ gfc_real_kinds[i].mode_precision);
}
-real_compnt_info;
-enum rounding_mode { RND_ROUND, RND_TRUNC, RND_CEIL, RND_FLOOR };
/* Evaluate the arguments to an intrinsic function. The value
of NARGS may be less than the actual number of arguments in EXPR
@@ -353,14 +371,10 @@ build_round_expr (tree arg, tree restype)
gcc_unreachable ();
/* Now, depending on the argument type, we choose between intrinsics. */
- if (argprec == TYPE_PRECISION (float_type_node))
- fn = built_in_decls[longlong ? BUILT_IN_LLROUNDF : BUILT_IN_LROUNDF];
- else if (argprec == TYPE_PRECISION (double_type_node))
- fn = built_in_decls[longlong ? BUILT_IN_LLROUND : BUILT_IN_LROUND];
- else if (argprec == TYPE_PRECISION (long_double_type_node))
- fn = built_in_decls[longlong ? BUILT_IN_LLROUNDL : BUILT_IN_LROUNDL];
+ if (longlong)
+ fn = builtin_decl_for_precision (BUILT_IN_LLROUND, argprec);
else
- gcc_unreachable ();
+ fn = builtin_decl_for_precision (BUILT_IN_LROUND, argprec);
return fold_convert (restype, build_call_expr_loc (input_location,
fn, 1, arg));
@@ -416,6 +430,7 @@ gfc_conv_intrinsic_aint (gfc_se * se, gfc_expr * expr, enum rounding_mode op)
tree arg[2];
tree tmp;
tree cond;
+ tree decl;
mpfr_t huge;
int n, nargs;
int kind;
@@ -423,44 +438,16 @@ gfc_conv_intrinsic_aint (gfc_se * se, gfc_expr * expr, enum rounding_mode op)
kind = expr->ts.kind;
nargs = gfc_intrinsic_argument_list_length (expr);
- n = END_BUILTINS;
+ decl = NULL_TREE;
/* We have builtin functions for some cases. */
switch (op)
{
case RND_ROUND:
- switch (kind)
- {
- case 4:
- n = BUILT_IN_ROUNDF;
- break;
-
- case 8:
- n = BUILT_IN_ROUND;
- break;
-
- case 10:
- case 16:
- n = BUILT_IN_ROUNDL;
- break;
- }
+ decl = builtin_decl_for_float_kind (BUILT_IN_ROUND, kind);
break;
case RND_TRUNC:
- switch (kind)
- {
- case 4:
- n = BUILT_IN_TRUNCF;
- break;
-
- case 8:
- n = BUILT_IN_TRUNC;
- break;
-
- case 10:
- case 16:
- n = BUILT_IN_TRUNCL;
- break;
- }
+ decl = builtin_decl_for_float_kind (BUILT_IN_TRUNC, kind);
break;
default:
@@ -472,11 +459,9 @@ gfc_conv_intrinsic_aint (gfc_se * se, gfc_expr * expr, enum rounding_mode op)
gfc_conv_intrinsic_function_args (se, expr, arg, nargs);
/* Use a builtin function if one exists. */
- if (n != END_BUILTINS)
+ if (decl != NULL_TREE)
{
- tmp = built_in_decls[n];
- se->expr = build_call_expr_loc (input_location,
- tmp, 1, arg[0]);
+ se->expr = build_call_expr_loc (input_location, decl, 1, arg[0]);
return;
}
@@ -580,24 +565,30 @@ gfc_build_intrinsic_lib_fndecls (void)
gfc_intrinsic_map_t *m;
/* Add GCC builtin functions. */
- for (m = gfc_intrinsic_map; m->id != GFC_ISYM_NONE; m++)
+ for (m = gfc_intrinsic_map;
+ m->id != GFC_ISYM_NONE || m->double_built_in != END_BUILTINS; m++)
{
- if (m->code_r4 != END_BUILTINS)
- m->real4_decl = built_in_decls[m->code_r4];
- if (m->code_r8 != END_BUILTINS)
- m->real8_decl = built_in_decls[m->code_r8];
- if (m->code_r10 != END_BUILTINS)
- m->real10_decl = built_in_decls[m->code_r10];
- if (m->code_r16 != END_BUILTINS)
- m->real16_decl = built_in_decls[m->code_r16];
- if (m->code_c4 != END_BUILTINS)
- m->complex4_decl = built_in_decls[m->code_c4];
- if (m->code_c8 != END_BUILTINS)
- m->complex8_decl = built_in_decls[m->code_c8];
- if (m->code_c10 != END_BUILTINS)
- m->complex10_decl = built_in_decls[m->code_c10];
- if (m->code_c16 != END_BUILTINS)
- m->complex16_decl = built_in_decls[m->code_c16];
+ if (m->float_built_in != END_BUILTINS)
+ m->real4_decl = built_in_decls[m->float_built_in];
+ if (m->complex_float_built_in != END_BUILTINS)
+ m->complex4_decl = built_in_decls[m->complex_float_built_in];
+ if (m->double_built_in != END_BUILTINS)
+ m->real8_decl = built_in_decls[m->double_built_in];
+ if (m->complex_double_built_in != END_BUILTINS)
+ m->complex8_decl = built_in_decls[m->complex_double_built_in];
+
+ /* If real(kind=10) exists, it is always long double. */
+ if (m->long_double_built_in != END_BUILTINS)
+ m->real10_decl = built_in_decls[m->long_double_built_in];
+ if (m->complex_long_double_built_in != END_BUILTINS)
+ m->complex10_decl = built_in_decls[m->complex_long_double_built_in];
+
+ /* For now, we assume that if real(kind=16) exists, it is long double.
+ Later, we will deal with __float128 and break this assumption. */
+ if (m->long_double_built_in != END_BUILTINS)
+ m->real16_decl = built_in_decls[m->long_double_built_in];
+ if (m->complex_long_double_built_in != END_BUILTINS)
+ m->complex16_decl = built_in_decls[m->complex_long_double_built_in];
}
}
@@ -666,18 +657,18 @@ gfc_get_intrinsic_lib_fndecl (gfc_intrinsic_map_t * m, gfc_expr * expr)
if (m->libm_name)
{
- if (ts->kind == 4)
+ int n = gfc_validate_kind (BT_REAL, ts->kind, false);
+ if (gfc_real_kinds[n].c_float)
snprintf (name, sizeof (name), "%s%s%s",
- ts->type == BT_COMPLEX ? "c" : "", m->name, "f");
- else if (ts->kind == 8)
+ ts->type == BT_COMPLEX ? "c" : "", m->name, "f");
+ else if (gfc_real_kinds[n].c_double)
snprintf (name, sizeof (name), "%s%s",
- ts->type == BT_COMPLEX ? "c" : "", m->name);
+ ts->type == BT_COMPLEX ? "c" : "", m->name);
+ else if (gfc_real_kinds[n].c_long_double)
+ snprintf (name, sizeof (name), "%s%s%s",
+ ts->type == BT_COMPLEX ? "c" : "", m->name, "l");
else
- {
- gcc_assert (ts->kind == 10 || ts->kind == 16);
- snprintf (name, sizeof (name), "%s%s%s",
- ts->type == BT_COMPLEX ? "c" : "", m->name, "l");
- }
+ gcc_unreachable ();
}
else
{
@@ -725,7 +716,8 @@ gfc_conv_intrinsic_lib_function (gfc_se * se, gfc_expr * expr)
id = expr->value.function.isym->id;
/* Find the entry for this function. */
- for (m = gfc_intrinsic_map; m->id != GFC_ISYM_NONE; m++)
+ for (m = gfc_intrinsic_map;
+ m->id != GFC_ISYM_NONE || m->double_built_in != END_BUILTINS; m++)
{
if (id == m->id)
break;
@@ -787,31 +779,16 @@ gfc_trans_same_strlen_check (const char* intr_name, locus* where,
static void
gfc_conv_intrinsic_exponent (gfc_se *se, gfc_expr *expr)
{
- tree arg, type, res, tmp;
- int frexp;
+ tree arg, type, res, tmp, frexp;
- switch (expr->value.function.actual->expr->ts.kind)
- {
- case 4:
- frexp = BUILT_IN_FREXPF;
- break;
- case 8:
- frexp = BUILT_IN_FREXP;
- break;
- case 10:
- case 16:
- frexp = BUILT_IN_FREXPL;
- break;
- default:
- gcc_unreachable ();
- }
+ frexp = builtin_decl_for_float_kind (BUILT_IN_FREXP,
+ expr->value.function.actual->expr->ts.kind);
gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
res = gfc_create_var (integer_type_node, NULL);
- tmp = build_call_expr_loc (input_location,
- built_in_decls[frexp], 2, arg,
- gfc_build_addr_expr (NULL_TREE, res));
+ tmp = build_call_expr_loc (input_location, frexp, 2, arg,
+ gfc_build_addr_expr (NULL_TREE, res));
gfc_add_expr_to_block (&se->pre, tmp);
type = gfc_typenode_for_spec (&expr->ts);
@@ -991,8 +968,7 @@ gfc_conv_intrinsic_bound (gfc_se * se, gfc_expr * expr, int upper)
static void
gfc_conv_intrinsic_abs (gfc_se * se, gfc_expr * expr)
{
- tree arg;
- int n;
+ tree arg, cabs;
gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
@@ -1004,23 +980,8 @@ gfc_conv_intrinsic_abs (gfc_se * se, gfc_expr * expr)
break;
case BT_COMPLEX:
- switch (expr->ts.kind)
- {
- case 4:
- n = BUILT_IN_CABSF;
- break;
- case 8:
- n = BUILT_IN_CABS;
- break;
- case 10:
- case 16:
- n = BUILT_IN_CABSL;
- break;
- default:
- gcc_unreachable ();
- }
- se->expr = build_call_expr_loc (input_location,
- built_in_decls[n], 1, arg);
+ cabs = builtin_decl_for_float_kind (BUILT_IN_CABS, expr->ts.kind);
+ se->expr = build_call_expr_loc (input_location, cabs, 1, arg);
break;
default:
@@ -1072,6 +1033,7 @@ gfc_conv_intrinsic_mod (gfc_se * se, gfc_expr * expr, int modulo)
tree tmp;
tree test;
tree test2;
+ tree fmod;
mpfr_t huge;
int n, ikind;
tree args[2];
@@ -1091,33 +1053,16 @@ gfc_conv_intrinsic_mod (gfc_se * se, gfc_expr * expr, int modulo)
break;
case BT_REAL:
- n = END_BUILTINS;
+ fmod = NULL_TREE;
/* Check if we have a builtin fmod. */
- switch (expr->ts.kind)
- {
- case 4:
- n = BUILT_IN_FMODF;
- break;
-
- case 8:
- n = BUILT_IN_FMOD;
- break;
-
- case 10:
- case 16:
- n = BUILT_IN_FMODL;
- break;
-
- default:
- break;
- }
+ fmod = builtin_decl_for_float_kind (BUILT_IN_FMOD, expr->ts.kind);
/* Use it if it exists. */
- if (n != END_BUILTINS)
+ if (fmod != NULL_TREE)
{
- tmp = build_addr (built_in_decls[n], current_function_decl);
+ tmp = build_addr (fmod, current_function_decl);
se->expr = build_call_array_loc (input_location,
- TREE_TYPE (TREE_TYPE (built_in_decls[n])),
+ TREE_TYPE (TREE_TYPE (fmod)),
tmp, 2, args);
if (modulo == 0)
return;
@@ -1135,7 +1080,7 @@ gfc_conv_intrinsic_mod (gfc_se * se, gfc_expr * expr, int modulo)
test = (fmod (arg, arg2) != 0) && ((arg < 0) xor (arg2 < 0))
thereby avoiding another division and retaining the accuracy
of the builtin function. */
- if (n != END_BUILTINS && modulo)
+ if (fmod != NULL_TREE && modulo)
{
tree zero = gfc_build_const (type, integer_zero_node);
tmp = gfc_evaluate_now (se->expr, &se->pre);
@@ -1232,24 +1177,8 @@ gfc_conv_intrinsic_sign (gfc_se * se, gfc_expr * expr)
{
tree abs;
- switch (expr->ts.kind)
- {
- case 4:
- tmp = built_in_decls[BUILT_IN_COPYSIGNF];
- abs = built_in_decls[BUILT_IN_FABSF];
- break;
- case 8:
- tmp = built_in_decls[BUILT_IN_COPYSIGN];
- abs = built_in_decls[BUILT_IN_FABS];
- break;
- case 10:
- case 16:
- tmp = built_in_decls[BUILT_IN_COPYSIGNL];
- abs = built_in_decls[BUILT_IN_FABSL];
- break;
- default:
- gcc_unreachable ();
- }
+ tmp = builtin_decl_for_float_kind (BUILT_IN_COPYSIGN, expr->ts.kind);
+ abs = builtin_decl_for_float_kind (BUILT_IN_FABS, expr->ts.kind);
/* We explicitly have to ignore the minus sign. We do so by using
result = (arg1 == 0) ? abs(arg0) : copysign(arg0, arg1). */
@@ -1264,8 +1193,8 @@ gfc_conv_intrinsic_sign (gfc_se * se, gfc_expr * expr)
build_call_expr (tmp, 2, args[0], args[1]));
}
else
- se->expr = build_call_expr_loc (input_location,
- tmp, 2, args[0], args[1]);
+ se->expr = build_call_expr_loc (input_location, tmp, 2,
+ args[0], args[1]);
return;
}
@@ -1400,7 +1329,7 @@ gfc_conv_intrinsic_fdate (gfc_se * se, gfc_expr * expr)
args = (tree *) alloca (sizeof (tree) * num_args);
var = gfc_create_var (pchar_type_node, "pstr");
- len = gfc_create_var (gfc_get_int_type (4), "len");
+ len = gfc_create_var (gfc_charlen_type_node, "len");
gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
args[0] = gfc_build_addr_expr (NULL_TREE, var);
@@ -1441,7 +1370,7 @@ gfc_conv_intrinsic_ttynam (gfc_se * se, gfc_expr * expr)
args = (tree *) alloca (sizeof (tree) * num_args);
var = gfc_create_var (pchar_type_node, "pstr");
- len = gfc_create_var (gfc_get_int_type (4), "len");
+ len = gfc_create_var (gfc_charlen_type_node, "len");
gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
args[0] = gfc_build_addr_expr (NULL_TREE, var);
@@ -3620,32 +3549,16 @@ gfc_conv_intrinsic_merge (gfc_se * se, gfc_expr * expr)
static void
gfc_conv_intrinsic_fraction (gfc_se * se, gfc_expr * expr)
{
- tree arg, type, tmp;
- int frexp;
+ tree arg, type, tmp, frexp;
- switch (expr->ts.kind)
- {
- case 4:
- frexp = BUILT_IN_FREXPF;
- break;
- case 8:
- frexp = BUILT_IN_FREXP;
- break;
- case 10:
- case 16:
- frexp = BUILT_IN_FREXPL;
- break;
- default:
- gcc_unreachable ();
- }
+ frexp = builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
type = gfc_typenode_for_spec (&expr->ts);
gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
tmp = gfc_create_var (integer_type_node, NULL);
- se->expr = build_call_expr_loc (input_location,
- built_in_decls[frexp], 2,
- fold_convert (type, arg),
- gfc_build_addr_expr (NULL_TREE, tmp));
+ se->expr = build_call_expr_loc (input_location, frexp, 2,
+ fold_convert (type, arg),
+ gfc_build_addr_expr (NULL_TREE, tmp));
se->expr = fold_convert (type, se->expr);
}
@@ -3657,41 +3570,19 @@ gfc_conv_intrinsic_fraction (gfc_se * se, gfc_expr * expr)
static void
gfc_conv_intrinsic_nearest (gfc_se * se, gfc_expr * expr)
{
- tree args[2], type, tmp;
- int nextafter, copysign, huge_val;
+ tree args[2], type, tmp, nextafter, copysign, huge_val;
- switch (expr->ts.kind)
- {
- case 4:
- nextafter = BUILT_IN_NEXTAFTERF;
- copysign = BUILT_IN_COPYSIGNF;
- huge_val = BUILT_IN_HUGE_VALF;
- break;
- case 8:
- nextafter = BUILT_IN_NEXTAFTER;
- copysign = BUILT_IN_COPYSIGN;
- huge_val = BUILT_IN_HUGE_VAL;
- break;
- case 10:
- case 16:
- nextafter = BUILT_IN_NEXTAFTERL;
- copysign = BUILT_IN_COPYSIGNL;
- huge_val = BUILT_IN_HUGE_VALL;
- break;
- default:
- gcc_unreachable ();
- }
+ nextafter = builtin_decl_for_float_kind (BUILT_IN_NEXTAFTER, expr->ts.kind);
+ copysign = builtin_decl_for_float_kind (BUILT_IN_COPYSIGN, expr->ts.kind);
+ huge_val = builtin_decl_for_float_kind (BUILT_IN_HUGE_VAL, expr->ts.kind);
type = gfc_typenode_for_spec (&expr->ts);
gfc_conv_intrinsic_function_args (se, expr, args, 2);
- tmp = build_call_expr_loc (input_location,
- built_in_decls[copysign], 2,
- build_call_expr_loc (input_location,
- built_in_decls[huge_val], 0),
- fold_convert (type, args[1]));
- se->expr = build_call_expr_loc (input_location,
- built_in_decls[nextafter], 2,
- fold_convert (type, args[0]), tmp);
+ tmp = build_call_expr_loc (input_location, copysign, 2,
+ build_call_expr_loc (input_location, huge_val, 0),
+ fold_convert (type, args[1]));
+ se->expr = build_call_expr_loc (input_location, nextafter, 2,
+ fold_convert (type, args[0]), tmp);
se->expr = fold_convert (type, se->expr);
}
@@ -3717,8 +3608,8 @@ static void
gfc_conv_intrinsic_spacing (gfc_se * se, gfc_expr * expr)
{
tree arg, type, prec, emin, tiny, res, e;
- tree cond, tmp;
- int frexp, scalbn, k;
+ tree cond, tmp, frexp, scalbn;
+ int k;
stmtblock_t block;
k = gfc_validate_kind (BT_REAL, expr->ts.kind, false);
@@ -3726,24 +3617,8 @@ gfc_conv_intrinsic_spacing (gfc_se * se, gfc_expr * expr)
emin = build_int_cst (NULL_TREE, gfc_real_kinds[k].min_exponent - 1);
tiny = gfc_conv_mpfr_to_tree (gfc_real_kinds[k].tiny, expr->ts.kind, 0);
- switch (expr->ts.kind)
- {
- case 4:
- frexp = BUILT_IN_FREXPF;
- scalbn = BUILT_IN_SCALBNF;
- break;
- case 8:
- frexp = BUILT_IN_FREXP;
- scalbn = BUILT_IN_SCALBN;
- break;
- case 10:
- case 16:
- frexp = BUILT_IN_FREXPL;
- scalbn = BUILT_IN_SCALBNL;
- break;
- default:
- gcc_unreachable ();
- }
+ frexp = builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
+ scalbn = builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
arg = gfc_evaluate_now (arg, &se->pre);
@@ -3755,17 +3630,15 @@ gfc_conv_intrinsic_spacing (gfc_se * se, gfc_expr * expr)
/* Build the block for s /= 0. */
gfc_start_block (&block);
- tmp = build_call_expr_loc (input_location,
- built_in_decls[frexp], 2, arg,
- gfc_build_addr_expr (NULL_TREE, e));
+ tmp = build_call_expr_loc (input_location, frexp, 2, arg,
+ gfc_build_addr_expr (NULL_TREE, e));
gfc_add_expr_to_block (&block, tmp);
tmp = fold_build2 (MINUS_EXPR, integer_type_node, e, prec);
gfc_add_modify (&block, e, fold_build2 (MAX_EXPR, integer_type_node,
tmp, emin));
- tmp = build_call_expr_loc (input_location,
- built_in_decls[scalbn], 2,
+ tmp = build_call_expr_loc (input_location, scalbn, 2,
build_real_from_int_cst (type, integer_one_node), e);
gfc_add_modify (&block, res, tmp);
@@ -3796,33 +3669,16 @@ gfc_conv_intrinsic_spacing (gfc_se * se, gfc_expr * expr)
static void
gfc_conv_intrinsic_rrspacing (gfc_se * se, gfc_expr * expr)
{
- tree arg, type, e, x, cond, stmt, tmp;
- int frexp, scalbn, fabs, prec, k;
+ tree arg, type, e, x, cond, stmt, tmp, frexp, scalbn, fabs;
+ int prec, k;
stmtblock_t block;
k = gfc_validate_kind (BT_REAL, expr->ts.kind, false);
prec = gfc_real_kinds[k].digits;
- switch (expr->ts.kind)
- {
- case 4:
- frexp = BUILT_IN_FREXPF;
- scalbn = BUILT_IN_SCALBNF;
- fabs = BUILT_IN_FABSF;
- break;
- case 8:
- frexp = BUILT_IN_FREXP;
- scalbn = BUILT_IN_SCALBN;
- fabs = BUILT_IN_FABS;
- break;
- case 10:
- case 16:
- frexp = BUILT_IN_FREXPL;
- scalbn = BUILT_IN_SCALBNL;
- fabs = BUILT_IN_FABSL;
- break;
- default:
- gcc_unreachable ();
- }
+
+ frexp = builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
+ scalbn = builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
+ fabs = builtin_decl_for_float_kind (BUILT_IN_FABS, expr->ts.kind);
type = gfc_typenode_for_spec (&expr->ts);
gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
@@ -3831,20 +3687,17 @@ gfc_conv_intrinsic_rrspacing (gfc_se * se, gfc_expr * expr)
e = gfc_create_var (integer_type_node, NULL);
x = gfc_create_var (type, NULL);
gfc_add_modify (&se->pre, x,
- build_call_expr_loc (input_location,
- built_in_decls[fabs], 1, arg));
+ build_call_expr_loc (input_location, fabs, 1, arg));
gfc_start_block (&block);
- tmp = build_call_expr_loc (input_location,
- built_in_decls[frexp], 2, arg,
- gfc_build_addr_expr (NULL_TREE, e));
+ tmp = build_call_expr_loc (input_location, frexp, 2, arg,
+ gfc_build_addr_expr (NULL_TREE, e));
gfc_add_expr_to_block (&block, tmp);
tmp = fold_build2 (MINUS_EXPR, integer_type_node,
build_int_cst (NULL_TREE, prec), e);
- tmp = build_call_expr_loc (input_location,
- built_in_decls[scalbn], 2, x, tmp);
+ tmp = build_call_expr_loc (input_location, scalbn, 2, x, tmp);
gfc_add_modify (&block, x, tmp);
stmt = gfc_finish_block (&block);
@@ -3861,31 +3714,15 @@ gfc_conv_intrinsic_rrspacing (gfc_se * se, gfc_expr * expr)
static void
gfc_conv_intrinsic_scale (gfc_se * se, gfc_expr * expr)
{
- tree args[2], type;
- int scalbn;
+ tree args[2], type, scalbn;
- switch (expr->ts.kind)
- {
- case 4:
- scalbn = BUILT_IN_SCALBNF;
- break;
- case 8:
- scalbn = BUILT_IN_SCALBN;
- break;
- case 10:
- case 16:
- scalbn = BUILT_IN_SCALBNL;
- break;
- default:
- gcc_unreachable ();
- }
+ scalbn = builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
type = gfc_typenode_for_spec (&expr->ts);
gfc_conv_intrinsic_function_args (se, expr, args, 2);
- se->expr = build_call_expr_loc (input_location,
- built_in_decls[scalbn], 2,
- fold_convert (type, args[0]),
- fold_convert (integer_type_node, args[1]));
+ se->expr = build_call_expr_loc (input_location, scalbn, 2,
+ fold_convert (type, args[0]),
+ fold_convert (integer_type_node, args[1]));
se->expr = fold_convert (type, se->expr);
}
@@ -3895,39 +3732,20 @@ gfc_conv_intrinsic_scale (gfc_se * se, gfc_expr * expr)
static void
gfc_conv_intrinsic_set_exponent (gfc_se * se, gfc_expr * expr)
{
- tree args[2], type, tmp;
- int frexp, scalbn;
+ tree args[2], type, tmp, frexp, scalbn;
- switch (expr->ts.kind)
- {
- case 4:
- frexp = BUILT_IN_FREXPF;
- scalbn = BUILT_IN_SCALBNF;
- break;
- case 8:
- frexp = BUILT_IN_FREXP;
- scalbn = BUILT_IN_SCALBN;
- break;
- case 10:
- case 16:
- frexp = BUILT_IN_FREXPL;
- scalbn = BUILT_IN_SCALBNL;
- break;
- default:
- gcc_unreachable ();
- }
+ frexp = builtin_decl_for_float_kind (BUILT_IN_FREXP, expr->ts.kind);
+ scalbn = builtin_decl_for_float_kind (BUILT_IN_SCALBN, expr->ts.kind);
type = gfc_typenode_for_spec (&expr->ts);
gfc_conv_intrinsic_function_args (se, expr, args, 2);
tmp = gfc_create_var (integer_type_node, NULL);
- tmp = build_call_expr_loc (input_location,
- built_in_decls[frexp], 2,
- fold_convert (type, args[0]),
- gfc_build_addr_expr (NULL_TREE, tmp));
- se->expr = build_call_expr_loc (input_location,
- built_in_decls[scalbn], 2, tmp,
- fold_convert (integer_type_node, args[1]));
+ tmp = build_call_expr_loc (input_location, frexp, 2,
+ fold_convert (type, args[0]),
+ gfc_build_addr_expr (NULL_TREE, tmp));
+ se->expr = build_call_expr_loc (input_location, scalbn, 2, tmp,
+ fold_convert (integer_type_node, args[1]));
se->expr = fold_convert (type, se->expr);
}
@@ -4598,6 +4416,8 @@ gfc_conv_associated (gfc_se *se, gfc_expr *expr)
else
{
/* An optional target. */
+ if (arg2->expr->ts.type == BT_CLASS)
+ gfc_add_component_ref (arg2->expr, "$data");
ss2 = gfc_walk_expr (arg2->expr);
nonzero_charlen = NULL_TREE;
@@ -4805,7 +4625,7 @@ gfc_conv_intrinsic_trim (gfc_se * se, gfc_expr * expr)
var = gfc_create_var (gfc_get_pchar_type (expr->ts.kind), "pstr");
addr = gfc_build_addr_expr (ppvoid_type_node, var);
- len = gfc_create_var (gfc_get_int_type (4), "len");
+ len = gfc_create_var (gfc_charlen_type_node, "len");
gfc_conv_intrinsic_function_args (se, expr, &args[2], num_args - 2);
args[0] = gfc_build_addr_expr (NULL_TREE, len);
diff --git a/gcc/fortran/trans-openmp.c b/gcc/fortran/trans-openmp.c
index 50e7847d0e1..7a7d33088d7 100644
--- a/gcc/fortran/trans-openmp.c
+++ b/gcc/fortran/trans-openmp.c
@@ -75,7 +75,10 @@ gfc_omp_privatize_by_reference (const_tree decl)
enum omp_clause_default_kind
gfc_omp_predetermined_sharing (tree decl)
{
- if (DECL_ARTIFICIAL (decl) && ! GFC_DECL_RESULT (decl))
+ if (DECL_ARTIFICIAL (decl)
+ && ! GFC_DECL_RESULT (decl)
+ && ! (DECL_LANG_SPECIFIC (decl)
+ && GFC_DECL_SAVED_DESCRIPTOR (decl)))
return OMP_CLAUSE_DEFAULT_SHARED;
/* Cray pointees shouldn't be listed in any clauses and should be
@@ -118,6 +121,19 @@ gfc_omp_predetermined_sharing (tree decl)
return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
}
+/* Return decl that should be used when reporting DEFAULT(NONE)
+ diagnostics. */
+
+tree
+gfc_omp_report_decl (tree decl)
+{
+ if (DECL_ARTIFICIAL (decl)
+ && DECL_LANG_SPECIFIC (decl)
+ && GFC_DECL_SAVED_DESCRIPTOR (decl))
+ return GFC_DECL_SAVED_DESCRIPTOR (decl);
+
+ return decl;
+}
/* Return true if DECL in private clause needs
OMP_CLAUSE_PRIVATE_OUTER_REF on the private clause. */
@@ -1134,6 +1150,14 @@ gfc_trans_omp_critical (gfc_code *code)
return build2 (OMP_CRITICAL, void_type_node, stmt, name);
}
+typedef struct dovar_init_d {
+ tree var;
+ tree init;
+} dovar_init;
+
+DEF_VEC_O(dovar_init);
+DEF_VEC_ALLOC_O(dovar_init,heap);
+
static tree
gfc_trans_omp_do (gfc_code *code, stmtblock_t *pblock,
gfc_omp_clauses *do_clauses, tree par_clauses)
@@ -1145,7 +1169,9 @@ gfc_trans_omp_do (gfc_code *code, stmtblock_t *pblock,
stmtblock_t body;
gfc_omp_clauses *clauses = code->ext.omp_clauses;
int i, collapse = clauses->collapse;
- tree dovar_init = NULL_TREE;
+ VEC(dovar_init,heap) *inits = NULL;
+ dovar_init *di;
+ unsigned ix;
if (collapse <= 0)
collapse = 1;
@@ -1260,7 +1286,9 @@ gfc_trans_omp_do (gfc_code *code, stmtblock_t *pblock,
/* Initialize DOVAR. */
tmp = fold_build2 (MULT_EXPR, type, count, step);
tmp = fold_build2 (PLUS_EXPR, type, from, tmp);
- dovar_init = tree_cons (dovar, tmp, dovar_init);
+ di = VEC_safe_push (dovar_init, heap, inits, NULL);
+ di->var = dovar;
+ di->init = tmp;
}
if (!dovar_found)
@@ -1329,24 +1357,18 @@ gfc_trans_omp_do (gfc_code *code, stmtblock_t *pblock,
gfc_start_block (&body);
- dovar_init = nreverse (dovar_init);
- while (dovar_init)
- {
- gfc_add_modify (&body, TREE_PURPOSE (dovar_init),
- TREE_VALUE (dovar_init));
- dovar_init = TREE_CHAIN (dovar_init);
- }
+ for (ix = 0; VEC_iterate (dovar_init, inits, ix, di); ix++)
+ gfc_add_modify (&body, di->var, di->init);
+ VEC_free (dovar_init, heap, inits);
/* Cycle statement is implemented with a goto. Exit statement must not be
present for this loop. */
cycle_label = gfc_build_label_decl (NULL_TREE);
- /* Put these labels where they can be found later. We put the
- labels in a TREE_LIST node (because TREE_CHAIN is already
- used). cycle_label goes in TREE_PURPOSE (backend_decl), exit
- label in TREE_VALUE (backend_decl). */
+ /* Put these labels where they can be found later. */
- code->block->backend_decl = tree_cons (cycle_label, NULL, NULL);
+ code->block->cycle_label = cycle_label;
+ code->block->exit_label = NULL_TREE;
/* Main loop body. */
tmp = gfc_trans_omp_code (code->block->next, true);
diff --git a/gcc/fortran/trans-stmt.c b/gcc/fortran/trans-stmt.c
index 37b577f2cc4..6fa84b91694 100644
--- a/gcc/fortran/trans-stmt.c
+++ b/gcc/fortran/trans-stmt.c
@@ -850,7 +850,7 @@ gfc_trans_block_construct (gfc_code* code)
stmtblock_t body;
tree tmp;
- ns = code->ext.ns;
+ ns = code->ext.block.ns;
gcc_assert (ns);
sym = ns->proc_name;
gcc_assert (sym);
@@ -928,7 +928,8 @@ gfc_trans_simple_do (gfc_code * code, stmtblock_t *pblock, tree dovar,
exit_label = gfc_build_label_decl (NULL_TREE);
/* Put the labels where they can be found later. See gfc_trans_do(). */
- code->block->backend_decl = tree_cons (cycle_label, exit_label, NULL);
+ code->block->cycle_label = cycle_label;
+ code->block->exit_label = exit_label;
/* Loop body. */
gfc_start_block (&body);
@@ -1196,12 +1197,10 @@ gfc_trans_do (gfc_code * code, tree exit_cond)
/* Loop body. */
gfc_start_block (&body);
- /* Put these labels where they can be found later. We put the
- labels in a TREE_LIST node (because TREE_CHAIN is already
- used). cycle_label goes in TREE_PURPOSE (backend_decl), exit
- label in TREE_VALUE (backend_decl). */
+ /* Put these labels where they can be found later. */
- code->block->backend_decl = tree_cons (cycle_label, exit_label, NULL);
+ code->block->cycle_label = cycle_label;
+ code->block->exit_label = exit_label;
/* Main loop body. */
tmp = gfc_trans_code_cond (code->block->next, exit_cond);
@@ -1305,7 +1304,8 @@ gfc_trans_do_while (gfc_code * code)
exit_label = gfc_build_label_decl (NULL_TREE);
/* Put the labels where they can be found later. See gfc_trans_do(). */
- code->block->backend_decl = tree_cons (cycle_label, exit_label, NULL);
+ code->block->cycle_label = cycle_label;
+ code->block->exit_label = exit_label;
/* Create a GIMPLE version of the exit condition. */
gfc_init_se (&cond, NULL);
@@ -4080,7 +4080,7 @@ gfc_trans_cycle (gfc_code * code)
{
tree cycle_label;
- cycle_label = TREE_PURPOSE (code->ext.whichloop->backend_decl);
+ cycle_label = code->ext.whichloop->cycle_label;
TREE_USED (cycle_label) = 1;
return build1_v (GOTO_EXPR, cycle_label);
}
@@ -4095,7 +4095,7 @@ gfc_trans_exit (gfc_code * code)
{
tree exit_label;
- exit_label = TREE_VALUE (code->ext.whichloop->backend_decl);
+ exit_label = code->ext.whichloop->exit_label;
TREE_USED (exit_label) = 1;
return build1_v (GOTO_EXPR, exit_label);
}
@@ -4155,20 +4155,23 @@ gfc_trans_allocate (gfc_code * code)
/* A scalar or derived type. */
/* Determine allocate size. */
- if (code->expr3 && code->expr3->ts.type == BT_CLASS)
+ if (al->expr->ts.type == BT_CLASS && code->expr3)
{
- gfc_expr *sz;
- gfc_se se_sz;
- sz = gfc_copy_expr (code->expr3);
- gfc_add_component_ref (sz, "$vptr");
- gfc_add_component_ref (sz, "$size");
- gfc_init_se (&se_sz, NULL);
- gfc_conv_expr (&se_sz, sz);
- gfc_free_expr (sz);
- memsz = se_sz.expr;
+ if (code->expr3->ts.type == BT_CLASS)
+ {
+ gfc_expr *sz;
+ gfc_se se_sz;
+ sz = gfc_copy_expr (code->expr3);
+ gfc_add_component_ref (sz, "$vptr");
+ gfc_add_component_ref (sz, "$size");
+ gfc_init_se (&se_sz, NULL);
+ gfc_conv_expr (&se_sz, sz);
+ gfc_free_expr (sz);
+ memsz = se_sz.expr;
+ }
+ else
+ memsz = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&code->expr3->ts));
}
- else if (code->expr3 && code->expr3->ts.type != BT_CLASS)
- memsz = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&code->expr3->ts));
else if (code->ext.alloc.ts.type != BT_UNKNOWN)
memsz = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&code->ext.alloc.ts));
else
@@ -4230,7 +4233,7 @@ gfc_trans_allocate (gfc_code * code)
gfc_add_expr_to_block (&block, tmp);
/* Initialization via SOURCE block. */
- if (code->expr3)
+ if (code->expr3 && !code->expr3->mold)
{
gfc_expr *rhs = gfc_copy_expr (code->expr3);
if (al->expr->ts.type == BT_CLASS)
@@ -4266,7 +4269,7 @@ gfc_trans_allocate (gfc_code * code)
rhs = NULL;
if (code->expr3 && code->expr3->ts.type == BT_CLASS)
{
- /* VPTR must be determined at run time. */
+ /* Polymorphic SOURCE: VPTR must be determined at run time. */
rhs = gfc_copy_expr (code->expr3);
gfc_add_component_ref (rhs, "$vptr");
tmp = gfc_trans_pointer_assignment (lhs, rhs);
diff --git a/gcc/fortran/trans-types.c b/gcc/fortran/trans-types.c
index d794c2fb668..2f5b759886d 100644
--- a/gcc/fortran/trans-types.c
+++ b/gcc/fortran/trans-types.c
@@ -1202,7 +1202,8 @@ gfc_is_nodesc_array (gfc_symbol * sym)
static tree
gfc_build_array_type (tree type, gfc_array_spec * as,
- enum gfc_array_kind akind, bool restricted)
+ enum gfc_array_kind akind, bool restricted,
+ bool contiguous)
{
tree lbound[GFC_MAX_DIMENSIONS];
tree ubound[GFC_MAX_DIMENSIONS];
@@ -1219,7 +1220,8 @@ gfc_build_array_type (tree type, gfc_array_spec * as,
}
if (as->type == AS_ASSUMED_SHAPE)
- akind = GFC_ARRAY_ASSUMED_SHAPE;
+ akind = contiguous ? GFC_ARRAY_ASSUMED_SHAPE_CONT
+ : GFC_ARRAY_ASSUMED_SHAPE;
return gfc_get_array_type_bounds (type, as->rank, as->corank, lbound,
ubound, 0, akind, restricted);
}
@@ -1390,8 +1392,8 @@ gfc_get_nodesc_array_type (tree etype, gfc_array_spec * as, gfc_packed packed,
type = make_node (ARRAY_TYPE);
GFC_ARRAY_TYPE_P (type) = 1;
- TYPE_LANG_SPECIFIC (type) = (struct lang_type *)
- ggc_alloc_cleared (sizeof (struct lang_type));
+ TYPE_LANG_SPECIFIC (type)
+ = ggc_alloc_cleared_lang_type (sizeof (struct lang_type));
known_stride = (packed != PACKED_NO);
known_offset = 1;
@@ -1631,8 +1633,8 @@ gfc_get_array_type_bounds (tree etype, int dimen, int codimen, tree * lbound,
TYPE_NAME (fat_type) = get_identifier (name);
GFC_DESCRIPTOR_TYPE_P (fat_type) = 1;
- TYPE_LANG_SPECIFIC (fat_type) = (struct lang_type *)
- ggc_alloc_cleared (sizeof (struct lang_type));
+ TYPE_LANG_SPECIFIC (fat_type)
+ = ggc_alloc_cleared_lang_type (sizeof (struct lang_type));
GFC_TYPE_ARRAY_RANK (fat_type) = dimen;
GFC_TYPE_ARRAY_DTYPE (fat_type) = NULL_TREE;
@@ -1799,10 +1801,12 @@ gfc_sym_type (gfc_symbol * sym)
{
enum gfc_array_kind akind = GFC_ARRAY_UNKNOWN;
if (sym->attr.pointer)
- akind = GFC_ARRAY_POINTER;
+ akind = sym->attr.contiguous ? GFC_ARRAY_POINTER_CONT
+ : GFC_ARRAY_POINTER;
else if (sym->attr.allocatable)
akind = GFC_ARRAY_ALLOCATABLE;
- type = gfc_build_array_type (type, sym->as, akind, restricted);
+ type = gfc_build_array_type (type, sym->as, akind, restricted,
+ sym->attr.contiguous);
}
}
else
@@ -2121,14 +2125,16 @@ gfc_get_derived_type (gfc_symbol * derived)
{
enum gfc_array_kind akind;
if (c->attr.pointer)
- akind = GFC_ARRAY_POINTER;
+ akind = c->attr.contiguous ? GFC_ARRAY_POINTER_CONT
+ : GFC_ARRAY_POINTER;
else
akind = GFC_ARRAY_ALLOCATABLE;
/* Pointers to arrays aren't actually pointer types. The
descriptors are separate, but the data is common. */
field_type = gfc_build_array_type (field_type, c->as, akind,
!c->attr.target
- && !c->attr.pointer);
+ && !c->attr.pointer,
+ c->attr.contiguous);
}
else
field_type = gfc_get_nodesc_array_type (field_type, c->as,
@@ -2516,7 +2522,8 @@ gfc_get_array_descr_info (const_tree type, struct array_descr_info *info)
if (int_size_in_bytes (etype) <= 0)
return false;
/* Nor non-constant lower bounds in assumed shape arrays. */
- if (GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ASSUMED_SHAPE)
+ if (GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ASSUMED_SHAPE
+ || GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ASSUMED_SHAPE_CONT)
{
for (dim = 0; dim < rank; dim++)
if (GFC_TYPE_ARRAY_LBOUND (type, dim) == NULL_TREE
@@ -2565,7 +2572,8 @@ gfc_get_array_descr_info (const_tree type, struct array_descr_info *info)
if (GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE)
info->allocated = build2 (NE_EXPR, boolean_type_node,
info->data_location, null_pointer_node);
- else if (GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER)
+ else if (GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER
+ || GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER_CONT)
info->associated = build2 (NE_EXPR, boolean_type_node,
info->data_location, null_pointer_node);
@@ -2579,7 +2587,8 @@ gfc_get_array_descr_info (const_tree type, struct array_descr_info *info)
size_binop (PLUS_EXPR, dim_off, upper_suboff));
t = build1 (INDIRECT_REF, gfc_array_index_type, t);
info->dimen[dim].upper_bound = t;
- if (GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ASSUMED_SHAPE)
+ if (GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ASSUMED_SHAPE
+ || GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ASSUMED_SHAPE_CONT)
{
/* Assumed shape arrays have known lower bounds. */
info->dimen[dim].upper_bound
diff --git a/gcc/fortran/trans.h b/gcc/fortran/trans.h
index 9ee81480c5b..02361fc8466 100644
--- a/gcc/fortran/trans.h
+++ b/gcc/fortran/trans.h
@@ -523,6 +523,7 @@ bool gfc_get_array_descr_info (const_tree, struct array_descr_info *);
/* In trans-openmp.c */
bool gfc_omp_privatize_by_reference (const_tree);
enum omp_clause_default_kind gfc_omp_predetermined_sharing (tree);
+tree gfc_omp_report_decl (tree);
tree gfc_omp_clause_default_ctor (tree, tree, tree);
tree gfc_omp_clause_copy_ctor (tree, tree, tree);
tree gfc_omp_clause_assign_op (tree, tree, tree);
@@ -619,18 +620,24 @@ extern GTY(()) tree gfor_fndecl_sr_kind;
/* True if node is an integer constant. */
#define INTEGER_CST_P(node) (TREE_CODE(node) == INTEGER_CST)
-/* G95-specific declaration information. */
+/* gfortran-specific declaration information, the _CONT versions denote
+ arrays with CONTIGUOUS attribute. */
enum gfc_array_kind
{
GFC_ARRAY_UNKNOWN,
GFC_ARRAY_ASSUMED_SHAPE,
+ GFC_ARRAY_ASSUMED_SHAPE_CONT,
GFC_ARRAY_ALLOCATABLE,
- GFC_ARRAY_POINTER
+ GFC_ARRAY_POINTER,
+ GFC_ARRAY_POINTER_CONT
};
/* Array types only. */
-struct GTY(()) lang_type {
+/* FIXME: the variable_size annotation here is needed because these types are
+ variable-sized in some other frontends. Due to gengtype deficiency the GTY
+ options of such types have to agree across all frontends. */
+struct GTY((variable_size)) lang_type {
int rank;
enum gfc_array_kind akind;
tree lbound[GFC_MAX_DIMENSIONS];
@@ -644,7 +651,7 @@ struct GTY(()) lang_type {
tree base_decl[2];
};
-struct GTY(()) lang_decl {
+struct GTY((variable_size)) lang_decl {
/* Dummy variables. */
tree saved_descriptor;
/* Assigned integer nodes. Stringlength is the IO format string's length.