https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98797
Bug ID: 98797 Summary: Simpler version of the XFAIL in casts-1.c with proposed solution Product: gcc Version: 11.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: analyzer Assignee: dmalcolm at gcc dot gnu.org Reporter: brian.sobulefsky at protonmail dot com Target Milestone: --- I took some time to investigate the bug concerning the XFAILs in file gcc/testsuite/gcc.dg/analyzer/casts-1.c and found that there is a simpler manifestation of this error unrelated to casts. I also have a tentative solution I can offer. I am new here so I'm sorry if I should be suggesting this elsewhere, just let me know. In the casts-1.c file, a test is run of the form: struct s1 { char a; char b; char c; char d; }; struct s2 { char arr[4]; }; struct s2 x = {{'A', 'B', 'C', 'D'}}; struct s1 *p = (struct s1 *)&x; __analyzer_eval (p->a == 'A'); Which should obviously be TRUE but comes out as UNKNOWN. The problem can actually be replicated with just char arc[4] = {{'A', 'B', 'C', 'D'}}; char *ptc = arc; __analyzer_eval(*ptc == 'A'); __analyzer_eval(*(ptc+1) == 'B'); Both of these should obviously be TRUE, and they will print out UNKNOWN. These do not require any contorted type conversion and suffer the same failure. Briefly, this problem only occurs if you initialize an entire array and then point to the array and try to access the individual values by pointer de-reference. It does not occur if you initialize the array and try to access the array element directly (you already programmed that case into it), and it does not happen if you assign to the array elements directly for either case (array access or pointer de-reference). Because direct assignment to the array solves the problem, we do not see this problem with integers, as the initialization of an integer array evidently compiles to individual assignments to each element. The easiest issue to solve was the *(ptc+1) version. This case runs as expected through the whole program, just as arc[1] would, until we get to region_model_manager::maybe_fold_sub_svalue. In the section of this method commented /* Handle getting individual chars from a STRING_CST. */, there is only a case for an element_region. By simply adding a analogous case for an offset_region, modified as necessary for the different class, this can be handled. This solves *(ptc+N) for any N except 0. It also does not solve *ptc, which evidently compiles the same as *(ptc+0). For this case, a modification can be made to region_model_manager::get_offset_region in for section commented /* If BYTE_OFFSET is zero, return PARENT. */. Before checking the zerop condition and calling get_cast_region, we check a special case where argument region *parent is of type ARRAY_TYPE and the type of that ARRAY_TYPE is the same as argument tree type. In this case, we allow the normal method conclusion of building an offset_region with a byte_offset of 0. After this, the fix described in the prior paragraph will work for this case. Finally, for the original issue involving converting between structs, an analogous case can again be added again to the /* Handle getting individual chars from a STRING_CST. */ section of region_model_manager::maybe_fold_sub_svalue for a field_reg. This will solve the three manifestations described here. It is known to not solve the case where struct s2 was defined as {char arr1[2]; char arr2[2];}, which I am actually close to solving already. I have posted the current status of my solution to GitHub. In the code, I left descriptive comments where I made changes so that it is obvious. If you want to keep the changes, of course remove the comments. In the ChangeLog, I put an entry that is a bit more appropriate. It is currently the only branch, but I have the branch named xfail-casts-1-soln0. https://github.com/poisson-aerohead/gcc