• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

Commit MetaInfo

Revisionb345a09fb7b519045db566d5f50bd9302c88227c (tree)
Time2016-02-21 03:26:59
Authorpault <pault@138b...>
Commiterpault

Log Message

2016-02-20 Paul Thomas <pault@gcc.gnu.org>

PR fortran/69423
* trans-decl.c (create_function_arglist): Deferred character
length functions, with and without declared results, address
the passed reference type as '.result' and the local string
length as '..result'.
(gfc_null_and_pass_deferred_len): Helper function to null and
return deferred string lengths, as needed.
(gfc_trans_deferred_vars): Call it, thereby reducing repeated
code, add call for deferred arrays and reroute pointer function
results. Avoid using 'tmp' for anything other that a temporary
tree by introducing 'type_of_array' for the arrayspec type.

2016-02-20 Paul Thomas <pault@gcc.gnu.org>

PR fortran/69423
* gfortran.dg/deferred_character_15.f90 : New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@233589 138bc75d-0d04-0410-961f-82ee72b054a4

Change Summary

Incremental Difference

--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,17 @@
1+2016-02-20 Paul Thomas <pault@gcc.gnu.org>
2+
3+ PR fortran/69423
4+ * trans-decl.c (create_function_arglist): Deferred character
5+ length functions, with and without declared results, address
6+ the passed reference type as '.result' and the local string
7+ length as '..result'.
8+ (gfc_null_and_pass_deferred_len): Helper function to null and
9+ return deferred string lengths, as needed.
10+ (gfc_trans_deferred_vars): Call it, thereby reducing repeated
11+ code, add call for deferred arrays and reroute pointer function
12+ results. Avoid using 'tmp' for anything other that a temporary
13+ tree by introducing 'type_of_array' for the arrayspec type.
14+
115 2015-02-16 Thomas Koenig <tkoenig@gcc.gnu.org>
216
317 PR fortran/69742
--- a/gcc/fortran/trans-decl.c
+++ b/gcc/fortran/trans-decl.c
@@ -2234,7 +2234,12 @@ create_function_arglist (gfc_symbol * sym)
22342234 PARM_DECL,
22352235 get_identifier (".__result"),
22362236 len_type);
2237- if (!sym->ts.u.cl->length)
2237+ if (POINTER_TYPE_P (len_type))
2238+ {
2239+ sym->ts.u.cl->passed_length = length;
2240+ TREE_USED (length) = 1;
2241+ }
2242+ else if (!sym->ts.u.cl->length)
22382243 {
22392244 sym->ts.u.cl->backend_decl = length;
22402245 TREE_USED (length) = 1;
@@ -2271,13 +2276,6 @@ create_function_arglist (gfc_symbol * sym)
22712276 type = gfc_sym_type (arg);
22722277 arg->backend_decl = backend_decl;
22732278 type = build_reference_type (type);
2274-
2275- if (POINTER_TYPE_P (len_type))
2276- {
2277- sym->ts.u.cl->passed_length = length;
2278- sym->ts.u.cl->backend_decl =
2279- build_fold_indirect_ref_loc (input_location, length);
2280- }
22812279 }
22822280 }
22832281
@@ -3917,6 +3915,62 @@ init_intent_out_dt (gfc_symbol * proc_sym, gfc_wrapped_block * block)
39173915 }
39183916
39193917
3918+/* Helper function to manage deferred string lengths. */
3919+
3920+static tree
3921+gfc_null_and_pass_deferred_len (gfc_symbol *sym, stmtblock_t *init,
3922+ locus *loc)
3923+{
3924+ tree tmp;
3925+
3926+ /* Character length passed by reference. */
3927+ tmp = sym->ts.u.cl->passed_length;
3928+ tmp = build_fold_indirect_ref_loc (input_location, tmp);
3929+ tmp = fold_convert (gfc_charlen_type_node, tmp);
3930+
3931+ if (!sym->attr.dummy || sym->attr.intent == INTENT_OUT)
3932+ /* Zero the string length when entering the scope. */
3933+ gfc_add_modify (init, sym->ts.u.cl->backend_decl,
3934+ build_int_cst (gfc_charlen_type_node, 0));
3935+ else
3936+ {
3937+ tree tmp2;
3938+
3939+ tmp2 = fold_build2_loc (input_location, MODIFY_EXPR,
3940+ gfc_charlen_type_node,
3941+ sym->ts.u.cl->backend_decl, tmp);
3942+ if (sym->attr.optional)
3943+ {
3944+ tree present = gfc_conv_expr_present (sym);
3945+ tmp2 = build3_loc (input_location, COND_EXPR,
3946+ void_type_node, present, tmp2,
3947+ build_empty_stmt (input_location));
3948+ }
3949+ gfc_add_expr_to_block (init, tmp2);
3950+ }
3951+
3952+ gfc_restore_backend_locus (loc);
3953+
3954+ /* Pass the final character length back. */
3955+ if (sym->attr.intent != INTENT_IN)
3956+ {
3957+ tmp = fold_build2_loc (input_location, MODIFY_EXPR,
3958+ gfc_charlen_type_node, tmp,
3959+ sym->ts.u.cl->backend_decl);
3960+ if (sym->attr.optional)
3961+ {
3962+ tree present = gfc_conv_expr_present (sym);
3963+ tmp = build3_loc (input_location, COND_EXPR,
3964+ void_type_node, present, tmp,
3965+ build_empty_stmt (input_location));
3966+ }
3967+ }
3968+ else
3969+ tmp = NULL_TREE;
3970+
3971+ return tmp;
3972+}
3973+
39203974 /* Generate function entry and exit code, and add it to the function body.
39213975 This includes:
39223976 Allocation and initialization of array variables.
@@ -3966,7 +4020,19 @@ gfc_trans_deferred_vars (gfc_symbol * proc_sym, gfc_wrapped_block * block)
39664020 /* An automatic character length, pointer array result. */
39674021 if (proc_sym->ts.type == BT_CHARACTER
39684022 && TREE_CODE (proc_sym->ts.u.cl->backend_decl) == VAR_DECL)
3969- gfc_trans_dummy_character (proc_sym, proc_sym->ts.u.cl, block);
4023+ {
4024+ tmp = NULL;
4025+ if (proc_sym->ts.deferred)
4026+ {
4027+ gfc_save_backend_locus (&loc);
4028+ gfc_set_backend_locus (&proc_sym->declared_at);
4029+ gfc_start_block (&init);
4030+ tmp = gfc_null_and_pass_deferred_len (proc_sym, &init, &loc);
4031+ gfc_add_init_cleanup (block, gfc_finish_block (&init), tmp);
4032+ }
4033+ else
4034+ gfc_trans_dummy_character (proc_sym, proc_sym->ts.u.cl, block);
4035+ }
39704036 }
39714037 else if (proc_sym->ts.type == BT_CHARACTER)
39724038 {
@@ -3993,7 +4059,8 @@ gfc_trans_deferred_vars (gfc_symbol * proc_sym, gfc_wrapped_block * block)
39934059
39944060 /* Pass back the string length on exit. */
39954061 tmp = proc_sym->ts.u.cl->backend_decl;
3996- if (TREE_CODE (tmp) != INDIRECT_REF)
4062+ if (TREE_CODE (tmp) != INDIRECT_REF
4063+ && proc_sym->ts.u.cl->passed_length)
39974064 {
39984065 tmp = proc_sym->ts.u.cl->passed_length;
39994066 tmp = build_fold_indirect_ref_loc (input_location, tmp);
@@ -4072,21 +4139,21 @@ gfc_trans_deferred_vars (gfc_symbol * proc_sym, gfc_wrapped_block * block)
40724139 = gfc_class_set_static_fields (sym->backend_decl, vptr, tmp);
40734140 TREE_CONSTANT (DECL_INITIAL (sym->backend_decl)) = 1;
40744141 }
4075- else if (sym->attr.dimension || sym->attr.codimension
4076- || (IS_CLASS_ARRAY (sym) && !CLASS_DATA (sym)->attr.allocatable))
4142+ else if ((sym->attr.dimension || sym->attr.codimension
4143+ || (IS_CLASS_ARRAY (sym) && !CLASS_DATA (sym)->attr.allocatable)))
40774144 {
40784145 bool is_classarray = IS_CLASS_ARRAY (sym);
40794146 symbol_attribute *array_attr;
40804147 gfc_array_spec *as;
4081- array_type tmp;
4148+ array_type type_of_array;
40824149
40834150 array_attr = is_classarray ? &CLASS_DATA (sym)->attr : &sym->attr;
40844151 as = is_classarray ? CLASS_DATA (sym)->as : sym->as;
40854152 /* Assumed-size Cray pointees need to be treated as AS_EXPLICIT. */
4086- tmp = as->type;
4087- if (tmp == AS_ASSUMED_SIZE && as->cp_was_assumed)
4088- tmp = AS_EXPLICIT;
4089- switch (tmp)
4153+ type_of_array = as->type;
4154+ if (type_of_array == AS_ASSUMED_SIZE && as->cp_was_assumed)
4155+ type_of_array = AS_EXPLICIT;
4156+ switch (type_of_array)
40904157 {
40914158 case AS_EXPLICIT:
40924159 if (sym->attr.dummy || sym->attr.result)
@@ -4169,6 +4236,15 @@ gfc_trans_deferred_vars (gfc_symbol * proc_sym, gfc_wrapped_block * block)
41694236 case AS_DEFERRED:
41704237 seen_trans_deferred_array = true;
41714238 gfc_trans_deferred_array (sym, block);
4239+ if (sym->ts.type == BT_CHARACTER && sym->ts.deferred
4240+ && sym->attr.result)
4241+ {
4242+ gfc_start_block (&init);
4243+ gfc_save_backend_locus (&loc);
4244+ gfc_set_backend_locus (&sym->declared_at);
4245+ tmp = gfc_null_and_pass_deferred_len (sym, &init, &loc);
4246+ gfc_add_init_cleanup (block, gfc_finish_block (&init), tmp);
4247+ }
41724248 break;
41734249
41744250 default:
@@ -4183,6 +4259,7 @@ gfc_trans_deferred_vars (gfc_symbol * proc_sym, gfc_wrapped_block * block)
41834259 continue;
41844260 else if ((!sym->attr.dummy || sym->ts.deferred)
41854261 && (sym->attr.allocatable
4262+ || (sym->attr.pointer && sym->attr.result)
41864263 || (sym->ts.type == BT_CLASS
41874264 && CLASS_DATA (sym)->attr.allocatable)))
41884265 {
@@ -4190,96 +4267,50 @@ gfc_trans_deferred_vars (gfc_symbol * proc_sym, gfc_wrapped_block * block)
41904267 {
41914268 tree descriptor = NULL_TREE;
41924269
4193- /* Nullify and automatic deallocation of allocatable
4194- scalars. */
4195- e = gfc_lval_expr_from_sym (sym);
4196- if (sym->ts.type == BT_CLASS)
4197- gfc_add_data_component (e);
4198-
4199- gfc_init_se (&se, NULL);
4200- if (sym->ts.type != BT_CLASS
4201- || sym->ts.u.derived->attr.dimension
4202- || sym->ts.u.derived->attr.codimension)
4203- {
4204- se.want_pointer = 1;
4205- gfc_conv_expr (&se, e);
4206- }
4207- else if (sym->ts.type == BT_CLASS
4208- && !CLASS_DATA (sym)->attr.dimension
4209- && !CLASS_DATA (sym)->attr.codimension)
4210- {
4211- se.want_pointer = 1;
4212- gfc_conv_expr (&se, e);
4213- }
4214- else
4215- {
4216- se.descriptor_only = 1;
4217- gfc_conv_expr (&se, e);
4218- descriptor = se.expr;
4219- se.expr = gfc_conv_descriptor_data_addr (se.expr);
4220- se.expr = build_fold_indirect_ref_loc (input_location, se.expr);
4221- }
4222- gfc_free_expr (e);
4223-
42244270 gfc_save_backend_locus (&loc);
42254271 gfc_set_backend_locus (&sym->declared_at);
42264272 gfc_start_block (&init);
42274273
4228- if (!sym->attr.dummy || sym->attr.intent == INTENT_OUT)
4274+ if (!sym->attr.pointer)
42294275 {
4230- /* Nullify when entering the scope. */
4231- tmp = fold_build2_loc (input_location, MODIFY_EXPR,
4232- TREE_TYPE (se.expr), se.expr,
4233- fold_convert (TREE_TYPE (se.expr),
4234- null_pointer_node));
4235- if (sym->attr.optional)
4276+ /* Nullify and automatic deallocation of allocatable
4277+ scalars. */
4278+ e = gfc_lval_expr_from_sym (sym);
4279+ if (sym->ts.type == BT_CLASS)
4280+ gfc_add_data_component (e);
4281+
4282+ gfc_init_se (&se, NULL);
4283+ if (sym->ts.type != BT_CLASS
4284+ || sym->ts.u.derived->attr.dimension
4285+ || sym->ts.u.derived->attr.codimension)
42364286 {
4237- tree present = gfc_conv_expr_present (sym);
4238- tmp = build3_loc (input_location, COND_EXPR,
4239- void_type_node, present, tmp,
4240- build_empty_stmt (input_location));
4287+ se.want_pointer = 1;
4288+ gfc_conv_expr (&se, e);
4289+ }
4290+ else if (sym->ts.type == BT_CLASS
4291+ && !CLASS_DATA (sym)->attr.dimension
4292+ && !CLASS_DATA (sym)->attr.codimension)
4293+ {
4294+ se.want_pointer = 1;
4295+ gfc_conv_expr (&se, e);
42414296 }
4242- gfc_add_expr_to_block (&init, tmp);
4243- }
4244-
4245- if ((sym->attr.dummy || sym->attr.result)
4246- && sym->ts.type == BT_CHARACTER
4247- && sym->ts.deferred)
4248- {
4249- /* Character length passed by reference. */
4250- tmp = sym->ts.u.cl->passed_length;
4251- tmp = build_fold_indirect_ref_loc (input_location, tmp);
4252- tmp = fold_convert (gfc_charlen_type_node, tmp);
4253-
4254- if (!sym->attr.dummy || sym->attr.intent == INTENT_OUT)
4255- /* Zero the string length when entering the scope. */
4256- gfc_add_modify (&init, sym->ts.u.cl->backend_decl,
4257- build_int_cst (gfc_charlen_type_node, 0));
42584297 else
42594298 {
4260- tree tmp2;
4261-
4262- tmp2 = fold_build2_loc (input_location, MODIFY_EXPR,
4263- gfc_charlen_type_node,
4264- sym->ts.u.cl->backend_decl, tmp);
4265- if (sym->attr.optional)
4266- {
4267- tree present = gfc_conv_expr_present (sym);
4268- tmp2 = build3_loc (input_location, COND_EXPR,
4269- void_type_node, present, tmp2,
4270- build_empty_stmt (input_location));
4271- }
4272- gfc_add_expr_to_block (&init, tmp2);
4299+ se.descriptor_only = 1;
4300+ gfc_conv_expr (&se, e);
4301+ descriptor = se.expr;
4302+ se.expr = gfc_conv_descriptor_data_addr (se.expr);
4303+ se.expr = build_fold_indirect_ref_loc (input_location, se.expr);
42734304 }
4305+ gfc_free_expr (e);
42744306
4275- gfc_restore_backend_locus (&loc);
4276-
4277- /* Pass the final character length back. */
4278- if (sym->attr.intent != INTENT_IN)
4307+ if (!sym->attr.dummy || sym->attr.intent == INTENT_OUT)
42794308 {
4309+ /* Nullify when entering the scope. */
42804310 tmp = fold_build2_loc (input_location, MODIFY_EXPR,
4281- gfc_charlen_type_node, tmp,
4282- sym->ts.u.cl->backend_decl);
4311+ TREE_TYPE (se.expr), se.expr,
4312+ fold_convert (TREE_TYPE (se.expr),
4313+ null_pointer_node));
42834314 if (sym->attr.optional)
42844315 {
42854316 tree present = gfc_conv_expr_present (sym);
@@ -4287,16 +4318,21 @@ gfc_trans_deferred_vars (gfc_symbol * proc_sym, gfc_wrapped_block * block)
42874318 void_type_node, present, tmp,
42884319 build_empty_stmt (input_location));
42894320 }
4321+ gfc_add_expr_to_block (&init, tmp);
42904322 }
4291- else
4292- tmp = NULL_TREE;
42934323 }
4324+
4325+ if ((sym->attr.dummy || sym->attr.result)
4326+ && sym->ts.type == BT_CHARACTER
4327+ && sym->ts.deferred
4328+ && sym->ts.u.cl->passed_length)
4329+ tmp = gfc_null_and_pass_deferred_len (sym, &init, &loc);
42944330 else
42954331 gfc_restore_backend_locus (&loc);
42964332
42974333 /* Deallocate when leaving the scope. Nullifying is not
42984334 needed. */
4299- if (!sym->attr.result && !sym->attr.dummy
4335+ if (!sym->attr.result && !sym->attr.dummy && !sym->attr.pointer
43004336 && !sym->ns->proc_name->attr.is_main_program)
43014337 {
43024338 if (sym->ts.type == BT_CLASS
@@ -4313,6 +4349,7 @@ gfc_trans_deferred_vars (gfc_symbol * proc_sym, gfc_wrapped_block * block)
43134349 gfc_free_expr (expr);
43144350 }
43154351 }
4352+
43164353 if (sym->ts.type == BT_CLASS)
43174354 {
43184355 /* Initialize _vptr to declared type. */
@@ -4353,19 +4390,9 @@ gfc_trans_deferred_vars (gfc_symbol * proc_sym, gfc_wrapped_block * block)
43534390 if (sym->attr.dummy)
43544391 {
43554392 gfc_start_block (&init);
4356-
4357- /* Character length passed by reference. */
4358- tmp = sym->ts.u.cl->passed_length;
4359- tmp = build_fold_indirect_ref_loc (input_location, tmp);
4360- tmp = fold_convert (gfc_charlen_type_node, tmp);
4361- gfc_add_modify (&init, sym->ts.u.cl->backend_decl, tmp);
4362- /* Pass the final character length back. */
4363- if (sym->attr.intent != INTENT_IN)
4364- tmp = fold_build2_loc (input_location, MODIFY_EXPR,
4365- gfc_charlen_type_node, tmp,
4366- sym->ts.u.cl->backend_decl);
4367- else
4368- tmp = NULL_TREE;
4393+ gfc_save_backend_locus (&loc);
4394+ gfc_set_backend_locus (&sym->declared_at);
4395+ tmp = gfc_null_and_pass_deferred_len (sym, &init, &loc);
43694396 gfc_add_init_cleanup (block, gfc_finish_block (&init), tmp);
43704397 }
43714398 }
@@ -4427,6 +4454,7 @@ gfc_trans_deferred_vars (gfc_symbol * proc_sym, gfc_wrapped_block * block)
44274454 gfc_add_init_cleanup (block, gfc_finish_block (&tmpblock), NULL_TREE);
44284455 }
44294456
4457+
44304458 struct module_hasher : ggc_ptr_hash<module_htab_entry>
44314459 {
44324460 typedef const char *compare_type;
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
1+2016-02-20 Paul Thomas <pault@gcc.gnu.org>
2+
3+ PR fortran/69423
4+ * gfortran.dg/deferred_character_15.f90 : New test.
5+
16 2016-02-20 Dominique d'Humieres <dominiq@lps.ens.fr>
27
38 PR fortran/57365
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/deferred_character_15.f90
@@ -0,0 +1,44 @@
1+! { dg-do run }
2+!
3+! Test the fix for PR69423.
4+!
5+! Contributed by Antony Lewis <antony@cosmologist.info>
6+!
7+program tester
8+ character(LEN=:), allocatable :: S
9+ S= test(2)
10+ if (len(S) .ne. 4) call abort
11+ if (S .ne. "test") call abort
12+ if (allocated (S)) deallocate (S)
13+
14+ S= test2(2)
15+ if (len(S) .ne. 4) call abort
16+ if (S .ne. "test") call abort
17+ if (allocated (S)) deallocate (S)
18+contains
19+ function test(alen)
20+ character(LEN=:), allocatable :: test
21+ integer alen, i
22+ do i = alen, 1, -1
23+ test = 'test'
24+ exit
25+ end do
26+! This line would print nothing when compiled with -O1 and higher.
27+! print *, len(test),test
28+ if (len(test) .ne. 4) call abort
29+ if (test .ne. "test") call abort
30+ end function test
31+
32+ function test2(alen) result (test)
33+ character(LEN=:), allocatable :: test
34+ integer alen, i
35+ do i = alen, 1, -1
36+ test = 'test'
37+ exit
38+ end do
39+! This worked before the fix.
40+! print *, len(test),test
41+ if (len(test) .ne. 4) call abort
42+ if (test .ne. "test") call abort
43+ end function test2
44+end program tester