https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77941
--- Comment #10 from Steve Kargl <sgk at troutmask dot apl.washington.edu> --- On Thu, Mar 22, 2018 at 02:27:25PM +0000, jb at gcc dot gnu.org wrote: > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77941 > > --- Comment #8 from Janne Blomqvist <jb at gcc dot gnu.org> --- > (In reply to Steve Kargl from comment #7) > > On Thu, Mar 22, 2018 at 07:53:14AM +0000, jb at gcc dot gnu.org wrote: > > > > > > It works on x86_64-pc-linux-gnu (including running it), but the ICE > > > remains on > > > i686-pc-linux-gnu. > > > > > > > Janne, thanks for checking. 2_8**32+1 is 4GB+1byte of memory. > > Without PAE, i686 is limited to less than 4GB once an OS grabs a > > small portion of wired memory. Do we care if an ICE occurs? > > I suppose one could always check that a length type parameter > > less than some max integer based on 32-bit vs 64-bit system, > > but that would pessimize all uses of strings as this would > > need to be a runtime check. > > If one looks at the -fdump-tree-original dumps, for both i686 and x86-64 the > function f() looks Ok. However, the program p differs significantly. For > x86-64 > the working program p is: > Dumps compressed down to needed lines. x86_64 > static void f (character(kind=1)[1:] &, integer(kind=8), integer(kind=8)); > > character(kind=1)[1:4294967297] * pstr.1; > void * restrict D.3781; > > D.3781 = (void * restrict) __builtin_malloc (4294967297); i686 > static void f (character(kind=1)[1:] &, integer(kind=4), integer(kind=8)); > > character(kind=1) str.1[1]; > > f ((character(kind=1)[1:1] *) &str.1, 1(OVF), 4294967297); > _gfortran_transfer_character_write (&dt_parm.0, (character(kind=1)[1:1] > *) &str.1, 1(OVF)); The dumps are a little misleading in that f(n) is inlined. Here, the middle/backend can see n = 2_8**32+1, so it can generate the OVF. If f(n) is in a file by itself the dump looks much different. (where I've wrapped long lines and this is on x86_64 and comments in-lined.). f (character(kind=1)[1:..__result] & __result, integer(kind=8) .__result, integer(kind=8) n) { integer(kind=8) ..__result; bitsizetype D.3766; sizetype D.3767; ..__result = MAX_EXPR <n, 0>; So, gfortran (or middle/backend) protect against a negative number on i686 .__result is int32. The above MAXEXPR may cause 2-complement wrap around. What I want to avoid is if (n >= intmax_t) { runtime error here. } for all routines that take a string. D.3766 = (bitsizetype)(sizetype)NON_LVALUE_EXPR<..__result> * 8; D.3767 = (sizetype) NON_LVALUE_EXPR <..__result>; { integer(kind=8) D.3764; integer(kind=8) D.3765; D.3764 = ..__result; D.3765 = NON_LVALUE_EXPR <D.3764> + -1; if (D.3764 > 0) { if (NON_LVALUE_EXPR <D.3764> > 1) { __builtin_memmove ((void *) __result, (void *) &"a"[1]{lb: 1 sz: 1}, 1); __builtin_memset ((void *) __result + 1, 32,i (unsigned long) D.3765); } else { __builtin_memmove ((void *) __result, (void *) &"a"[1]{lb: 1 sz: 1}, (unsigned long) NON_LVALUE_EXPR <D.3764>); } } } }