Re: [PATCH] Fix PR70985

2019-12-13 Thread Richard Biener
On December 14, 2019 6:28:48 AM GMT+01:00, Andrew Pinski  
wrote:
>On Mon, May 9, 2016 at 2:32 AM Richard Biener 
>wrote:
>>
>>
>> I am testing the following followup to my BIT_FIELD_REF
>simplification
>> changes which resolve issues when applying to memory BIT_FIELD_REFs.
>>
>> Bootstrap and regtest running on x86_64-unknown-linux-gnu.
>
>My question is not directly related to this patch but is partly
>related.
>While I was working on lowering bit-field access patch, I ran into a
>problem where I am building the lhs, I use fold_build3 to build the
>BIT_FIELD_REF and we get a convert expression from it.
>Should we be using a fold_build3 for the BIT_FIELD_REF that will be
>used on the lhs or should we just disable this optimization for non
>GIMPLE?
>The testcases where I ran into the issue are the ones which I added
>back in October; gcc.c-torture/compile/20191015-1.c and
>gcc.c-torture/compile/20191015-2.c.  I added them so when I submit the
>patch for lowering for GCC 11, we don't regress (there was no testcase
>beforehand).

You should never apply fold_* to where you require an lvalue. 

Richard. 

>Thanks,
>Andrew Pinski
>
>>
>> Richard.
>>
>> 2016-05-09  Richard Biener  
>>
>> PR tree-optimization/70985
>> * match.pd (BIT_FIELD_REF -> (type)): Disable on GIMPLE when
>> op0 isn't a gimple register.
>>
>> * gcc.dg/torture/pr70985.c: New testcase.
>>
>> Index: gcc/match.pd
>> ===
>> *** gcc/match.pd(revision 236021)
>> --- gcc/match.pd(working copy)
>> *** DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
>> *** 3244,3249 
>> --- 3244,3251 
>>(view_convert (imagpart @0)
>> (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
>>  && INTEGRAL_TYPE_P (type)
>> +/* On GIMPLE this should only apply to register arguments. 
>*/
>> +&& (! GIMPLE || is_gimple_reg (@0))
>>  /* A bit-field-ref that referenced the full argument can be
>stripped.  */
>>  && ((compare_tree_int (@1, TYPE_PRECISION (TREE_TYPE (@0)))
>== 0
>> && integer_zerop (@2))
>> Index: gcc/testsuite/gcc.dg/torture/pr70985.c
>> ===
>> *** gcc/testsuite/gcc.dg/torture/pr70985.c  (revision 0)
>> --- gcc/testsuite/gcc.dg/torture/pr70985.c  (working copy)
>> ***
>> *** 0 
>> --- 1,28 
>> + /* { dg-do compile } */
>> + /* { dg-require-effective-target int32plus } */
>> +
>> + struct
>> + {
>> +   int f0:24;
>> + } a, c, d;
>> +
>> + int b;
>> +
>> + int
>> + fn1 ()
>> + {
>> +   return 0;
>> + }
>> +
>> + void
>> + fn2 ()
>> + {
>> +   int e;
>> +   if (b)
>> + for (; e;)
>> +   {
>> +   d = c;
>> +   if (fn1 (b))
>> + b = a.f0;
>> +   }
>> + }



Re: [PATCH] Fix PR70985

2019-12-13 Thread Andrew Pinski
On Mon, May 9, 2016 at 2:32 AM Richard Biener  wrote:
>
>
> I am testing the following followup to my BIT_FIELD_REF simplification
> changes which resolve issues when applying to memory BIT_FIELD_REFs.
>
> Bootstrap and regtest running on x86_64-unknown-linux-gnu.

My question is not directly related to this patch but is partly related.
While I was working on lowering bit-field access patch, I ran into a
problem where I am building the lhs, I use fold_build3 to build the
BIT_FIELD_REF and we get a convert expression from it.
Should we be using a fold_build3 for the BIT_FIELD_REF that will be
used on the lhs or should we just disable this optimization for non
GIMPLE?
The testcases where I ran into the issue are the ones which I added
back in October; gcc.c-torture/compile/20191015-1.c and
gcc.c-torture/compile/20191015-2.c.  I added them so when I submit the
patch for lowering for GCC 11, we don't regress (there was no testcase
beforehand).

Thanks,
Andrew Pinski

>
> Richard.
>
> 2016-05-09  Richard Biener  
>
> PR tree-optimization/70985
> * match.pd (BIT_FIELD_REF -> (type)): Disable on GIMPLE when
> op0 isn't a gimple register.
>
> * gcc.dg/torture/pr70985.c: New testcase.
>
> Index: gcc/match.pd
> ===
> *** gcc/match.pd(revision 236021)
> --- gcc/match.pd(working copy)
> *** DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
> *** 3244,3249 
> --- 3244,3251 
>(view_convert (imagpart @0)
> (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
>  && INTEGRAL_TYPE_P (type)
> +/* On GIMPLE this should only apply to register arguments.  */
> +&& (! GIMPLE || is_gimple_reg (@0))
>  /* A bit-field-ref that referenced the full argument can be 
> stripped.  */
>  && ((compare_tree_int (@1, TYPE_PRECISION (TREE_TYPE (@0))) == 0
> && integer_zerop (@2))
> Index: gcc/testsuite/gcc.dg/torture/pr70985.c
> ===
> *** gcc/testsuite/gcc.dg/torture/pr70985.c  (revision 0)
> --- gcc/testsuite/gcc.dg/torture/pr70985.c  (working copy)
> ***
> *** 0 
> --- 1,28 
> + /* { dg-do compile } */
> + /* { dg-require-effective-target int32plus } */
> +
> + struct
> + {
> +   int f0:24;
> + } a, c, d;
> +
> + int b;
> +
> + int
> + fn1 ()
> + {
> +   return 0;
> + }
> +
> + void
> + fn2 ()
> + {
> +   int e;
> +   if (b)
> + for (; e;)
> +   {
> +   d = c;
> +   if (fn1 (b))
> + b = a.f0;
> +   }
> + }


Re: [PATCH, c] all plattforms: support using a CC_REG instead cc0_rtx

2019-12-13 Thread Stefan Franke

Am 2019-12-14 04:03, schrieb Andrew Pinski:

On Fri, Dec 13, 2019 at 6:56 PM Stefan Franke  wrote:


Am 2019-12-13 21:59, schrieb Segher Boessenkool:
> On Fri, Dec 13, 2019 at 08:55:15PM +0100, Stefan Franke wrote:
>> Am 2019-12-13 18:58, schrieb Segher Boessenkool:
>> >On Fri, Dec 13, 2019 at 05:25:41PM +0100, Stefan Franke wrote:
>> >>Why? If you are using a cc register plus your architecture as many
>> >>instructions which may clobber that cc register, some passes (e.g.
>> >>gcse)
>> >>will reorder the insns. This can lead to the situation that an insn is
>> >>moved between a compare and it' consuming jump insn. Which yields
>> >>invalid code. (Note that at these stages clobbers are not yet tracked
>> >>as
>> >>CLOBBER insns).
>> >
>> >Then that port has a bug.  In the m68k port, there are no separate
>> >compare
>> >and jump insns ever, but for most ports those won't yet exist during
>> >gcse.
>>
>> it looks like t2o insn for the m68k
>>
>> (insn 115 114 116 5 (set (cc0)
>> (compare (subreg:HI (reg:SI 272) 2)
>> (reg:HI 273)))
>> /tmp/compiler-explorer-compiler1191113-13975-1allrsj.w8mc/example.c:216
>> 17 {*m68k.md:559}
>>  (nil))
>> (jump_insn 116 115 117 5 (set (pc)
>> (if_then_else (ne (cc0)
>> (const_int 0 [0]))
>> (label_ref 99)
>> (pc)))
>> /tmp/compiler-explorer-compiler1191113-13975-1allrsj.w8mc/example.c:216
>> 411 {bne}
>>  (int_list:REG_BR_PROB 4 (nil))
>>  -> 99)
>
> This is an older compiler.  m68k no longer uses cc0 (except it is still
> mentioned in two comments (well, commented-out code)).
>
>> >This is not unique to cc0 conversions: every port has a similar problem
>> >with all FIXED_REGISTERS.
>>
>> It's not related to fixed registers.
>
> No, it is exactly the same situation.  You cannot introduce uses of
> such
> a register if it might already exist in the insn stream somewhere, not
> without checking first, and you better have a backup plan too.
>
>> It's unique to CC registers since
>> these are on some plattforms modified by side effects. So after split2
>> it's modelled using CLOBBERs
>
> There are no such implicit side effects if you have gotten rid of cc0.
> That is the *point* of removing cc0.
>
>> >@findex cc0_rtx
>> >There is only one expression object of code @code{cc0}; it is the
>> >value of the variable @code{cc0_rtx}.  Any attempt to create an
>> >expression of code @code{cc0} will return @code{cc0_rtx}.
>> >
>> >There is a lot of code that depends on this property, you cannot break
>> >it without fixing everything.
>>
>> There is no need to change the definition or modify any piece
>> elsewhere.
>> And the modified comparison will still work for cc0.
>
> Then you do not need your patch.  You can compare cc0_rtx by identity.
>
>
> Segher


since I still don't get it: i386.md expands cbranch into two insns, 
e.g.



(insn 17 16 18 4 (set (reg:CCNO 17 flags)
 (compare:CCNO (reg/v:SI 96 [  ])
 (const_int 0 [0]))) "x.c":2 3 {*cmpsi_ccno_1}
  (nil))
(jump_insn 18 17 19 4 (set (pc)
 (if_then_else (le (reg:CCNO 17 flags)
 (const_int 0 [0]))
 (label_ref:DI 28)
 (pc))) "x.c":2 627 {*jcc_1}
  (int_list:REG_BR_PROB 1500 (nil))


What mechanism guarantees that no other insn is inserted inbetween the
compare and the jump?



(Note that at these stages clobbers are not yet tracked as

CLOBBER insns).

All of the instructions that need CLOBBER has it at this point.
So I think your back-end is not describing what it should be 
describing.

The old saying inside GCC is lie to reload and get wrong code.  That
rings true here too.

Thanks,
Andrew Pinski




Thanks, now I do understand.

Stefan


Re: [PATCH, c] all plattforms: support using a CC_REG instead cc0_rtx

2019-12-13 Thread Andrew Pinski
On Fri, Dec 13, 2019 at 6:56 PM Stefan Franke  wrote:
>
> Am 2019-12-13 21:59, schrieb Segher Boessenkool:
> > On Fri, Dec 13, 2019 at 08:55:15PM +0100, Stefan Franke wrote:
> >> Am 2019-12-13 18:58, schrieb Segher Boessenkool:
> >> >On Fri, Dec 13, 2019 at 05:25:41PM +0100, Stefan Franke wrote:
> >> >>Why? If you are using a cc register plus your architecture as many
> >> >>instructions which may clobber that cc register, some passes (e.g.
> >> >>gcse)
> >> >>will reorder the insns. This can lead to the situation that an insn is
> >> >>moved between a compare and it' consuming jump insn. Which yields
> >> >>invalid code. (Note that at these stages clobbers are not yet tracked
> >> >>as
> >> >>CLOBBER insns).
> >> >
> >> >Then that port has a bug.  In the m68k port, there are no separate
> >> >compare
> >> >and jump insns ever, but for most ports those won't yet exist during
> >> >gcse.
> >>
> >> it looks like t2o insn for the m68k
> >>
> >> (insn 115 114 116 5 (set (cc0)
> >> (compare (subreg:HI (reg:SI 272) 2)
> >> (reg:HI 273)))
> >> /tmp/compiler-explorer-compiler1191113-13975-1allrsj.w8mc/example.c:216
> >> 17 {*m68k.md:559}
> >>  (nil))
> >> (jump_insn 116 115 117 5 (set (pc)
> >> (if_then_else (ne (cc0)
> >> (const_int 0 [0]))
> >> (label_ref 99)
> >> (pc)))
> >> /tmp/compiler-explorer-compiler1191113-13975-1allrsj.w8mc/example.c:216
> >> 411 {bne}
> >>  (int_list:REG_BR_PROB 4 (nil))
> >>  -> 99)
> >
> > This is an older compiler.  m68k no longer uses cc0 (except it is still
> > mentioned in two comments (well, commented-out code)).
> >
> >> >This is not unique to cc0 conversions: every port has a similar problem
> >> >with all FIXED_REGISTERS.
> >>
> >> It's not related to fixed registers.
> >
> > No, it is exactly the same situation.  You cannot introduce uses of
> > such
> > a register if it might already exist in the insn stream somewhere, not
> > without checking first, and you better have a backup plan too.
> >
> >> It's unique to CC registers since
> >> these are on some plattforms modified by side effects. So after split2
> >> it's modelled using CLOBBERs
> >
> > There are no such implicit side effects if you have gotten rid of cc0.
> > That is the *point* of removing cc0.
> >
> >> >@findex cc0_rtx
> >> >There is only one expression object of code @code{cc0}; it is the
> >> >value of the variable @code{cc0_rtx}.  Any attempt to create an
> >> >expression of code @code{cc0} will return @code{cc0_rtx}.
> >> >
> >> >There is a lot of code that depends on this property, you cannot break
> >> >it without fixing everything.
> >>
> >> There is no need to change the definition or modify any piece
> >> elsewhere.
> >> And the modified comparison will still work for cc0.
> >
> > Then you do not need your patch.  You can compare cc0_rtx by identity.
> >
> >
> > Segher
>
>
> since I still don't get it: i386.md expands cbranch into two insns, e.g.
>
>
> (insn 17 16 18 4 (set (reg:CCNO 17 flags)
>  (compare:CCNO (reg/v:SI 96 [  ])
>  (const_int 0 [0]))) "x.c":2 3 {*cmpsi_ccno_1}
>   (nil))
> (jump_insn 18 17 19 4 (set (pc)
>  (if_then_else (le (reg:CCNO 17 flags)
>  (const_int 0 [0]))
>  (label_ref:DI 28)
>  (pc))) "x.c":2 627 {*jcc_1}
>   (int_list:REG_BR_PROB 1500 (nil))
>
>
> What mechanism guarantees that no other insn is inserted inbetween the
> compare and the jump?

>(Note that at these stages clobbers are not yet tracked as
CLOBBER insns).

All of the instructions that need CLOBBER has it at this point.
So I think your back-end is not describing what it should be describing.
The old saying inside GCC is lie to reload and get wrong code.  That
rings true here too.

Thanks,
Andrew Pinski

>
> Or is i386 also "broken"?
>
> Stefan


Re: [PATCH, c] all plattforms: support using a CC_REG instead cc0_rtx

2019-12-13 Thread Stefan Franke

Am 2019-12-13 21:59, schrieb Segher Boessenkool:

On Fri, Dec 13, 2019 at 08:55:15PM +0100, Stefan Franke wrote:

Am 2019-12-13 18:58, schrieb Segher Boessenkool:
>On Fri, Dec 13, 2019 at 05:25:41PM +0100, Stefan Franke wrote:
>>Why? If you are using a cc register plus your architecture as many
>>instructions which may clobber that cc register, some passes (e.g.
>>gcse)
>>will reorder the insns. This can lead to the situation that an insn is
>>moved between a compare and it' consuming jump insn. Which yields
>>invalid code. (Note that at these stages clobbers are not yet tracked
>>as
>>CLOBBER insns).
>
>Then that port has a bug.  In the m68k port, there are no separate
>compare
>and jump insns ever, but for most ports those won't yet exist during
>gcse.

it looks like t2o insn for the m68k

(insn 115 114 116 5 (set (cc0)
(compare (subreg:HI (reg:SI 272) 2)
(reg:HI 273)))
/tmp/compiler-explorer-compiler1191113-13975-1allrsj.w8mc/example.c:216
17 {*m68k.md:559}
 (nil))
(jump_insn 116 115 117 5 (set (pc)
(if_then_else (ne (cc0)
(const_int 0 [0]))
(label_ref 99)
(pc)))
/tmp/compiler-explorer-compiler1191113-13975-1allrsj.w8mc/example.c:216
411 {bne}
 (int_list:REG_BR_PROB 4 (nil))
 -> 99)


This is an older compiler.  m68k no longer uses cc0 (except it is still
mentioned in two comments (well, commented-out code)).


>This is not unique to cc0 conversions: every port has a similar problem
>with all FIXED_REGISTERS.

It's not related to fixed registers.


No, it is exactly the same situation.  You cannot introduce uses of 
such

a register if it might already exist in the insn stream somewhere, not
without checking first, and you better have a backup plan too.


It's unique to CC registers since
these are on some plattforms modified by side effects. So after split2
it's modelled using CLOBBERs


There are no such implicit side effects if you have gotten rid of cc0.
That is the *point* of removing cc0.


>@findex cc0_rtx
>There is only one expression object of code @code{cc0}; it is the
>value of the variable @code{cc0_rtx}.  Any attempt to create an
>expression of code @code{cc0} will return @code{cc0_rtx}.
>
>There is a lot of code that depends on this property, you cannot break
>it without fixing everything.

There is no need to change the definition or modify any piece 
elsewhere.

And the modified comparison will still work for cc0.


Then you do not need your patch.  You can compare cc0_rtx by identity.


Segher



since I still don't get it: i386.md expands cbranch into two insns, e.g.


(insn 17 16 18 4 (set (reg:CCNO 17 flags)
(compare:CCNO (reg/v:SI 96 [  ])
(const_int 0 [0]))) "x.c":2 3 {*cmpsi_ccno_1}
 (nil))
(jump_insn 18 17 19 4 (set (pc)
(if_then_else (le (reg:CCNO 17 flags)
(const_int 0 [0]))
(label_ref:DI 28)
(pc))) "x.c":2 627 {*jcc_1}
 (int_list:REG_BR_PROB 1500 (nil))


What mechanism guarantees that no other insn is inserted inbetween the 
compare and the jump?


Or is i386 also "broken"?

Stefan


Re: [PING 3][PATCH] track dynamic allocation in strlen (PR 91582)

2019-12-13 Thread Martin Sebor

After more testing by Jeff's buildbot and correcting the problems
it exposed I have committed the attached patch in r279392.

Martin

On 12/11/19 4:23 PM, Martin Sebor wrote:

Jeff's buildbot exposed a bug in the patch that caused false
positives in cases involving negative offsets into destinations
involving pointers pointing into multiple regions of the same
object.  The attached revision fixes that bug, plus makes
a few minor other fixes pointed out in PR 92868.

On 12/6/19 5:19 PM, Martin Sebor wrote:

With part 2 (below) of this work committed, I've rebased the patch
on the top of trunk and on top of the updated part 1 (also below).
Attached is the result, retested on x86_64-linux.

[1] include size and offset in -Wstringop-overflow
 https://gcc.gnu.org/ml/gcc-patches/2019-12/msg00392.html

[2] extend -Wstringop-overflow to allocated objects
 (committed in r278983)
 https://gcc.gnu.org/ml/gcc-patches/2019-12/msg00263.html

On 11/25/19 10:54 AM, Martin Sebor wrote:

Ping: https://gcc.gnu.org/ml/gcc-patches/2019-11/msg00812.html

On 11/18/19 11:23 AM, Martin Sebor wrote:

Ping: https://gcc.gnu.org/ml/gcc-patches/2019-11/msg00812.html

On 11/11/19 6:27 PM, Martin Sebor wrote:

The attached patch extends the strlen pass to detect out-of-bounds
accesses to memory allocated by calls to other allocation functions
besides calloc and malloc, as well as VLAs, and user-defined
functions declared with attribute alloc_size.  There is some
overlap with the _FORTIFY_SOURCE detection but thanks to
the extensive use of ranges, this enhancement detects many more
cases of overflow.

The solution primarily improves warnings but some of the changes
also improve codegen in some cases as a side-effect.  I hope to
take better advantage of the optimization opportunities the dynamic
memory tracking opens up (and also better buffer overflow and array
out-of-bounds detection) in GCC 11.

Although the strlen pass already tracks some dynamic memory calls
(calloc and malloc) rather than extending the same infrastructure
(strinfo::stmt) to others I took the approach of adding a separate
data member for the other calls (strinfo::alloc) and tracking those
independently.  I did this to keep the changes only minimally
intrusive.  In the future (post GCC 10) it might be worth
considering merging both.

Besides introducing the new member and making use of it, the rest
of the changes were prompted by weaknesses exposed by test cases
involving dynamically allocated objects.

The patch is intended to apply on top of the two related patches
posted last week ([1] and [2]).  For all tests to pass also expects
the fix for PR 92412 posted earlier today ([3]).

Martin

[1] https://gcc.gnu.org/ml/gcc-patches/2019-11/msg00429.html
[2] https://gcc.gnu.org/ml/gcc-patches/2019-11/msg00652.html
[3] https://gcc.gnu.org/ml/gcc-patches/2019-11/msg00800.html










PR middle-end/91582 - missing heap overflow detection for strcpy
PR middle-end/92868 - ICE: tree check: expected integer_cst, have ssa_name

gcc/ChangeLog:

	PR middle-end/91582
	PR middle-end/92868
	* builtins.c (addr_decl_size): New function.
	(gimple_call_alloc_size): Add arguments.
	(compute_objsize): Add an argument.  Set *PDECL even for allocated
	objects.
	Correct checking for negative wide_int.
	Correct handling of negative outer offsets into unknown regions
	or with unknown inner offsets.
	Extend offsets to at most sizetype precision.
	Only handle constant subobject sizes.
	* builtins.h (gimple_call_alloc_size): Add arguments.
	* gcc/tree.c (component_ref_size): Always return sizetype.
	* tree-ssa-strlen.c (strinfo::alloc): New member.
	(get_addr_stridx): Add argument.
	(get_stridx): Use ptrdiff_t.  Add argument.
	(new_strinfo): Set new member.
	(get_string_length): Handle alloca and VLA.
	(dump_strlen_info): Dump more state.
	(maybe_invalidate): Print more info.  Decrease indentation.
	(unshare_strinfo): Set new member.
	(valid_builtin_call): Handle alloca and VLA.
	(maybe_warn_overflow): Check and set no-warning bit.  Improve
	handling of offsets.  Print allocated objects.
	(handle_builtin_strlen): Handle strinfo records with null lengths.
	(handle_builtin_strcpy): Add argument.  Call maybe_warn_overflow.
	(is_strlen_related_p): Handle dynamically allocated objects.
	(get_range): Add argument.
	(handle_builtin_malloc): Rename...
	(handle_aalloc): ...to this and handle all allocation functions.
	(handle_builtin_memset): Call maybe_warn_overflow.
	(count_nonzero_bytes): Handle more MEM_REF forms.
	(strlen_check_and_optimize_call): Call handle_alloc_call.  Pass
	arguments to more callees.
	(handle_integral_assign): Add argument.  Create strinfo entries
	for MEM_REF assignments.
	(check_and_optimize_stmt): Handle more MEM_REF forms.

gcc/testsuite/ChangeLog:

	PR middle-end/91582
	* c-c++-common/Wrestrict.c: Adjust expected warnings.
	* gcc/testsuite/c-c++-common/Wstringop-truncation-4.c: Enable more
	warnings.
	* gcc/testsuite/c-c++-common/Wstringop-truncation.c: Remove 

Re: 'find_group_last' (was: [PATCH] OpenACC reference count overhaul)

2019-12-13 Thread Julian Brown
On Fri, 13 Dec 2019 16:25:25 +0100
Thomas Schwinge  wrote:

> Hi Julian!
> 
> On 2019-10-29T12:15:01+, Julian Brown 
> wrote:
> >  static int
> > -find_pointer (int pos, size_t mapnum, unsigned short *kinds)
> > +find_group_last (int pos, size_t mapnum, unsigned short *kinds)
> >  {
> > -  if (pos + 1 >= mapnum)
> > -return 0;
> > +  unsigned char kind0 = kinds[pos] & 0xff;
> > +  int first_pos = pos, last_pos = pos;
> >  
> > -  unsigned char kind = kinds[pos+1] & 0xff;
> > -
> > -  if (kind == GOMP_MAP_TO_PSET)
> > -return 3;
> > -  else if (kind == GOMP_MAP_POINTER)
> > -return 2;
> > +  if (kind0 == GOMP_MAP_TO_PSET)
> > +{
> > +  while (pos + 1 < mapnum && (kinds[pos + 1] & 0xff) ==
> > GOMP_MAP_POINTER)
> > +   last_pos = ++pos;
> > +  /* We expect at least one GOMP_MAP_POINTER after a
> > GOMP_MAP_TO_PSET.  */
> > +  assert (last_pos > first_pos);
> > +}
> > +  else
> > +{
> > +  /* GOMP_MAP_ALWAYS_POINTER can only appear directly after
> > some other
> > +mapping.  */
> > +  if (pos + 1 < mapnum
> > + && (kinds[pos + 1] & 0xff) == GOMP_MAP_ALWAYS_POINTER)
> > +   return pos + 1;
> > +
> > +  /* We can have one or several GOMP_MAP_POINTER mappings
> > after a to/from
> > +(etc.) mapping.  */
> > +  while (pos + 1 < mapnum && (kinds[pos + 1] & 0xff) ==
> > GOMP_MAP_POINTER)
> > +   last_pos = ++pos;
> > +}
> >  
> > -  return 0;
> > +  return last_pos;
> >  }  
> 
> So I ran a simple experiment where I did:
> 
> assert (find_group_last (i, mapnum, kinds) == i + pointer);
> 
> ... where 'pointer' is the current 'find_pointer' function.  (That is,
> compare that the old and new way are doing the same things, given the
> current GCC code generation/test cases.)
> 
> This 'assert' triggers for a few test cases:
> 'libgomp.oacc-fortran/allocatable-array-1.f90',
> 'libgomp.oacc-fortran/data-2.f90', 'libgomp.oacc-fortran/data-3.f90',
> 'libgomp.oacc-fortran/data-4-2.f90',
> 'libgomp.oacc-fortran/data-4.f90', 'libgomp.oacc-fortran/data-5.f90',
> 'libgomp.oacc-fortran/if-1.f90',
> 'libgomp.oacc-fortran/optional-data-enter-exit.f90'.  (Maybe those
> are the only ones actually using that stuff?)
> 
> I looked into the first one
> ('libgomp.oacc-fortran/allocatable-array-1.f90'), and for:
> 
> integer, parameter :: n = 40
> integer, allocatable :: ar(:,:,:)
> 
> allocate (ar(1:n,0:n-1,0:n-1))
> !$acc enter data copyin (ar)
> 
> ... found:
> 
> (gdb) print mapnum
> $2 = 3
> (gdb) print kinds[0]
> $3 = 1 // GOMP_MAP_TO
> (gdb) print kinds[1]
> $4 = 773
> (gdb) print kinds[1] & 0xff
> $5 = 5 // GOMP_MAP_TO_PSET
> (gdb) print kinds[2]
> $6 = 772
> (gdb) print kinds[2] & 0xff
> $7 = 4 // GOMP_MAP_POINTER
> 
> Current behavior: 'find_pointer (0, mapnum, kinds) == 3', so all three
> get mapped as one group.
> 
> New behavior: 'find_group_last (0, mapnum, kinds) == 0', so the
> 'GOMP_MAP_TO' gets mapped alone.  Then, 'find_group_last (1, mapnum,
> kinds) == 2', so the 'GOMP_MAP_TO_PSET', 'GOMP_MAP_POINTER' get
> mapped as one group.
> 
> Is that intentional?

Yes. In a previous iteration of the refcount overhaul patch, we had the
"magic" code fragment:

> +   for (int j = 0; j < 2; j++)  
> + gomp_map_vars_async (acc_dev, aq,
> +  (j == 0 || pointer == 2) ? 1 : 2,
> +  [i + j], NULL,
> +  [i + j], [i + j], true,
> +  GOMP_MAP_VARS_OPENACC_ENTER_DATA);  

The "pointer == 3" case here will do precisely the same thing as the
current iteration of the patch: pass the GOMP_MAP_TO to one
gomp_map_vars_async call, and pass the GOMP_MAP_TO_PSET +
GOMP_MAP_POINTER as a pair in a second call.

The "pointer == 2" case (i.e. with a GOMP_MAP_TO and a
GOMP_MAP_POINTER) will also handle the mappings separately in both the
earlier patch iteration and this one.

That's different from the current behaviour, because we don't want all
three mappings to be bound together. The problematic cases of doing
so might only appear with the manual deep copy patch applied also,
though (and/or with the refcount-checking patch applied/enabled). (I
don't remember exactly which test cases this affected, but I can check.)

The GOMP_MAP_TO_PSET plus the following GOMP_MAP_POINTER mappings are
treated as a group within gomp_map_vars_internal. So I'm not sure... 

> Any then, compating that to
> 'libgomp/target.c:GOMP_target_enter_exit_data', where (aside from
> 'GOMP_MAP_STRUCT'; not relevant for us right now, yes?) everything
> always gets mapped alone:
> 
> for (i = 0; i < mapnum; i++)
>   if ((kinds[i] & 0xff) == GOMP_MAP_STRUCT)
> { [...] }
>   else
> gomp_map_vars (devicep, 1, [i], NULL, [i],
> [i], true, GOMP_MAP_VARS_ENTER_DATA);
> 
> Is it just an "accident" that for OpenACC we were and still are going
> to do this differently, or is there 

Re: [OpenACC] Elaborate/simplify 'exit data' 'finalize' handling (was: [OpenACC] Update OpenACC data clause semantics to the 2.5 behavior)

2019-12-13 Thread Julian Brown
On Fri, 13 Dec 2019 15:13:53 +0100
Thomas Schwinge  wrote:

> Hi!
> 
> Julian, Tobias, regarding the following OpenACC 'exit data' 'finalize'
> handling:
> 
> On 2018-05-25T13:01:58-0700, Cesar Philippidis
>  wrote:
> > --- a/gcc/gimplify.c
> > +++ b/gcc/gimplify.c  
> 
> > @@ -10859,6 +10849,53 @@ gimplify_omp_target_update (tree *expr_p,
> > gimple_seq *pre_p)  
> 
> > +  else if (TREE_CODE (expr) == OACC_EXIT_DATA
> > +  && omp_find_clause (OMP_STANDALONE_CLAUSES (expr),
> > +  OMP_CLAUSE_FINALIZE))
> > +{
> > +  /* Use GOMP_MAP_DELETE/GOMP_MAP_FORCE_FROM to denote that
> > "finalize"
> > +semantics apply to all mappings of this OpenACC
> > directive.  */
> > +  bool finalize_marked = false;
> > +  for (tree c = OMP_STANDALONE_CLAUSES (expr); c; c =
> > OMP_CLAUSE_CHAIN (c))
> > +   if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP)
> > + switch (OMP_CLAUSE_MAP_KIND (c))
> > +   {
> > +   case GOMP_MAP_FROM:
> > + OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_FORCE_FROM);
> > + finalize_marked = true;
> > + break;
> > +   case GOMP_MAP_RELEASE:
> > + OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_DELETE);
> > + finalize_marked = true;
> > + break;
> > +   default:
> > + /* Check consistency: libgomp relies on the very
> > first data
> > +mapping clause being marked, so make sure we did
> > that before
> > +any other mapping clauses.  */
> > + gcc_assert (finalize_marked);
> > + break;
> > +   }
> > +}  
> 
> > --- a/libgomp/oacc-parallel.c
> > +++ b/libgomp/oacc-parallel.c  
> 
> > @@ -286,6 +360,17 @@ GOACC_enter_exit_data (int device, size_t
> > mapnum,  
> 
> > +  /* Determine whether "finalize" semantics apply to all mappings
> > of this
> > + OpenACC directive.  */
> > +  bool finalize = false;
> > +  if (mapnum > 0)
> > +{
> > +  unsigned char kind = kinds[0] & 0xff;
> > +  if (kind == GOMP_MAP_DELETE
> > + || kind == GOMP_MAP_FORCE_FROM)
> > +   finalize = true;
> > +}
> > +  
> 
> > @@ -360,22 +458,28 @@ GOACC_enter_exit_data (int device, size_t
> > mapnum,  
> 
> > switch (kind)
> >   {
> > - case GOMP_MAP_POINTER:
> > -   gomp_acc_remove_pointer (hostaddrs[i], (kinds[i] &
> > 0xff)
> > -== GOMP_MAP_FORCE_FROM,
> > -async, 1);
> > -   break;
> > + case GOMP_MAP_RELEASE:
> >   case GOMP_MAP_DELETE:
> > -   acc_delete (hostaddrs[i], sizes[i]);
> > +   if (acc_is_present (hostaddrs[i], sizes[i]))
> > + {
> > +   if (finalize)
> > + acc_delete_finalize (hostaddrs[i], sizes[i]);
> > +   else
> > + acc_delete (hostaddrs[i], sizes[i]);
> > + }
> > break;
> > + case GOMP_MAP_FROM:
> >   case GOMP_MAP_FORCE_FROM:
> > -   acc_copyout (hostaddrs[i], sizes[i]);
> > +   if (finalize)
> > + acc_copyout_finalize (hostaddrs[i], sizes[i]);
> > +   else
> > + acc_copyout (hostaddrs[i], sizes[i]);
> > break;
> >   default:
> > gomp_fatal (" GOACC_enter_exit_data UNHANDLED
> > kind 0x%.2x", @@ -385,10 +489,12 @@ GOACC_enter_exit_data (int
> > device, size_t mapnum, }
> > else
> >   {
> > -   gomp_acc_remove_pointer (hostaddrs[i], (kinds[i] &
> > 0xff)
> > -== GOMP_MAP_FORCE_FROM,
> > async, 3); +[...]
> > +   gomp_acc_remove_pointer (hostaddrs[i], sizes[i],
> > copyfrom, async,
> > +finalize, pointer);  
> 
> ... does the attached patch "[OpenACC] Elaborate/simplify 'exit data'
> 'finalize' handling" (with "No functional changes") match your
> understanding of what's going on?

Your patch looks OK to me, FWIW. As you mentioned at some point though,
it might be good to get rid of this style of finalize handling,
replacing it with a flag passed to GOACC_exit_data -- presuming that at
the same time, we separate out the needlessly-dual-purpose
GOACC_enter_exit_data API entry point into "enter" and "exit" halves.

Thanks,

Julian


Re: C++ PATCH for c++/88337 - Implement P1327R1: Allow dynamic_cast in constexpr

2019-12-13 Thread Jason Merrill

On 12/13/19 3:20 PM, Marek Polacek wrote:

On Thu, Dec 12, 2019 at 02:38:29PM -0500, Jason Merrill wrote:

On 12/11/19 5:50 PM, Marek Polacek wrote:

On Fri, Nov 22, 2019 at 04:11:53PM -0500, Jason Merrill wrote:

On 11/8/19 4:24 PM, Marek Polacek wrote:



2) [class.cdtor] says that when a dynamic_cast is used in a constructor or
destructor and the operand of the dynamic_cast refers to the object under
construction or destruction, this object is considered to be a most derived
object.


This means that during the 'tor the vtable pointer refers to the type_info
for that class and the offset-to-top is 0.  Can you use that?


I can't seem to: For e.g.

struct C : A, C2 { A *c = dynamic_cast(static_cast(this)); };

the object under construction is C, the call to __dynamic_cast will be
__dynamic_cast (SAVE_EXPR <&((struct C *) this)->D.2119>, &_ZTI2C2, &_ZTI1A, -2)
here, OBJ is f.D.2156.D.2119 and ctx->global->ctor_object is f.D.2156.  So OBJ
refers to the object under construction.

But I don't see C anywhere; CLASSTYPE_TYPEINFO_VAR of OBJTYPE is _ZTI2C2.

Am I looking into the wrong place?


Evaluating build_vfield_ref (obj, objtype) will give you the vtable pointer,
in this case &_ZTV1C + 40.  And then you can get C from DECL_CONTEXT
(_ZTV1C).

Or get_tinfo_decl_dynamic (obj) will give you the type_info.


Awesome, thanks a lot!  The following patch uses the first approach.  I've
also simplified the code somewhat.  constexpr-dynamic11.C was expanded a bit.

The error handling inflates the patch, but I'm not sure if a helper macro
would be preferable.

Bootstrapped/regtested on x86_64-linux, ok for trunk?

2019-12-13  Marek Polacek  

PR c++/88337 - Implement P1327R1: Allow dynamic_cast in constexpr.
* constexpr.c (cxx_dynamic_cast_fn_p): New function.
(extract_obj_from_addr_offset): New function.
(get_component_with_type): New function.
(cxx_eval_dynamic_cast_fn): New function.
(cxx_eval_call_expression): Call cxx_eval_dynamic_cast_fn for a call
to __dynamic_cast.
(potential_constant_expression_1): Don't give up on
cxx_dynamic_cast_fn_p.
* rtti.c (build_dynamic_cast_1): When creating a call to
__dynamic_cast, use the location of the original expression.

* g++.dg/cpp2a/constexpr-dynamic1.C: New test.
* g++.dg/cpp2a/constexpr-dynamic10.C: New test.
* g++.dg/cpp2a/constexpr-dynamic11.C: New test.
* g++.dg/cpp2a/constexpr-dynamic12.C: New test.
* g++.dg/cpp2a/constexpr-dynamic13.C: New test.
* g++.dg/cpp2a/constexpr-dynamic14.C: New test.
* g++.dg/cpp2a/constexpr-dynamic2.C: New test.
* g++.dg/cpp2a/constexpr-dynamic3.C: New test.
* g++.dg/cpp2a/constexpr-dynamic4.C: New test.
* g++.dg/cpp2a/constexpr-dynamic5.C: New test.
* g++.dg/cpp2a/constexpr-dynamic6.C: New test.
* g++.dg/cpp2a/constexpr-dynamic7.C: New test.
* g++.dg/cpp2a/constexpr-dynamic8.C: New test.
* g++.dg/cpp2a/constexpr-dynamic9.C: New test.

diff --git gcc/cp/constexpr.c gcc/cp/constexpr.c
index 19e09c74760..1db9c9a96a4 100644
--- gcc/cp/constexpr.c
+++ gcc/cp/constexpr.c
@@ -1692,6 +1692,239 @@ is_std_allocator_allocate (tree fndecl)
return decl_in_std_namespace_p (decl);
  }
  
+/* Return true if FNDECL is __dynamic_cast.  */

+
+static inline bool
+cxx_dynamic_cast_fn_p (tree fndecl)
+{
+  return (cxx_dialect >= cxx2a
+ && id_equal (DECL_NAME (fndecl), "__dynamic_cast")
+ && CP_DECL_CONTEXT (fndecl) == global_namespace);
+}
+
+/* Often, we have an expression in the form of address + offset, e.g.
+   "&_ZTV1A + 16".  Extract the object from it, i.e. "_ZTV1A".  */
+
+static tree
+extract_obj_from_addr_offset (tree expr)
+{
+  if (TREE_CODE (expr) == POINTER_PLUS_EXPR)
+expr = TREE_OPERAND (expr, 0);
+  STRIP_NOPS (expr);
+  if (TREE_CODE (expr) == ADDR_EXPR)
+expr = TREE_OPERAND (expr, 0);
+  return expr;
+}
+
+/* Given a PATH like
+
+ g.D.2181.D.2154.D.2102.D.2093
+
+   find a component with type TYPE.  Return NULL_TREE if not found, and
+   error_mark_node if the component is not accessible.  */
+
+static tree
+get_component_with_type (tree path, tree type)
+{
+  while (true)
+{
+  if (same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (path), type))
+   /* Found it.  */
+   return path;
+  else if (TREE_CODE (path) == COMPONENT_REF
+  && DECL_FIELD_IS_BASE (TREE_OPERAND (path, 1)))
+   {
+ /* We need to check that the component we're accessing is in fact
+accessible.  */
+ if (TREE_PRIVATE (TREE_OPERAND (path, 1))
+ || TREE_PROTECTED (TREE_OPERAND (path, 1)))
+   return error_mark_node;
+ path = TREE_OPERAND (path, 0);
+   }
+  else
+   return NULL_TREE;
+}
+}
+
+/* Evaluate a call to __dynamic_cast (permitted by P1327R1).
+
+   The declaration of __dynamic_cast is:
+
+   void* __dynamic_cast (const 

gccgo branch updated

2019-12-13 Thread Ian Lance Taylor
I've updated the gccgo branch to revision 279380 of trunk.

Ian


[PATCH] Fix pretty printers tests

2019-12-13 Thread François Dumont
Here is a patch to fix prettyprinters.exp failures in normal and debug 
modes.


In 80276.cc I replicate the #define with comment from other tests even 
if it isn't true that cxx11 abi string isn't supported. It's just that 
it doesn't appear as 'std::string', the aliasing doesn't work.


I still have failures when running with versioned namespace which I am 
going to check now.


    * python/libstdcxx/v6/printers.py (lookup_node_type): Remove redundant
    call to lookup_node_type.
    * testsuite/libstdc++-prettyprinters/80276.cc: Define
    _GLIBCXX_USE_CXX11_ABI to 0.
    * testsuite/libstdc++-prettyprinters/91997.cc: Use regexp-test to check
    'a' content.

Ok to commit ?

François

diff --git a/libstdc++-v3/python/libstdcxx/v6/printers.py b/libstdc++-v3/python/libstdcxx/v6/printers.py
index 08327516b28..5119e6fab7e 100644
--- a/libstdc++-v3/python/libstdcxx/v6/printers.py
+++ b/libstdc++-v3/python/libstdcxx/v6/printers.py
@@ -146,7 +146,6 @@ def lookup_node_type(nodename, containertype):
 if is_member_of_namespace(containertype, 'std::__cxx1998',
   'std::__debug', '__gnu_debug'):
 nodename = nodename.replace('::', '::__cxx1998::', 1)
-return lookup_templ_spec(nodename, valtype)
 try:
 return lookup_templ_spec(nodename, valtype)
 except gdb.error:
diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/80276.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/80276.cc
index 3425b499e3a..272adb86e0c 100644
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/80276.cc
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/80276.cc
@@ -18,6 +18,9 @@
 // with this library; see the file COPYING3.  If not see
 // .
 
+// Type printers only recognize the old std::string for now.
+#define _GLIBCXX_USE_CXX11_ABI 0
+
 #include 
 #include 
 #include 
diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/91997.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/91997.cc
index 393c5680e2e..059ac9aa97f 100644
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/91997.cc
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/91997.cc
@@ -41,7 +41,7 @@ int main()
   // { dg-final { note-test mit {{first = 1, second = 2}} } }
 
   std::any a = m;
-  // { dg-final { note-test a {std::any containing std::map with 1 element = {[1] = 2}} } }
+  // { dg-final { regexp-test a {std::any containing std::(__debug::)?map with 1 element = {\[1\] = 2}} } }
 
   std::set s{1, 2};
   auto sit = s.begin();


[Darwin, PPC, committed] Use Darwin9 dylib header for Rosetta builds.

2019-12-13 Thread Iain Sandoe
On Darwin10 it's possible to make a 32b PPC build using the
'Rosetta' emulator.  However, these builds need to make use of
Darwin9 crts (for exes and dylibs).  This adds the change to
cater for dylibs.

tested on a powerpc-darwin10 native and a powerpc-darwin10 
cross from x86_64-darwin16.
applied to mainline,
thanks
Iain

gcc/ChangeLog:

2019-12-13  Iain Sandoe  

* config/rs6000/darwin.h (DARWIN_DYLIB1_SPEC): New.

diff --git a/gcc/config/rs6000/darwin.h b/gcc/config/rs6000/darwin.h
index d1a096f..8cf25b0 100644
--- a/gcc/config/rs6000/darwin.h
+++ b/gcc/config/rs6000/darwin.h
@@ -173,6 +173,12 @@
%:version-compare(!> 10.4 mmacosx-version-min= crt3_2.o%s) \
   }}"
 
+/* We need to jam the dylib1 to 10.5 for 10.6 (Rosetta) use.  */
+#undef DARWIN_DYLIB1_SPEC
+#define DARWIN_DYLIB1_SPEC \
+  "%:version-compare(!> 10.5 mmacosx-version-min= -ldylib1.o)  \
+   %:version-compare(>< 10.5 10.7 mmacosx-version-min= -ldylib1.10.5.o)"
+
 /* The PPC regs save/restore functions are leaves and could, conceivably
be used by the tm destructor.  */
 #undef ENDFILE_SPEC



Re: [PATCH, c] all plattforms: support using a CC_REG instead cc0_rtx

2019-12-13 Thread Segher Boessenkool
On Fri, Dec 13, 2019 at 08:55:15PM +0100, Stefan Franke wrote:
> Am 2019-12-13 18:58, schrieb Segher Boessenkool:
> >On Fri, Dec 13, 2019 at 05:25:41PM +0100, Stefan Franke wrote:
> >>Why? If you are using a cc register plus your architecture as many
> >>instructions which may clobber that cc register, some passes (e.g. 
> >>gcse)
> >>will reorder the insns. This can lead to the situation that an insn is
> >>moved between a compare and it' consuming jump insn. Which yields
> >>invalid code. (Note that at these stages clobbers are not yet tracked 
> >>as
> >>CLOBBER insns).
> >
> >Then that port has a bug.  In the m68k port, there are no separate 
> >compare
> >and jump insns ever, but for most ports those won't yet exist during 
> >gcse.
> 
> it looks like t2o insn for the m68k
> 
> (insn 115 114 116 5 (set (cc0)
> (compare (subreg:HI (reg:SI 272) 2)
> (reg:HI 273))) 
> /tmp/compiler-explorer-compiler1191113-13975-1allrsj.w8mc/example.c:216 
> 17 {*m68k.md:559}
>  (nil))
> (jump_insn 116 115 117 5 (set (pc)
> (if_then_else (ne (cc0)
> (const_int 0 [0]))
> (label_ref 99)
> (pc))) 
> /tmp/compiler-explorer-compiler1191113-13975-1allrsj.w8mc/example.c:216 
> 411 {bne}
>  (int_list:REG_BR_PROB 4 (nil))
>  -> 99)

This is an older compiler.  m68k no longer uses cc0 (except it is still
mentioned in two comments (well, commented-out code)).

> >This is not unique to cc0 conversions: every port has a similar problem
> >with all FIXED_REGISTERS.
> 
> It's not related to fixed registers.

No, it is exactly the same situation.  You cannot introduce uses of such
a register if it might already exist in the insn stream somewhere, not
without checking first, and you better have a backup plan too.

> It's unique to CC registers since 
> these are on some plattforms modified by side effects. So after split2 
> it's modelled using CLOBBERs

There are no such implicit side effects if you have gotten rid of cc0.
That is the *point* of removing cc0.

> >@findex cc0_rtx
> >There is only one expression object of code @code{cc0}; it is the
> >value of the variable @code{cc0_rtx}.  Any attempt to create an
> >expression of code @code{cc0} will return @code{cc0_rtx}.
> >
> >There is a lot of code that depends on this property, you cannot break
> >it without fixing everything.
> 
> There is no need to change the definition or modify any piece elsewhere. 
> And the modified comparison will still work for cc0.

Then you do not need your patch.  You can compare cc0_rtx by identity.


Segher


Re: C++ PATCH for c++/88337 - Implement P1327R1: Allow dynamic_cast in constexpr

2019-12-13 Thread Marek Polacek
On Thu, Dec 12, 2019 at 02:38:29PM -0500, Jason Merrill wrote:
> On 12/11/19 5:50 PM, Marek Polacek wrote:
> > On Fri, Nov 22, 2019 at 04:11:53PM -0500, Jason Merrill wrote:
> > > On 11/8/19 4:24 PM, Marek Polacek wrote:
> 
> > > > 2) [class.cdtor] says that when a dynamic_cast is used in a constructor 
> > > > or
> > > > destructor and the operand of the dynamic_cast refers to the object 
> > > > under
> > > > construction or destruction, this object is considered to be a most 
> > > > derived
> > > > object.
> > > 
> > > This means that during the 'tor the vtable pointer refers to the type_info
> > > for that class and the offset-to-top is 0.  Can you use that?
> > 
> > I can't seem to: For e.g.
> > 
> > struct C : A, C2 { A *c = dynamic_cast(static_cast(this)); };
> > 
> > the object under construction is C, the call to __dynamic_cast will be
> > __dynamic_cast (SAVE_EXPR <&((struct C *) this)->D.2119>, &_ZTI2C2, 
> > &_ZTI1A, -2)
> > here, OBJ is f.D.2156.D.2119 and ctx->global->ctor_object is f.D.2156.  So 
> > OBJ
> > refers to the object under construction.
> > 
> > But I don't see C anywhere; CLASSTYPE_TYPEINFO_VAR of OBJTYPE is _ZTI2C2.
> > 
> > Am I looking into the wrong place?
> 
> Evaluating build_vfield_ref (obj, objtype) will give you the vtable pointer,
> in this case &_ZTV1C + 40.  And then you can get C from DECL_CONTEXT
> (_ZTV1C).
> 
> Or get_tinfo_decl_dynamic (obj) will give you the type_info.

Awesome, thanks a lot!  The following patch uses the first approach.  I've
also simplified the code somewhat.  constexpr-dynamic11.C was expanded a bit.

The error handling inflates the patch, but I'm not sure if a helper macro
would be preferable.

Bootstrapped/regtested on x86_64-linux, ok for trunk?

2019-12-13  Marek Polacek  

PR c++/88337 - Implement P1327R1: Allow dynamic_cast in constexpr.
* constexpr.c (cxx_dynamic_cast_fn_p): New function.
(extract_obj_from_addr_offset): New function.
(get_component_with_type): New function.
(cxx_eval_dynamic_cast_fn): New function.
(cxx_eval_call_expression): Call cxx_eval_dynamic_cast_fn for a call
to __dynamic_cast.
(potential_constant_expression_1): Don't give up on
cxx_dynamic_cast_fn_p.
* rtti.c (build_dynamic_cast_1): When creating a call to
__dynamic_cast, use the location of the original expression.

* g++.dg/cpp2a/constexpr-dynamic1.C: New test.
* g++.dg/cpp2a/constexpr-dynamic10.C: New test.
* g++.dg/cpp2a/constexpr-dynamic11.C: New test.
* g++.dg/cpp2a/constexpr-dynamic12.C: New test.
* g++.dg/cpp2a/constexpr-dynamic13.C: New test.
* g++.dg/cpp2a/constexpr-dynamic14.C: New test.
* g++.dg/cpp2a/constexpr-dynamic2.C: New test.
* g++.dg/cpp2a/constexpr-dynamic3.C: New test.
* g++.dg/cpp2a/constexpr-dynamic4.C: New test.
* g++.dg/cpp2a/constexpr-dynamic5.C: New test.
* g++.dg/cpp2a/constexpr-dynamic6.C: New test.
* g++.dg/cpp2a/constexpr-dynamic7.C: New test.
* g++.dg/cpp2a/constexpr-dynamic8.C: New test.
* g++.dg/cpp2a/constexpr-dynamic9.C: New test.

diff --git gcc/cp/constexpr.c gcc/cp/constexpr.c
index 19e09c74760..1db9c9a96a4 100644
--- gcc/cp/constexpr.c
+++ gcc/cp/constexpr.c
@@ -1692,6 +1692,239 @@ is_std_allocator_allocate (tree fndecl)
   return decl_in_std_namespace_p (decl);
 }
 
+/* Return true if FNDECL is __dynamic_cast.  */
+
+static inline bool
+cxx_dynamic_cast_fn_p (tree fndecl)
+{
+  return (cxx_dialect >= cxx2a
+ && id_equal (DECL_NAME (fndecl), "__dynamic_cast")
+ && CP_DECL_CONTEXT (fndecl) == global_namespace);
+}
+
+/* Often, we have an expression in the form of address + offset, e.g.
+   "&_ZTV1A + 16".  Extract the object from it, i.e. "_ZTV1A".  */
+
+static tree
+extract_obj_from_addr_offset (tree expr)
+{
+  if (TREE_CODE (expr) == POINTER_PLUS_EXPR)
+expr = TREE_OPERAND (expr, 0);
+  STRIP_NOPS (expr);
+  if (TREE_CODE (expr) == ADDR_EXPR)
+expr = TREE_OPERAND (expr, 0);
+  return expr;
+}
+
+/* Given a PATH like
+
+ g.D.2181.D.2154.D.2102.D.2093
+
+   find a component with type TYPE.  Return NULL_TREE if not found, and
+   error_mark_node if the component is not accessible.  */
+
+static tree
+get_component_with_type (tree path, tree type)
+{
+  while (true)
+{
+  if (same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (path), type))
+   /* Found it.  */
+   return path;
+  else if (TREE_CODE (path) == COMPONENT_REF
+  && DECL_FIELD_IS_BASE (TREE_OPERAND (path, 1)))
+   {
+ /* We need to check that the component we're accessing is in fact
+accessible.  */
+ if (TREE_PRIVATE (TREE_OPERAND (path, 1))
+ || TREE_PROTECTED (TREE_OPERAND (path, 1)))
+   return error_mark_node;
+ path = TREE_OPERAND (path, 0);
+   }
+  else
+   return NULL_TREE;
+}
+}
+
+/* Evaluate a call to 

libbacktrace patch committed: Add DWARF 5 support

2019-12-13 Thread Ian Lance Taylor
This patch to libbacktrace adds DWARF 5 support.  I tested this with
GCC 8, GCC tip, and clang 8, using the -gdwarf-5 option.  Bootstrapped
and ran libbacktrace and libgo tests on x86_64-pc-linux-gnu.
Committed to mainline.

Ian

2019-12-13  Ian Lance Taylor  

Add DWARF 5 support.
* dwarf.c (struct attr): Add val field.
(enum attr_val_encoding): Add ATTR_VAL_ADDDRESS_INDEX,
ATTR_VAL_STRING_INDEX, ATTR_VAL_RNGLISTS_INDEX.
(struct line_header): Add addrsize field.
(struct line_header_format): Define.
(struct unit): Add str_offsets_base, addr_base, and rnglists_base
fields.
(read_uint24): New static function.
(read_attribute): Add implicit_val parameter.  Replace dwarf_str
and dwarf_str_size parameters with dwarf_sections parameter.  Add
support for new DWARF 5 forms.  Change all callers.
(resolve_string): New static function.
(resolve_addr_index): Likewise.
(read_abbrevs): Support DW_FORM_implicit_const.
(struct pcrange): Add lowpc_is_addr_index, highpc_is_addr_Index,
and ranges_is_index fields.
(update_pcrange): Support DWARF 5 encodings.
(add_high_low_range): New static function, split out of
add_ranges.
(add_ranges_from_ranges): Likewise.
(add_ranges_from_rnglists): New static function.
(add_ranges): Just call new helper functions.
(find_address_ranges): Use resolve_string for strings, after
reading all attributes.  Handle new DWARF 5 attributes.
(build_address_map): Support DWARF 5 compilation units.
(read_v2_paths): New static function, split out of
read_line_header.
(read_lnct): New static function.
(read_line_header_format_entries): Likewise.
(read_line_header): Add ddata parameter.  Support DWARF 5 line
headers.  Call new helper functions.  Change all callers.
(read_line_program): Use addrsize from line program header.  Don't
special case directory index 0 for DWARF 5.
(read_referenced_name): Use resolve_string.
(read_function_entry): Handle DWARF 5 encodings.  Use
resolve_string.
* internal.h (enum dwarf_section): Add DEBUG_ADDR,
DEBUG_STR_OFFSETS, DEBUG_LINE_STR, DEBUG_RNGLISTS.
* elf.c (dwarf_section_names): Add new section names.
* pecoff.c (dwarf_section_names): Likewise.
* xcoff.c (xcoff_add): Clear dwarf_sections before setting
fields.
* configure.ac: Define HAVE_DWARF5 automake conditional.
* Makefile.am (dwarf5_SOURCES): New variable if HAVE_DWARF5.
(dwarf5_CFLAGS, dwarf5_LDADD): Likewise.
(dwarf5_alloc_SOURCES, dwarf5_alloc_CFLAGS): Likewise.
(dwarf5_alloc_LDADD): Likewise.
(BUILDTESTS): Add dwarf5 tests if HAVE_DWARF5.
(CLEANFILES, clean-local): Define.
Index: Makefile.am
===
--- Makefile.am (revision 279211)
+++ Makefile.am (working copy)
@@ -385,12 +385,33 @@ BUILDTESTS += ctestg_alloc ctesta_alloc
 
 endif
 
+if HAVE_DWARF5
+
+dwarf5_SOURCES = btest.c testlib.c
+dwarf5_CFLAGS = $(AM_CFLAGS) -gdwarf-5
+dwarf5_LDADD = libbacktrace.la
+
+BUILDTESTS += dwarf5
+
+dwarf5_alloc_SOURCES = $(dwarf5_SOURCES)
+dwarf5_alloc_CFLAGS = $(dwarf5_CFLAGS)
+dwarf5_alloc_LDADD = libbacktrace_alloc.la
+
+BUILDTESTS += dwarf5_alloc
+
+endif
+
 endif NATIVE
 
 check_PROGRAMS += $(BUILDTESTS)
 
 TESTS += $(BUILDTESTS)
 
+CLEANFILES = $(TESTS) *.debug elf_for_test.c edtest2_build.c gen_edtest2_build
+
+clean-local:
+   -rm -rf usr
+
 # We can't use automake's automatic dependency tracking, because it
 # breaks when using bootstrap-lean.  Automatic dependency tracking
 # with GCC bootstrap will cause some of the objects to depend on
Index: configure.ac
===
--- configure.ac(revision 279211)
+++ configure.ac(working copy)
@@ -420,6 +420,17 @@ AC_SUBST(PTHREAD_CFLAGS)
 
 AM_CONDITIONAL(HAVE_PTHREAD, test "$libgo_cv_lib_pthread" = yes)
 
+dnl Test whether the compiler supports the -gdwarf-5 option.
+AC_CACHE_CHECK([whether -gdwarf-5 is supported],
+[libbacktrace_cv_lib_dwarf5],
+[CFLAGS_hold=$CFLAGS
+CFLAGS="$CFLAGS -gdwarf-5"
+AC_COMPILE_IFELSE([AC_LANG_SOURCE([int i;])],
+[libbacktrace_cv_lib_dwarf5=yes],
+[libbacktrace_cv_lib_dwarf5=no])
+CFLAGS=$CFLAGS_hold])
+AM_CONDITIONAL(HAVE_DWARF5, test "$libbacktrace_cv_lib_dwarf5" = yes)
+
 AC_CHECK_LIB([z], [compress],
 [AC_DEFINE(HAVE_ZLIB, 1, [Define if -lz is available.])])
 AM_CONDITIONAL(HAVE_ZLIB, test "$ac_cv_lib_z_compress" = yes)
Index: dwarf.c
===
--- dwarf.c (revision 279211)
+++ dwarf.c (working copy)
@@ -92,6 +92,8 @@ struct attr
   enum dwarf_attribute name;
   /* The attribute form.  */
   enum dwarf_form form;
+  /* The attribute value, for DW_FORM_implicit_const.  */
+  int64_t val;
 };
 
 /* A single DWARF abbreviation.  */
@@ -133,22 +135,29 @@ enum attr_val_encoding
   ATTR_VAL_NONE,
   /* An address.  */
   ATTR_VAL_ADDRESS,
+  /* An index into the .debug_addr section, whose value is relative to
+   * the DW_AT_addr_base attribute of the compilation unit.  */
+  ATTR_VAL_ADDRESS_INDEX,
   /* A unsigned integer.  */
   

Re: [PATCH, c] all plattforms: support using a CC_REG instead cc0_rtx

2019-12-13 Thread Stefan Franke

Am 2019-12-13 18:58, schrieb Segher Boessenkool:

Hi!

On Fri, Dec 13, 2019 at 05:25:41PM +0100, Stefan Franke wrote:
I suggest this patch to allow architectures do substitute cc0_rtx with 
a

generated cc register.

Why? If you are using a cc register plus your architecture as many
instructions which may clobber that cc register, some passes (e.g. 
gcse)

will reorder the insns. This can lead to the situation that an insn is
moved between a compare and it' consuming jump insn. Which yields
invalid code. (Note that at these stages clobbers are not yet tracked 
as

CLOBBER insns).


Then that port has a bug.  In the m68k port, there are no separate 
compare
and jump insns ever, but for most ports those won't yet exist during 
gcse.


it looks like t2o insn for the m68k

(insn 115 114 116 5 (set (cc0)
(compare (subreg:HI (reg:SI 272) 2)
(reg:HI 273))) 
/tmp/compiler-explorer-compiler1191113-13975-1allrsj.w8mc/example.c:216 
17 {*m68k.md:559}

 (nil))
(jump_insn 116 115 117 5 (set (pc)
(if_then_else (ne (cc0)
(const_int 0 [0]))
(label_ref 99)
(pc))) 
/tmp/compiler-explorer-compiler1191113-13975-1allrsj.w8mc/example.c:216 
411 {bne}

 (int_list:REG_BR_PROB 4 (nil))
 -> 99)


and the i386 uses too two insns:

(insn 17 16 18 4 (set (reg:CCNO 17 flags)
(compare:CCNO (reg/v:SI 96 [  ])
(const_int 0 [0]))) "x.c":2 3 {*cmpsi_ccno_1}
 (nil))
(jump_insn 18 17 19 4 (set (pc)
(if_then_else (le (reg:CCNO 17 flags)
(const_int 0 [0]))
(label_ref:DI 28)
(pc))) "x.c":2 627 {*jcc_1}
 (int_list:REG_BR_PROB 1500 (nil))


Now consider an insn gets moved in between modifiyng that status 
register...




This is not unique to cc0 conversions: every port has a similar problem
with all FIXED_REGISTERS.


It's not related to fixed registers. It's unique to CC registers since 
these are on some plattforms modified by side effects. So after split2 
it's modelled using CLOBBERs




--- a/gcc/jump.c
+++ b/gcc/jump.c
@@ -1028,7 +1028,7 @@ sets_cc0_p (const_rtx x)
   if (INSN_P (x))
 x = PATTERN (x);

-  if (GET_CODE (x) == SET && SET_DEST (x) == cc0_rtx)
+  if (GET_CODE (x) == SET && rtx_equal_p(SET_DEST (x), cc0_rtx))
 return 1;


@findex cc0_rtx
There is only one expression object of code @code{cc0}; it is the
value of the variable @code{cc0_rtx}.  Any attempt to create an
expression of code @code{cc0} will return @code{cc0_rtx}.

There is a lot of code that depends on this property, you cannot break
it without fixing everything.


Segher


There is no need to change the definition or modify any piece elsewhere. 
And the modified comparison will still work for cc0.



Stefan


Re: [PATCH 16/45] analyzer: new builtins

2019-12-13 Thread David Malcolm
On Fri, 2019-12-13 at 19:27 +0100, Jakub Jelinek wrote:
> On Fri, Dec 13, 2019 at 01:11:05PM -0500, David Malcolm wrote:
> > gcc/ChangeLog:
> > * builtins.def (BUILT_IN_ANALYZER_BREAK): New builtin.
> > (BUILT_IN_ANALYZER_DUMP): New builtin.
> > (BUILT_IN_ANALYZER_DUMP_EXPLODED_NODES): New builtin.
> > (BUILT_IN_ANALYZER_DUMP_NUM_HEAP_REGIONS): New builtin.
> > (BUILT_IN_ANALYZER_DUMP_PATH): New builtin.
> > (BUILT_IN_ANALYZER_DUMP_REGION_MODEL): New builtin.
> > (BUILT_IN_ANALYZER_EVAL): New builtin.
> 
> Is it a good idea to add further builtins without __builtin_
> prefix (unless required for interoperability etc.)?

I think I can do all of these with just string matching on the fndecl
names; would that be preferable to having them as builtins?

Dave



Re: [PATCH 16/45] analyzer: new builtins

2019-12-13 Thread Jakub Jelinek
On Fri, Dec 13, 2019 at 01:11:05PM -0500, David Malcolm wrote:
> gcc/ChangeLog:
>   * builtins.def (BUILT_IN_ANALYZER_BREAK): New builtin.
>   (BUILT_IN_ANALYZER_DUMP): New builtin.
>   (BUILT_IN_ANALYZER_DUMP_EXPLODED_NODES): New builtin.
>   (BUILT_IN_ANALYZER_DUMP_NUM_HEAP_REGIONS): New builtin.
>   (BUILT_IN_ANALYZER_DUMP_PATH): New builtin.
>   (BUILT_IN_ANALYZER_DUMP_REGION_MODEL): New builtin.
>   (BUILT_IN_ANALYZER_EVAL): New builtin.

Is it a good idea to add further builtins without __builtin_
prefix (unless required for interoperability etc.)?

Jakub



[PATCH 33/45] analyzer: new file: sm-signal.cc

2019-12-13 Thread David Malcolm
New in v4; part of:
  https://gcc.gnu.org/ml/gcc-patches/2019-12/msg00214.html
with various fixups

gcc/ChangeLog:
* analyzer/sm-signal.cc: New file.
---
 gcc/analyzer/sm-signal.cc | 306 ++
 1 file changed, 306 insertions(+)
 create mode 100644 gcc/analyzer/sm-signal.cc

diff --git a/gcc/analyzer/sm-signal.cc b/gcc/analyzer/sm-signal.cc
new file mode 100644
index ..e01ff30d9172
--- /dev/null
+++ b/gcc/analyzer/sm-signal.cc
@@ -0,0 +1,306 @@
+/* An experimental state machine, for tracking bad calls from within
+   signal handlers.
+
+   Copyright (C) 2019 Free Software Foundation, Inc.
+   Contributed by David Malcolm .
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tree.h"
+#include "function.h"
+#include "basic-block.h"
+#include "gimple.h"
+#include "diagnostic-path.h"
+#include "diagnostic-metadata.h"
+#include "analyzer/analyzer.h"
+#include "analyzer/checker-path.h"
+#include "analyzer/exploded-graph.h"
+#include "analyzer/pending-diagnostic.h"
+#include "analyzer/sm.h"
+
+#if ENABLE_ANALYZER
+
+namespace {
+
+/* An experimental state machine, for tracking calls to async-signal-unsafe
+   functions from within signal handlers.  */
+
+class signal_state_machine : public state_machine
+{
+public:
+  signal_state_machine (logger *logger);
+
+  bool inherited_state_p () const FINAL OVERRIDE { return false; }
+
+  bool on_stmt (sm_context *sm_ctxt,
+   const supernode *node,
+   const gimple *stmt) const FINAL OVERRIDE;
+
+  void on_condition (sm_context *sm_ctxt,
+const supernode *node,
+const gimple *stmt,
+tree lhs,
+enum tree_code op,
+tree rhs) const FINAL OVERRIDE;
+
+  bool can_purge_p (state_t s) const FINAL OVERRIDE;
+
+  /* These states are "global", rather than per-expression.  */
+
+  /* Start state.  */
+  state_t m_start;
+
+  /* State for when we're in a signal handler.  */
+  state_t m_in_signal_handler;
+
+  /* Stop state.  */
+  state_t m_stop;
+};
+
+/* Concrete subclass for describing call to an async-signal-unsafe function
+   from a signal handler.  */
+
+class signal_unsafe_call
+  : public pending_diagnostic_subclass
+{
+public:
+  signal_unsafe_call (const signal_state_machine , const gcall *unsafe_call,
+ tree unsafe_fndecl)
+  : m_sm (sm), m_unsafe_call (unsafe_call), m_unsafe_fndecl (unsafe_fndecl)
+  {
+gcc_assert (m_unsafe_fndecl);
+  }
+
+  const char *get_kind () const FINAL OVERRIDE { return "signal_unsafe_call"; }
+
+  bool operator== (const signal_unsafe_call ) const
+  {
+return m_unsafe_call == other.m_unsafe_call;
+  }
+
+  bool emit (rich_location *rich_loc) FINAL OVERRIDE
+  {
+diagnostic_metadata m;
+/* CWE-479: Signal Handler Use of a Non-reentrant Function.  */
+m.add_cwe (479);
+return warning_at (rich_loc, m,
+  OPT_Wanalyzer_unsafe_call_within_signal_handler,
+  "call to %qD from within signal handler",
+  m_unsafe_fndecl);
+  }
+
+  label_text describe_state_change (const evdesc::state_change )
+FINAL OVERRIDE
+  {
+if (change.is_global_p ()
+   && change.m_new_state == m_sm.m_in_signal_handler)
+  {
+   function *handler
+ = change.m_event.m_dst_state.m_region_model->get_current_function ();
+   return change.formatted_print ("registering %qD as signal handler",
+  handler->decl);
+  }
+return label_text ();
+  }
+
+  label_text describe_final_event (const evdesc::final_event ) FINAL 
OVERRIDE
+  {
+return ev.formatted_print ("call to %qD from within signal handler",
+  m_unsafe_fndecl);
+  }
+
+private:
+  const signal_state_machine _sm;
+  const gcall *m_unsafe_call;
+  tree m_unsafe_fndecl;
+};
+
+/* signal_state_machine's ctor.  */
+
+signal_state_machine::signal_state_machine (logger *logger)
+: state_machine ("signal", logger)
+{
+  m_start = add_state ("start");
+  m_in_signal_handler = add_state ("in_signal_handler");
+  m_stop = add_state ("stop");
+}
+
+/* Update MODEL for edges that simulate HANDLER_FUN being called as
+   an signal-handler in response to a signal.  */
+
+static void

[PATCH 35/45] analyzer: new files: analysis-plan.{cc|h}

2019-12-13 Thread David Malcolm
Changed in v4:
- Remove include of gcc-plugin.h, reworking includes accordingly.
- Wrap everything in #if ENABLE_ANALYZER
- Use TV_ANALYZER_PLAN rather than an auto_client_timevar.
- Update for new param API.
- Add DISABLE_COPY_AND_ASSIGN (analysis_plan);

This patch adds an analysis_plan class, which encapsulate decisions about
how the analysis should happen (e.g. the order in which functions should
be traversed).

gcc/ChangeLog:
* analyzer/analysis-plan.cc: New file.
* analyzer/analysis-plan.h: New file.
---
 gcc/analyzer/analysis-plan.cc | 118 ++
 gcc/analyzer/analysis-plan.h  |  58 +
 2 files changed, 176 insertions(+)
 create mode 100644 gcc/analyzer/analysis-plan.cc
 create mode 100644 gcc/analyzer/analysis-plan.h

diff --git a/gcc/analyzer/analysis-plan.cc b/gcc/analyzer/analysis-plan.cc
new file mode 100644
index ..ca9b01b32c96
--- /dev/null
+++ b/gcc/analyzer/analysis-plan.cc
@@ -0,0 +1,118 @@
+/* A class to encapsulate decisions about how the analysis should happen.
+   Copyright (C) 2019 Free Software Foundation, Inc.
+   Contributed by David Malcolm .
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tree.h"
+#include "options.h"
+#include "cgraph.h"
+#include "timevar.h"
+#include "ipa-utils.h"
+#include "analyzer/analyzer.h"
+#include "analyzer/analysis-plan.h"
+#include "analyzer/supergraph.h"
+
+#if ENABLE_ANALYZER
+
+/* class analysis_plan.  */
+
+/* analysis_plan's ctor.  */
+
+analysis_plan::analysis_plan (const supergraph , logger *logger)
+: log_user (logger), m_sg (sg),
+  m_cgraph_node_postorder (XCNEWVEC (struct cgraph_node *,
+symtab->cgraph_count)),
+  m_index_by_uid (symtab->cgraph_max_uid)
+{
+  LOG_SCOPE (logger);
+  auto_timevar time (TV_ANALYZER_PLAN);
+
+  m_num_cgraph_nodes = ipa_reverse_postorder (m_cgraph_node_postorder);
+  gcc_assert (m_num_cgraph_nodes == symtab->cgraph_count);
+  if (get_logger_file ())
+ipa_print_order (get_logger_file (),
+"analysis_plan", m_cgraph_node_postorder,
+m_num_cgraph_nodes);
+
+  /* Populate m_index_by_uid.  */
+  for (int i = 0; i < symtab->cgraph_max_uid; i++)
+m_index_by_uid.quick_push (-1);
+  for (int i = 0; i < m_num_cgraph_nodes; i++)
+{
+  gcc_assert (m_cgraph_node_postorder[i]->get_uid ()
+ < symtab->cgraph_max_uid);
+  m_index_by_uid[m_cgraph_node_postorder[i]->get_uid ()] = i;
+}
+}
+
+/* analysis_plan's dtor.  */
+
+analysis_plan::~analysis_plan ()
+{
+  free (m_cgraph_node_postorder);
+}
+
+/* Comparator for use by the exploded_graph's worklist, to order FUN_A
+   and FUN_B so that functions that are to be summarized are visited
+   before the summary is needed (based on a sort of the callgraph).  */
+
+int
+analysis_plan::cmp_function (function *fun_a, function *fun_b) const
+{
+  cgraph_node *node_a = cgraph_node::get (fun_a->decl);
+  cgraph_node *node_b = cgraph_node::get (fun_b->decl);
+
+  int idx_a = m_index_by_uid[node_a->get_uid ()];
+  int idx_b = m_index_by_uid[node_b->get_uid ()];
+
+  return idx_b - idx_a;
+}
+
+/* Return true if the call EDGE should be analyzed using a call summary.
+   Return false if it should be analyzed using a full call and return.  */
+
+bool
+analysis_plan::use_summary_p (const cgraph_edge *edge) const
+{
+  /* Don't use call summaries if -fno-analyzer-call-summaries.  */
+  if (!flag_analyzer_call_summaries)
+return false;
+
+  /* TODO: don't count callsites each time.  */
+  int num_call_sites = 0;
+  const cgraph_node *callee = edge->callee;
+  for (cgraph_edge *edge = callee->callers; edge; edge = edge->next_caller)
+++num_call_sites;
+
+  /* Don't use a call summary if there's only one call site.  */
+  if (num_call_sites <= 1)
+return false;
+
+  /* Require the callee to be sufficiently complex to be worth
+ summarizing.  */
+  if ((int)m_sg.get_num_snodes (callee->get_fun ())
+  < param_analyzer_min_snodes_for_call_summary)
+return false;
+
+  return true;
+}
+
+#endif /* #if ENABLE_ANALYZER */
diff --git a/gcc/analyzer/analysis-plan.h b/gcc/analyzer/analysis-plan.h
new file mode 100644
index ..f22e7338b1e7
--- /dev/null
+++ b/gcc/analyzer/analysis-plan.h
@@ -0,0 +1,58 @@
+/* A class to encapsulate 

[PATCH 31/45] analyzer: new file: sm-pattern-test.cc

2019-12-13 Thread David Malcolm
Changed in v4:
- Remove include of gcc-plugin.h, reworking includes accordingly.
- Wrap everything in #if ENABLE_ANALYZER
- Remove /// comment lines
- Rework on_leak vfunc:
https://gcc.gnu.org/ml/gcc-patches/2019-11/msg02028.html

This patch adds a custom state machine checker intended purely for DejaGnu
testing of the sm "machinery".

gcc/ChangeLog:
* analyzer/sm-pattern-test.cc: New file.
---
 gcc/analyzer/sm-pattern-test.cc | 149 
 1 file changed, 149 insertions(+)
 create mode 100644 gcc/analyzer/sm-pattern-test.cc

diff --git a/gcc/analyzer/sm-pattern-test.cc b/gcc/analyzer/sm-pattern-test.cc
new file mode 100644
index ..f7fc21f04049
--- /dev/null
+++ b/gcc/analyzer/sm-pattern-test.cc
@@ -0,0 +1,149 @@
+/* A state machine for use in DejaGnu tests, to check that
+   pattern-matching works as expected.
+
+   Copyright (C) 2019 Free Software Foundation, Inc.
+   Contributed by David Malcolm .
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tree.h"
+#include "function.h"
+#include "basic-block.h"
+#include "gimple.h"
+#include "tree-pretty-print.h"
+#include "diagnostic-path.h"
+#include "diagnostic-metadata.h"
+#include "analyzer/analyzer.h"
+#include "analyzer/pending-diagnostic.h"
+#include "analyzer/sm.h"
+
+#if ENABLE_ANALYZER
+
+namespace {
+
+/* A state machine for use in DejaGnu tests, to check that
+   pattern-matching works as expected.  */
+
+class pattern_test_state_machine : public state_machine
+{
+public:
+  pattern_test_state_machine (logger *logger);
+
+  bool inherited_state_p () const FINAL OVERRIDE { return false; }
+
+  bool on_stmt (sm_context *sm_ctxt,
+   const supernode *node,
+   const gimple *stmt) const FINAL OVERRIDE;
+
+  void on_condition (sm_context *sm_ctxt,
+const supernode *node,
+const gimple *stmt,
+tree lhs,
+enum tree_code op,
+tree rhs) const FINAL OVERRIDE;
+
+  bool can_purge_p (state_t s) const FINAL OVERRIDE;
+
+private:
+  state_t m_start;
+};
+
+class pattern_match : public pending_diagnostic_subclass
+{
+public:
+  pattern_match (tree lhs, enum tree_code op, tree rhs)
+  : m_lhs (lhs), m_op (op), m_rhs (rhs) {}
+
+  const char *get_kind () const FINAL OVERRIDE { return "pattern_match"; }
+
+  bool operator== (const pattern_match ) const
+  {
+return (m_lhs == other.m_lhs
+   && m_op == other.m_op
+   && m_rhs == other.m_rhs);
+  }
+
+  bool emit (rich_location *rich_loc) FINAL OVERRIDE
+  {
+return warning_at (rich_loc, 0, "pattern match on %<%E %s %E%>",
+  m_lhs, op_symbol_code (m_op), m_rhs);
+  }
+
+private:
+  tree m_lhs;
+  enum tree_code m_op;
+  tree m_rhs;
+};
+
+pattern_test_state_machine::pattern_test_state_machine (logger *logger)
+: state_machine ("pattern-test", logger)
+{
+  m_start = add_state ("start");
+}
+
+bool
+pattern_test_state_machine::on_stmt (sm_context *sm_ctxt ATTRIBUTE_UNUSED,
+const supernode *node ATTRIBUTE_UNUSED,
+const gimple *stmt ATTRIBUTE_UNUSED) const
+{
+  return false;
+}
+
+/* Implementation of state_machine::on_condition vfunc for
+   pattern_test_state_machine.
+
+   Queue a pattern_match diagnostic for any comparison against a
+   constant.  */
+
+void
+pattern_test_state_machine::on_condition (sm_context *sm_ctxt,
+ const supernode *node,
+ const gimple *stmt,
+ tree lhs,
+ enum tree_code op,
+ tree rhs) const
+{
+  if (stmt == NULL)
+return;
+
+  if (!CONSTANT_CLASS_P (rhs))
+return;
+
+  pending_diagnostic *diag = new pattern_match (lhs, op, rhs);
+  sm_ctxt->warn_for_state (node, stmt, lhs, m_start, diag);
+}
+
+bool
+pattern_test_state_machine::can_purge_p (state_t s ATTRIBUTE_UNUSED) const
+{
+  return true;
+}
+
+} // anonymous namespace
+
+/* Internal interface to this file. */
+
+state_machine *
+make_pattern_test_state_machine (logger *logger)
+{
+  return new pattern_test_state_machine (logger);
+}
+
+#endif /* #if ENABLE_ANALYZER */
-- 
2.21.0



[PATCH 38/45] analyzer: new files: program-state.{cc|h}

2019-12-13 Thread David Malcolm
Changed in v4:
- Remove include of gcc-plugin.h, reworking includes accordingly.
- Wrap everything in #if ENABLE_ANALYZER
- Remove /// comment lines
- Add support for global state:
  - https://gcc.gnu.org/ml/gcc-patches/2019-12/msg00217.html
- Rework logging to avoid exploded_graph multiple-inheritance (moving
  log_user base to a member)

This patch introduces classes for tracking the state at a particular
path of analysis.

gcc/ChangeLog:
* analyzer/program-state.cc: New file.
* analyzer/program-state.h: New file.
---
 gcc/analyzer/program-state.cc | 1331 +
 gcc/analyzer/program-state.h  |  365 +
 2 files changed, 1696 insertions(+)
 create mode 100644 gcc/analyzer/program-state.cc
 create mode 100644 gcc/analyzer/program-state.h

diff --git a/gcc/analyzer/program-state.cc b/gcc/analyzer/program-state.cc
new file mode 100644
index ..6222ce9cd627
--- /dev/null
+++ b/gcc/analyzer/program-state.cc
@@ -0,0 +1,1331 @@
+/* Classes for representing the state of interest at a given path of analysis.
+   Copyright (C) 2019 Free Software Foundation, Inc.
+   Contributed by David Malcolm .
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tree.h"
+#include "diagnostic.h"
+#include "analyzer/analyzer.h"
+#include "analyzer/program-state.h"
+#include "analyzer/constraint-manager.h"
+#include "analyzer/exploded-graph.h"
+#include "analyzer/state-purge.h"
+#include "analyzer/analyzer-selftests.h"
+
+#if ENABLE_ANALYZER
+
+/* class sm_state_map.  */
+
+/* sm_state_map's ctor.  */
+
+sm_state_map::sm_state_map ()
+: m_map (), m_global_state (0)
+{
+}
+
+/* Clone the sm_state_map.  */
+
+sm_state_map *
+sm_state_map::clone () const
+{
+  return new sm_state_map (*this);
+}
+
+/* Clone this sm_state_map, remapping all svalue_ids within it with ID_MAP.
+
+   Return NULL if there are any svalue_ids that have sm-state for which
+   ID_MAP maps them to svalue_id::null (and thus the clone would have lost
+   the sm-state information). */
+
+sm_state_map *
+sm_state_map::clone_with_remapping (const one_way_svalue_id_map _map) const
+{
+  sm_state_map *result = new sm_state_map ();
+  for (typename map_t::iterator iter = m_map.begin ();
+   iter != m_map.end ();
+   ++iter)
+{
+  svalue_id sid = (*iter).first;
+  gcc_assert (!sid.null_p ());
+  entry_t e = (*iter).second;
+  /* TODO: what should we do if the origin maps from non-null to null?
+Is that loss of information acceptable?  */
+  id_map.update (_origin);
+
+  svalue_id new_sid = id_map.get_dst_for_src (sid);
+  if (new_sid.null_p ())
+   {
+ delete result;
+ return NULL;
+   }
+  result->m_map.put (new_sid, e);
+}
+  return result;
+}
+
+/* Print this sm_state_map (for SM) to PP.  */
+
+void
+sm_state_map::print (const state_machine , pretty_printer *pp) const
+{
+  bool first = true;
+  pp_string (pp, "{");
+  if (m_global_state != 0)
+{
+  pp_printf (pp, "global: %s", sm.get_state_name (m_global_state));
+  first = false;
+}
+  for (typename map_t::iterator iter = m_map.begin ();
+   iter != m_map.end ();
+   ++iter)
+{
+  if (!first)
+   pp_string (pp, ", ");
+  first = false;
+  svalue_id sid = (*iter).first;
+  sid.print (pp);
+
+  entry_t e = (*iter).second;
+  pp_printf (pp, ": %s (origin: ",
+sm.get_state_name (e.m_state));
+  e.m_origin.print (pp);
+  pp_string (pp, ")");
+}
+  pp_string (pp, "}");
+}
+
+/* Dump this object (for SM) to stderr.  */
+
+DEBUG_FUNCTION void
+sm_state_map::dump (const state_machine ) const
+{
+  pretty_printer pp;
+  pp_show_color () = pp_show_color (global_dc->printer);
+  pp.buffer->stream = stderr;
+  print (sm, );
+  pp_newline ();
+  pp_flush ();
+}
+
+/* Return true if no states have been set within this map
+   (all expressions are for the start state).  */
+
+bool
+sm_state_map::is_empty_p () const
+{
+  return m_map.elements () == 0 && m_global_state == 0;
+}
+
+/* Generate a hash value for this sm_state_map.  */
+
+hashval_t
+sm_state_map::hash () const
+{
+  hashval_t result = 0;
+
+  /* Accumulate the result by xoring a hash for each slot, so that the
+ result doesn't depend on the ordering of the slots in the map.  */
+
+  for 

[PATCH 30/45] analyzer: new file: sm-file.cc

2019-12-13 Thread David Malcolm
Changed in v4:
- Remove include of gcc-plugin.h, reworking includes accordingly.
- Wrap everything in #if ENABLE_ANALYZER
- Remove /// comment lines
- Rework on_leak vfunc:
https://gcc.gnu.org/ml/gcc-patches/2019-11/msg02028.html
- Rework for changes to is_named_call_p, resolving function pointers:
   https://gcc.gnu.org/ml/gcc-patches/2019-12/msg00178.html

This patch adds a state machine checker for stdio's FILE stream API.

gcc/ChangeLog:
* analyzer/sm-file.cc: New file.
---
 gcc/analyzer/sm-file.cc | 334 
 1 file changed, 334 insertions(+)
 create mode 100644 gcc/analyzer/sm-file.cc

diff --git a/gcc/analyzer/sm-file.cc b/gcc/analyzer/sm-file.cc
new file mode 100644
index ..20963c3e59b4
--- /dev/null
+++ b/gcc/analyzer/sm-file.cc
@@ -0,0 +1,334 @@
+/* A state machine for detecting misuses of 's FILE * API.
+   Copyright (C) 2019 Free Software Foundation, Inc.
+   Contributed by David Malcolm .
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tree.h"
+#include "function.h"
+#include "basic-block.h"
+#include "gimple.h"
+#include "options.h"
+#include "diagnostic-path.h"
+#include "diagnostic-metadata.h"
+#include "analyzer/analyzer.h"
+#include "analyzer/pending-diagnostic.h"
+#include "analyzer/sm.h"
+
+#if ENABLE_ANALYZER
+
+namespace {
+
+/* A state machine for detecting misuses of 's FILE * API.  */
+
+class fileptr_state_machine : public state_machine
+{
+public:
+  fileptr_state_machine (logger *logger);
+
+  bool inherited_state_p () const FINAL OVERRIDE { return false; }
+
+  bool on_stmt (sm_context *sm_ctxt,
+   const supernode *node,
+   const gimple *stmt) const FINAL OVERRIDE;
+
+  void on_condition (sm_context *sm_ctxt,
+const supernode *node,
+const gimple *stmt,
+tree lhs,
+enum tree_code op,
+tree rhs) const FINAL OVERRIDE;
+
+  bool can_purge_p (state_t s) const FINAL OVERRIDE;
+  pending_diagnostic *on_leak (tree var) const FINAL OVERRIDE;
+
+  /* Start state.  */
+  state_t m_start;
+
+  /* State for a FILE * returned from fopen that hasn't been checked for
+ NULL.
+ It could be an open stream, or could be NULL.  */
+  state_t m_unchecked;
+
+  /* State for a FILE * that's known to be NULL.  */
+  state_t m_null;
+
+  /* State for a FILE * that's known to be a non-NULL open stream.  */
+  state_t m_nonnull;
+
+  /* State for a FILE * that's had fclose called on it.  */
+  state_t m_closed;
+
+  /* Stop state, for a FILE * we don't want to track any more.  */
+  state_t m_stop;
+};
+
+/* Base class for diagnostics relative to fileptr_state_machine.  */
+
+class file_diagnostic : public pending_diagnostic
+{
+public:
+  file_diagnostic (const fileptr_state_machine , tree arg)
+  : m_sm (sm), m_arg (arg)
+  {}
+
+  bool subclass_equal_p (const pending_diagnostic _other) const OVERRIDE
+  {
+return m_arg == ((const file_diagnostic &)base_other).m_arg;
+  }
+
+  label_text describe_state_change (const evdesc::state_change )
+OVERRIDE
+  {
+if (change.m_old_state == m_sm.m_start
+   && change.m_new_state == m_sm.m_unchecked)
+  // TODO: verify that it's the fopen stmt, not a copy
+  return label_text::borrow ("opened here");
+if (change.m_old_state == m_sm.m_unchecked
+   && change.m_new_state == m_sm.m_nonnull)
+  return change.formatted_print ("assuming %qE is non-NULL",
+change.m_expr);
+if (change.m_new_state == m_sm.m_null)
+  return change.formatted_print ("assuming %qE is NULL",
+change.m_expr);
+return label_text ();
+  }
+
+protected:
+  const fileptr_state_machine _sm;
+  tree m_arg;
+};
+
+class double_fclose : public file_diagnostic
+{
+public:
+  double_fclose (const fileptr_state_machine , tree arg)
+: file_diagnostic (sm, arg)
+  {}
+
+  const char *get_kind () const FINAL OVERRIDE { return "double_fclose"; }
+
+  bool emit (rich_location *rich_loc) FINAL OVERRIDE
+  {
+return warning_at (rich_loc, OPT_Wanalyzer_double_fclose,
+  "double % of FILE %qE",
+  m_arg);
+  }
+
+  label_text describe_state_change (const evdesc::state_change )
+OVERRIDE
+  {
+

[PATCH 25/45] analyzer: new files: constraint-manager.{cc|h}

2019-12-13 Thread David Malcolm
Changed in v4:
- Remove include of gcc-plugin.h, reworking includes accordingly.
- Wrap everything in #if ENABLE_ANALYZER
- Remove /// comment lines

This patch adds classes for tracking the equivalence classes and
constraints that hold at a point on an execution path.

gcc/ChangeLog:
* analyzer/constraint-manager.cc: New file.
* analyzer/constraint-manager.h: New file.
---
 gcc/analyzer/constraint-manager.cc | 2251 
 gcc/analyzer/constraint-manager.h  |  248 +++
 2 files changed, 2499 insertions(+)
 create mode 100644 gcc/analyzer/constraint-manager.cc
 create mode 100644 gcc/analyzer/constraint-manager.h

diff --git a/gcc/analyzer/constraint-manager.cc 
b/gcc/analyzer/constraint-manager.cc
new file mode 100644
index ..f5f415924f11
--- /dev/null
+++ b/gcc/analyzer/constraint-manager.cc
@@ -0,0 +1,2251 @@
+/* Tracking equivalence classes and constraints at a point on an execution 
path.
+   Copyright (C) 2019 Free Software Foundation, Inc.
+   Contributed by David Malcolm .
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tree.h"
+#include "function.h"
+#include "basic-block.h"
+#include "gimple.h"
+#include "gimple-iterator.h"
+#include "fold-const.h"
+#include "selftest.h"
+#include "graphviz.h"
+#include "analyzer/analyzer.h"
+#include "analyzer/supergraph.h"
+#include "analyzer/constraint-manager.h"
+#include "analyzer/analyzer-selftests.h"
+
+#if ENABLE_ANALYZER
+
+/* One of the end-points of a range.  */
+
+struct bound
+{
+  bound () : m_constant (NULL_TREE), m_closed (false) {}
+  bound (tree constant, bool closed)
+  : m_constant (constant), m_closed (closed) {}
+
+  void ensure_closed (bool is_upper);
+
+  const char * get_relation_as_str () const;
+
+  tree m_constant;
+  bool m_closed;
+};
+
+/* A range of values, used for determining if a value has been
+   constrained to just one possible constant value.  */
+
+struct range
+{
+  range () : m_lower_bound (), m_upper_bound () {}
+  range (const bound , const bound )
+  : m_lower_bound (lower), m_upper_bound (upper) {}
+
+  void dump (pretty_printer *pp) const;
+
+  bool constrained_to_single_element (tree *out);
+
+  bound m_lower_bound;
+  bound m_upper_bound;
+};
+
+/* struct bound.  */
+
+/* Ensure that this bound is closed by converting an open bound to a
+   closed one.  */
+
+void
+bound::ensure_closed (bool is_upper)
+{
+  if (!m_closed)
+{
+  /* Offset by 1 in the appropriate direction.
+For example, convert 3 < x into 4 <= x,
+and convert x < 5 into x <= 4.  */
+  gcc_assert (CONSTANT_CLASS_P (m_constant));
+  m_constant = fold_build2 (is_upper ? MINUS_EXPR : PLUS_EXPR,
+   TREE_TYPE (m_constant),
+   m_constant, integer_one_node);
+  gcc_assert (CONSTANT_CLASS_P (m_constant));
+  m_closed = true;
+}
+}
+
+/* Get "<=" vs "<" for this bound.  */
+
+const char *
+bound::get_relation_as_str () const
+{
+  if (m_closed)
+return "<=";
+  else
+return "<";
+}
+
+/* struct range.  */
+
+/* Dump this range to PP, which must support %E for tree.  */
+
+void
+range::dump (pretty_printer *pp) const
+{
+PUSH_IGNORE_WFORMAT
+  pp_printf (pp, "%qE %s x %s %qE",
+m_lower_bound.m_constant,
+m_lower_bound.get_relation_as_str (),
+m_upper_bound.get_relation_as_str (),
+m_upper_bound.m_constant);
+POP_IGNORE_WFORMAT
+}
+
+/* Determine if there is only one possible value for this range.
+   If so, return true and write the constant to *OUT.
+   Otherwise, return false.  */
+
+bool
+range::constrained_to_single_element (tree *out)
+{
+  if (!INTEGRAL_TYPE_P (TREE_TYPE (m_lower_bound.m_constant)))
+return false;
+  if (!INTEGRAL_TYPE_P (TREE_TYPE (m_upper_bound.m_constant)))
+return false;
+
+  /* Convert any open bounds to closed bounds.  */
+  m_lower_bound.ensure_closed (false);
+  m_upper_bound.ensure_closed (true);
+
+  // Are they equal?
+  tree comparison
+= fold_build2 (EQ_EXPR, boolean_type_node,
+  m_lower_bound.m_constant,
+  m_upper_bound.m_constant);
+  if (comparison == boolean_true_node)
+{
+  *out = m_lower_bound.m_constant;
+  return true;
+}
+  else
+return false;
+}
+
+/* class equiv_class.  */
+
+/* 

[PATCH 21/45] analyzer: new files: digraph.{cc|h} and shortest-paths.h

2019-12-13 Thread David Malcolm
Changed in v4:
  - Moved from gcc/analyzer to gcc, renaming selftests accordingly
  - Remove  comments
  - Replace auto_client_timevar with TV_ANALYZER_SHORTEST_PATHS

This patch adds template classes for directed graphs, their nodes
and edges, and for finding the shortest path through such a graph.

gcc/ChangeLog:
* digraph.cc: New file.
* digraph.h: New file.
* shortest-paths.h: New file.
---
 gcc/digraph.cc   | 188 +
 gcc/digraph.h| 246 +++
 gcc/shortest-paths.h | 145 +
 3 files changed, 579 insertions(+)
 create mode 100644 gcc/digraph.cc
 create mode 100644 gcc/digraph.h
 create mode 100644 gcc/shortest-paths.h

diff --git a/gcc/digraph.cc b/gcc/digraph.cc
new file mode 100644
index ..4473fad26c50
--- /dev/null
+++ b/gcc/digraph.cc
@@ -0,0 +1,188 @@
+/* Template classes for directed graphs.
+   Copyright (C) 2019 Free Software Foundation, Inc.
+   Contributed by David Malcolm .
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "diagnostic.h"
+#include "graphviz.h"
+#include "digraph.h"
+#include "shortest-paths.h"
+#include "selftest.h"
+
+#if CHECKING_P
+
+namespace selftest {
+
+/* A family of digraph classes for writing selftests.  */
+
+struct test_node;
+struct test_edge;
+struct test_graph;
+struct test_dump_args_t {};
+struct test_cluster;
+
+struct test_graph_traits
+{
+  typedef test_node node_t;
+  typedef test_edge edge_t;
+  typedef test_graph graph_t;
+  typedef test_dump_args_t dump_args_t;
+  typedef test_cluster cluster_t;
+};
+
+struct test_node : public dnode
+{
+  test_node (const char *name, int index) : m_name (name), m_index (index) {}
+  void dump_dot (graphviz_out *, const dump_args_t &) const OVERRIDE
+  {
+  }
+
+  const char *m_name;
+  int m_index;
+};
+
+struct test_edge : public dedge
+{
+  test_edge (node_t *src, node_t *dest)
+  : dedge (src, dest)
+  {}
+
+  void dump_dot (graphviz_out *gv, const dump_args_t &) const OVERRIDE
+  {
+gv->println ("%s -> %s;", m_src->m_name, m_dest->m_name);
+  }
+};
+
+struct test_graph : public digraph
+{
+  test_node *add_test_node (const char *name)
+  {
+test_node *result = new test_node (name, m_nodes.length ());
+add_node (result);
+return result;
+  }
+
+  test_edge *add_test_edge (test_node *src, test_node *dst)
+  {
+test_edge *result = new test_edge (src, dst);
+add_edge (result);
+return result;
+  }
+};
+
+struct test_cluster : public cluster
+{
+};
+
+struct test_path
+{
+  auto_vec m_edges;
+};
+
+/* Smoketest of digraph dumping.  */
+
+static void
+test_dump_to_dot ()
+{
+  test_graph g;
+  test_node *a = g.add_test_node ("a");
+  test_node *b = g.add_test_node ("b");
+  g.add_test_edge (a, b);
+
+  pretty_printer pp;
+  pp.buffer->stream = NULL;
+  test_dump_args_t dump_args;
+  g.dump_dot_to_pp (, NULL, dump_args);
+
+  ASSERT_STR_CONTAINS (pp_formatted_text (),
+  "a -> b;\n");
+}
+
+/* Test shortest paths from A in this digraph,
+   where edges run top-to-bottom if not otherwise labeled:
+
+  A
+ / \
+B   C-->D
+|   |
+E   |
+ \ /
+  F.  */
+
+static void
+test_shortest_paths ()
+{
+  test_graph g;
+  test_node *a = g.add_test_node ("a");
+  test_node *b = g.add_test_node ("b");
+  test_node *c = g.add_test_node ("d");
+  test_node *d = g.add_test_node ("d");
+  test_node *e = g.add_test_node ("e");
+  test_node *f = g.add_test_node ("f");
+
+  test_edge *ab = g.add_test_edge (a, b);
+  test_edge *ac = g.add_test_edge (a, c);
+  test_edge *cd = g.add_test_edge (c, d);
+  test_edge *be = g.add_test_edge (b, e);
+  g.add_test_edge (e, f);
+  test_edge *cf = g.add_test_edge (c, f);
+
+  shortest_paths sp (g, a);
+
+  test_path path_to_a = sp.get_shortest_path (a);
+  ASSERT_EQ (path_to_a.m_edges.length (), 0);
+
+  test_path path_to_b = sp.get_shortest_path (b);
+  ASSERT_EQ (path_to_b.m_edges.length (), 1);
+  ASSERT_EQ (path_to_b.m_edges[0], ab);
+
+  test_path path_to_c = sp.get_shortest_path (c);
+  ASSERT_EQ (path_to_c.m_edges.length (), 1);
+  ASSERT_EQ (path_to_c.m_edges[0], ac);
+
+  test_path path_to_d = sp.get_shortest_path (d);
+  ASSERT_EQ (path_to_d.m_edges.length (), 2);
+  ASSERT_EQ (path_to_d.m_edges[0], ac);
+  ASSERT_EQ 

[PATCH 43/45] analyzer: new files: diagnostic-manager.{cc|h}

2019-12-13 Thread David Malcolm
Changed in v4:
- Remove include of gcc-plugin.h, reworking includes accordingly.
- Wrap everything in #if ENABLE_ANALYZER
- Remove /// comment lines
- Add custom events:
https://gcc.gnu.org/ml/gcc-patches/2019-12/msg00213.html
- Generalize rewind_info_t to exploded_edge::custom_info_t
https://gcc.gnu.org/ml/gcc-patches/2019-12/msg00219.html
- Add support for global state:
https://gcc.gnu.org/ml/gcc-patches/2019-12/msg00217.html
- Show rewind destination for leaks due to longjmp
https://gcc.gnu.org/ml/gcc-patches/2019-11/msg02029.html
- Split diagnostic_manager::prune_path into subroutines
- Add DISABLE_COPY_AND_ASSIGN (saved_diagnostic);

This patch adds diagnostic_manager and related support classes for
saving, deduplicating, and emitting analyzer diagnostics.

gcc/ChangeLog:
* analyzer/diagnostic-manager.cc: New file.
* analyzer/diagnostic-manager.h: New file.
---
 gcc/analyzer/diagnostic-manager.cc | 1217 
 gcc/analyzer/diagnostic-manager.h  |  137 
 2 files changed, 1354 insertions(+)
 create mode 100644 gcc/analyzer/diagnostic-manager.cc
 create mode 100644 gcc/analyzer/diagnostic-manager.h

diff --git a/gcc/analyzer/diagnostic-manager.cc 
b/gcc/analyzer/diagnostic-manager.cc
new file mode 100644
index ..b8aae115ae67
--- /dev/null
+++ b/gcc/analyzer/diagnostic-manager.cc
@@ -0,0 +1,1217 @@
+/* Classes for saving, deduplicating, and emitting analyzer diagnostics.
+   Copyright (C) 2019 Free Software Foundation, Inc.
+   Contributed by David Malcolm .
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tree.h"
+#include "pretty-print.h"
+#include "gcc-rich-location.h"
+#include "gimple-pretty-print.h"
+#include "analyzer/analyzer.h"
+#include "analyzer/diagnostic-manager.h"
+#include "analyzer/exploded-graph.h"
+#include "analyzer/checker-path.h"
+
+#if ENABLE_ANALYZER
+
+/* class saved_diagnostic.  */
+
+/* saved_diagnostic's ctor.
+   Take ownership of D and STMT_FINDER.  */
+
+saved_diagnostic::saved_diagnostic (const state_machine *sm,
+   const exploded_node *enode,
+   const supernode *snode, const gimple *stmt,
+   stmt_finder *stmt_finder,
+   tree var, state_machine::state_t state,
+   pending_diagnostic *d)
+: m_sm (sm), m_enode (enode), m_snode (snode), m_stmt (stmt),
+ /* stmt_finder could be on-stack; we want our own copy that can
+outlive that.  */
+  m_stmt_finder (stmt_finder ? stmt_finder->clone () : NULL),
+  m_var (var), m_state (state),
+  m_d (d), m_trailing_eedge (NULL)
+{
+  gcc_assert (m_stmt || m_stmt_finder);
+
+  /* We must have an enode in order to be able to look for paths
+ through the exploded_graph to this diagnostic.  */
+  gcc_assert (m_enode);
+}
+
+/* saved_diagnostic's dtor.  */
+
+saved_diagnostic::~saved_diagnostic ()
+{
+  delete m_stmt_finder;
+  delete m_d;
+}
+
+/* class diagnostic_manager.  */
+
+/* diagnostic_manager's ctor.  */
+
+diagnostic_manager::diagnostic_manager (logger *logger, int verbosity)
+: log_user (logger), m_verbosity (verbosity)
+{
+}
+
+/* Queue pending_diagnostic D at ENODE for later emission.  */
+
+void
+diagnostic_manager::add_diagnostic (const state_machine *sm,
+   const exploded_node *enode,
+   const supernode *snode, const gimple *stmt,
+   stmt_finder *finder,
+   tree var, state_machine::state_t state,
+   pending_diagnostic *d)
+{
+  LOG_FUNC (get_logger ());
+
+  /* We must have an enode in order to be able to look for paths
+ through the exploded_graph to the diagnostic.  */
+  gcc_assert (enode);
+
+  saved_diagnostic *sd
+= new saved_diagnostic (sm, enode, snode, stmt, finder, var, state, d);
+  m_saved_diagnostics.safe_push (sd);
+  if (get_logger ())
+log ("adding saved diagnostic %i at SN %i: %qs",
+m_saved_diagnostics.length () - 1,
+snode->m_index, d->get_kind ());
+}
+
+/* Queue pending_diagnostic D at ENODE for later emission.  */
+
+void
+diagnostic_manager::add_diagnostic (const exploded_node *enode,
+   

[PATCH 41/45] analyzer: new files: engine.{cc|h}

2019-12-13 Thread David Malcolm
Changed in v4:
- Remove include of gcc-plugin.h, reworking includes accordingly.
- Wrap everything in #if ENABLE_ANALYZER
- Remove /// comment lines
- Rework logging to avoid exploded_graph multiple-inheritance (moving
  log_user base to a member)
- Support resolving function pointers:
   https://gcc.gnu.org/ml/gcc-patches/2019-12/msg00178.html
- Add support for global state:
https://gcc.gnu.org/ml/gcc-patches/2019-12/msg00217.html
- Rework on_leak vfunc:
https://gcc.gnu.org/ml/gcc-patches/2019-11/msg02028.html
- Add more validation, part of:
https://gcc.gnu.org/ml/gcc-patches/2019-11/msg02517.html
- Fix .dot output:
https://gcc.gnu.org/ml/gcc-patches/2019-11/msg02461.html
- Generalize rewind_info_t to exploded_edge::custom_info_t
https://gcc.gnu.org/ml/gcc-patches/2019-12/msg00219.html
- Support showing rewind destination for leaks due to longjmp
https://gcc.gnu.org/ml/gcc-patches/2019-11/msg02029.html
- Use TV_ANALYZER_SCC, TV_ANALYZER_WORKLIST, and TV_ANALYZER_DUMP rather
  than auto_client_timevar.  Drop top-level auto_client_timevar in
  favor of tv within pass.
- Port to new param API

This patch adds the core analysis code, which explores "interesting"
interprocedual paths in the code, updating state machines to check
for API misuses, and issuing diagnostics for such misuses.

gcc/ChangeLog:
* analyzer/engine.cc: New file.
* analyzer/engine.h: New file.
---
 gcc/analyzer/engine.cc | 3583 
 gcc/analyzer/engine.h  |   26 +
 2 files changed, 3609 insertions(+)
 create mode 100644 gcc/analyzer/engine.cc
 create mode 100644 gcc/analyzer/engine.h

diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc
new file mode 100644
index ..93babf67a87b
--- /dev/null
+++ b/gcc/analyzer/engine.cc
@@ -0,0 +1,3583 @@
+/* The analysis "engine".
+   Copyright (C) 2019 Free Software Foundation, Inc.
+   Contributed by David Malcolm .
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tree.h"
+#include "fold-const.h"
+#include "gcc-rich-location.h"
+#include "analyzer/exploded-graph.h"
+#include "analyzer/analysis-plan.h"
+#include "analyzer/checker-path.h"
+#include "analyzer/state-purge.h"
+
+/* For an overview, see gcc/doc/analyzer.texi.  */
+
+#if ENABLE_ANALYZER
+
+static int readability_comparator (const void *p1, const void *p2);
+
+/* class impl_region_model_context : public region_model_context, public 
log_user.  */
+
+impl_region_model_context::
+impl_region_model_context (exploded_graph ,
+  const exploded_node *enode_for_diag,
+  const program_state *old_state,
+  program_state *new_state,
+  state_change *change,
+  const gimple *stmt,
+  stmt_finder *stmt_finder)
+: m_eg (), m_logger (eg.get_logger ()),
+  m_enode_for_diag (enode_for_diag),
+  m_old_state (old_state),
+  m_new_state (new_state),
+  m_change (change),
+  m_stmt (stmt),
+  m_stmt_finder (stmt_finder),
+  m_ext_state (eg.get_ext_state ())
+{
+}
+
+impl_region_model_context::
+impl_region_model_context (program_state *state,
+  state_change *change,
+  const extrinsic_state _state)
+: m_eg (NULL), m_logger (NULL), m_enode_for_diag (NULL),
+  m_old_state (NULL),
+  m_new_state (state),
+  m_change (change),
+  m_stmt (NULL),
+  m_stmt_finder (NULL),
+  m_ext_state (ext_state)
+{
+}
+
+void
+impl_region_model_context::warn (pending_diagnostic *d)
+{
+  LOG_FUNC (get_logger ());
+  if (m_eg)
+m_eg->get_diagnostic_manager ().add_diagnostic
+  (m_enode_for_diag, m_enode_for_diag->get_supernode (),
+   m_stmt, m_stmt_finder, d);
+}
+
+void
+impl_region_model_context::remap_svalue_ids (const svalue_id_map )
+{
+  m_new_state->remap_svalue_ids (map);
+  if (m_change)
+m_change->remap_svalue_ids (map);
+}
+
+int
+impl_region_model_context::on_svalue_purge (svalue_id first_unused_sid,
+   const svalue_id_map )
+{
+  int total = 0;
+  int sm_idx;
+  sm_state_map *smap;
+  FOR_EACH_VEC_ELT (m_new_state->m_checker_states, sm_idx, smap)
+{
+  const state_machine  = m_ext_state.get_sm (sm_idx);
+  total += smap->on_svalue_purge (sm, sm_idx, 

[PATCH 44/45] gdbinit.in: add break-on-saved-diagnostic

2019-12-13 Thread David Malcolm
This patch adds a "break-on-saved-diagnostic" command to gdbinit.in,
useful for debugging when a diagnostic is queued by the analyzer.

gcc/ChangeLog:
* gdbinit.in (break-on-saved-diagnostic): New command.
---
 gcc/gdbinit.in | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/gcc/gdbinit.in b/gcc/gdbinit.in
index 42302aecfe3c..c7e4a5f4 100644
--- a/gcc/gdbinit.in
+++ b/gcc/gdbinit.in
@@ -219,6 +219,16 @@ is emitted (as opposed to those warnings that are 
suppressed by
 command-line options).
 end
 
+define break-on-saved-diagnostic
+break diagnostic_manager::add_diagnostic
+end
+
+document break-on-saved-diagnostic
+Put a breakpoint on diagnostic_manager::add_diagnostic, called within
+the analyzer whenever a diagnostic is saved for later de-duplication and
+possible emission.
+end
+
 define reload-gdbhooks
 python import imp; imp.reload(gdbhooks)
 end
-- 
2.21.0



[PATCH 40/45] analyzer: new files: state-purge.{cc|h}

2019-12-13 Thread David Malcolm
Changed in v4:
- Remove include of gcc-plugin.h, reworking includes accordingly.
- Wrap everything in #if ENABLE_ANALYZER
- Remove /// comment lines
- Use TV_ANALYZER_STATE_PURGE rather than an auto_client_timevar
- Fix .dot output:
https://gcc.gnu.org/ml/gcc-patches/2019-11/msg02461.html
- Add DISABLE_COPY_AND_ASSIGN (state_purge_map);

This patch adds classes for tracking what state can be safely purged
at any given point in the program.

gcc/ChangeLog:
* analyzer/state-purge.cc: New file.
* analyzer/state-purge.h: New file.
---
 gcc/analyzer/state-purge.cc | 525 
 gcc/analyzer/state-purge.h  | 164 +++
 2 files changed, 689 insertions(+)
 create mode 100644 gcc/analyzer/state-purge.cc
 create mode 100644 gcc/analyzer/state-purge.h

diff --git a/gcc/analyzer/state-purge.cc b/gcc/analyzer/state-purge.cc
new file mode 100644
index ..0cad07b7bfae
--- /dev/null
+++ b/gcc/analyzer/state-purge.cc
@@ -0,0 +1,525 @@
+/* Classes for purging state at function_points.
+   Copyright (C) 2019 Free Software Foundation, Inc.
+   Contributed by David Malcolm .
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tree.h"
+#include "timevar.h"
+#include "tree-ssa-alias.h"
+#include "function.h"
+#include "basic-block.h"
+#include "gimple.h"
+#include "stringpool.h"
+#include "tree-vrp.h"
+#include "gimple-ssa.h"
+#include "tree-ssanames.h"
+#include "tree-phinodes.h"
+#include "options.h"
+#include "ssa-iterators.h"
+#include "gimple-pretty-print.h"
+#include "analyzer/analyzer.h"
+#include "analyzer/state-purge.h"
+
+#if ENABLE_ANALYZER
+
+/* state_purge_map's ctor.  Walk all SSA names in all functions, building
+   a state_purge_per_ssa_name instance for each.  */
+
+state_purge_map::state_purge_map (const supergraph ,
+ logger *logger)
+: log_user (logger), m_sg (sg)
+{
+  LOG_FUNC (logger);
+
+  auto_timevar tv (TV_ANALYZER_STATE_PURGE);
+
+  cgraph_node *node;
+  FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
+  {
+function *fun = node->get_fun ();
+if (logger)
+  log ("function: %s", function_name (fun));
+//printf ("function: %s\n", function_name (fun));
+tree name;
+unsigned int i;;
+FOR_EACH_SSA_NAME (i, name, fun)
+  {
+   /* For now, don't bother tracking the .MEM SSA names.  */
+   if (tree var = SSA_NAME_VAR (name))
+ if (TREE_CODE (var) == VAR_DECL)
+   if (VAR_DECL_IS_VIRTUAL_OPERAND (var))
+ continue;
+   m_map.put (name, new state_purge_per_ssa_name (*this, name, fun));
+  }
+  }
+}
+
+/* state_purge_map's dtor.  */
+
+state_purge_map::~state_purge_map ()
+{
+  for (iterator iter = m_map.begin (); iter != m_map.end (); ++iter)
+delete (*iter).second;
+}
+
+/* state_purge_per_ssa_name's ctor.
+
+   Locate all uses of VAR within FUN.
+   Walk backwards from each use, marking program points, until
+   we reach the def stmt, populating m_points_needing_var.
+
+   We have to track program points rather than
+   just stmts since there could be empty basic blocks on the way.  */
+
+state_purge_per_ssa_name::state_purge_per_ssa_name (const state_purge_map ,
+   tree name,
+   function *fun)
+: m_points_needing_name (), m_name (name), m_fun (fun)
+{
+  LOG_FUNC (map.get_logger ());
+
+  if (map.get_logger ())
+{
+  map.log ("SSA name: %qE within %qD", name, fun->decl);
+
+  /* Show def stmt.  */
+  const gimple *def_stmt = SSA_NAME_DEF_STMT (name);
+  pretty_printer pp;
+  pp_gimple_stmt_1 (, def_stmt, 0, (dump_flags_t)0);
+  map.log ("def stmt: %s", pp_formatted_text ());
+}
+
+  auto_vec worklist;
+
+  /* Add all immediate uses of name to the worklist.
+ Compare with debug_immediate_uses.  */
+  imm_use_iterator iter;
+  use_operand_p use_p;
+  FOR_EACH_IMM_USE_FAST (use_p, iter, name)
+{
+  if (USE_STMT (use_p))
+   {
+ const gimple *use_stmt = USE_STMT (use_p);
+ if (map.get_logger ())
+   {
+ pretty_printer pp;
+ pp_gimple_stmt_1 (, use_stmt, 0, (dump_flags_t)0);
+ map.log ("used by stmt: %s", pp_formatted_text ());
+   }
+
+ const supernode *snode
+   

[PATCH 42/45] analyzer: new files: checker-path.{cc|h}

2019-12-13 Thread David Malcolm
Changed in v4:
- Remove include of gcc-plugin.h, reworking includes accordingly.
- Wrap everything in #if ENABLE_ANALYZER
- Remove /// comment lines
- Add custom events:
https://gcc.gnu.org/ml/gcc-patches/2019-12/msg00213.html
- Add support for global state:
https://gcc.gnu.org/ml/gcc-patches/2019-12/msg00217.html
- start_cfg_edge_event::maybe_describe_condition: special-case the description
  of edges based on the result of strcmp
- Generalize rewind_info_t to exploded_edge::custom_info_t
https://gcc.gnu.org/ml/gcc-patches/2019-12/msg00219.html
- Add checker_path::debug
https://gcc.gnu.org/ml/gcc-patches/2019-11/msg02033.html

This patch adds a family of classes for representing paths of events
for analyzer diagnostics.

gcc/ChangeLog:
* analyzer/checker-path.cc: New file.
* analyzer/checker-path.h: New file.
---
 gcc/analyzer/checker-path.cc | 931 +++
 gcc/analyzer/checker-path.h  | 589 ++
 2 files changed, 1520 insertions(+)
 create mode 100644 gcc/analyzer/checker-path.cc
 create mode 100644 gcc/analyzer/checker-path.h

diff --git a/gcc/analyzer/checker-path.cc b/gcc/analyzer/checker-path.cc
new file mode 100644
index ..f40e4f0197c4
--- /dev/null
+++ b/gcc/analyzer/checker-path.cc
@@ -0,0 +1,931 @@
+/* Subclasses of diagnostic_path and diagnostic_event for analyzer diagnostics.
+   Copyright (C) 2019 Free Software Foundation, Inc.
+   Contributed by David Malcolm .
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tree.h"
+#include "function.h"
+#include "basic-block.h"
+#include "gimple.h"
+#include "gimple-pretty-print.h"
+#include "fold-const.h"
+#include "analyzer/analyzer.h"
+#include "analyzer/checker-path.h"
+#include "analyzer/supergraph.h"
+#include "analyzer/diagnostic-manager.h"
+#include "analyzer/exploded-graph.h"
+
+#if ENABLE_ANALYZER
+
+/* Get a string for EK.  */
+
+const char *
+event_kind_to_string (enum event_kind ek)
+{
+  switch (ek)
+{
+default:
+  gcc_unreachable ();
+case EK_DEBUG:
+  return "EK_DEBUG";
+case EK_CUSTOM:
+  return "EK_CUSTOM";
+case EK_STMT:
+  return "EK_STMT";
+case EK_FUNCTION_ENTRY:
+  return "EK_FUNCTION_ENTRY";
+case EK_STATE_CHANGE:
+  return "EK_STATE_CHANGE";
+case EK_START_CFG_EDGE:
+  return "EK_START_CFG_EDGE";
+case EK_END_CFG_EDGE:
+  return "EK_END_CFG_EDGE";
+case EK_CALL_EDGE:
+  return "EK_CALL_EDGE";
+case EK_RETURN_EDGE:
+  return "EK_RETURN_EDGE";
+case EK_SETJMP:
+  return "EK_SETJMP";
+case EK_REWIND_FROM_LONGJMP:
+  return "EK_REWIND_FROM_LONGJMP";
+case EK_REWIND_TO_SETJMP:
+  return "EK_REWIND_TO_SETJMP";
+case EK_WARNING:
+  return "EK_WARNING";
+}
+}
+
+/* class checker_event : public diagnostic_event.  */
+
+/* Dump this event to PP (for debugging/logging purposes).  */
+
+void
+checker_event::dump (pretty_printer *pp) const
+{
+  label_text event_desc (get_desc (false));
+  pp_printf (pp, "\"%s\" (depth %i, m_loc=%x)",
+event_desc.m_buffer,
+get_stack_depth (),
+get_location ());
+  event_desc.maybe_free ();
+}
+
+/* Hook for being notified when this event has its final id EMISSION_ID
+   and is about to emitted for PD.
+
+   Base implementation of checker_event::prepare_for_emission vfunc;
+   subclasses that override this should chain up to it.
+
+   Record PD and EMISSION_ID, and call the get_desc vfunc, so that any
+   side-effects of the call to get_desc take place before
+   pending_diagnostic::emit is called.
+
+   For example, state_change_event::get_desc can call
+   pending_diagnostic::describe_state_change; free_of_non_heap can use this
+   to tweak the message (TODO: would be neater to simply capture the
+   pertinent data within the sm-state).  */
+
+void
+checker_event::prepare_for_emission (checker_path *,
+pending_diagnostic *pd,
+diagnostic_event_id_t emission_id)
+{
+  m_pending_diagnostic = pd;
+  m_emission_id = emission_id;
+
+  label_text desc = get_desc (false);
+  desc.maybe_free ();
+}
+
+/* class debug_event : public checker_event.  */
+
+/* Implementation of diagnostic_event::get_desc vfunc for
+   debug_event.
+   Use the saved 

[PATCH 39/45] analyzer: new file: exploded-graph.h

2019-12-13 Thread David Malcolm
Changed in v4:
- Remove /// comment lines
- Don't use multiple inheritance, instead adding a log_user member.
- Add more validation, part of:
https://gcc.gnu.org/ml/gcc-patches/2019-11/msg02517.html
- Generalize rewind_info_t to exploded_edge::custom_info_t
https://gcc.gnu.org/ml/gcc-patches/2019-12/msg00219.html
- Add DISABLE_COPY_AND_ASSIGN (exploded_node);
- Add DISABLE_COPY_AND_ASSIGN (exploded_edge);
- Add DISABLE_COPY_AND_ASSIGN (exploded_graph);

This patch adds exploded_graph and related classes, for managing
exploring paths through the user's code as a directed graph
of  pairs.

gcc/ChangeLog:
* analyzer/exploded-graph.h: New file.
---
 gcc/analyzer/exploded-graph.h | 830 ++
 1 file changed, 830 insertions(+)
 create mode 100644 gcc/analyzer/exploded-graph.h

diff --git a/gcc/analyzer/exploded-graph.h b/gcc/analyzer/exploded-graph.h
new file mode 100644
index ..8e3df18fadbf
--- /dev/null
+++ b/gcc/analyzer/exploded-graph.h
@@ -0,0 +1,830 @@
+/* Classes for managing a directed graph of  pairs.
+   Copyright (C) 2019 Free Software Foundation, Inc.
+   Contributed by David Malcolm .
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+.  */
+
+#ifndef GCC_ANALYZER_EXPLODED_GRAPH_H
+#define GCC_ANALYZER_EXPLODED_GRAPH_H
+
+#include "alloc-pool.h"
+#include "fibonacci_heap.h"
+#include "shortest-paths.h"
+#include "analyzer/analyzer-logging.h"
+#include "analyzer/constraint-manager.h"
+#include "analyzer/diagnostic-manager.h"
+#include "analyzer/program-point.h"
+#include "analyzer/program-state.h"
+
+/* Concrete implementation of region_model_context, wiring it up to the
+   rest of the analysis engine.  */
+
+class impl_region_model_context : public region_model_context
+{
+ public:
+  impl_region_model_context (exploded_graph ,
+const exploded_node *enode_for_diag,
+
+/* TODO: should we be getting the ECs from the
+   old state, rather than the new?  */
+const program_state *old_state,
+program_state *new_state,
+state_change *change,
+
+const gimple *stmt,
+stmt_finder *stmt_finder = NULL);
+
+  impl_region_model_context (program_state *state,
+state_change *change,
+const extrinsic_state _state);
+
+  void warn (pending_diagnostic *d) FINAL OVERRIDE;
+
+  void remap_svalue_ids (const svalue_id_map ) FINAL OVERRIDE;
+
+  int on_svalue_purge (svalue_id first_unused_sid,
+  const svalue_id_map ) FINAL OVERRIDE;
+
+  logger *get_logger () FINAL OVERRIDE
+  {
+return m_logger.get_logger ();
+  }
+
+  void on_state_leak (const state_machine ,
+ int sm_idx,
+ svalue_id sid,
+ svalue_id first_unused_sid,
+ const svalue_id_map ,
+ state_machine::state_t state);
+
+  void on_inherited_svalue (svalue_id parent_sid,
+   svalue_id child_sid) FINAL OVERRIDE;
+
+  void on_cast (svalue_id src_sid,
+   svalue_id dst_sid) FINAL OVERRIDE;
+
+  void on_condition (tree lhs, enum tree_code op, tree rhs) FINAL OVERRIDE;
+
+  exploded_graph *m_eg;
+  log_user m_logger;
+  const exploded_node *m_enode_for_diag;
+  const program_state *m_old_state;
+  program_state *m_new_state;
+  state_change *m_change;
+  const gimple *m_stmt;
+  stmt_finder *m_stmt_finder;
+  const extrinsic_state _ext_state;
+};
+
+/* A  pair, used internally by
+   exploded_node as its immutable data, and as a key for identifying
+   exploded_nodes we've already seen in the graph.  */
+
+struct point_and_state
+{
+  point_and_state (const program_point ,
+  const program_state )
+  : m_point (point),
+m_state (state),
+m_hash (m_point.hash () ^ m_state.hash ())
+  {
+  }
+
+  hashval_t hash () const
+  {
+return m_hash;
+  }
+  bool operator== (const point_and_state ) const
+  {
+return m_point == other.m_point && m_state == other.m_state;
+  }
+
+  void set_state (const program_state )
+  {
+m_state = state;
+m_hash = m_point.hash () ^ m_state.hash ();
+  }
+
+  void validate (const extrinsic_state _state) const;
+
+  program_point m_point;
+  

[PATCH 34/45] analyzer: new file: sm-taint.cc

2019-12-13 Thread David Malcolm
Changed in v4:
- Remove include of gcc-plugin.h, reworking includes accordingly.
- Wrap everything in #if ENABLE_ANALYZER
- Remove /// comment lines
- Rework on_leak vfunc:
https://gcc.gnu.org/ml/gcc-patches/2019-11/msg02028.html
- Rework for changes to is_named_call_p, resolving function pointers:
   https://gcc.gnu.org/ml/gcc-patches/2019-12/msg00178.html

This patch adds a state machine checker for tracking "taint",
where data potentially under an attacker's control is used for
things like array indices without sanitization (CWE-129).

This checker isn't ready for production, and is presented as a
proof-of-concept of the sm-based approach.

gcc/ChangeLog:
* analyzer/sm-taint.cc: New file.
---
 gcc/analyzer/sm-taint.cc | 325 +++
 1 file changed, 325 insertions(+)
 create mode 100644 gcc/analyzer/sm-taint.cc

diff --git a/gcc/analyzer/sm-taint.cc b/gcc/analyzer/sm-taint.cc
new file mode 100644
index ..8b20f78ffe60
--- /dev/null
+++ b/gcc/analyzer/sm-taint.cc
@@ -0,0 +1,325 @@
+/* An experimental state machine, for tracking "taint": unsanitized uses
+   of data potentially under an attacker's control.
+
+   Copyright (C) 2019 Free Software Foundation, Inc.
+   Contributed by David Malcolm .
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tree.h"
+#include "function.h"
+#include "basic-block.h"
+#include "gimple.h"
+#include "options.h"
+#include "diagnostic-path.h"
+#include "diagnostic-metadata.h"
+#include "analyzer/analyzer.h"
+#include "analyzer/pending-diagnostic.h"
+#include "analyzer/sm.h"
+
+#if ENABLE_ANALYZER
+
+namespace {
+
+/* An experimental state machine, for tracking "taint": unsanitized uses
+   of data potentially under an attacker's control.  */
+
+class taint_state_machine : public state_machine
+{
+public:
+  taint_state_machine (logger *logger);
+
+  bool inherited_state_p () const FINAL OVERRIDE { return true; }
+
+  bool on_stmt (sm_context *sm_ctxt,
+   const supernode *node,
+   const gimple *stmt) const FINAL OVERRIDE;
+
+  void on_condition (sm_context *sm_ctxt,
+const supernode *node,
+const gimple *stmt,
+tree lhs,
+enum tree_code op,
+tree rhs) const FINAL OVERRIDE;
+
+  bool can_purge_p (state_t s) const FINAL OVERRIDE;
+
+  /* Start state.  */
+  state_t m_start;
+
+  /* State for a "tainted" value: unsanitized data potentially under an
+ attacker's control.  */
+  state_t m_tainted;
+
+  /* State for a "tainted" value that has a lower bound.  */
+  state_t m_has_lb;
+
+  /* State for a "tainted" value that has an upper bound.  */
+  state_t m_has_ub;
+
+  /* Stop state, for a value we don't want to track any more.  */
+  state_t m_stop;
+};
+
+enum bounds
+{
+  BOUNDS_NONE,
+  BOUNDS_UPPER,
+  BOUNDS_LOWER
+};
+
+class tainted_array_index
+  : public pending_diagnostic_subclass
+{
+public:
+  tainted_array_index (const taint_state_machine , tree arg,
+  enum bounds has_bounds)
+  : m_sm (sm), m_arg (arg), m_has_bounds (has_bounds) {}
+
+  const char *get_kind () const FINAL OVERRIDE { return "tainted_array_index"; 
}
+
+  bool operator== (const tainted_array_index ) const
+  {
+return m_arg == other.m_arg;
+  }
+
+  bool emit (rich_location *rich_loc) FINAL OVERRIDE
+  {
+diagnostic_metadata m;
+m.add_cwe (129);
+switch (m_has_bounds)
+  {
+  default:
+   gcc_unreachable ();
+  case BOUNDS_NONE:
+   return warning_at (rich_loc, m, OPT_Wanalyzer_tainted_array_index,
+  "use of tainted value %qE in array lookup"
+  " without bounds checking",
+  m_arg);
+   break;
+  case BOUNDS_UPPER:
+   return warning_at (rich_loc, m, OPT_Wanalyzer_tainted_array_index,
+  "use of tainted value %qE in array lookup"
+  " without lower-bounds checking",
+  m_arg);
+   break;
+  case BOUNDS_LOWER:
+   return warning_at (rich_loc, m, OPT_Wanalyzer_tainted_array_index,
+  "use of tainted value %qE in array lookup"
+  " without upper-bounds checking",
+  m_arg);

[PATCH 36/45] analyzer: new files: call-string.{cc|h}

2019-12-13 Thread David Malcolm
Changed in v4:
- Remove include of gcc-plugin.h, reworking includes accordingly.
- Wrap everything in #if ENABLE_ANALYZER
- Add call_string::validate, part of:
https://gcc.gnu.org/ml/gcc-patches/2019-11/msg02517.html

This patch adds call_string, a class for representing the
call stacks at a program_point, so that we can ensure that
paths through the code are interprocedurally valid.

gcc/ChangeLog:
* analyzer/call-string.cc: New file.
* analyzer/call-string.h: New file.
---
 gcc/analyzer/call-string.cc | 224 
 gcc/analyzer/call-string.h  |  76 
 2 files changed, 300 insertions(+)
 create mode 100644 gcc/analyzer/call-string.cc
 create mode 100644 gcc/analyzer/call-string.h

diff --git a/gcc/analyzer/call-string.cc b/gcc/analyzer/call-string.cc
new file mode 100644
index ..a9ff9cbfca44
--- /dev/null
+++ b/gcc/analyzer/call-string.cc
@@ -0,0 +1,224 @@
+/* Call stacks at program points.
+   Copyright (C) 2019 Free Software Foundation, Inc.
+   Contributed by David Malcolm .
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "pretty-print.h"
+#include "tree.h"
+#include "options.h"
+#include "analyzer/call-string.h"
+#include "analyzer/supergraph.h"
+
+#if ENABLE_ANALYZER
+
+/* class call_string.  */
+
+/* call_string's copy ctor.  */
+
+call_string::call_string (const call_string )
+: m_return_edges (other.m_return_edges.length ())
+{
+  const return_superedge *e;
+  int i;
+  FOR_EACH_VEC_ELT (other.m_return_edges, i, e)
+m_return_edges.quick_push (e);
+}
+
+/* call_string's assignment operator.  */
+
+call_string&
+call_string::operator= (const call_string )
+{
+  // would be much simpler if we could rely on vec<> assignment op
+  m_return_edges.truncate (0);
+  m_return_edges.reserve (other.m_return_edges.length (), true);
+  const return_superedge *e;
+  int i;
+  FOR_EACH_VEC_ELT (other.m_return_edges, i, e)
+m_return_edges.quick_push (e);
+  return *this;
+}
+
+/* call_string's equality operator.  */
+
+bool
+call_string::operator== (const call_string ) const
+{
+  if (m_return_edges.length () != other.m_return_edges.length ())
+return false;
+  const return_superedge *e;
+  int i;
+  FOR_EACH_VEC_ELT (m_return_edges, i, e)
+if (e != other.m_return_edges[i])
+  return false;
+  return true;
+}
+
+/* Print this to PP.  */
+
+void
+call_string::print (pretty_printer *pp) const
+{
+  pp_string (pp, "[");
+
+  const return_superedge *e;
+  int i;
+  FOR_EACH_VEC_ELT (m_return_edges, i, e)
+{
+  if (i > 0)
+   pp_string (pp, ", ");
+  pp_printf (pp, "(SN: %i -> SN: %i in %s)",
+e->m_src->m_index, e->m_dest->m_index,
+function_name (e->m_dest->m_fun));
+}
+
+  pp_string (pp, "]");
+}
+
+/* Generate a hash value for this call_string.  */
+
+hashval_t
+call_string::hash () const
+{
+  inchash::hash hstate;
+  int i;
+  const return_superedge *e;
+  FOR_EACH_VEC_ELT (m_return_edges, i, e)
+hstate.add_ptr (e);
+  return hstate.end ();
+}
+
+/* Push the return superedge for CALL_SEDGE onto the end of this
+   call_string.  */
+
+void
+call_string::push_call (const supergraph ,
+   const call_superedge *call_sedge)
+{
+  gcc_assert (call_sedge);
+  const return_superedge *return_sedge = call_sedge->get_edge_for_return (sg);
+  gcc_assert (return_sedge);
+  m_return_edges.safe_push (return_sedge);
+}
+
+/* Count the number of times the top-most call site appears in the
+   stack.  */
+
+int
+call_string::calc_recursion_depth () const
+{
+  if (m_return_edges.is_empty ())
+return 0;
+  const return_superedge *top_return_sedge
+= m_return_edges[m_return_edges.length () - 1];
+
+  int result = 0;
+  const return_superedge *e;
+  int i;
+  FOR_EACH_VEC_ELT (m_return_edges, i, e)
+if (e == top_return_sedge)
+  ++result;
+  return result;
+}
+
+/* Comparator for call strings.
+   Return negative if A is before B.
+   Return positive if B is after A.
+   Return 0 if they are equal.  */
+
+int
+call_string::cmp (const call_string ,
+ const call_string )
+{
+  int result = cmp_1 (a, b);
+
+  /* Check that the ordering is symmetric  */
+#if CHECKING_P
+  int reversed = cmp_1 (b, a);
+  gcc_assert (reversed == -result);
+#endif
+
+  /* We should only have 0 for equal 

[PATCH 37/45] analyzer: new files: program-point.{cc|h}

2019-12-13 Thread David Malcolm
Changed in v4:
- Remove include of gcc-plugin.h, reworking includes accordingly.
- Wrap everything in #if ENABLE_ANALYZER
- Remove /// comment lines
- Add support for more validation, part of:
https://gcc.gnu.org/ml/gcc-patches/2019-11/msg02517.html
- Rework logging to avoid exploded_graph multiple-inheritance (moving
  log_user base to a member)
- Port to new param API

This patch introduces function_point and program_point, classes
for tracking locations within the program (the latter adding
a call_string for tracking interprocedural location).

gcc/ChangeLog:
* analyzer/program-point.cc: New file.
* analyzer/program-point.h: New file.
---
 gcc/analyzer/program-point.cc | 529 ++
 gcc/analyzer/program-point.h  | 313 
 2 files changed, 842 insertions(+)
 create mode 100644 gcc/analyzer/program-point.cc
 create mode 100644 gcc/analyzer/program-point.h

diff --git a/gcc/analyzer/program-point.cc b/gcc/analyzer/program-point.cc
new file mode 100644
index ..8e2ead047427
--- /dev/null
+++ b/gcc/analyzer/program-point.cc
@@ -0,0 +1,529 @@
+/* Classes for representing locations within the program.
+   Copyright (C) 2019 Free Software Foundation, Inc.
+   Contributed by David Malcolm .
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tree.h"
+#include "gimple-pretty-print.h"
+#include "gcc-rich-location.h"
+#include "analyzer/program-point.h"
+#include "analyzer/exploded-graph.h"
+#include "analyzer/analysis-plan.h"
+
+#if ENABLE_ANALYZER
+
+/* Get a string for PK.  */
+
+const char *
+point_kind_to_string (enum point_kind pk)
+{
+  switch (pk)
+{
+default:
+  gcc_unreachable ();
+case PK_ORIGIN:
+  return "PK_ORIGIN";
+case PK_BEFORE_SUPERNODE:
+  return "PK_BEFORE_SUPERNODE";
+case PK_BEFORE_STMT:
+  return "PK_BEFORE_STMT";
+case PK_AFTER_SUPERNODE:
+  return "PK_AFTER_SUPERNODE";
+case PK_EMPTY:
+  return "PK_EMPTY";
+case PK_DELETED:
+  return "PK_DELETED";
+}
+}
+
+/* class function_point.  */
+
+/* Print this function_point to PP.  */
+
+void
+function_point::print (pretty_printer *pp, const format ) const
+{
+  switch (get_kind ())
+{
+default:
+  gcc_unreachable ();
+
+case PK_ORIGIN:
+  pp_printf (pp, "origin");
+  break;
+
+case PK_BEFORE_SUPERNODE:
+  {
+   if (m_from_edge)
+ pp_printf (pp, "before SN: %i (from SN: %i)",
+m_supernode->m_index, m_from_edge->m_src->m_index);
+   else
+ pp_printf (pp, "before SN: %i (NULL from-edge)",
+m_supernode->m_index);
+   f.spacer (pp);
+   for (gphi_iterator gpi
+  = const_cast(get_supernode ())->start_phis ();
+!gsi_end_p (gpi); gsi_next ())
+ {
+   const gphi *phi = gpi.phi ();
+   pp_gimple_stmt_1 (pp, phi, 0, (dump_flags_t)0);
+ }
+  }
+  break;
+
+case PK_BEFORE_STMT:
+  pp_printf (pp, "before (SN: %i stmt: %i): ", m_supernode->m_index,
+m_stmt_idx);
+  f.spacer (pp);
+  pp_gimple_stmt_1 (pp, get_stmt (), 0, (dump_flags_t)0);
+  if (f.m_newlines)
+   {
+ pp_newline (pp);
+ print_source_line (pp);
+   }
+  break;
+
+case PK_AFTER_SUPERNODE:
+  pp_printf (pp, "after SN: %i", m_supernode->m_index);
+  break;
+}
+}
+
+/* Generate a hash value for this function_point.  */
+
+hashval_t
+function_point::hash () const
+{
+  inchash::hash hstate;
+  if (m_supernode)
+hstate.add_int (m_supernode->m_index);
+  hstate.add_ptr (m_from_edge);
+  hstate.add_int (m_stmt_idx);
+  hstate.add_int (m_kind);
+  return hstate.end ();
+}
+
+/* Get the gimple stmt for this function_point, if any.  */
+
+const gimple *
+function_point::get_stmt () const
+{
+  if (m_kind == PK_BEFORE_STMT)
+return m_supernode->m_stmts[m_stmt_idx];
+  else if (m_kind == PK_AFTER_SUPERNODE)
+return m_supernode->get_last_stmt ();
+  else
+return NULL;
+}
+
+/* Get a location for this function_point, if any.  */
+
+location_t
+function_point::get_location () const
+{
+  const gimple *stmt = get_stmt ();
+  if (stmt)
+return stmt->location;
+
+  return UNKNOWN_LOCATION;
+}
+
+/* A subclass of diagnostic_context for use by
+   

[PATCH 32/45] analyzer: new file: sm-sensitive.cc

2019-12-13 Thread David Malcolm
Changed in v4:
- Remove include of gcc-plugin.h, reworking includes accordingly.
- Wrap everything in #if ENABLE_ANALYZER
- Remove /// comment lines
- Rework on_leak vfunc:
https://gcc.gnu.org/ml/gcc-patches/2019-11/msg02028.html
- Rework for changes to is_named_call_p, resolving function pointers:
   https://gcc.gnu.org/ml/gcc-patches/2019-12/msg00178.html
- Implement precision-of-wording vfuncs

This patch adds a state machine checker for tracking exposure of
sensitive data (e.g. writing passwords to log files).

This checker isn't ready for production, and is presented as a
proof-of-concept of the sm-based approach.

gcc/ChangeLog:
* analyzer/sm-sensitive.cc: New file.
---
 gcc/analyzer/sm-sensitive.cc | 245 +++
 1 file changed, 245 insertions(+)
 create mode 100644 gcc/analyzer/sm-sensitive.cc

diff --git a/gcc/analyzer/sm-sensitive.cc b/gcc/analyzer/sm-sensitive.cc
new file mode 100644
index ..37219b915da3
--- /dev/null
+++ b/gcc/analyzer/sm-sensitive.cc
@@ -0,0 +1,245 @@
+/* An experimental state machine, for tracking exposure of sensitive
+   data (e.g. through logging).
+   Copyright (C) 2019 Free Software Foundation, Inc.
+   Contributed by David Malcolm .
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tree.h"
+#include "function.h"
+#include "function.h"
+#include "basic-block.h"
+#include "gimple.h"
+#include "options.h"
+#include "diagnostic-path.h"
+#include "diagnostic-metadata.h"
+#include "analyzer/analyzer.h"
+#include "analyzer/pending-diagnostic.h"
+#include "analyzer/sm.h"
+
+#if ENABLE_ANALYZER
+
+namespace {
+
+/* An experimental state machine, for tracking exposure of sensitive
+   data (e.g. through logging).  */
+
+class sensitive_state_machine : public state_machine
+{
+public:
+  sensitive_state_machine (logger *logger);
+
+  bool inherited_state_p () const FINAL OVERRIDE { return true; }
+
+  bool on_stmt (sm_context *sm_ctxt,
+   const supernode *node,
+   const gimple *stmt) const FINAL OVERRIDE;
+
+  void on_condition (sm_context *sm_ctxt,
+const supernode *node,
+const gimple *stmt,
+tree lhs,
+enum tree_code op,
+tree rhs) const FINAL OVERRIDE;
+
+  bool can_purge_p (state_t s) const FINAL OVERRIDE;
+
+  /* Start state.  */
+  state_t m_start;
+
+  /* State for "sensitive" data, such as a password.  */
+  state_t m_sensitive;
+
+  /* Stop state, for a value we don't want to track any more.  */
+  state_t m_stop;
+
+private:
+  void warn_for_any_exposure (sm_context *sm_ctxt,
+ const supernode *node,
+ const gimple *stmt,
+ tree arg) const;
+};
+
+class exposure_through_output_file
+  : public pending_diagnostic_subclass
+{
+public:
+  exposure_through_output_file (const sensitive_state_machine , tree arg)
+  : m_sm (sm), m_arg (arg)
+  {}
+
+  const char *get_kind () const FINAL OVERRIDE
+  {
+return "exposure_through_output_file";
+  }
+
+  bool operator== (const exposure_through_output_file ) const
+  {
+return m_arg == other.m_arg;
+  }
+
+  bool emit (rich_location *rich_loc) FINAL OVERRIDE
+  {
+diagnostic_metadata m;
+/* CWE-532: Information Exposure Through Log Files */
+m.add_cwe (532);
+return warning_at (rich_loc, m, OPT_Wanalyzer_exposure_through_output_file,
+  "sensitive value %qE written to output file",
+  m_arg);
+  }
+
+  label_text describe_state_change (const evdesc::state_change )
+FINAL OVERRIDE
+  {
+if (change.m_new_state == m_sm.m_sensitive)
+  {
+   m_first_sensitive_event = change.m_event_id;
+   return change.formatted_print ("sensitive value acquired here");
+  }
+return label_text ();
+  }
+
+  label_text describe_call_with_state (const evdesc::call_with_state )
+FINAL OVERRIDE
+  {
+if (info.m_state == m_sm.m_sensitive)
+  return info.formatted_print
+   ("passing sensitive value %qE in call to %qE from %qE",
+info.m_expr, info.m_callee_fndecl, info.m_caller_fndecl);
+return label_text ();
+  }
+
+  label_text describe_return_of_state (const evdesc::return_of_state )
+FINAL OVERRIDE
+  {
+if 

[PATCH 10/45] Add diagnostic paths

2019-12-13 Thread David Malcolm
Changed in v4:
- Add support for paths for signal-handlers:
  https://gcc.gnu.org/ml/gcc-patches/2019-12/msg00215.html
- Fix comment

Changed in v3:
- Fixup for rebase (r278634): c-format.c: get_pointer_to_named_type -> 
get_named_type
https://gcc.gnu.org/ml/gcc-patches/2019-12/msg00530.html

Changed in v2:
- Fixup for rebase (r277284) for json::number -> json::integer_number
https://gcc.gnu.org/ml/gcc-patches/2019-11/msg02035.html

This patch adds support for associating a "diagnostic_path" with a
diagnostic: a sequence of events predicted by the compiler that leads to
the problem occurring, with their locations in the user's source,
text descriptions, and stack information (for handling interprocedural
paths).

For example, the following (hypothetical) error has a 3-event
intraprocedural path:

test.c: In function 'demo':
test.c:29:5: error: passing NULL as argument 1 to 'PyList_Append' which
  requires a non-NULL parameter
   29 | PyList_Append(list, item);
  | ^
  'demo': events 1-3
 |
 |   25 |   list = PyList_New(0);
 |  |  ^
 |  |  |
 |  |  (1) when 'PyList_New' fails, returning NULL
 |   26 |
 |   27 |   for (i = 0; i < count; i++) {
 |  |   ~~~
 |  |   |
 |  |   (2) when 'i < count'
 |   28 | item = PyLong_FromLong(random());
 |   29 | PyList_Append(list, item);
 |  | ~
 |  | |
 |  | (3) when calling 'PyList_Append', passing NULL from (1) as 
argument 1
 |

The patch adds a new "%@" format code for printing event IDs, so that
in the above, the description of event (3) mentions event (1), showing
the user where the bogus NULL value comes from (the event IDs are
colorized to draw the user's attention to them).

There is a separation between data vs presentation: the above shows how
the diagnostic-printing code has consolidated the path into a single run
of events, since all the events are near each other and within the same
function; more complicated examples (such as interprocedural paths)
might be printed as multiple runs of events.

Examples of how interprocedural paths are printed can be seen in the
test suite (which uses a plugin to exercise the code without relying
on specific warnings using this functionality).

Other output formats include
- JSON,
- printing each event as a separate "note", and
- to not emit paths.

(I have a separate script that can generate HTML from the JSON, but HTML
is not my speciality; help from a web front-end expert to make it look
good would be appreciated).

gcc/ChangeLog:
* Makefile.in (OBJS): Add tree-diagnostic-path.o.
* common.opt (fdiagnostics-path-format=): New option.
(diagnostic_path_format): New enum.
(fdiagnostics-show-path-depths): New option.
* coretypes.h (diagnostic_event_id_t): New forward decl.
* diagnostic-color.c (color_dict): Add "path".
* diagnostic-event-id.h: New file.
* diagnostic-format-json.cc (json_from_expanded_location): Make
non-static.
(json_end_diagnostic): Call context->make_json_for_path if it
exists and the diagnostic has a path.
(diagnostic_output_format_init): Clear context->print_path.
* diagnostic-path.h: New file.
* diagnostic-show-locus.c (colorizer::set_range): Special-case
when printing a run of events in a diagnostic_path so that they
all get the same color.
(layout::m_diagnostic_path_p): New field.
(layout::layout): Initialize it.
(layout::print_any_labels): Don't colorize the label text for an
event in a diagnostic_path.
(gcc_rich_location::add_location_if_nearby): Add
"restrict_to_current_line_spans" and "label" params.  Pass the
former to layout.maybe_add_location_range; pass the latter
when calling add_range.
* diagnostic.c: Include "diagnostic-path.h".
(diagnostic_initialize): Initialize context->path_format and
context->show_path_depths.
(diagnostic_show_any_path): New function.
(diagnostic_path::interprocedural_p): New function.
(diagnostic_report_diagnostic): Call diagnostic_show_any_path.
(simple_diagnostic_path::num_events): New function.
(simple_diagnostic_path::get_event): New function.
(simple_diagnostic_path::add_event): New function.
(simple_diagnostic_event::simple_diagnostic_event): New ctor.
(simple_diagnostic_event::~simple_diagnostic_event): New dtor.
(debug): New overload taking a diagnostic_path *.
* diagnostic.def (DK_DIAGNOSTIC_PATH): New.
* diagnostic.h (enum diagnostic_path_format): New enum.
(json::value): New forward decl.
(diagnostic_context::path_format): New field.
(diagnostic_context::show_path_depths): New field.

[PATCH 29/45] analyzer: new files: sm-malloc.cc and sm-malloc.dot

2019-12-13 Thread David Malcolm
Changed in v4:
- Remove include of gcc-plugin.h, reworking includes accordingly.
- Wrap everything in #if ENABLE_ANALYZER
- Remove /// comment lines
- Rework on_leak vfunc:
https://gcc.gnu.org/ml/gcc-patches/2019-11/msg02028.html
- Rework for changes to is_named_call_p, resolving function pointers:
   https://gcc.gnu.org/ml/gcc-patches/2019-12/msg00178.html
- Support the "__builtin_"-prefixed spellings of malloc, calloc and free
- Add malloc.dot

This patch adds a state machine checker for malloc/free.

gcc/ChangeLog:
* analyzer/sm-malloc.cc: New file.
* analyzer/sm-malloc.dot: New file.
---
 gcc/analyzer/sm-malloc.cc  | 794 +
 gcc/analyzer/sm-malloc.dot |  89 +
 2 files changed, 883 insertions(+)
 create mode 100644 gcc/analyzer/sm-malloc.cc
 create mode 100644 gcc/analyzer/sm-malloc.dot

diff --git a/gcc/analyzer/sm-malloc.cc b/gcc/analyzer/sm-malloc.cc
new file mode 100644
index ..badae51e1d75
--- /dev/null
+++ b/gcc/analyzer/sm-malloc.cc
@@ -0,0 +1,794 @@
+/* A state machine for detecting misuses of the malloc/free API.
+   Copyright (C) 2019 Free Software Foundation, Inc.
+   Contributed by David Malcolm .
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tree.h"
+#include "function.h"
+#include "basic-block.h"
+#include "gimple.h"
+#include "options.h"
+#include "bitmap.h"
+#include "diagnostic-path.h"
+#include "diagnostic-metadata.h"
+#include "analyzer/analyzer.h"
+#include "analyzer/pending-diagnostic.h"
+#include "analyzer/sm.h"
+
+#if ENABLE_ANALYZER
+
+namespace {
+
+/* A state machine for detecting misuses of the malloc/free API.
+
+   See sm-malloc.dot for an overview (keep this in-sync with that file).  */
+
+class malloc_state_machine : public state_machine
+{
+public:
+  malloc_state_machine (logger *logger);
+
+  bool inherited_state_p () const FINAL OVERRIDE { return false; }
+
+  bool on_stmt (sm_context *sm_ctxt,
+   const supernode *node,
+   const gimple *stmt) const FINAL OVERRIDE;
+
+  void on_condition (sm_context *sm_ctxt,
+const supernode *node,
+const gimple *stmt,
+tree lhs,
+enum tree_code op,
+tree rhs) const FINAL OVERRIDE;
+
+  bool can_purge_p (state_t s) const FINAL OVERRIDE;
+  pending_diagnostic *on_leak (tree var) const FINAL OVERRIDE;
+
+  /* Start state.  */
+  state_t m_start;
+
+  /* State for a pointer returned from malloc that hasn't been checked for
+ NULL.
+ It could be a pointer to heap-allocated memory, or could be NULL.  */
+  state_t m_unchecked;
+
+  /* State for a pointer that's known to be NULL.  */
+  state_t m_null;
+
+  /* State for a pointer to heap-allocated memory, known to be non-NULL.  */
+  state_t m_nonnull;
+
+  /* State for a pointer to freed memory.  */
+  state_t m_freed;
+
+  /* State for a pointer that's known to not be on the heap (e.g. to a local
+ or global).  */
+  state_t m_non_heap; // TODO: or should this be a different state machine?
+  // or do we need child values etc?
+
+  /* Stop state, for pointers we don't want to track any more.  */
+  state_t m_stop;
+};
+
+/* Class for diagnostics relating to malloc_state_machine.  */
+
+class malloc_diagnostic : public pending_diagnostic
+{
+public:
+  malloc_diagnostic (const malloc_state_machine , tree arg)
+  : m_sm (sm), m_arg (arg)
+  {}
+
+  bool subclass_equal_p (const pending_diagnostic _other) const OVERRIDE
+  {
+return m_arg == ((const malloc_diagnostic &)base_other).m_arg;
+  }
+
+  label_text describe_state_change (const evdesc::state_change )
+OVERRIDE
+  {
+if (change.m_old_state == m_sm.m_start
+   && change.m_new_state == m_sm.m_unchecked)
+  // TODO: verify that it's the allocation stmt, not a copy
+  return label_text::borrow ("allocated here");
+if (change.m_old_state == m_sm.m_unchecked
+   && change.m_new_state == m_sm.m_nonnull)
+  return change.formatted_print ("assuming %qE is non-NULL",
+change.m_expr);
+if (change.m_new_state == m_sm.m_null)
+  return change.formatted_print ("assuming %qE is NULL",
+change.m_expr);
+return label_text ();
+  }
+
+protected:
+  const 

[PATCH 27/45] analyzer: new files: pending-diagnostic.{cc|h}

2019-12-13 Thread David Malcolm
Changed in v4:
- Remove include of gcc-plugin.h, reworking includes accordingly.
- Wrap everything in #if ENABLE_ANALYZER
- Capture const state_change_event& in evdesc_state_change:
https://gcc.gnu.org/ml/gcc-patches/2019-12/msg00218.html

This patch adds classes used by the analyzer for handling its diagnostics
(queueing them, deduplicating them, precision-of-wording hooks).

gcc/ChangeLog:
* analyzer/pending-diagnostic.cc: New file.
* analyzer/pending-diagnostic.h: New file.
---
 gcc/analyzer/pending-diagnostic.cc |  64 +++
 gcc/analyzer/pending-diagnostic.h  | 269 +
 2 files changed, 333 insertions(+)
 create mode 100644 gcc/analyzer/pending-diagnostic.cc
 create mode 100644 gcc/analyzer/pending-diagnostic.h

diff --git a/gcc/analyzer/pending-diagnostic.cc 
b/gcc/analyzer/pending-diagnostic.cc
new file mode 100644
index ..ae61b47bef66
--- /dev/null
+++ b/gcc/analyzer/pending-diagnostic.cc
@@ -0,0 +1,64 @@
+/* Classes for analyzer diagnostics.
+   Copyright (C) 2019 Free Software Foundation, Inc.
+   Contributed by David Malcolm .
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tree.h"
+#include "intl.h"
+#include "diagnostic.h"
+#include "analyzer/analyzer.h"
+#include "analyzer/pending-diagnostic.h"
+
+#if ENABLE_ANALYZER
+
+/* Generate a label_text by printing FMT.
+
+   Use a clone of the global_dc for formatting callbacks.
+
+   Use this evdesc::event_desc's m_colorize flag to control colorization
+   (so that e.g. we can disable it for JSON output).  */
+
+label_text
+evdesc::event_desc::formatted_print (const char *fmt, ...) const
+{
+  pretty_printer *pp = global_dc->printer->clone ();
+
+  pp_show_color (pp) = m_colorize;
+
+  text_info ti;
+  rich_location rich_loc (line_table, UNKNOWN_LOCATION);
+  va_list ap;
+  va_start (ap, fmt);
+  ti.format_spec = _(fmt);
+  ti.args_ptr = 
+  ti.err_no = 0;
+  ti.x_data = NULL;
+  ti.m_richloc = _loc;
+  pp_format (pp, );
+  pp_output_formatted_text (pp);
+  va_end (ap);
+
+  label_text result = label_text::take (xstrdup (pp_formatted_text (pp)));
+  delete pp;
+  return result;
+}
+
+#endif /* #if ENABLE_ANALYZER */
diff --git a/gcc/analyzer/pending-diagnostic.h 
b/gcc/analyzer/pending-diagnostic.h
new file mode 100644
index ..15a1379e8fd1
--- /dev/null
+++ b/gcc/analyzer/pending-diagnostic.h
@@ -0,0 +1,269 @@
+/* Classes for analyzer diagnostics.
+   Copyright (C) 2019 Free Software Foundation, Inc.
+   Contributed by David Malcolm .
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+.  */
+
+#ifndef GCC_ANALYZER_PENDING_DIAGNOSTIC_H
+#define GCC_ANALYZER_PENDING_DIAGNOSTIC_H
+
+#include "diagnostic-event-id.h"
+#include "analyzer/sm.h"
+
+/* Various bundles of information used for generating more precise
+   messages for events within a diagnostic_path, for passing to the
+   various "describe_*" vfuncs of pending_diagnostic.  See those
+   for more information.  */
+
+namespace evdesc {
+
+struct event_desc
+{
+  event_desc (bool colorize) : m_colorize (colorize) {}
+
+  label_text formatted_print (const char *fmt, ...) const
+ATTRIBUTE_GCC_DIAG(2,3);
+
+  bool m_colorize;
+};
+
+/* For use by pending_diagnostic::describe_state_change.  */
+
+struct state_change : public event_desc
+{
+  state_change (bool colorize,
+   tree expr,
+   tree origin,
+   state_machine::state_t old_state,
+   state_machine::state_t new_state,
+   diagnostic_event_id_t event_id,
+   const state_change_event )
+  : event_desc (colorize),
+m_expr (expr), m_origin (origin),
+m_old_state (old_state), m_new_state (new_state),
+m_event_id (event_id), m_event (event)
+  {}
+
+  bool 

[PATCH 24/45] analyzer: new files: tristate.{cc|h}

2019-12-13 Thread David Malcolm
Changed in v4:
- moved from gcc/analyzer to gcc

gcc/ChangeLog:
* tristate.cc: New file.
* tristate.h: New file.
---
 gcc/tristate.cc | 221 
 gcc/tristate.h  |  82 ++
 2 files changed, 303 insertions(+)
 create mode 100644 gcc/tristate.cc
 create mode 100644 gcc/tristate.h

diff --git a/gcc/tristate.cc b/gcc/tristate.cc
new file mode 100644
index ..78217f196804
--- /dev/null
+++ b/gcc/tristate.cc
@@ -0,0 +1,221 @@
+/* "True" vs "False" vs "Unknown".
+   Copyright (C) 2019 Free Software Foundation, Inc.
+   Contributed by David Malcolm .
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tristate.h"
+#include "selftest.h"
+
+const char *
+tristate::as_string () const
+{
+  switch (m_value)
+{
+default:
+  gcc_unreachable ();
+case TS_UNKNOWN:
+  return "UNKNOWN";
+case TS_TRUE:
+  return "TRUE";
+case TS_FALSE:
+  return "FALSE";
+}
+}
+
+tristate
+tristate::not_ () const
+{
+  switch (m_value)
+{
+default:
+  gcc_unreachable ();
+case TS_UNKNOWN:
+  return tristate (TS_UNKNOWN);
+case TS_TRUE:
+  return tristate (TS_FALSE);
+case TS_FALSE:
+  return tristate (TS_TRUE);
+}
+}
+
+tristate
+tristate::or_ (tristate other) const
+{
+  switch (m_value)
+{
+default:
+  gcc_unreachable ();
+case TS_UNKNOWN:
+  if (other.is_true ())
+   return tristate (TS_TRUE);
+  else
+   return tristate (TS_UNKNOWN);
+case TS_FALSE:
+  return other;
+case TS_TRUE:
+  return tristate (TS_TRUE);
+}
+}
+
+tristate
+tristate::and_ (tristate other) const
+{
+  switch (m_value)
+{
+default:
+  gcc_unreachable ();
+case TS_UNKNOWN:
+  if (other.is_false ())
+   return tristate (TS_FALSE);
+  else
+   return tristate (TS_UNKNOWN);
+case TS_TRUE:
+  return other;
+case TS_FALSE:
+  return tristate (TS_FALSE);
+}
+}
+
+#if CHECKING_P
+
+namespace selftest {
+
+#define ASSERT_TRISTATE_TRUE(TRISTATE) \
+  SELFTEST_BEGIN_STMT  \
+  ASSERT_EQ (TRISTATE, tristate (tristate::TS_TRUE));  \
+  SELFTEST_END_STMT
+
+#define ASSERT_TRISTATE_FALSE(TRISTATE) \
+  SELFTEST_BEGIN_STMT  \
+  ASSERT_EQ (TRISTATE, tristate (tristate::TS_FALSE)); \
+  SELFTEST_END_STMT
+
+#define ASSERT_TRISTATE_UNKNOWN(TRISTATE) \
+  SELFTEST_BEGIN_STMT  \
+  ASSERT_EQ (TRISTATE, tristate (tristate::TS_UNKNOWN));   \
+  SELFTEST_END_STMT
+
+/* Test tristate's ctors, along with is_*, as_string, operator==, and
+   operator!=.  */
+
+static void
+test_ctors ()
+{
+  tristate u (tristate::TS_UNKNOWN);
+  ASSERT_FALSE (u.is_known ());
+  ASSERT_FALSE (u.is_true ());
+  ASSERT_FALSE (u.is_false ());
+  ASSERT_STREQ (u.as_string (), "UNKNOWN");
+
+  tristate t (tristate::TS_TRUE);
+  ASSERT_TRUE (t.is_known ());
+  ASSERT_TRUE (t.is_true ());
+  ASSERT_FALSE (t.is_false ());
+  ASSERT_STREQ (t.as_string (), "TRUE");
+
+  tristate f (tristate::TS_FALSE);
+  ASSERT_TRUE (f.is_known ());
+  ASSERT_FALSE (f.is_true ());
+  ASSERT_TRUE (f.is_false ());
+  ASSERT_STREQ (f.as_string (), "FALSE");
+
+  ASSERT_EQ (u, u);
+  ASSERT_EQ (t, t);
+  ASSERT_EQ (f, f);
+  ASSERT_NE (u, t);
+  ASSERT_NE (u, f);
+  ASSERT_NE (t, f);
+
+  tristate t2 (true);
+  ASSERT_TRUE (t2.is_true ());
+  ASSERT_EQ (t, t2);
+
+  tristate f2 (false);
+  ASSERT_TRUE (f2.is_false ());
+  ASSERT_EQ (f, f2);
+
+  tristate u2 (tristate::unknown ());
+  ASSERT_TRUE (!u2.is_known ());
+  ASSERT_EQ (u, u2);
+}
+
+/* Test && on tristate instances.  */
+
+static void
+test_and ()
+{
+  ASSERT_TRISTATE_UNKNOWN (tristate::unknown () && tristate::unknown ());
+
+  ASSERT_TRISTATE_FALSE (tristate (false) && tristate (false));
+  ASSERT_TRISTATE_FALSE (tristate (false) && tristate (true));
+  ASSERT_TRISTATE_FALSE (tristate (true) && tristate (false));
+  ASSERT_TRISTATE_TRUE (tristate (true) && tristate (true));
+
+  ASSERT_TRISTATE_UNKNOWN (tristate::unknown () && tristate (true));
+  ASSERT_TRISTATE_UNKNOWN (tristate (true) && tristate::unknown ());
+
+  ASSERT_TRISTATE_FALSE (tristate::unknown () && tristate (false));
+  ASSERT_TRISTATE_FALSE (tristate (false) && tristate::unknown ());
+}

[PATCH 22/45] analyzer: new files: supergraph.{cc|h}

2019-12-13 Thread David Malcolm
Changed in v4:
- Rework includes to avoid gcc-plugin.h
- Wrap everything with #if ENABLE_ANALYZER
- Replace auto_client_timevar with TV_ANALYZER_SUPERGRAPH
- Fix .dot output
  https://gcc.gnu.org/ml/gcc-patches/2019-11/msg02461.html
- Update for move of digraph.h

This patch adds a "supergraph" class that combines CFGs and callgraph into
one directed graph, along with "supernode" and "superedge" classes.

gcc/ChangeLog:
* analyzer/supergraph.cc: New file.
* analyzer/supergraph.h: New file.
---
 gcc/analyzer/supergraph.cc | 955 +
 gcc/analyzer/supergraph.h  | 564 ++
 2 files changed, 1519 insertions(+)
 create mode 100644 gcc/analyzer/supergraph.cc
 create mode 100644 gcc/analyzer/supergraph.h

diff --git a/gcc/analyzer/supergraph.cc b/gcc/analyzer/supergraph.cc
new file mode 100644
index ..59c9264d5a08
--- /dev/null
+++ b/gcc/analyzer/supergraph.cc
@@ -0,0 +1,955 @@
+/* "Supergraph" classes that combine CFGs and callgraph into one digraph.
+   Copyright (C) 2019 Free Software Foundation, Inc.
+   Contributed by David Malcolm .
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tree.h"
+#include "tm.h"
+#include "toplev.h"
+#include "hash-table.h"
+#include "vec.h"
+#include "ggc.h"
+#include "basic-block.h"
+#include "function.h"
+#include "gimple-fold.h"
+#include "tree-eh.h"
+#include "gimple-expr.h"
+#include "is-a.h"
+#include "timevar.h"
+#include "gimple.h"
+#include "gimple-iterator.h"
+#include "gimple-pretty-print.h"
+#include "tree-pretty-print.h"
+#include "graphviz.h"
+#include "cgraph.h"
+#include "tree-dfa.h"
+#include "cfganal.h"
+#include "analyzer/analyzer.h"
+#include "analyzer/supergraph.h"
+#include "analyzer/analyzer-logging.h"
+
+#if ENABLE_ANALYZER
+
+/* Get the cgraph_edge, but only if there's an underlying function body.  */
+
+cgraph_edge *
+supergraph_call_edge (function *fun, gimple *stmt)
+{
+  gcall *call = dyn_cast (stmt);
+  if (!call)
+return NULL;
+  cgraph_edge *edge = cgraph_node::get (fun->decl)->get_edge (stmt);
+  if (!edge)
+return NULL;
+  if (!edge->callee)
+return NULL; /* e.g. for a function pointer.  */
+  if (!edge->callee->get_fun ())
+return NULL;
+  return edge;
+}
+
+/* supergraph's ctor.  Walk the callgraph, building supernodes for each
+   CFG basic block, splitting the basic blocks at callsites.  Join
+   together the supernodes with interprocedural and intraprocedural
+   superedges as appropriate.  */
+
+supergraph::supergraph (logger *logger)
+{
+  auto_timevar tv (TV_ANALYZER_SUPERGRAPH);
+
+  LOG_FUNC (logger);
+
+  /* First pass: make supernodes.  */
+  {
+/* Sort the cgraph_nodes?  */
+cgraph_node *node;
+FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
+{
+  function *fun = node->get_fun ();
+
+  /* Ensure that EDGE_DFS_BACK is correct for every CFG edge in
+the supergraph (by doing it per-function).  */
+  auto_cfun sentinel (fun);
+  mark_dfs_back_edges ();
+
+  const int start_idx = m_nodes.length ();
+
+  basic_block bb;
+  FOR_ALL_BB_FN (bb, fun)
+   {
+ /* The initial supernode for the BB gets the phi nodes (if any).  */
+ supernode *node_for_stmts = add_node (fun, bb, NULL, phi_nodes (bb));
+ m_bb_to_initial_node.put (bb, node_for_stmts);
+ for (gphi_iterator gpi = gsi_start_phis (bb); !gsi_end_p (gpi);
+  gsi_next ())
+   {
+ gimple *stmt = gsi_stmt (gpi);
+ m_stmt_to_node_t.put (stmt, node_for_stmts);
+   }
+
+ /* Append statements from BB to the current supernode, splitting
+them into a new supernode at each call site; such call statements
+appear in both supernodes (representing call and return).  */
+ gimple_stmt_iterator gsi;
+ for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next ())
+   {
+ gimple *stmt = gsi_stmt (gsi);
+ node_for_stmts->m_stmts.safe_push (stmt);
+ m_stmt_to_node_t.put (stmt, node_for_stmts);
+ if (cgraph_edge *edge = supergraph_call_edge (fun, stmt))
+   {
+ m_cgraph_edge_to_caller_prev_node.put(edge, node_for_stmts);
+ node_for_stmts = add_node (fun, bb, as_a  (stmt), 
NULL);
+   

[PATCH 28/45] analyzer: new files: sm.{cc|h}

2019-12-13 Thread David Malcolm
Changed in v4:
- Remove include of gcc-plugin.h, reworking includes accordingly.
- Wrap everything in #if ENABLE_ANALYZER
- Remove /// comment lines
- Add call to make_signal_state_machine:
https://gcc.gnu.org/ml/gcc-patches/2019-12/msg00214.html
- Rework on_leak vfunc:
https://gcc.gnu.org/ml/gcc-patches/2019-11/msg02028.html
- Add DISABLE_COPY_AND_ASSIGN to state_machine
- Add support for global states and custom transitions:
https://gcc.gnu.org/ml/gcc-patches/2019-12/msg00217.html

This patch adds a "state_machine" base class for describing
API checkers in terms of state machine transitions.  Followup
patches use this to add specific API checkers.

gcc/ChangeLog:
* analyzer/sm.cc: New file.
* analyzer/sm.h: New file.
---
 gcc/analyzer/sm.cc | 136 +
 gcc/analyzer/sm.h  | 182 +
 2 files changed, 318 insertions(+)
 create mode 100644 gcc/analyzer/sm.cc
 create mode 100644 gcc/analyzer/sm.h

diff --git a/gcc/analyzer/sm.cc b/gcc/analyzer/sm.cc
new file mode 100644
index ..0723d8d2d8e4
--- /dev/null
+++ b/gcc/analyzer/sm.cc
@@ -0,0 +1,136 @@
+/* Modeling API uses and misuses via state machines.
+   Copyright (C) 2019 Free Software Foundation, Inc.
+   Contributed by David Malcolm .
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tree.h"
+#include "function.h"
+#include "basic-block.h"
+#include "gimple.h"
+#include "options.h"
+#include "analyzer/analyzer.h"
+#include "analyzer/sm.h"
+
+#if ENABLE_ANALYZER
+
+/* If STMT is an assignment to zero, return the LHS.  */
+
+tree
+is_zero_assignment (const gimple *stmt)
+{
+  const gassign *assign_stmt = dyn_cast  (stmt);
+  if (!assign_stmt)
+return NULL_TREE;
+
+  enum tree_code op = gimple_assign_rhs_code (assign_stmt);
+  if (op != INTEGER_CST)
+return NULL_TREE;
+
+  if (!zerop (gimple_assign_rhs1 (assign_stmt)))
+return NULL_TREE;
+
+  return gimple_assign_lhs (assign_stmt);
+}
+
+/* If COND_STMT is a comparison against zero of the form (LHS OP 0),
+   return true and write what's being compared to *OUT_LHS and the kind of
+   the comparison to *OUT_OP.  */
+
+bool
+is_comparison_against_zero (const gcond *cond_stmt,
+   tree *out_lhs, enum tree_code *out_op)
+{
+  enum tree_code op = gimple_cond_code (cond_stmt);
+  tree lhs = gimple_cond_lhs (cond_stmt);
+  tree rhs = gimple_cond_rhs (cond_stmt);
+  if (!zerop (rhs))
+return false;
+  // TODO: make it symmetric?
+
+  switch (op)
+{
+case NE_EXPR:
+case EQ_EXPR:
+  *out_lhs = lhs;
+  *out_op = op;
+  return true;
+
+default:
+  return false;
+}
+}
+
+bool
+any_pointer_p (tree var)
+{
+  if (TREE_CODE (TREE_TYPE (var)) != POINTER_TYPE)
+return false;
+
+  return true;
+}
+
+state_machine::state_t
+state_machine::add_state (const char *name)
+{
+  m_state_names.safe_push (name);
+  return m_state_names.length () - 1;
+}
+
+const char *
+state_machine::get_state_name (state_t s) const
+{
+  return m_state_names[s];
+}
+
+void
+state_machine::validate (state_t s) const
+{
+  gcc_assert (s < m_state_names.length ());
+}
+
+void
+make_checkers (auto_delete_vec  , logger *logger)
+{
+  out.safe_push (make_malloc_state_machine (logger));
+  out.safe_push (make_fileptr_state_machine (logger));
+  out.safe_push (make_taint_state_machine (logger));
+  out.safe_push (make_sensitive_state_machine (logger));
+  out.safe_push (make_signal_state_machine (logger));
+
+  /* We only attempt to run the pattern tests if it might have been manually
+ enabled (for DejaGnu purposes).  */
+  if (flag_analyzer_checker)
+out.safe_push (make_pattern_test_state_machine (logger));
+
+  if (flag_analyzer_checker)
+{
+  unsigned read_index, write_index;
+  state_machine **sm;
+
+  /* TODO: this leaks the machines
+Would be nice to log the things that were removed.  */
+  VEC_ORDERED_REMOVE_IF (out, read_index, write_index, sm,
+0 != strcmp (flag_analyzer_checker,
+ (*sm)->get_name ()));
+}
+}
+
+#endif /* #if ENABLE_ANALYZER */
diff --git a/gcc/analyzer/sm.h b/gcc/analyzer/sm.h
new file mode 100644
index ..56e300f65433
--- /dev/null
+++ b/gcc/analyzer/sm.h
@@ -0,0 +1,182 

[PATCH 20/45] analyzer: new files: graphviz.{cc|h}

2019-12-13 Thread David Malcolm
Changed in v3:
- https://gcc.gnu.org/ml/gcc-patches/2019-11/msg02461.html
- moved from gcc/analyzer to gcc

This patch adds a simple wrapper class to make it easier to
write human-readable .dot files.

gcc/ChangeLog:
* graphviz.cc: New file.
* graphviz.h: New file.
---
 gcc/graphviz.cc | 100 
 gcc/graphviz.h  |  53 +
 2 files changed, 153 insertions(+)
 create mode 100644 gcc/graphviz.cc
 create mode 100644 gcc/graphviz.h

diff --git a/gcc/graphviz.cc b/gcc/graphviz.cc
new file mode 100644
index ..ec5045290eb3
--- /dev/null
+++ b/gcc/graphviz.cc
@@ -0,0 +1,100 @@
+/* Helper code for graphviz output.
+   Copyright (C) 2019 Free Software Foundation, Inc.
+   Contributed by David Malcolm .
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "graphviz.h"
+
+/* graphviz_out's ctor, wrapping PP.  */
+
+graphviz_out::graphviz_out (pretty_printer *pp)
+: m_pp (pp),
+  m_indent (0)
+{
+}
+
+/* Formatted print of FMT.  */
+
+void
+graphviz_out::print (const char *fmt, ...)
+{
+  text_info text;
+  va_list ap;
+
+  va_start (ap, fmt);
+  text.err_no = errno;
+  text.args_ptr = 
+  text.format_spec = fmt;
+  pp_format (m_pp, );
+  pp_output_formatted_text (m_pp);
+  va_end (ap);
+}
+
+/* Formatted print of FMT.  The text is indented by the current
+   indent, and a newline is added.  */
+
+void
+graphviz_out::println (const char *fmt, ...)
+{
+  text_info text;
+  va_list ap;
+
+  write_indent ();
+
+  va_start (ap, fmt);
+  text.err_no = errno;
+  text.args_ptr = 
+  text.format_spec = fmt;
+  pp_format (m_pp, );
+  pp_output_formatted_text (m_pp);
+  va_end (ap);
+
+  pp_newline (m_pp);
+}
+
+/* Print the current indent to the underlying pp.  */
+
+void
+graphviz_out::write_indent ()
+{
+  for (int i = 0; i < m_indent * 2; ++i)
+pp_space (m_pp);
+}
+
+/* Write the start of an HTML-like row via , writing to the stream
+   so that followup text can be escaped.  */
+
+void
+graphviz_out::begin_tr ()
+{
+  pp_string (m_pp, "");
+  pp_write_text_to_stream (m_pp);
+}
+
+/* Write the end of an HTML-like row via , writing to the stream
+   so that followup text can be escaped.  */
+
+void
+graphviz_out::end_tr ()
+{
+  pp_string (m_pp, "");
+  pp_write_text_to_stream (m_pp);
+}
diff --git a/gcc/graphviz.h b/gcc/graphviz.h
new file mode 100644
index ..7ddd4ce36c15
--- /dev/null
+++ b/gcc/graphviz.h
@@ -0,0 +1,53 @@
+/* Helper code for graphviz output.
+   Copyright (C) 2019 Free Software Foundation, Inc.
+   Contributed by David Malcolm .
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+.  */
+
+#ifndef GCC_ANALYZER_GRAPHVIZ_H
+#define GCC_ANALYZER_GRAPHVIZ_H
+
+#include "pretty-print.h" /* for ATTRIBUTE_GCC_PPDIAG.  */
+
+/* A class for writing .dot output to a pretty_printer with
+   indentation to show nesting.  */
+
+class graphviz_out {
+ public:
+  graphviz_out (pretty_printer *pp);
+
+  void print (const char *fmt, ...)
+ATTRIBUTE_GCC_PPDIAG(2,3);
+  void println (const char *fmt, ...)
+ATTRIBUTE_GCC_PPDIAG(2,3);
+
+  void indent () { m_indent++; }
+  void outdent () { m_indent--; }
+
+  void write_indent ();
+
+  void begin_tr ();
+  void end_tr ();
+
+  pretty_printer *get_pp () const { return m_pp; }
+
+ private:
+  pretty_printer *m_pp;
+  int m_indent;
+};
+
+#endif /* GCC_ANALYZER_GRAPHVIZ_H */
-- 
2.21.0



[PATCH 23/45] analyzer: new files: analyzer.{cc|h}

2019-12-13 Thread David Malcolm
Changed in v4:
- Remove include of gcc-plugin.h, reworking includes accordingly.
- Wrap everything in #if ENABLE_ANALYZER
- Remove /// comment lines
- Update is_named_call_p to support function pointers:
https://gcc.gnu.org/ml/gcc-patches/2019-12/msg00178.html

gcc/ChangeLog:
* analyzer/analyzer.cc: New file.
* analyzer/analyzer.h: New file.
---
 gcc/analyzer/analyzer.cc | 150 +++
 gcc/analyzer/analyzer.h  | 124 
 2 files changed, 274 insertions(+)
 create mode 100644 gcc/analyzer/analyzer.cc
 create mode 100644 gcc/analyzer/analyzer.h

diff --git a/gcc/analyzer/analyzer.cc b/gcc/analyzer/analyzer.cc
new file mode 100644
index ..3f073371f936
--- /dev/null
+++ b/gcc/analyzer/analyzer.cc
@@ -0,0 +1,150 @@
+/* Utility functions for the analyzer.
+   Copyright (C) 2019 Free Software Foundation, Inc.
+   Contributed by David Malcolm .
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tree.h"
+#include "function.h"
+#include "basic-block.h"
+#include "gimple.h"
+#include "diagnostic.h"
+#include "intl.h"
+#include "analyzer/analyzer.h"
+
+#if ENABLE_ANALYZER
+
+/* Helper function for checkers.  Is the CALL to the given function name,
+   and with the given number of arguments?
+
+   This doesn't resolve function pointers via the region model;
+   is_named_call_p should be used instead, using a fndecl from
+   get_fndecl_for_call; this function should only be used for special cases
+   where it's not practical to get at the region model, or for special
+   analyzer functions such as __analyzer_dump.  */
+
+bool
+is_special_named_call_p (const gcall *call, const char *funcname,
+unsigned int num_args)
+{
+  gcc_assert (funcname);
+
+  tree fndecl = gimple_call_fndecl (call);
+  if (!fndecl)
+return false;
+
+  return is_named_call_p (fndecl, funcname, call, num_args);
+}
+
+/* Helper function for checkers.  Does FNDECL have the given FUNCNAME?  */
+
+bool
+is_named_call_p (tree fndecl, const char *funcname)
+{
+  gcc_assert (fndecl);
+  gcc_assert (funcname);
+
+  return 0 == strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)), funcname);
+}
+
+/* Helper function for checkers.  Does FNDECL have the given FUNCNAME, and
+   does CALL have the given number of arguments?  */
+
+bool
+is_named_call_p (tree fndecl, const char *funcname,
+const gcall *call, unsigned int num_args)
+{
+  gcc_assert (fndecl);
+  gcc_assert (funcname);
+
+  if (!is_named_call_p (fndecl, funcname))
+return false;
+
+  if (gimple_call_num_args (call) != num_args)
+return false;
+
+  return true;
+}
+
+/* Return true if stmt is a setjmp call.  */
+
+bool
+is_setjmp_call_p (const gimple *stmt)
+{
+  /* TODO: is there a less hacky way to check for "setjmp"?  */
+  if (const gcall *call = dyn_cast  (stmt))
+if (is_special_named_call_p (call, "_setjmp", 1))
+  return true;
+
+  return false;
+}
+
+/* Return true if stmt is a longjmp call.  */
+
+bool
+is_longjmp_call_p (const gcall *call)
+{
+  /* TODO: is there a less hacky way to check for "longjmp"?  */
+  if (is_special_named_call_p (call, "longjmp", 2))
+return true;
+
+  return false;
+}
+
+/* Generate a label_text instance by formatting FMT, using a
+   temporary clone of the global_dc's printer (thus using its
+   formatting callbacks).
+
+   Colorize if the global_dc supports colorization and CAN_COLORIZE is
+   true.  */
+
+label_text
+make_label_text (bool can_colorize, const char *fmt, ...)
+{
+  pretty_printer *pp = global_dc->printer->clone ();
+  pp_clear_output_area (pp);
+
+  if (!can_colorize)
+pp_show_color (pp) = false;
+
+  text_info ti;
+  rich_location rich_loc (line_table, UNKNOWN_LOCATION);
+
+  va_list ap;
+
+  va_start (ap, fmt);
+
+  ti.format_spec = _(fmt);
+  ti.args_ptr = 
+  ti.err_no = 0;
+  ti.x_data = NULL;
+  ti.m_richloc = _loc;
+
+  pp_format (pp, );
+  pp_output_formatted_text (pp);
+
+  va_end (ap);
+
+  label_text result = label_text::take (xstrdup (pp_formatted_text (pp)));
+  delete pp;
+  return result;
+}
+
+#endif /* #if ENABLE_ANALYZER */
diff --git a/gcc/analyzer/analyzer.h b/gcc/analyzer/analyzer.h
new file mode 100644
index ..987e2fe43f4c
--- /dev/null
+++ b/gcc/analyzer/analyzer.h
@@ -0,0 +1,124 @@
+/* Utility 

[PATCH 15/45] analyzer: new files: analyzer-selftests.{cc|h}

2019-12-13 Thread David Malcolm
Changed in v4:
- Remove include of gcc-plugin.h
- call run_analyzer_selftests directly, rather than via plugin
  registration; wrap the analyzer selftests in #if ENABLE_ANALYZER
- fixup for moves of digraph.cc and tristate.cc from gcc/analyzer to gcc

gcc/ChangeLog:
* analyzer/analyzer-selftests.cc: New file.
* analyzer/analyzer-selftests.h: New file.
---
 gcc/analyzer/analyzer-selftests.cc | 60 ++
 gcc/analyzer/analyzer-selftests.h  | 44 ++
 gcc/selftest-run-tests.c   |  6 +++
 gcc/selftest.h |  2 +
 4 files changed, 112 insertions(+)
 create mode 100644 gcc/analyzer/analyzer-selftests.cc
 create mode 100644 gcc/analyzer/analyzer-selftests.h

diff --git a/gcc/analyzer/analyzer-selftests.cc 
b/gcc/analyzer/analyzer-selftests.cc
new file mode 100644
index ..3a1f5ada3776
--- /dev/null
+++ b/gcc/analyzer/analyzer-selftests.cc
@@ -0,0 +1,60 @@
+/* Selftest support for the analyzer.
+   Copyright (C) 2019 Free Software Foundation, Inc.
+   Contributed by David Malcolm .
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tree.h"
+#include "stringpool.h"
+#include "analyzer/analyzer.h"
+#include "analyzer/analyzer-selftests.h"
+
+#if CHECKING_P
+
+namespace selftest {
+
+/* Build a VAR_DECL named NAME of type TYPE, simulating a file-level
+   static variable.  */
+
+tree
+build_global_decl (const char *name, tree type)
+{
+  tree decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
+ get_identifier (name), type);
+  TREE_STATIC (decl) = 1;
+  return decl;
+}
+
+/* Run all analyzer-specific selftests.  */
+
+void
+run_analyzer_selftests ()
+{
+#if ENABLE_ANALYZER
+  analyzer_constraint_manager_cc_tests ();
+  analyzer_program_point_cc_tests ();
+  analyzer_program_state_cc_tests ();
+  analyzer_region_model_cc_tests ();
+#endif /* #if ENABLE_ANALYZER */
+}
+
+} /* end of namespace selftest.  */
+
+#endif /* #if CHECKING_P */
diff --git a/gcc/analyzer/analyzer-selftests.h 
b/gcc/analyzer/analyzer-selftests.h
new file mode 100644
index ..513df3702385
--- /dev/null
+++ b/gcc/analyzer/analyzer-selftests.h
@@ -0,0 +1,44 @@
+/* Selftests for the analyzer.
+   Copyright (C) 2019 Free Software Foundation, Inc.
+   Contributed by David Malcolm .
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+.  */
+
+#ifndef GCC_ANALYZER_SELFTESTS_H
+#define GCC_ANALYZER_SELFTESTS_H
+
+#if CHECKING_P
+
+namespace selftest {
+
+extern tree build_global_decl (const char *name, tree type);
+
+extern void run_analyzer_selftests ();
+
+/* Declarations for specific families of tests (by source file), in
+   alphabetical order.  */
+extern void analyzer_checker_script_cc_tests ();
+extern void analyzer_constraint_manager_cc_tests ();
+extern void analyzer_program_point_cc_tests ();
+extern void analyzer_program_state_cc_tests ();
+extern void analyzer_region_model_cc_tests ();
+
+} /* end of namespace selftest.  */
+
+#endif /* #if CHECKING_P */
+
+#endif /* GCC_ANALYZER_SELFTESTS_H */
diff --git a/gcc/selftest-run-tests.c b/gcc/selftest-run-tests.c
index 156575a6695c..17452e8a9f3b 100644
--- a/gcc/selftest-run-tests.c
+++ b/gcc/selftest-run-tests.c
@@ -27,6 +27,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "options.h"
 #include "stringpool.h"
 #include "attribs.h"
+#include "analyzer/analyzer-selftests.h"
 
 /* This function needed to be split out from selftest.c as it references
tests from the whole source tree, and so is within
@@ -86,6 +87,8 @@ selftest::run_tests ()
   gimple_c_tests ();
   rtl_tests_c_tests ();
   read_rtl_function_c_tests ();
+  digraph_cc_tests ();
+  tristate_cc_tests ();
 
   /* Higher-level tests, or for components that other 

[PATCH 11/45] Add ordered_hash_map

2019-12-13 Thread David Malcolm
This patch adds an ordered_hash_map template, which is similar to
hash_map, but preserves insertion order.

gcc/ChangeLog:
* Makefile.in (OBJS): Add ordered-hash-map-tests.o.
* ordered-hash-map-tests.cc: New file.
* ordered-hash-map.h: New file.
* selftest-run-tests.c (selftest::run_tests): Call
selftest::ordered_hash_map_tests_cc_tests.
* selftest.h (selftest::ordered_hash_map_tests_cc_tests): New
decl.
---
 gcc/Makefile.in   |   1 +
 gcc/ordered-hash-map-tests.cc | 247 ++
 gcc/ordered-hash-map.h| 184 +
 gcc/selftest-run-tests.c  |   1 +
 gcc/selftest.h|   1 +
 5 files changed, 434 insertions(+)
 create mode 100644 gcc/ordered-hash-map-tests.cc
 create mode 100644 gcc/ordered-hash-map.h

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index c1ca429935d4..77a12d5c7258 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1443,6 +1443,7 @@ OBJS = \
optinfo-emit-json.o \
options-save.o \
opts-global.o \
+   ordered-hash-map-tests.o \
passes.o \
plugin.o \
postreload-gcse.o \
diff --git a/gcc/ordered-hash-map-tests.cc b/gcc/ordered-hash-map-tests.cc
new file mode 100644
index ..266f60c06b63
--- /dev/null
+++ b/gcc/ordered-hash-map-tests.cc
@@ -0,0 +1,247 @@
+/* Unit tests for ordered-hash-map.h.
+   Copyright (C) 2015-2019 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "opts.h"
+#include "hash-set.h"
+#include "fixed-value.h"
+#include "alias.h"
+#include "flags.h"
+#include "symtab.h"
+#include "tree-core.h"
+#include "stor-layout.h"
+#include "tree.h"
+#include "stringpool.h"
+#include "ordered-hash-map.h"
+#include "selftest.h"
+
+#if CHECKING_P
+
+namespace selftest {
+
+/* Populate *OUT_KVS with the key/value pairs of M.  */
+
+template 
+static void
+get_kv_pairs (const HashMap ,
+ auto_vec > *out_kvs)
+{
+  for (typename HashMap::iterator iter = m.begin ();
+   iter != m.end ();
+   ++iter)
+out_kvs->safe_push (std::make_pair ((*iter).first, (*iter).second));
+}
+
+/* Construct an ordered_hash_map  and verify that
+   various operations work correctly.  */
+
+static void
+test_map_of_strings_to_int ()
+{
+  ordered_hash_map  m;
+
+  const char *ostrich = "ostrich";
+  const char *elephant = "elephant";
+  const char *ant = "ant";
+  const char *spider = "spider";
+  const char *millipede = "Illacme plenipes";
+  const char *eric = "half a bee";
+
+  /* A fresh hash_map should be empty.  */
+  ASSERT_EQ (0, m.elements ());
+  ASSERT_EQ (NULL, m.get (ostrich));
+
+  /* Populate the hash_map.  */
+  ASSERT_EQ (false, m.put (ostrich, 2));
+  ASSERT_EQ (false, m.put (elephant, 4));
+  ASSERT_EQ (false, m.put (ant, 6));
+  ASSERT_EQ (false, m.put (spider, 8));
+  ASSERT_EQ (false, m.put (millipede, 750));
+  ASSERT_EQ (false, m.put (eric, 3));
+
+  /* Verify that we can recover the stored values.  */
+  ASSERT_EQ (6, m.elements ());
+  ASSERT_EQ (2, *m.get (ostrich));
+  ASSERT_EQ (4, *m.get (elephant));
+  ASSERT_EQ (6, *m.get (ant));
+  ASSERT_EQ (8, *m.get (spider));
+  ASSERT_EQ (750, *m.get (millipede));
+  ASSERT_EQ (3, *m.get (eric));
+
+  /* Verify that the order of insertion is preserved.  */
+  auto_vec > kvs;
+  get_kv_pairs (m, );
+  ASSERT_EQ (kvs.length (), 6);
+  ASSERT_EQ (kvs[0].first, ostrich);
+  ASSERT_EQ (kvs[0].second, 2);
+  ASSERT_EQ (kvs[1].first, elephant);
+  ASSERT_EQ (kvs[1].second, 4);
+  ASSERT_EQ (kvs[2].first, ant);
+  ASSERT_EQ (kvs[2].second, 6);
+  ASSERT_EQ (kvs[3].first, spider);
+  ASSERT_EQ (kvs[3].second, 8);
+  ASSERT_EQ (kvs[4].first, millipede);
+  ASSERT_EQ (kvs[4].second, 750);
+  ASSERT_EQ (kvs[5].first, eric);
+  ASSERT_EQ (kvs[5].second, 3);
+}
+
+/* Construct an ordered_hash_map using int_hash and verify that various
+   operations work correctly.  */
+
+static void
+test_map_of_int_to_strings ()
+{
+  const int EMPTY = -1;
+  const int DELETED = -2;
+  typedef int_hash  int_hash_t;
+  ordered_hash_map  m;
+
+  const char *ostrich = "ostrich";
+  const char *elephant = "elephant";
+  const char *ant = "ant";
+  const char *spider = "spider";
+  const char *millipede = "Illacme plenipes";
+  const char *eric = "half a 

[PATCH 18/45] analyzer: logging support

2019-12-13 Thread David Malcolm
Changed in v4:
- wrap with #if ENABLE_ANALYZER
- add DISABLE_COPY_AND_ASSIGN

This patch adds a logging framework to the analyzer which handles
hierarchical messages (showing the nested structure of the calls).

This code is largely based on that in the "jit" subdirectory (with
a few changes).  An alternative would be to generalize that code
and move it to the gcc parent directory.

gcc/ChangeLog:
* analyzer/analyzer-logging.cc: New file.
* analyzer/analyzer-logging.h: New file.
---
 gcc/analyzer/analyzer-logging.cc | 224 ++
 gcc/analyzer/analyzer-logging.h  | 262 +++
 2 files changed, 486 insertions(+)
 create mode 100644 gcc/analyzer/analyzer-logging.cc
 create mode 100644 gcc/analyzer/analyzer-logging.h

diff --git a/gcc/analyzer/analyzer-logging.cc b/gcc/analyzer/analyzer-logging.cc
new file mode 100644
index ..2010cb78a176
--- /dev/null
+++ b/gcc/analyzer/analyzer-logging.cc
@@ -0,0 +1,224 @@
+/* Hierarchical log messages for the analyzer.
+   Copyright (C) 2014-2019 Free Software Foundation, Inc.
+   Contributed by David Malcolm .
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "toplev.h" /* for print_version */
+#include "pretty-print.h" /* for print_version */
+#include "diagnostic.h"
+#include "tree-diagnostic.h"
+
+#include "analyzer/analyzer-logging.h"
+
+#if ENABLE_ANALYZER
+
+/* Implementation of class logger.  */
+
+/* ctor for logger.  */
+
+logger::logger (FILE *f_out,
+   int, /* flags */
+   int /* verbosity */,
+   const pretty_printer _pp) :
+  m_refcount (0),
+  m_f_out (f_out),
+  m_indent_level (0),
+  m_log_refcount_changes (false),
+  m_pp (reference_pp.clone ())
+{
+  pp_show_color (m_pp) = 0;
+  pp_buffer (m_pp)->stream = f_out;
+
+  /* %qE in logs for SSA_NAMEs should show the ssa names, rather than
+ trying to prettify things by showing the underlying var.  */
+  pp_format_decoder (m_pp) = default_tree_printer;
+
+  /* Begin the log by writing the GCC version.  */
+  print_version (f_out, "", false);
+}
+
+/* The destructor for logger, invoked via
+   the decref method when the refcount hits zero.
+   Note that we do not close the underlying FILE * (m_f_out).  */
+
+logger::~logger ()
+{
+  /* This should be the last message emitted.  */
+  log ("%s", __PRETTY_FUNCTION__);
+  gcc_assert (m_refcount == 0);
+  delete m_pp;
+}
+
+/* Increment the reference count of the logger.  */
+
+void
+logger::incref (const char *reason)
+{
+  m_refcount++;
+  if (m_log_refcount_changes)
+log ("%s: reason: %s refcount now %i ",
+__PRETTY_FUNCTION__, reason, m_refcount);
+}
+
+/* Decrement the reference count of the logger,
+   deleting it if nothing is referring to it.  */
+
+void
+logger::decref (const char *reason)
+{
+  gcc_assert (m_refcount > 0);
+  --m_refcount;
+  if (m_log_refcount_changes)
+log ("%s: reason: %s refcount now %i",
+__PRETTY_FUNCTION__, reason, m_refcount);
+  if (m_refcount == 0)
+delete this;
+}
+
+/* Write a formatted message to the log, by calling the log_va method.  */
+
+void
+logger::log (const char *fmt, ...)
+{
+  va_list ap;
+  va_start (ap, fmt);
+  log_va (fmt, );
+  va_end (ap);
+}
+
+/* Write an indented line to the log file.
+
+   We explicitly flush after each line: if something crashes the process,
+   we want the logfile/stream to contain the most up-to-date hint about the
+   last thing that was happening, without it being hidden in an in-process
+   buffer.  */
+
+void
+logger::log_va (const char *fmt, va_list *ap)
+{
+  start_log_line ();
+  log_va_partial (fmt, ap);
+  end_log_line ();
+}
+
+void
+logger::start_log_line ()
+{
+  for (int i = 0; i < m_indent_level; i++)
+fputc (' ', m_f_out);
+}
+
+void
+logger::log_partial (const char *fmt, ...)
+{
+  va_list ap;
+  va_start (ap, fmt);
+  log_va_partial (fmt, );
+  va_end (ap);
+}
+
+void
+logger::log_va_partial (const char *fmt, va_list *ap)
+{
+  text_info text;
+  text.format_spec = fmt;
+  text.args_ptr = ap;
+  text.err_no = 0;
+  pp_format (m_pp, );
+  pp_output_formatted_text (m_pp);
+}
+
+void
+logger::end_log_line ()
+{
+  pp_flush (m_pp);
+  pp_clear_output_area (m_pp);
+  fprintf (m_f_out, "\n");
+  fflush (m_f_out);
+}
+
+/* Record the entry within a particular scope, indenting 

[PATCH 17/45] analyzer: command-line options

2019-12-13 Thread David Malcolm
Changed in v4:
- Renamed gcc/analyzer/plugin.opt to gcc/analyzer/analyzer.opt

- Change option from -analyzer to -fanalyzer, changed it from
  Driver to Common.

- Various commits on 2019-11-12 including r278083 through r278087
  reimplemented parameter-handling in terms of options, so that
  params are defined in params.opt rather than params.def.

  This patch adds the params for the analyzer to analyzer.opt,
  replacing the patch:
[PATCH 22/49] analyzer: params.def: new parameters
  https://gcc.gnu.org/ml/gcc-patches/2019-11/msg01520.html
  from the original version of the patch kit.

- Added -Wanalyzer-unsafe-call-within-signal-handler from
https://gcc.gnu.org/ml/gcc-patches/2019-12/msg00214.html

This patch contains the command-line options for the analyzer.

gcc/ChangeLog:
* analyzer/analyzer.opt: New file.
* common.opt (-fanalyzer): New driver option.
---
 gcc/analyzer/analyzer.opt | 181 ++
 gcc/common.opt|   4 +
 2 files changed, 185 insertions(+)
 create mode 100644 gcc/analyzer/analyzer.opt

diff --git a/gcc/analyzer/analyzer.opt b/gcc/analyzer/analyzer.opt
new file mode 100644
index ..d722667dea09
--- /dev/null
+++ b/gcc/analyzer/analyzer.opt
@@ -0,0 +1,181 @@
+; plugin.opt -- Options for the analyzer.
+
+; Copyright (C) 2019 Free Software Foundation, Inc.
+;
+; This file is part of GCC.
+;
+; GCC is free software; you can redistribute it and/or modify it under
+; the terms of the GNU General Public License as published by the Free
+; Software Foundation; either version 3, or (at your option) any later
+; version.
+; 
+; GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+; WARRANTY; without even the implied warranty of MERCHANTABILITY or
+; FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+; for more details.
+; 
+; You should have received a copy of the GNU General Public License
+; along with GCC; see the file COPYING3.  If not see
+; .
+
+; See the GCC internals manual for a description of this file's format.
+
+; Please try to keep this file in ASCII collating order.
+
+-param=analyzer-bb-explosion-factor=
+Common Joined UInteger Var(param_analyzer_bb_explosion_factor) Init(5) Param
+The maximum number of 'after supernode' exploded nodes within the analyzer per 
supernode, before terminating analysis.
+
+-param=analyzer-max-enodes-per-program-point=
+Common Joined UInteger Var(param_analyzer_max_enodes_per_program_point) 
Init(8) Param
+The maximum number of exploded nodes per program point within the analyzer, 
before terminating analysis of that point.
+
+-param=analyzer-max-recursion-depth=
+Common Joined UInteger Var(param_analyzer_max_recursion_depth) Init(2) Param
+The maximum number of times a callsite can appear in a call stack within the 
analyzer, before terminating analysis of a call tha would recurse deeper.
+
+-param=analyzer-min-snodes-for-call-summary=
+Common Joined UInteger Var(param_analyzer_min_snodes_for_call_summary) 
Init(10) Param
+The minimum number of supernodes within a function for the analyzer to 
consider summarizing its effects at call sites.
+
+Wanalyzer-double-fclose
+Common Var(warn_analyzer_double_fclose) Init(1) Warning
+Warn about code paths in which a stdio FILE can be closed more than once.
+
+Wanalyzer-double-free
+Common Var(warn_analyzer_double_free) Init(1) Warning
+Warn about code paths in which a pointer can be freed more than once.
+
+Wanalyzer-exposure-through-output-file
+Common Var(warn_analyzer_exposure_through_output_file) Init(1) Warning
+Warn about code paths in which sensitive data is written to a file.
+
+Wanalyzer-file-leak
+Common Var(warn_analyzer_file_leak) Init(1) Warning
+Warn about code paths in which a stdio FILE is not closed.
+
+Wanalyzer-free-of-non-heap
+Common Var(warn_analyzer_free_of_non_heap) Init(1) Warning
+Warn about code paths in which a non-heap pointer is freed.
+
+Wanalyzer-malloc-leak
+Common Var(warn_analyzer_malloc_leak) Init(1) Warning
+Warn about code paths in which a heap-allocated pointer leaks.
+
+Wanalyzer-possible-null-argument
+Common Var(warn_analyzer_possible_null_argument) Init(1) Warning
+Warn about code paths in which a possibly-NULL value is passed to a 
must-not-be-NULL function argument.
+
+Wanalyzer-possible-null-dereference
+Common Var(warn_analyzer_possible_null_dereference) Init(1) Warning
+Warn about code paths in which a possibly-NULL pointer is dereferenced.
+
+Wanalyzer-unsafe-call-within-signal-handler
+Common Var(warn_analyzer_unsafe_call_within_signal_handler) Init(1) Warning
+Warn about code paths in which an async-signal-unsafe function is called from 
a signal handler.
+
+Wanalyzer-null-argument
+Common Var(warn_analyzer_null_argument) Init(1) Warning
+Warn about code paths in which NULL is passed to a must-not-be-NULL function 
argument.
+
+Wanalyzer-null-dereference
+Common Var(warn_analyzer_null_dereference) Init(1) 

[PATCH 19/45] analyzer: new file: analyzer-pass.cc and pass registration

2019-12-13 Thread David Malcolm
Changed in v4:
- Remove include of gcc-plugin.h, reworking includes accordingly.
- Use TV_ANALYZER rather than TV_NONE for the pass
- Add a gate function to the pass
- Move the check for #if ENABLE_ANALYZER from the driver to the
  pass's execute vfunc
- Expose the pass via make_pass_analyzer, rather than via the plugin
  pass registration mechanism

Changed in v3:
- added to passes.def and tree-pass.h

gcc/ChangeLog:
* analyzer/analyzer-pass.cc: New file.
* passes.def (pass_analyzer): Add before
pass_ipa_whole_program_visibility.
* tree-pass.h (make_pass_analyzer): New decl.
---
 gcc/analyzer/analyzer-pass.cc | 102 ++
 gcc/passes.def|   1 +
 gcc/tree-pass.h   |   1 +
 3 files changed, 104 insertions(+)
 create mode 100644 gcc/analyzer/analyzer-pass.cc

diff --git a/gcc/analyzer/analyzer-pass.cc b/gcc/analyzer/analyzer-pass.cc
new file mode 100644
index ..60535a944dc9
--- /dev/null
+++ b/gcc/analyzer/analyzer-pass.cc
@@ -0,0 +1,102 @@
+/* Integration of the analyzer with GCC's pass manager.
+   Copyright (C) 2019 Free Software Foundation, Inc.
+   Contributed by David Malcolm .
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "context.h"
+#include "tree-pass.h"
+#include "diagnostic.h"
+#include "options.h"
+#include "analyzer/engine.h"
+
+namespace {
+
+/* Data for the analyzer pass.  */
+
+const pass_data pass_data_analyzer =
+{
+  IPA_PASS, /* type */
+  "analyzer", /* name */
+  OPTGROUP_NONE, /* optinfo_flags */
+  TV_ANALYZER, /* tv_id */
+  PROP_ssa, /* properties_required */
+  0, /* properties_provided */
+  0, /* properties_destroyed */
+  0, /* todo_flags_start */
+  0, /* todo_flags_finish */
+};
+
+/* The analyzer pass.  */
+
+class pass_analyzer : public ipa_opt_pass_d
+{
+public:
+   pass_analyzer(gcc::context *ctxt)
+   : ipa_opt_pass_d (pass_data_analyzer, ctxt,
+NULL, /* generate_summary */
+NULL, /* write_summary */
+NULL, /* read_summary */
+NULL, /* write_optimization_summary */
+NULL, /* read_optimization_summary */
+NULL, /* stmt_fixup */
+0, /* function_transform_todo_flags_start */
+NULL, /* function_transform */
+NULL) /* variable_transform */
+  {}
+
+  /* opt_pass methods: */
+  bool gate (function *) FINAL OVERRIDE;
+  unsigned int execute (function *) FINAL OVERRIDE;
+}; // class pass_analyzer
+
+/* Only run the analyzer if -fanalyzer.  */
+
+bool
+pass_analyzer::gate (function *)
+{
+  return flag_analyzer != 0;
+}
+
+/* Entrypoint for the analyzer pass.  */
+
+unsigned int
+pass_analyzer::execute (function *)
+{
+#if ENABLE_ANALYZER
+  run_checkers ();
+#else
+  sorry ("%qs was not enabled in this build of GCC"
+" (missing configure-time option %qs)",
+"-fanalyzer", "--enable-analyzer");
+#endif
+
+  return 0;
+}
+
+} // anon namespace
+
+/* Make an instance of the analyzer pass.  */
+
+ipa_opt_pass_d *
+make_pass_analyzer (gcc::context *ctxt)
+{
+  return new pass_analyzer (ctxt);
+}
diff --git a/gcc/passes.def b/gcc/passes.def
index 798a391bd351..0ee8b621016c 100644
--- a/gcc/passes.def
+++ b/gcc/passes.def
@@ -142,6 +142,7 @@ along with GCC; see the file COPYING3.  If not see
   TERMINATE_PASS_LIST (all_small_ipa_passes)
 
   INSERT_PASSES_AFTER (all_regular_ipa_passes)
+  NEXT_PASS (pass_analyzer);
   NEXT_PASS (pass_ipa_whole_program_visibility);
   NEXT_PASS (pass_ipa_profile);
   NEXT_PASS (pass_ipa_icf);
diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h
index a987661530ea..59a5fa6ad4a5 100644
--- a/gcc/tree-pass.h
+++ b/gcc/tree-pass.h
@@ -490,6 +490,7 @@ extern simple_ipa_opt_pass *make_pass_build_ssa_passes 
(gcc::context *ctxt);
 extern simple_ipa_opt_pass *make_pass_local_optimization_passes (gcc::context 
*ctxt);
 extern simple_ipa_opt_pass *make_pass_ipa_remove_symbols (gcc::context *ctxt);
 
+extern ipa_opt_pass_d *make_pass_analyzer (gcc::context *ctxt);
 extern ipa_opt_pass_d *make_pass_ipa_whole_program_visibility (gcc::context
   *ctxt);
 extern simple_ipa_opt_pass *make_pass_ipa_increase_alignment (gcc::context
-- 
2.21.0



[PATCH 00/45] v4 of analyzer patch kit

2019-12-13 Thread David Malcolm
Here's an updated version of the patch kit, addressing many issues from
review, and squashing in other changes.

This is v4, and is relative to r279310 (2019-12-12)
Earlier versions:
v3: https://gcc.gnu.org/ml/gcc-patches/2019-12/msg00529.html
v2: https://gcc.gnu.org/ml/gcc-patches/2019-11/msg02024.html
v1: https://gcc.gnu.org/ml/gcc-patches/2019-11/msg01543.html

See also: https://gcc.gnu.org/wiki/DavidMalcolm/StaticAnalyzer


High-level changes (relative to v1):
- dropped the in-tree plugin idea; the analyzer is now part of the
  compiler
- added a configure-time way to disable the build of the compiler.
  It is built by default (but off by default at compile-time);
  all of the analyzer-specific code is guarded by
  #if ENABLE_ANALYZER
- moved some files from "gcc/analyzer" to "gcc" (digraph.cc.h,
  graphviz.cc/h, shortest-paths.h, and tristate.cc/h).
  I've kept the "gcc/analyzer" subdirectory.  I assume that it's sane
  to have a gcc/analyzer subdirectory, and that it ought to have its
  own ChangeLog file (it doesn't yet).
- renamed the option from --analyzer to -fanalyzer; -fno-analyzer is
  now supported (and the last one wins)
- fixed the LTO crasher, so basic cross-TU analysis via "-flto -fanalyzer"
  works
- added a new sm-signal.cc for detecting fprintf calls in signal
  handlers, along with various cleanups and generalizations this needed
  (which will be helpful long-term for e.g. C++ exception support)
- I've already committed some of v1's approved preliminary patches to
  trunk


Other changes:
- the various fixups needed due to rebasing (changes to param-handling,
  json API)
- rewrote .dot output to avoid shape=record, as it's poorly supported
  in more recent versions of GraphViz
- fixed missing leak diagnostic on longjmp past a free, and show the
  rewind destination for this case
- fixed issues in diagnostic_manager::prune_path
- added an sm-malloc.dot to visualize the state machine
- added more internal validation
- better support for resolving function pointers
- added DISABLE_COPY_AND_ASSIGN in various places
- split diagnostic_manager::prune_path into subroutines as per review
- special-case strcmp calls when describing edge events (I found this
  helpful for debugging the reproducer for detecting CVE-2005-1689)
- added a test for .dot output to the testsuite, with directives such as:
 /* { dg-require-dot "" } */
  and
 /* { dg-final { dg-check-dot "dot-output.c.callgraph.dot" } } */
- dropped all those  comment lines


Not yet changed:
- this currently needs the fix to hash_table::empty_slow from:
https://gcc.gnu.org/ml/gcc-patches/2019-12/msg00776.html
  which I still need to gather info about
- I've experimented with eliminating make_label_text, and have something
  that works, but the patch currently has a lot warnings, so am deferring
  for now
- struct vs class in exploded-graph.h
- probably other things


Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Pushed to the git mirror as branch "dmalcolm/analyzer-v4":
  
https://gcc.gnu.org/git/?p=gcc.git;a=shortlog;h=refs/heads/dmalcolm/analyzer-v4


Dave

David Malcolm (45):
  gimple const-correctness fixes
  hash-map-tests.c: add a selftest involving int_hash
  analyzer: user-facing documentation
  analyzer: internal documentation
  Add pp_write_text_as_html_like_dot_to_stream
  sbitmap.h: add operator const sbitmap & to auto_sbitmap
  vec.h: add auto_delete_vec
  Add -fdiagnostics-nn-line-numbers
  Add diagnostic_metadata and CWE support
  Add diagnostic paths
  Add ordered_hash_map
  timevar.def: add TVs for analyzer
  analyzer: changes to configure.ac
  analyzer: add new files to Makefile.in
  analyzer: new files: analyzer-selftests.{cc|h}
  analyzer: new builtins
  analyzer: command-line options
  analyzer: logging support
  analyzer: new file: analyzer-pass.cc and pass registration
  analyzer: new files: graphviz.{cc|h}
  analyzer: new files: digraph.{cc|h} and shortest-paths.h
  analyzer: new files: supergraph.{cc|h}
  analyzer: new files: analyzer.{cc|h}
  analyzer: new files: tristate.{cc|h}
  analyzer: new files: constraint-manager.{cc|h}
  analyzer: new files: region-model.{cc|h}
  analyzer: new files: pending-diagnostic.{cc|h}
  analyzer: new files: sm.{cc|h}
  analyzer: new files: sm-malloc.cc and sm-malloc.dot
  analyzer: new file: sm-file.cc
  analyzer: new file: sm-pattern-test.cc
  analyzer: new file: sm-sensitive.cc
  analyzer: new file: sm-signal.cc
  analyzer: new file: sm-taint.cc
  analyzer: new files: analysis-plan.{cc|h}
  analyzer: new files: call-string.{cc|h}
  analyzer: new files: program-point.{cc|h}
  analyzer: new files: program-state.{cc|h}
  analyzer: new file: exploded-graph.h
  analyzer: new files: state-purge.{cc|h}
  analyzer: new files: engine.{cc|h}
  analyzer: new files: checker-path.{cc|h}
  analyzer: new files: diagnostic-manager.{cc|h}
  gdbinit.in: add break-on-saved-diagnostic
  analyzer: test suite

 gcc/Makefile.in   |   36 

[PATCH 16/45] analyzer: new builtins

2019-12-13 Thread David Malcolm
gcc/ChangeLog:
* builtins.def (BUILT_IN_ANALYZER_BREAK): New builtin.
(BUILT_IN_ANALYZER_DUMP): New builtin.
(BUILT_IN_ANALYZER_DUMP_EXPLODED_NODES): New builtin.
(BUILT_IN_ANALYZER_DUMP_NUM_HEAP_REGIONS): New builtin.
(BUILT_IN_ANALYZER_DUMP_PATH): New builtin.
(BUILT_IN_ANALYZER_DUMP_REGION_MODEL): New builtin.
(BUILT_IN_ANALYZER_EVAL): New builtin.
---
 gcc/builtins.def | 33 +
 1 file changed, 33 insertions(+)

diff --git a/gcc/builtins.def b/gcc/builtins.def
index d8233f5f760f..f34e95fe4bb0 100644
--- a/gcc/builtins.def
+++ b/gcc/builtins.def
@@ -1107,4 +1107,37 @@ DEF_GCC_BUILTIN (BUILT_IN_LINE, "LINE", BT_FN_INT, 
ATTR_NOTHROW_LEAF_LIST)
 /* HSAIL/BRIG frontend builtins.  */
 #include "brig-builtins.def"
 
+
+/* Analyzer builtins.  */
+DEF_BUILTIN (BUILT_IN_ANALYZER_BREAK, "__analyzer_break",
+BUILT_IN_NORMAL, BT_FN_VOID, BT_LAST,
+false, false, false, ATTR_NULL, true, true)
+
+DEF_BUILTIN (BUILT_IN_ANALYZER_DUMP, "__analyzer_dump",
+BUILT_IN_NORMAL, BT_FN_VOID, BT_LAST,
+false, false, false, ATTR_NULL, true, true)
+
+DEF_BUILTIN (BUILT_IN_ANALYZER_DUMP_EXPLODED_NODES,
+"__analyzer_dump_exploded_nodes",
+BUILT_IN_NORMAL, BT_FN_VOID_INT, BT_LAST,
+false, false, false, ATTR_NULL, true, true)
+
+DEF_BUILTIN (BUILT_IN_ANALYZER_DUMP_NUM_HEAP_REGIONS,
+"__analyzer_dump_num_heap_regions",
+BUILT_IN_NORMAL, BT_FN_VOID, BT_LAST,
+false, false, false, ATTR_NULL, true, true)
+
+DEF_BUILTIN (BUILT_IN_ANALYZER_DUMP_PATH, "__analyzer_dump_path",
+BUILT_IN_NORMAL, BT_FN_VOID, BT_LAST,
+false, false, false, ATTR_NULL, true, true)
+
+DEF_BUILTIN (BUILT_IN_ANALYZER_DUMP_REGION_MODEL,
+"__analyzer_dump_region_model",
+BUILT_IN_NORMAL, BT_FN_VOID, BT_LAST,
+false, false, false, ATTR_NULL, true, true)
+
+DEF_BUILTIN (BUILT_IN_ANALYZER_EVAL, "__analyzer_eval",
+BUILT_IN_NORMAL, BT_FN_VOID_INT, BT_LAST,
+false, false, false, ATTR_NULL, true, true)
+
 #undef DEF_BUILTIN
-- 
2.21.0



[PATCH 14/45] analyzer: add new files to Makefile.in

2019-12-13 Thread David Malcolm
gcc/ChangeLog:
* Makefile.in (lang_opt_files): Add analyzer.opt.
(ANALYZER_OBJS): New.
(OBJS): Add digraph.o, graphviz.o, tristate.o and ANALYZER_OBJS.
---
 gcc/Makefile.in | 32 +++-
 1 file changed, 31 insertions(+), 1 deletion(-)

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 77a12d5c7258..e7a8cf1aa90e 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -567,7 +567,7 @@ xm_include_list=@xm_include_list@
 xm_defines=@xm_defines@
 lang_checks=
 lang_checks_parallelized=
-lang_opt_files=@lang_opt_files@ $(srcdir)/c-family/c.opt $(srcdir)/common.opt 
$(srcdir)/params.opt
+lang_opt_files=@lang_opt_files@ $(srcdir)/c-family/c.opt $(srcdir)/common.opt 
$(srcdir)/params.opt $(srcdir)/analyzer/analyzer.opt
 lang_specs_files=@lang_specs_files@
 lang_tree_files=@lang_tree_files@
 target_cpu_default=@target_cpu_default@
@@ -1214,6 +1214,32 @@ C_COMMON_OBJS = c-family/c-common.o 
c-family/c-cppbuiltin.o c-family/c-dump.o \
   c-family/c-ubsan.o c-family/known-headers.o \
   c-family/c-attribs.o c-family/c-warn.o c-family/c-spellcheck.o
 
+# Analyzer object files
+ANALYZER_OBJS = \
+   analyzer/analysis-plan.o \
+   analyzer/analyzer.o \
+   analyzer/analyzer-logging.o \
+   analyzer/analyzer-pass.o \
+   analyzer/analyzer-selftests.o \
+   analyzer/call-string.o \
+   analyzer/checker-path.o \
+   analyzer/constraint-manager.o \
+   analyzer/diagnostic-manager.o \
+   analyzer/engine.o \
+   analyzer/pending-diagnostic.o \
+   analyzer/program-point.o \
+   analyzer/program-state.o \
+   analyzer/region-model.o \
+   analyzer/sm.o \
+   analyzer/sm-file.o \
+   analyzer/sm-malloc.o \
+   analyzer/sm-pattern-test.o \
+   analyzer/sm-sensitive.o \
+   analyzer/sm-signal.o \
+   analyzer/sm-taint.o \
+   analyzer/state-purge.o \
+   analyzer/supergraph.o
+
 # Language-independent object files.
 # We put the *-match.o and insn-*.o files first so that a parallel make
 # will build them sooner, because they are large and otherwise tend to be
@@ -1283,6 +1309,7 @@ OBJS = \
df-problems.o \
df-scan.o \
dfp.o \
+   digraph.o \
dojump.o \
dominance.o \
domwalk.o \
@@ -1344,6 +1371,7 @@ OBJS = \
godump.o \
graph.o \
graphds.o \
+   graphviz.o \
graphite.o \
graphite-isl-ast-to-gimple.o \
graphite-dependences.o \
@@ -1601,6 +1629,7 @@ OBJS = \
tree-vector-builder.o \
tree-vrp.o \
tree.o \
+   tristate.o \
typed-splay-tree.o \
unique-ptr-tests.o \
valtrack.o \
@@ -1618,6 +1647,7 @@ OBJS = \
wide-int-print.o \
xcoffout.o \
$(out_object_file) \
+   $(ANALYZER_OBJS) \
$(EXTRA_OBJS) \
$(host_hook_obj)
 
-- 
2.21.0



[PATCH 13/45] analyzer: changes to configure.ac

2019-12-13 Thread David Malcolm
This patch adds a configuration option to disable building the analyzer.
It is built by default (but off by default at compile-time).

gcc/ChangeLog:
* configure.ac (--disable-analyzer, ENABLE_ANALYZER): New option.
(gccdepdir): Also create depdir for "analyzer" subdir.
---
 gcc/configure.ac | 14 +-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/gcc/configure.ac b/gcc/configure.ac
index 954c1496fb1c..dcd5e8dd38cc 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -909,6 +909,18 @@ vtable_verify=`if test x$enable_vtable_verify = xyes; then 
echo 1; else echo 0;
 AC_DEFINE_UNQUOTED(ENABLE_VTABLE_VERIFY, $vtable_verify,
 [Define 0/1 if vtable verification feature is enabled.])
 
+AC_ARG_ENABLE(analyzer,
+[AS_HELP_STRING([--disable-analyzer],
+   [disable -fanalyzer static analyzer])],
+if test x$enable_analyzer = xno; then
+   analyzer=0
+else
+   analyzer=1
+fi,
+analyzer=1)
+AC_DEFINE_UNQUOTED(ENABLE_ANALYZER, $analyzer,
+[Define 0/1 if static analyzer feature is enabled.])
+
 AC_ARG_ENABLE(objc-gc,
 [AS_HELP_STRING([--enable-objc-gc],
[enable the use of Boehm's garbage collector with
@@ -1214,7 +1226,7 @@ AC_CHECK_HEADERS(ext/hash_map)
 ZW_CREATE_DEPDIR
 AC_CONFIG_COMMANDS([gccdepdir],[
   ${CONFIG_SHELL-/bin/sh} $ac_aux_dir/mkinstalldirs build/$DEPDIR
-  for lang in $subdirs c-family common
+  for lang in $subdirs c-family common analyzer
   do
   ${CONFIG_SHELL-/bin/sh} $ac_aux_dir/mkinstalldirs $lang/$DEPDIR
   done], [subdirs="$subdirs" ac_aux_dir=$ac_aux_dir DEPDIR=$DEPDIR])
-- 
2.21.0



[PATCH 04/45] analyzer: internal documentation

2019-12-13 Thread David Malcolm
Changed in v4:
  https://gcc.gnu.org/ml/gcc-patches/2019-11/msg02026.html

gcc/ChangeLog:
* Makefile.in (TEXI_GCCINT_FILES): Add analyzer.texi.
* doc/analyzer.texi: New file.
* doc/gccint.texi ("Static Analyzer") New menu item.
(analyzer.texi): Include it.
---
 gcc/Makefile.in   |   2 +-
 gcc/doc/analyzer.texi | 496 ++
 gcc/doc/gccint.texi   |   2 +
 3 files changed, 499 insertions(+), 1 deletion(-)
 create mode 100644 gcc/doc/analyzer.texi

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 6b857bd75deb..860c5809e16e 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -3217,7 +3217,7 @@ TEXI_GCCINT_FILES = gccint.texi gcc-common.texi 
gcc-vers.texi \
 gnu.texi gpl_v3.texi fdl.texi contrib.texi languages.texi  \
 sourcebuild.texi gty.texi libgcc.texi cfg.texi tree-ssa.texi   \
 loop.texi generic.texi gimple.texi plugins.texi optinfo.texi   \
-match-and-simplify.texi ux.texi poly-int.texi
+match-and-simplify.texi analyzer.texi ux.texi poly-int.texi
 
 TEXI_GCCINSTALL_FILES = install.texi install-old.texi fdl.texi \
 gcc-common.texi gcc-vers.texi
diff --git a/gcc/doc/analyzer.texi b/gcc/doc/analyzer.texi
new file mode 100644
index ..3f5999f14dd0
--- /dev/null
+++ b/gcc/doc/analyzer.texi
@@ -0,0 +1,496 @@
+@c Copyright (C) 2019 Free Software Foundation, Inc.
+@c This is part of the GCC manual.
+@c For copying conditions, see the file gcc.texi.
+@c Contributed by David Malcolm .
+
+@node Static Analyzer
+@chapter Static Analyzer
+@cindex analyzer
+@cindex static analysis
+@cindex static analyzer
+
+@menu
+* Analyzer Internals::   Analyzer Internals
+* Debugging the Analyzer::   Useful debugging tips
+@end menu
+
+@node Analyzer Internals
+@section Analyzer Internals
+@cindex analyzer, internals
+@cindex static analyzer, internals
+
+@subsection Overview
+
+The analyzer implementation works on the gimple-SSA representation.
+(I chose this in the hopes of making it easy to work with LTO to
+do whole-program analysis).
+
+The implementation is read-only: it doesn't attempt to change anything,
+just emit warnings.
+
+First, we build a @code{supergraph} which combines the callgraph and all
+of the CFGs into a single directed graph, with both interprocedural and
+intraprocedural edges.  The nodes and edges in the supergraph are called
+``supernodes'' and ``superedges'', and often referred to in code as
+@code{snodes} and @code{sedges}.  Basic blocks in the CFGs are split at
+interprocedural calls, so there can be more than one supernode per
+basic block.  Most statements will be in just one supernode, but a call
+statement can appear in two supernodes: at the end of one for the call,
+and again at the start of another for the return.
+
+The supergraph can be seen using @option{-fdump-analyzer-supergraph}.
+
+We then build an @code{analysis_plan} which walks the callgraph to
+determine which calls might be suitable for being summarized (rather
+than fully explored) and thus in what order to explore the functions.
+
+Next is the heart of the analyzer: we use a worklist to explore state
+within the supergraph, building an "exploded graph".
+Nodes in the exploded graph correspond to  pairs, as in
+ "Precise Interprocedural Dataflow Analysis via Graph Reachability"
+ (Thomas Reps, Susan Horwitz and Mooly Sagiv).
+
+We reuse nodes for  pairs we've already seen, and avoid
+tracking state too closely, so that (hopefully) we rapidly converge
+on a final exploded graph, and terminate the analysis.  We also bail
+out if the number of exploded  nodes gets
+larger than a particular multiple of the total number of basic blocks
+(to ensure termination in the face of pathological state-explosion
+cases, or bugs).  We also stop exploring a point once we hit a limit
+of states for that point.
+
+We can identify problems directly when processing a 
+instance.  For example, if we're finding the successors of
+
+@smallexample
+   
+@end smallexample
+
+then we can detect a double-free of "ptr".  We can then emit a path
+to reach the problem by finding the simplest route through the graph.
+
+Program points in the analysis are much more fine-grained than in the
+CFG and supergraph, with points (and thus potentially exploded nodes)
+for various events, including before individual statements.
+By default the exploded graph merges multiple consecutive statements
+in a supernode into one exploded edge to minimize the size of the
+exploded graph.  This can be suppressed via
+@option{-fanalyzer-fine-grained}.
+The fine-grained approach seems to make things simpler and more debuggable
+that other approaches I tried, in that each point is responsible for one
+thing.
+
+Program points in the analysis also have a "call string" identifying the
+stack of callsites below them, so that paths in the exploded graph
+correspond to interprocedurally valid paths: we always return to 

[PATCH 05/45] Add pp_write_text_as_html_like_dot_to_stream

2019-12-13 Thread David Malcolm
gcc/ChangeLog:
* pretty-print.c (pp_write_text_as_html_like_dot_to_stream): New
function.
* pretty-print.h (pp_write_text_as_html_like_dot_to_stream): New decl.
---
 gcc/pretty-print.c | 48 ++
 gcc/pretty-print.h |  3 +++
 2 files changed, 51 insertions(+)

diff --git a/gcc/pretty-print.c b/gcc/pretty-print.c
index 084e03c73c78..2ecb0343ba05 100644
--- a/gcc/pretty-print.c
+++ b/gcc/pretty-print.c
@@ -907,6 +907,54 @@ pp_write_text_as_dot_label_to_stream (pretty_printer *pp, 
bool for_record)
   pp_clear_output_area (pp);
 }
 
+/* As pp_write_text_to_stream, but for GraphViz HTML-like strings.
+
+   Flush the formatted text of pretty-printer PP onto the attached stream,
+   escaping these characters
+ " & < >
+   using XML escape sequences.
+
+   http://www.graphviz.org/doc/info/lang.html#html states:
+  special XML escape sequences for ", &, <, and > may be necessary in
+  order to embed these characters in attribute values or raw text
+   This doesn't list "'" (which would normally be escaped in XML
+   as "" or in HTML as "");.
+
+   Experiments show that escaping "'" doesn't seem to be necessary.  */
+
+void
+pp_write_text_as_html_like_dot_to_stream (pretty_printer *pp)
+{
+  const char *text = pp_formatted_text (pp);
+  const char *p = text;
+  FILE *fp = pp_buffer (pp)->stream;
+
+  for (;*p; p++)
+{
+  switch (*p)
+   {
+   case '"':
+ fputs ("", fp);
+ break;
+   case '&':
+ fputs ("", fp);
+ break;
+   case '<':
+ fputs ("", fp);
+ break;
+   case '>':
+ fputs ("",fp);
+ break;
+
+   default:
+ fputc (*p, fp);
+ break;
+   }
+}
+
+  pp_clear_output_area (pp);
+}
+
 /* Wrap a text delimited by START and END into PRETTY-PRINTER.  */
 static void
 pp_wrap_text (pretty_printer *pp, const char *start, const char *end)
diff --git a/gcc/pretty-print.h b/gcc/pretty-print.h
index 493507d41419..86b9e869eeb7 100644
--- a/gcc/pretty-print.h
+++ b/gcc/pretty-print.h
@@ -393,8 +393,11 @@ extern void pp_indent (pretty_printer *);
 extern void pp_newline (pretty_printer *);
 extern void pp_character (pretty_printer *, int);
 extern void pp_string (pretty_printer *, const char *);
+
 extern void pp_write_text_to_stream (pretty_printer *);
 extern void pp_write_text_as_dot_label_to_stream (pretty_printer *, bool);
+extern void pp_write_text_as_html_like_dot_to_stream (pretty_printer *pp);
+
 extern void pp_maybe_space (pretty_printer *);
 
 extern void pp_begin_quote (pretty_printer *, bool);
-- 
2.21.0



[PATCH 12/45] timevar.def: add TVs for analyzer

2019-12-13 Thread David Malcolm
This takes the place of the auto_client_timevar code from v1 of the kit:
  https://gcc.gnu.org/ml/gcc-patches/2019-11/msg01519.html

gcc/ChangeLog:
* timevar.def (TV_ANALYZER): New timevar.
(TV_ANALYZER_SUPERGRAPH): Likewise.
(TV_ANALYZER_STATE_PURGE): Likewise.
(TV_ANALYZER_PLAN): Likewise.
(TV_ANALYZER_SCC): Likewise.
(TV_ANALYZER_WORKLIST): Likewise.
(TV_ANALYZER_DUMP): Likewise.
(TV_ANALYZER_DIAGNOSTICS): Likewise.
(TV_ANALYZER_SHORTEST_PATHS): Likewise.
---
 gcc/timevar.def | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/gcc/timevar.def b/gcc/timevar.def
index 357fcfd65c59..7fca9286d748 100644
--- a/gcc/timevar.def
+++ b/gcc/timevar.def
@@ -322,3 +322,14 @@ DEFTIMEVAR (TV_LINK , "link JIT code")
 DEFTIMEVAR (TV_LOAD , "load JIT result")
 DEFTIMEVAR (TV_JIT_ACQUIRING_MUTEX   , "acquiring JIT mutex")
 DEFTIMEVAR (TV_JIT_CLIENT_CODE   , "JIT client code")
+
+/* Analyzer timevars.  */
+DEFTIMEVAR (TV_ANALYZER  , "analyzer")
+DEFTIMEVAR (TV_ANALYZER_SUPERGRAPH   , "analyzer: supergraph")
+DEFTIMEVAR (TV_ANALYZER_STATE_PURGE  , "analyzer: state purge")
+DEFTIMEVAR (TV_ANALYZER_PLAN , "analyzer: planning")
+DEFTIMEVAR (TV_ANALYZER_SCC  , "analyzer: scc")
+DEFTIMEVAR (TV_ANALYZER_WORKLIST , "analyzer: processing worklist")
+DEFTIMEVAR (TV_ANALYZER_DUMP , "analyzer: dump")
+DEFTIMEVAR (TV_ANALYZER_DIAGNOSTICS  , "analyzer: emitting diagnostics")
+DEFTIMEVAR (TV_ANALYZER_SHORTEST_PATHS, "analyzer: shortest paths")
-- 
2.21.0



[PATCH 09/45] Add diagnostic_metadata and CWE support

2019-12-13 Thread David Malcolm
Changed in v2:
  fixup for json::number -> json::integer_number change (r277284)
https://gcc.gnu.org/ml/gcc-patches/2019-11/msg02027.html

This patch adds support for associating a diagnostic with an optional
diagnostic_metadata object, so that plugins can add extra data to their
diagnostics (e.g. mapping a diagnostic to a taxonomy or coding standard
such as from CERT or MISRA).

Currently this only supports associating a CWE identifier with a
diagnostic (which is what I'm using for the analyzer warnings later in
the patch kit), but adding a diagnostic_metadata class allows for future
growth in this area without an explosion of further "warning_at" overloads
for all of the different kinds of custom data that a plugin might want to
add.

gcc/ChangeLog:
* common.opt (fdiagnostics-show-metadata): New option.
* diagnostic-core.h (class diagnostic_metadata): New forward decl.
(warning_at): Add overload taking a const diagnostic_metadata &.
(emit_diagnostic_valist): Add overload taking a
const diagnostic_metadata *.
* diagnostic-format-json.cc: Include "diagnostic-metadata.h".
(json_from_metadata): New function.
(json_end_diagnostic): Call it to add "metadata" child for
diagnostics with metadata.
(diagnostic_output_format_init): Clear context->show_metadata.
* diagnostic-metadata.h: New file.
* diagnostic.c: Include "diagnostic-metadata.h".
(diagnostic_impl): Add const diagnostic_metadata * param.
(diagnostic_n_impl): Likewise.
(diagnostic_initialize): Initialize context->show_metadata.
(diagnostic_set_info_translated): Initialize diagnostic->metadata.
(get_cwe_url): New function.
(print_any_metadata): New function.
(diagnostic_report_diagnostic): Call print_any_metadata if the
diagnostic has non-NULL metadata.
(emit_diagnostic): Pass NULL as the metadata in the call to
diagnostic_impl.
(emit_diagnostic_valist): Likewise.
(emit_diagnostic_valist): New overload taking a
const diagnostic_metadata *.
(inform): Pass NULL as the metadata in the call to
diagnostic_impl.
(inform_n): Likewise for diagnostic_n_impl.
(warning): Likewise.
(warning_at): Likewise.  Add overload that takes a
const diagnostic_metadata &.
(warning_n): Pass NULL as the metadata in the call to
diagnostic_n_impl.
(pedwarn): Likewise for diagnostic_impl.
(permerror): Likewise.
(error): Likewise.
(error_n): Likewise.
(error_at): Likewise.
(sorry): Likewise.
(sorry_at): Likewise.
(fatal_error): Likewise.
(internal_error): Likewise.
(internal_error_no_backtrace): Likewise.
* diagnostic.h (diagnostic_info::metadata): New field.
(diagnostic_context::show_metadata): New field.
* doc/invoke.texi (-fno-diagnostics-show-metadata): New option.
* opts.c (common_handle_option): Handle
OPT_fdiagnostics_show_metadata.
* toplev.c (general_init): Initialize global_dc->show_metadata.
---
 gcc/common.opt|   4 +
 gcc/diagnostic-core.h |  10 +++
 gcc/diagnostic-format-json.cc |  24 ++
 gcc/diagnostic-metadata.h |  42 ++
 gcc/diagnostic.c  | 142 ++
 gcc/diagnostic.h  |   7 ++
 gcc/doc/invoke.texi   |   8 ++
 gcc/opts.c|   4 +
 gcc/toplev.c  |   2 +
 9 files changed, 212 insertions(+), 31 deletions(-)
 create mode 100644 gcc/diagnostic-metadata.h

diff --git a/gcc/common.opt b/gcc/common.opt
index d5727c300c07..0bde11b74917 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -1338,6 +1338,10 @@ fdiagnostics-show-option
 Common Var(flag_diagnostics_show_option) Init(1)
 Amend appropriate diagnostic messages with the command line option that 
controls them.
 
+fdiagnostics-show-metadata
+Common Var(flag_diagnostics_show_metadata) Init(1)
+Print additional metadata for diagnostic messages, where available.
+
 fdiagnostics-minimum-margin-width=
 Common Joined UInteger Var(diagnostics_minimum_margin_width) Init(6)
 Set minimum width of left margin of source code when showing source.
diff --git a/gcc/diagnostic-core.h b/gcc/diagnostic-core.h
index efafde4fa24a..2e7f12070fbd 100644
--- a/gcc/diagnostic-core.h
+++ b/gcc/diagnostic-core.h
@@ -45,6 +45,9 @@ class auto_diagnostic_group
   ~auto_diagnostic_group ();
 };
 
+/* Forward decl.  */
+class diagnostic_metadata; /* See diagnostic-metadata.h.  */
+
 extern const char *progname;
 
 extern const char *trim_filename (const char *);
@@ -78,6 +81,9 @@ extern bool warning_at (location_t, int, const char *, ...)
 ATTRIBUTE_GCC_DIAG(3,4);
 extern bool warning_at (rich_location *, int, const char *, ...)
 ATTRIBUTE_GCC_DIAG(3,4);
+extern bool warning_at (rich_location *, const diagnostic_metadata 

[PATCH 08/45] Add -fdiagnostics-nn-line-numbers

2019-12-13 Thread David Malcolm
This patch implements -fdiagnostics-nn-line-numbers, a new option
which makes diagnostic_show_locus print "NN" rather than specific
line numbers when printing the left margin.

This is intended purely to make it easier to write certain kinds of
DejaGnu test; various integration tests for diagnostic paths later
in the patch kit make use of it.

gcc/ChangeLog:
* common.opt (fdiagnostics-nn-line-numbers): New option.
* diagnostic-show-locus.c (layout::m_use_nn_for_line_numbers_p):
New field.
(layout::layout): Initialize it.
(layout::calculate_linenum_width): Use it when computing
m_linenum_width.
(layout::print_source_line): Implement printing "NN" rather than
the line number.
(selftest::test_line_numbers_multiline_range): Add a test of "NN"
printing.
* diagnostic.c (diagnostic_initialize): Initialize
use_nn_for_line_numbers_p.
(num_digits): Add "use_nn_p" param.
(selftest::test_num_digits): Add a test for use_nn_p==true.
* diagnostic.h (diagnostic_context::use_nn_for_line_numbers_p):
New field.
(num_digits): Add optional "use_nn_p" param.
* doc/invoke.texi (-fdiagnostics-nn-line-numbers): New option.
* dwarf2out.c (gen_producer_string): Ignore
OPT_fdiagnostics_nn_line_numbers.
* lto-wrapper.c (merge_and_complain): Handle
OPT_fdiagnostics_nn_line_numbers.
(append_compiler_options): Likewise.
(append_diag_options): Likewise.
* opts.c (common_handle_option): Likewise.
* toplev.c (general_init): Initialize
global_dc->use_nn_for_line_numbers_p.
---
 gcc/common.opt  |  4 +++
 gcc/diagnostic-show-locus.c | 51 ++---
 gcc/diagnostic.c| 13 --
 gcc/diagnostic.h|  6 -
 gcc/doc/invoke.texi |  7 +
 gcc/dwarf2out.c |  1 +
 gcc/lto-wrapper.c   |  3 +++
 gcc/opts.c  |  4 +++
 gcc/toplev.c|  2 ++
 9 files changed, 73 insertions(+), 18 deletions(-)

diff --git a/gcc/common.opt b/gcc/common.opt
index b4dc31c7490d..d5727c300c07 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -1261,6 +1261,10 @@ fdiagnostics-show-line-numbers
 Common Var(flag_diagnostics_show_line_numbers) Init(1)
 Show line numbers in the left margin when showing source.
 
+fdiagnostics-nn-line-numbers
+Common Var(flag_diagnostics_nn_line_numbers) Init(0)
+Replace line numbers with 'NN' when showing source.
+
 fdiagnostics-color
 Common Alias(fdiagnostics-color=,always,never)
 ;
diff --git a/gcc/diagnostic-show-locus.c b/gcc/diagnostic-show-locus.c
index c87603caf419..49832fd0ea03 100644
--- a/gcc/diagnostic-show-locus.c
+++ b/gcc/diagnostic-show-locus.c
@@ -385,6 +385,7 @@ class layout
   bool m_colorize_source_p;
   bool m_show_labels_p;
   bool m_show_line_numbers_p;
+  bool m_use_nn_for_line_numbers_p;
   auto_vec  m_layout_ranges;
   auto_vec  m_fixit_hints;
   auto_vec  m_line_spans;
@@ -958,6 +959,7 @@ layout::layout (diagnostic_context * context,
   m_colorize_source_p (context->colorize_source_p),
   m_show_labels_p (context->show_labels_p),
   m_show_line_numbers_p (context->show_line_numbers_p),
+  m_use_nn_for_line_numbers_p (context->use_nn_for_line_numbers_p),
   m_layout_ranges (richloc->get_num_locations ()),
   m_fixit_hints (richloc->get_num_fixit_hints ()),
   m_line_spans (1 + richloc->get_num_locations ()),
@@ -1343,7 +1345,7 @@ layout::calculate_linenum_width ()
   int highest_line = last_span->m_last_line;
   if (highest_line < 0)
 highest_line = 0;
-  m_linenum_width = num_digits (highest_line);
+  m_linenum_width = num_digits (highest_line, m_use_nn_for_line_numbers_p);
   /* If we're showing jumps in the line-numbering, allow at least 3 chars.  */
   if (m_line_spans.length () > 1)
 m_linenum_width = MAX (m_linenum_width, 3);
@@ -1449,10 +1451,13 @@ layout::print_source_line (linenum_type row, const char 
*line, int line_bytes,
   pp_emit_prefix (m_pp);
   if (m_show_line_numbers_p)
 {
-  int width = num_digits (row);
+  int width = num_digits (row, m_use_nn_for_line_numbers_p);
   for (int i = 0; i < m_linenum_width - width; i++)
pp_space (m_pp);
-  pp_printf (m_pp, "%i | ", row);
+  if (m_use_nn_for_line_numbers_p)
+   pp_printf (m_pp, "%s | ", "NN");
+  else
+   pp_printf (m_pp, "%i | ", row);
 }
   else
 pp_space (m_pp);
@@ -4968,18 +4973,34 @@ test_line_numbers_multiline_range ()
 = linemap_position_for_line_and_column (line_table, ord_map, 11, 4);
   location_t loc = make_location (caret, start, finish);
 
-  test_diagnostic_context dc;
-  dc.show_line_numbers_p = true;
-  dc.min_margin_width = 0;
-  gcc_rich_location richloc (loc);
-  diagnostic_show_locus (, , DK_ERROR);
-  ASSERT_STREQ (" 9 | this is line 9\n"
-   "   | ~~\n"
-   "10 | this is line 10\n"
-   " 

[PATCH 03/45] analyzer: user-facing documentation

2019-12-13 Thread David Malcolm
Changed in v4:
- Use -fanalyzer rather than --analyzer
- Add -W[no-]analyzer-unsafe-call-within-signal-handler

gcc/ChangeLog:
* doc/invoke.texi ("Static Analyzer Options"): New list and new section.
("Warning Options"): Add static analysis warnings to the list.
(-Wno-analyzer-double-fclose): New option.
(-Wno-analyzer-double-free): New option.
(-Wno-analyzer-exposure-through-output-file): New option.
(-Wno-analyzer-file-leak): New option.
(-Wno-analyzer-free-of-non-heap): New option.
(-Wno-analyzer-malloc-leak): New option.
(-Wno-analyzer-possible-null-argument): New option.
(-Wno-analyzer-possible-null-dereference): New option.
(-Wno-analyzer-null-argument): New option.
(-Wno-analyzer-null-dereference): New option.
(-Wno-analyzer-stale-setjmp-buffer): New option.
(-Wno-analyzer-tainted-array-index): New option.
(-Wno-analyzer-use-after-free): New option.
(-Wno-analyzer-use-of-pointer-in-stale-stack-frame): New option.
(-Wno-analyzer-use-of-uninitialized-value): New option.
(-Wanalyzer-too-complex): New option.
(-fanalyzer-call-summaries): New warning.
(-fanalyzer-checker=): New warning.
(-fanalyzer-fine-grained): New warning.
(-fno-analyzer-state-merge): New warning.
(-fno-analyzer-state-purge): New warning.
(-fanalyzer-transitivity): New warning.
(-fanalyzer-verbose-edges): New warning.
(-fanalyzer-verbose-state-changes): New warning.
(-fanalyzer-verbosity=): New warning.
(-fdump-analyzer): New warning.
(-fdump-analyzer-callgraph): New warning.
(-fdump-analyzer-exploded-graph): New warning.
(-fdump-analyzer-exploded-nodes): New warning.
(-fdump-analyzer-exploded-nodes-2): New warning.
(-fdump-analyzer-exploded-nodes-3): New warning.
(-fdump-analyzer-supergraph): New warning.
---
 gcc/doc/invoke.texi | 435 +++-
 1 file changed, 433 insertions(+), 2 deletions(-)

diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 157dc907eec7..19e0631f6ea5 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -153,6 +153,7 @@ listing and explanation of the binary and decimal byte size 
prefixes.
 * Diagnostic Message Formatting Options:: Controlling how diagnostics should
 be formatted.
 * Warning Options:: How picky should the compiler be?
+* Static Analyzer Options:: More expensive warnings.
 * Debugging Options::   Producing debuggable code.
 * Optimize Options::How much optimization?
 * Instrumentation Options:: Enabling profiling and extra run-time error 
checking.
@@ -284,13 +285,31 @@ Objective-C and Objective-C++ Dialects}.
 
 @item Warning Options
 @xref{Warning Options,,Options to Request or Suppress Warnings}.
-@gccoptlist{-fsyntax-only  -fmax-errors=@var{n}  -Wpedantic @gol
+@gccoptlist{-fanalyzer -fsyntax-only  -fmax-errors=@var{n}  -Wpedantic @gol
 -pedantic-errors @gol
 -w  -Wextra  -Wall  -Waddress  -Waddress-of-packed-member @gol
 -Waggregate-return  -Waligned-new @gol
 -Walloc-zero  -Walloc-size-larger-than=@var{byte-size} @gol
 -Walloca  -Walloca-larger-than=@var{byte-size} @gol
--Wno-aggressive-loop-optimizations  -Warray-bounds  -Warray-bounds=@var{n} @gol
+-Wno-aggressive-loop-optimizations @gol
+-Wno-analyzer-double-fclose @gol
+-Wno-analyzer-double-free @gol
+-Wno-analyzer-exposure-through-output-file @gol
+-Wno-analyzer-file-leak @gol
+-Wno-analyzer-free-of-non-heap @gol
+-Wno-analyzer-malloc-leak @gol
+-Wno-analyzer-possible-null-argument @gol
+-Wno-analyzer-possible-null-dereference @gol
+-Wno-analyzer-null-argument @gol
+-Wno-analyzer-null-dereference @gol
+-Wno-analyzer-stale-setjmp-buffer @gol
+-Wno-analyzer-tainted-array-index @gol
+-Wno-analyzer-unsafe-call-within-signal-handler @gol
+-Wno-analyzer-use-after-free @gol
+-Wno-analyzer-use-of-pointer-in-stale-stack-frame @gol
+-Wno-analyzer-use-of-uninitialized-value @gol
+-Wanalyzer-too-complex @gol
+-Warray-bounds  -Warray-bounds=@var{n} @gol
 -Wno-attributes  -Wattribute-alias=@var{n}  @gol
 -Wbool-compare  -Wbool-operation @gol
 -Wno-builtin-declaration-mismatch @gol
@@ -372,6 +391,44 @@ Objective-C and Objective-C++ Dialects}.
 -Wwrite-strings @gol
 -Wzero-as-null-pointer-constant}
 
+@item Static Analyzer Options
+@gccoptlist{-Wanalyzer-double-fclose @gol
+-Wanalyzer-double-free @gol
+-Wanalyzer-exposure-through-output-file @gol
+-Wanalyzer-file-leak @gol
+-Wanalyzer-free-of-non-heap @gol
+-Wanalyzer-malloc-leak @gol
+-Wanalyzer-null-argument @gol
+-Wanalyzer-null-dereference @gol
+-Wanalyzer-possible-null-argument @gol
+-Wanalyzer-possible-null-dereference @gol
+-Wanalyzer-stale-setjmp-buffer @gol
+-Wanalyzer-tainted-array-index @gol
+-Wanalyzer-unsafe-call-within-signal-handler @gol
+-Wanalyzer-use-after-free @gol
+-Wanalyzer-use-of-pointer-in-stale-stack-frame @gol

[PATCH 01/45] gimple const-correctness fixes

2019-12-13 Thread David Malcolm
This patch converts various "gimple *" to "const gimple *" and similar
fixes for gimple subclasses, adding is_a_helper for gimple subclasses
to support the const form of as_a, and adding a few "const" overloads
of accessors.

This is enough to make pp_gimple_stmt_1's stmt const.

gcc/ChangeLog:
* gimple-predict.h (gimple_predict_predictor): Make "gs" param
const.
(gimple_predict_outcome): Likewise.
* gimple-pretty-print.c (do_niy): Likewise.
(dump_unary_rhs): Likewise.
(dump_binary_rhs): Likewise.
(dump_ternary_rhs): Likewise.
(dump_gimple_assign): Likewise.
(dump_gimple_return): Likewise.
(dump_gimple_call_args): Likewise.
(pp_points_to_solution): Make "pt" param const.
(dump_gimple_call): Make "gs" param const.
(dump_gimple_switch): Likewise.
(dump_gimple_cond): Likewise.
(dump_gimple_label): Likewise.
(dump_gimple_goto): Likewise.
(dump_gimple_bind): Likewise.
(dump_gimple_try): Likewise.
(dump_gimple_catch): Likewise.
(dump_gimple_eh_filter): Likewise.
(dump_gimple_eh_must_not_throw): Likewise.
(dump_gimple_eh_else): Likewise.
(dump_gimple_resx): Likewise.
(dump_gimple_eh_dispatch): Likewise.
(dump_gimple_debug): Likewise.
(dump_gimple_omp_for): Likewise.
(dump_gimple_omp_continue): Likewise.
(dump_gimple_omp_single): Likewise.
(dump_gimple_omp_taskgroup): Likewise.
(dump_gimple_omp_target): Likewise.
(dump_gimple_omp_teams): Likewise.
(dump_gimple_omp_sections): Likewise.
(dump_gimple_omp_block): Likewise.
(dump_gimple_omp_critical): Likewise.
(dump_gimple_omp_ordered): Likewise.
(dump_gimple_omp_scan): Likewise.
(dump_gimple_omp_return): Likewise.
(dump_gimple_transaction): Likewise.
(dump_gimple_asm): Likewise.
(dump_gimple_phi): Make "phi" param const.
(dump_gimple_omp_parallel): Make "gs" param const.
(dump_gimple_omp_task): Likewise.
(dump_gimple_omp_atomic_load): Likewise.
(dump_gimple_omp_atomic_store): Likewise.
(dump_gimple_mem_ops): Likewise.
(pp_gimple_stmt_1): Likewise.  Add "const" to the various as_a <>
casts throughout.
* gimple-pretty-print.h (gimple_stmt_1): Make gimple * param const.
* gimple.h (is_a_helper ::test): New.
(is_a_helper ::test): New.
(is_a_helper ::test): New.
(is_a_helper ::test): New.
(is_a_helper ::test): New.
(is_a_helper ::test): New.
(is_a_helper ::test): New.
(is_a_helper ::test): New.
(gimple_call_tail_p): Make param const.
(gimple_call_return_slot_opt_p): Likewise.
(gimple_call_va_arg_pack_p): Likewise.
(gimple_call_use_set): Add const overload.
(gimple_call_clobber_set): Likewise.
(gimple_has_lhs): Make param const.
(gimple_bind_body): Likewise.
(gimple_catch_handler): Likewise.
(gimple_eh_filter_failure): Likewise.
(gimple_eh_must_not_throw_fndecl): Likewise.
(gimple_eh_else_n_body): Likewise.
(gimple_eh_else_e_body): Likewise.
(gimple_try_eval): Likewise.
(gimple_try_cleanup): Likewise.
(gimple_phi_arg): Add const overload.
(gimple_phi_arg_def): Make param const.
(gimple_phi_arg_edge): Likewise.
(gimple_phi_arg_location): Likewise.
(gimple_phi_arg_has_location): Likewise.
(gimple_debug_bind_get_var): Likewise.
(gimple_debug_bind_get_value): Likewise.
(gimple_debug_source_bind_get_var): Likewise.
(gimple_debug_source_bind_get_value): Likewise.
(gimple_omp_body): Likewise.
(gimple_omp_for_collapse): Likewise.
(gimple_omp_for_pre_body): Likewise.
(gimple_transaction_body): Likewise.
* tree-eh.c (lookup_stmt_eh_lp_fn): Make param "t" const.
(lookup_stmt_eh_lp): Likewise.
* tree-eh.h (lookup_stmt_eh_lp_fn): Make param const.
(lookup_stmt_eh_lp): Likewise.
* tree-ssa-alias.h (pt_solution_empty_p): Make param const.
* tree-ssa-structalias.c (pt_solution_empty_p): Likewise.
---
 gcc/gimple-predict.h   |   4 +-
 gcc/gimple-pretty-print.c  | 159 +++--
 gcc/gimple-pretty-print.h  |   3 +-
 gcc/gimple.h   | 156 
 gcc/tree-eh.c  |   6 +-
 gcc/tree-eh.h  |   4 +-
 gcc/tree-ssa-alias.h   |   2 +-
 gcc/tree-ssa-structalias.c |   2 +-
 8 files changed, 213 insertions(+), 123 deletions(-)

diff --git a/gcc/gimple-predict.h b/gcc/gimple-predict.h
index 761098b3ceb5..d9763175b8a1 100644
--- a/gcc/gimple-predict.h
+++ b/gcc/gimple-predict.h
@@ -26,7 +26,7 @@ along with GCC; see the file COPYING3.  If not see
 /* Return the predictor of GIMPLE_PREDICT statement GS.  */
 

[PATCH 07/45] vec.h: add auto_delete_vec

2019-12-13 Thread David Malcolm
Changed in v4: added DISABLE_COPY_AND_ASSIGN

This patch adds a class auto_delete_vec, a subclass of auto_vec 
that deletes all of its elements on destruction; it's used in many
places later in the kit.

This is a crude way for a vec to "own" the objects it points to
and clean up automatically (essentially a workaround for not being able
to use unique_ptr, due to C++98).

gcc/ChangeLog:
* vec.c (class selftest::count_dtor): New class.
(selftest::test_auto_delete_vec): New test.
(selftest::vec_c_tests): Call it.
* vec.h (class auto_delete_vec): New class template.
(auto_delete_vec::~auto_delete_vec): New dtor.
---
 gcc/vec.c | 27 +++
 gcc/vec.h | 38 ++
 2 files changed, 65 insertions(+)

diff --git a/gcc/vec.c b/gcc/vec.c
index bac5eb753a3c..a9c840de00a0 100644
--- a/gcc/vec.c
+++ b/gcc/vec.c
@@ -516,6 +516,32 @@ test_reverse ()
   }
 }
 
+/* A test class that increments a counter every time its dtor is called.  */
+
+class count_dtor
+{
+ public:
+  count_dtor (int *counter) : m_counter (counter) {}
+  ~count_dtor () { (*m_counter)++; }
+
+ private:
+  int *m_counter;
+};
+
+/* Verify that auto_delete_vec deletes the elements within it.  */
+
+static void
+test_auto_delete_vec ()
+{
+  int dtor_count = 0;
+  {
+auto_delete_vec  v;
+v.safe_push (new count_dtor (_count));
+v.safe_push (new count_dtor (_count));
+  }
+  ASSERT_EQ (dtor_count, 2);
+}
+
 /* Run all of the selftests within this file.  */
 
 void
@@ -533,6 +559,7 @@ vec_c_tests ()
   test_block_remove ();
   test_qsort ();
   test_reverse ();
+  test_auto_delete_vec ();
 }
 
 } // namespace selftest
diff --git a/gcc/vec.h b/gcc/vec.h
index 8070021223a6..cebc16ec68c4 100644
--- a/gcc/vec.h
+++ b/gcc/vec.h
@@ -1547,6 +1547,31 @@ class auto_string_vec : public auto_vec 
   ~auto_string_vec ();
 };
 
+/* A subclass of auto_vec  that deletes all of its elements on
+   destruction.
+
+   This is a crude way for a vec to "own" the objects it points to
+   and clean up automatically.
+
+   For example, no attempt is made to delete elements when an item
+   within the vec is overwritten.
+
+   We can't rely on gnu::unique_ptr within a container,
+   since we can't rely on move semantics in C++98.  */
+
+template 
+class auto_delete_vec : public auto_vec 
+{
+ public:
+  auto_delete_vec () {}
+  auto_delete_vec (size_t s) : auto_vec  (s) {}
+
+  ~auto_delete_vec ();
+
+private:
+  DISABLE_COPY_AND_ASSIGN(auto_delete_vec);
+};
+
 /* Conditionally allocate heap memory for VEC and its internal vector.  */
 
 template
@@ -1651,6 +1676,19 @@ auto_string_vec::~auto_string_vec ()
 free (str);
 }
 
+/* auto_delete_vec's dtor, deleting all contained items, automatically
+   chaining up to ~auto_vec , which frees the internal buffer.  */
+
+template 
+inline
+auto_delete_vec::~auto_delete_vec ()
+{
+  int i;
+  T *item;
+  FOR_EACH_VEC_ELT (*this, i, item)
+delete item;
+}
+
 
 /* Return a copy of this vector.  */
 
-- 
2.21.0



[PATCH 06/45] sbitmap.h: add operator const sbitmap & to auto_sbitmap

2019-12-13 Thread David Malcolm
gcc/ChangeLog:
* sbitmap.h (auto_sbitmap): Add operator const sbitmap &.
---
 gcc/sbitmap.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/gcc/sbitmap.h b/gcc/sbitmap.h
index a33175d26f75..3c5b0a47a004 100644
--- a/gcc/sbitmap.h
+++ b/gcc/sbitmap.h
@@ -295,6 +295,7 @@ public:
 
   /* Allow calling sbitmap functions on our bitmap.  */
   operator sbitmap () { return m_bitmap; }
+  operator const sbitmap &() const { return m_bitmap; }
 
 private:
   /* Prevent making a copy that refers to our sbitmap.  */
-- 
2.21.0



[PATCH 02/45] hash-map-tests.c: add a selftest involving int_hash

2019-12-13 Thread David Malcolm
gcc/ChangeLog:
* hash-map-tests.c (selftest::test_map_of_int_to_strings): New
selftest.
(selftest::hash_map_tests_c_tests): Call it.
---
 gcc/hash-map-tests.c | 41 +
 1 file changed, 41 insertions(+)

diff --git a/gcc/hash-map-tests.c b/gcc/hash-map-tests.c
index a42eac21ab36..9a13a80442c8 100644
--- a/gcc/hash-map-tests.c
+++ b/gcc/hash-map-tests.c
@@ -103,6 +103,46 @@ test_map_of_strings_to_int ()
   ASSERT_EQ (1, string_map.elements ());
 }
 
+/* Construct a hash_map using int_hash and verify that
+   various operations work correctly.  */
+
+static void
+test_map_of_int_to_strings ()
+{
+  const int EMPTY = -1;
+  const int DELETED = -2;
+  typedef int_hash  int_hash_t;
+  hash_map  m;
+
+  const char *ostrich = "ostrich";
+  const char *elephant = "elephant";
+  const char *ant = "ant";
+  const char *spider = "spider";
+  const char *millipede = "Illacme plenipes";
+  const char *eric = "half a bee";
+
+  /* A fresh hash_map should be empty.  */
+  ASSERT_EQ (0, m.elements ());
+  ASSERT_EQ (NULL, m.get (2));
+
+  /* Populate the hash_map.  */
+  ASSERT_EQ (false, m.put (2, ostrich));
+  ASSERT_EQ (false, m.put (4, elephant));
+  ASSERT_EQ (false, m.put (6, ant));
+  ASSERT_EQ (false, m.put (8, spider));
+  ASSERT_EQ (false, m.put (750, millipede));
+  ASSERT_EQ (false, m.put (3, eric));
+
+  /* Verify that we can recover the stored values.  */
+  ASSERT_EQ (6, m.elements ());
+  ASSERT_EQ (*m.get (2), ostrich);
+  ASSERT_EQ (*m.get (4), elephant);
+  ASSERT_EQ (*m.get (6), ant);
+  ASSERT_EQ (*m.get (8), spider);
+  ASSERT_EQ (*m.get (750), millipede);
+  ASSERT_EQ (*m.get (3), eric);
+}
+
 typedef class hash_map_test_val_t
 {
 public:
@@ -244,6 +284,7 @@ void
 hash_map_tests_c_tests ()
 {
   test_map_of_strings_to_int ();
+  test_map_of_int_to_strings ();
   test_map_of_type_with_ctor_and_dtor ();
 }
 
-- 
2.21.0



Re: [PATCH, c] all plattforms: support using a CC_REG instead cc0_rtx

2019-12-13 Thread Segher Boessenkool
Hi!

On Fri, Dec 13, 2019 at 05:25:41PM +0100, Stefan Franke wrote:
> I suggest this patch to allow architectures do substitute cc0_rtx with a 
> generated cc register.
> 
> Why? If you are using a cc register plus your architecture as many 
> instructions which may clobber that cc register, some passes (e.g. gcse) 
> will reorder the insns. This can lead to the situation that an insn is 
> moved between a compare and it' consuming jump insn. Which yields 
> invalid code. (Note that at these stages clobbers are not yet tracked as 
> CLOBBER insns).

Then that port has a bug.  In the m68k port, there are no separate compare
and jump insns ever, but for most ports those won't yet exist during gcse.

This is not unique to cc0 conversions: every port has a similar problem
with all FIXED_REGISTERS.

> --- a/gcc/jump.c
> +++ b/gcc/jump.c
> @@ -1028,7 +1028,7 @@ sets_cc0_p (const_rtx x)
>if (INSN_P (x))
>  x = PATTERN (x);
> 
> -  if (GET_CODE (x) == SET && SET_DEST (x) == cc0_rtx)
> +  if (GET_CODE (x) == SET && rtx_equal_p(SET_DEST (x), cc0_rtx))
>  return 1;

@findex cc0_rtx
There is only one expression object of code @code{cc0}; it is the
value of the variable @code{cc0_rtx}.  Any attempt to create an
expression of code @code{cc0} will return @code{cc0_rtx}.

There is a lot of code that depends on this property, you cannot break
it without fixing everything.


Segher


[patch] Let libstdc++ know that VxWorks has_nanosleep

2019-12-13 Thread Olivier Hainque

This change adjusts the libstdc++ configuration for VxWorks
to set ac_has_nanosleep=yes, which enables the use of nanosleep
from the library.

While this technically depends on the kernel configuration
(INCLUDE_POSIX_TIMERS) this is the normal configuration in all
the environments we have been given to work with for the past
decade and activating this improves the library in our experience.

Tested in accordance with the description in
https://gcc.gnu.org/ml/gcc-patches/2019-12/msg00911.html

Best Regards,

Olivier

2019-12-13  Corentin Gay  

libstdc++/
* acinclude.m4 (vxworks*): New entry. Set ac_has_nanosleep=yes.
* configure: Regenerate.

--- a/libstdc++-v3/acinclude.m4
+++ b/libstdc++-v3/acinclude.m4
@@ -1408,6 +1408,11 @@ AC_DEFUN([GLIBCXX_ENABLE_LIBSTDCXX_TIME], [
 ac_has_nanosleep=yes
 ac_has_sched_yield=yes
 ;;
+  # VxWorks has nanosleep as soon as the kernel is configured with
+  # INCLUDE_POSIX_TIMERS, which is normally/most-often the case.
+  vxworks*)
+ac_has_nanosleep=yes
+;;
   gnu* | linux* | kfreebsd*-gnu | knetbsd*-gnu)
 AC_MSG_CHECKING([for at least GNU libc 2.17])
 AC_TRY_COMPILE(
diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure
index fa86ca1e731..717f5c1d21d 100755
--- a/libstdc++-v3/configure
+++ b/libstdc++-v3/configure
@@ -20871,6 +20871,11 @@ ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
 ac_has_nanosleep=yes
 ac_has_sched_yield=yes
 ;;
+  # VxWorks has nanosleep as soon as the kernel is configured with
+  # INCLUDE_POSIX_TIMERS, which is normally/most-often the case.
+  vxworks*)
+ac_has_nanosleep=yes
+;;
   gnu* | linux* | kfreebsd*-gnu | knetbsd*-gnu)
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for at least GNU 
libc 2.17" >&5
 $as_echo_n "checking for at least GNU libc 2.17... " >&6; }
-- 
2.17.1



Re: [patch, openacc] Adjust tests for amdgcn offloading

2019-12-13 Thread Andrew Stubbs

On 19/11/2019 12:21, Andrew Stubbs wrote:
This patch adds GCN special casing for most of the OpenACC libgomp tests 
that require it. It also disables one testcase that explicitly uses CUDA.


The patches aren't all that controversial, should only change the 
results on amdgcn, and Tobias already went and obsoleted half the patch, 
so I've gone ahead and committed the attached.


I've clarified the reason for skipping tile-1.c, and removed the 
obsolete bits, but otherwise it is as it was.


You can remove this patch from your review list. :-)

Andrew
Update OpenACC tests for amdgcn

2019-12-13  Andrew Stubbs  

	libgomp/
	* testsuite/libgomp.oacc-c-c++-common/acc_prof-init-1.c: Handle gcn.
	* testsuite/libgomp.oacc-c-c++-common/acc_prof-kernels-1.c: Likewise.
	* testsuite/libgomp.oacc-c-c++-common/acc_prof-parallel-1.c: Likewise.
	* testsuite/libgomp.oacc-c-c++-common/asyncwait-nop-1.c: Likewise.
	* testsuite/libgomp.oacc-c-c++-common/function-not-offloaded.c:
	Likewise.
	* testsuite/libgomp.oacc-c-c++-common/async_queue-1.c: Disable on GCN.
	* testsuite/libgomp.oacc-c-c++-common/tile-1.c: Likewise.

diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/acc_prof-init-1.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/acc_prof-init-1.c
index b356feb8108..e82a03e8f3c 100644
--- a/libgomp/testsuite/libgomp.oacc-c-c++-common/acc_prof-init-1.c
+++ b/libgomp/testsuite/libgomp.oacc-c-c++-common/acc_prof-init-1.c
@@ -224,6 +224,8 @@ static void cb_compute_construct_end (acc_prof_info *prof_info, acc_event_info *
 
   if (acc_device_type == acc_device_host)
 assert (api_info->device_api == acc_device_api_none);
+  else if (acc_device_type == acc_device_gcn)
+assert (api_info->device_api == acc_device_api_other);
   else
 assert (api_info->device_api == acc_device_api_cuda);
   assert (api_info->valid_bytes == _ACC_API_INFO_VALID_BYTES);
diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/acc_prof-kernels-1.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/acc_prof-kernels-1.c
index 7cfc364e411..ddf647cda9b 100644
--- a/libgomp/testsuite/libgomp.oacc-c-c++-common/acc_prof-kernels-1.c
+++ b/libgomp/testsuite/libgomp.oacc-c-c++-common/acc_prof-kernels-1.c
@@ -106,6 +106,8 @@ static void cb_enqueue_launch_start (acc_prof_info *prof_info, acc_event_info *e
 assert (event_info->launch_event.vector_length >= 1);
   else if (acc_device_type == acc_device_nvidia) /* ... is special.  */
 assert (event_info->launch_event.vector_length == 32);
+  else if (acc_device_type == acc_device_gcn) /* ...and so is this.  */
+assert (event_info->launch_event.vector_length == 64);
   else
 {
 #ifdef __OPTIMIZE__
@@ -118,6 +120,8 @@ static void cb_enqueue_launch_start (acc_prof_info *prof_info, acc_event_info *e
 
   if (acc_device_type == acc_device_host)
 assert (api_info->device_api == acc_device_api_none);
+  else if (acc_device_type == acc_device_gcn)
+assert (api_info->device_api == acc_device_api_other);
   else
 assert (api_info->device_api == acc_device_api_cuda);
   assert (api_info->valid_bytes == _ACC_API_INFO_VALID_BYTES);
diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/acc_prof-parallel-1.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/acc_prof-parallel-1.c
index ac6eb48cbbe..dc7c7582ce2 100644
--- a/libgomp/testsuite/libgomp.oacc-c-c++-common/acc_prof-parallel-1.c
+++ b/libgomp/testsuite/libgomp.oacc-c-c++-common/acc_prof-parallel-1.c
@@ -265,6 +265,8 @@ static void cb_enter_data_end (acc_prof_info *prof_info, acc_event_info *event_i
 
   if (acc_device_type == acc_device_host)
 assert (api_info->device_api == acc_device_api_none);
+  else if (acc_device_type == acc_device_gcn)
+assert (api_info->device_api == acc_device_api_other);
   else
 assert (api_info->device_api == acc_device_api_cuda);
   assert (api_info->valid_bytes == _ACC_API_INFO_VALID_BYTES);
@@ -319,6 +321,8 @@ static void cb_exit_data_start (acc_prof_info *prof_info, acc_event_info *event_
 
   if (acc_device_type == acc_device_host)
 assert (api_info->device_api == acc_device_api_none);
+  else if (acc_device_type == acc_device_gcn)
+assert (api_info->device_api == acc_device_api_other);
   else
 assert (api_info->device_api == acc_device_api_cuda);
   assert (api_info->valid_bytes == _ACC_API_INFO_VALID_BYTES);
@@ -371,6 +375,8 @@ static void cb_exit_data_end (acc_prof_info *prof_info, acc_event_info *event_in
 
   if (acc_device_type == acc_device_host)
 assert (api_info->device_api == acc_device_api_none);
+  else if (acc_device_type == acc_device_gcn)
+assert (api_info->device_api == acc_device_api_other);
   else
 assert (api_info->device_api == acc_device_api_cuda);
   assert (api_info->valid_bytes == _ACC_API_INFO_VALID_BYTES);
@@ -510,6 +516,8 @@ static void cb_compute_construct_end (acc_prof_info *prof_info, acc_event_info *
 
   if (acc_device_type == acc_device_host)
 assert (api_info->device_api == acc_device_api_none);
+  else if (acc_device_type == 

Re: [PATCH 11/49] Add diagnostic_metadata and CWE support

2019-12-13 Thread David Malcolm
On Fri, 2019-12-13 at 09:43 -0700, Martin Sebor wrote:
> On 12/12/19 7:59 PM, David Malcolm wrote:
> > On Wed, 2019-12-04 at 10:36 -0700, Martin Sebor wrote:
> > > On 11/15/19 6:22 PM, David Malcolm wrote:
> > > > This patch adds support for associating a diagnostic with an
> > > > optional
> > > > diagnostic_metadata object, so that plugins can add extra data
> > > > to
> > > > their
> > > > diagnostics (e.g. mapping a diagnostic to a taxonomy or coding
> > > > standard
> > > > such as from CERT or MISRA).
> > > > 
> > > > Currently this only supports associating a CWE identifier with
> > > > a
> > > > diagnostic (which is what I'm using for the analyzer warnings
> > > > later
> > > > in
> > > > the patch kit), but adding a diagnostic_metadata class allows
> > > > for
> > > > future
> > > > growth in this area without an explosion of further
> > > > "warning_at"
> > > > overloads
> > > > for all of the different kinds of custom data that a plugin
> > > > might
> > > > want to
> > > > add.
> > > 
> > > We discussed this in the past so I'll be repeating some of my
> > > comments from that thread.  I like the feature at a high level,
> > > but I'm not sure I see how to make it work in a robust way.
> > > 
> > > There is no one-to-one mapping between GCC warnings and any of
> > > these classifications.  A single GCC warning might map to several
> > > CERT or MISRA guidelines, and a single guideline might map to two
> > > or more different GCC warnings.  This is an M to N mapping times
> > > the number of coding standards/classifications.  I haven't looked
> > > at the patch kit in enough detail to understand how it tries to
> > > handle it.  Can you explain?
> > 
> > The patch kit gives the ability to (optionally) specify a single
> > CWE
> > identifier when emitting a diagnostic.
> > 
> > The patch kit uses this in various places for its new warnings for
> > the
> > cases where there is a well-defined CWE weakness identifier (and
> > doesn't otherwise).
> > 
> > It doesn't attempt to classify any existing warnings.
> > 
> > It doesn't attempt to support other classifications in this patch,
> > but
> > it does introduce a diagnostic_metadata object that could gain this
> > functionality at some later time, if we come up with a scheme we're
> > happy with (a slight violation of YAGNI, but it's such a pain
> > touching
> > all the diagnostic fns that I prefer to do it once).
> 
> I wasn't necessarily asking about any classifications in particular,
> or even about pre-existing warnings.  I think it would be nice to be
> able to eventually make it work for them but I obviously realize that
> will take quite a bit retrofitting.
> 
> What I'd like to understand how the warning X classification-id
> mapping for the new analyzer warnings is supported in the design
> of the (new) diagnostic infrastructure (or how you envision it
> will be when it's more complete).
> 
> You said the analyzer currently only supports associating a CWE
> identifier with a diagnostic.  By "diagnostic" do you mean
> a particular instance of a given warning or all its instances?
> 
> Picking an uninitialized use as an example, there are three CWE's
> that discuss it:
> 
>CWE-457: Use of Uninitialized Variable
>CWE-824: Access of Uninitialized Pointer
>CWE-908: Use of Uninitialized Resource
> 
> but only one -Wanalyzer-use-of-uninitialized-value.  I'd like to
> see how the mapping works (or will work) between these three CWE's
> and instances of this analyzer option/warning.
> 
> I see on Goldbolt that for either the use of an uninitialized
> pointer (CWE-457) or for its dereference (CWE-824) the analyzer
> issues the same warning with the same CWE ID:
> 
>use of uninitialized value 'p' [CWE-457] 
> [-Wanalyzer-use-of-uninitialized-value]
> 
> It doesn't differentiate between the two CWE's.

That warning is implemented in analyzer/region-model.cc (see:
  https://gcc.gnu.org/ml/gcc-patches/2019-11/msg01554.html )

The code in question is in poisoned_value_diagnostic::emit

  case POISON_KIND_UNINIT:
{
  diagnostic_metadata m;
  m.add_cwe (457); /* "CWE-457: Use of Uninitialized Variable".  */
  return warning_at (rich_loc, m,
 OPT_Wanalyzer_use_of_uninitialized_value,
 "use of uninitialized value %qE",
 m_expr);
}
break;

and currently that's code is only called when detecting a dereference
of an uninitialized pointer.

So, yes, this one probably should be CWE-824, but that's merely a bug
in my code, not a problem with the "infrastructure".

It looks like I'll need an extra attribute for that class to
distinguish the type of access (read from local seems to be CWE-457,
deref pointer seems to be CWE-824; CWE-908 would be emitted from a
different place, if I'm understanding the definition correctly).


> If this limitation is baked into the design of the infrastructure
> then that's an obvious 

[patch] Adapt libstdc++ os_defines for VxWorks to more recent versions

2019-12-13 Thread Olivier Hainque
Hello,

This change reworks the VxWorks specific os_defines.h internal
lisbstdc++ header to help fix build and runtime failures of various
kinds in environments from 6.4/6.9 to 7 SR640, based on experiments
and observations conducted against real installs of these OSes for
different CPU architectures.

This is touching a vxworks specific header file and libstdc++
is currently not included in standard builds, so I'm planning
to commit to mainline in preparation of further changes which
will allow relaxing the current exclusion.

Best Regards,

Olivier

2019-12-13  Jerome Lambourg  
Olivier Hainque  

libstdc++
* config/os/vxworks/os_defines.h
(NOMINMAX): Always redefine to 1.
(_NO_CPP_INLINES): Likewise.
(_GLIBCXX_USE_WEAK_REF): Define to 1 for RTP on
VxWorks >= 7, to 0 otherwise.
(_GLIBCXX_HAVE_TLS): Define to 1.
For VxWorks >= 7:
(_GLIBCXX_USE_C99_MATH): Define to 1.
(_GLIBCXX_USE_C99_MATH_FP_MACROS_DYNAMIC): Define to 0.
(_HAS_TR1_DECLARATIONS): Redefine to 0.
For VxWorks < 7, RTP:
(_GLIBCXX_INCLUDE_NEXT_C_HEADERS): Define to 1.
(_GLIBCXX_USE_C99_FP_MACROS_DYNAMIC): Redefine to 1.
(__CORRECT_ISO_CPP11_MATH_H_PROTO_FP): Define.
For VxWorks < 7, kernel: #include 

 libstdc++-v3/config/os/vxworks/os_defines.h | 67 +++--
 1 file changed, 63 insertions(+), 4 deletions(-)

diff --git a/libstdc++-v3/config/os/vxworks/os_defines.h 
b/libstdc++-v3/config/os/vxworks/os_defines.h
index 3a9a9587622..c5573a40b0d 100644
--- a/libstdc++-v3/config/os/vxworks/os_defines.h
+++ b/libstdc++-v3/config/os/vxworks/os_defines.h
@@ -33,10 +33,69 @@
 // System-specific #define, typedefs, corrections, etc, go here.  This
 // file will come before all others.
 
-//Keep vxWorks from defining min()/max() as macros
-#ifdef NOMINMAX
-#undef NOMINMAX
+// The system environment we can rely on varies across VxWorks
+// versions.
+#include <_vxworks-versions.h>
+
+// Weak refs are supported starting with VxWorks 7, in RTP mode only
+
+#if _VXWORKS_MAJOR_GE(7) && defined(__RTP__)
+#define _GLIBCXX_USE_WEAK_REF 1
+#else
+#define _GLIBCXX_USE_WEAK_REF 0
 #endif
+
+// We support TLS on VxWorks (either directly or with emutls)
+#define _GLIBCXX_HAVE_TLS 1
+
+// VxWorks7 comes with a DinkumWare library and the system headers which we
+// are going to include for libstdc++ have a few related intrinsic
+// assumptions.  We control our own configuration here to best integrate with
+// this environment: use C99 math headers, do not use the FP macros for
+// dynamic cast by default (overriden for RTPs below) and arrange to disable
+// the system TR1 declarations as we'll provide ours.
+
+#if _VXWORKS_MAJOR_GE(7)
+
+#define _GLIBCXX_USE_C99_MATH 1
+#define _GLIBCXX_USE_C99_FP_MACROS_DYNAMIC 0
+
+#undef _HAS_TR1_DECLARATIONS
+#define _HAS_TR1_DECLARATIONS 0
+
+#else  // VXWORKS_MAJOR < 7
+
+// For RTPs, use the VxWorks headers as a basis, from which we can use
+// C99 dynamic FP macros and expect (after fixincludes) accurate c++11
+// prototypes for FP.
+
+#ifdef __RTP__
+
+#define _GLIBCXX_INCLUDE_NEXT_C_HEADERS 1
+
+#undef _GLIBCXX_USE_C99_FP_MACROS_DYNAMIC
+#define _GLIBCXX_USE_C99_FP_MACROS_DYNAMIC 1
+
+#define __CORRECT_ISO_CPP11_MATH_H_PROTO_FP
+
+#else // !__RTP__
+
+// libstdc++ will include system headers and vxWorks.h ought to have
+// been included ahead for VxWorks kernel modules prior to VxWorks 7
+#include 
+
+#endif // __RTP__
+
+#endif // _VXWORKS_MAJOR >= 7
+
+// The min/max "functions" may be refered to with a namespace prefix.
+// Prevent possible redefinitions as macros from VxWorks headers.
+#undef NOMINMAX
 #define NOMINMAX 1
 
-#endif
+// Do not include the inline definitions from VxWorks headers, as we'll
+// want to use the ones from libstdc++ instead.
+#undef _NO_CPP_INLINES
+#define _NO_CPP_INLINES 1
+
+#endif // _GLIBCXX_OS_DEFINES
-- 
2.17.1



[patch] Arrange to preinclude yvals.h ahead of stdint on VxWorks 7

2019-12-13 Thread Olivier Hainque

On Vxworks 7, includers of stdint.h (which we currently "provide")
need yvals.h to have been included ahead.

Instead of altering the common stdint-gcc.h with unpleasant
vxworks specific bits to do that, we arrange to provide stdint-gcc.h
on its own along with a stdint.h wrapper which preincludes yvals.h
on vx7 then includes stdint-gcc.h.

Tested in accordance with the description in
https://gcc.gnu.org/ml/gcc-patches/2019-12/msg00911.html

Committing soon to mainline.

Olivier

2019-12-13  Olivier Hainque  

* config/vxworks/stdint.h: New file.  Include _yvals.h
then stdint-gcc.h.
* config/t-vxworks: Arrange to install the stdint.h wrapper.
* config.gcc (*-*-vxworks*): Add stdint-gcc.h to $extra_headers
so it gets copied.  Set use_gcc_stdint to request _not_ crafting
stdint.h through the common Makefile rules.

 gcc/config.gcc  | 14 +++---
 gcc/config/t-vxworks| 12 
 gcc/config/vxworks/stdint.h | 28 
 3 files changed, 51 insertions(+), 3 deletions(-)
 create mode 100644 gcc/config/vxworks/stdint.h

diff --git a/gcc/config.gcc b/gcc/config.gcc
index 4790247a868..ca485af9619 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -962,9 +962,6 @@ case ${target} in
   extra_headers="${extra_headers} ../vxworks/vxworks-predef.h"
   target_has_targetcm="yes"
 
-  use_gcc_stdint=provide
-  tm_file="${tm_file} vxworks-stdint.h"
-
   # This private header exposes a consistent interface for checks on
   # the VxWorks version our runtime header files need to perform, based on
   # what the system headers adverstise:
@@ -982,6 +979,17 @@ case ${target} in
   extra_headers="${extra_headers} ../vxworks/math.h ../vxworks/complex.h"
   extra_headers="${extra_headers} ../vxworks/inttypes.h ../vxworks/setjmp.h"
 
+  # We provide stdint.h ...
+
+  tm_file="${tm_file} vxworks-stdint.h"
+
+  # .. only through the yvals conditional wrapping mentioned above
+  # to abide by the VxWorks 7 expectations.  The final copy is performed
+  # explicitly by a t-vxworks Makefile rule.
+
+  use_gcc_stdint=none
+  extra_headers="${extra_headers} ../../ginclude/stdint-gcc.h"
+
   case ${enable_threads} in
 no) ;;
 "" | yes | vxworks) thread_file='vxworks' ;;
diff --git a/gcc/config/t-vxworks b/gcc/config/t-vxworks
index ce30338ed13..4f9646dd961 100644
--- a/gcc/config/t-vxworks
+++ b/gcc/config/t-vxworks
@@ -24,6 +24,18 @@ vxworks-c.o: $(srcdir)/config/vxworks-c.c
$(COMPILE) $<
$(POSTCOMPILE)
 
+# Arrange to install our stdint.h wrapper, by copying it in the
+# build-time include dir before this include dir is installed and after
+# stmp-int-hdrs removes it (because it was told we don't provide it).
+
+INSTALL_HEADERS += install-stdint.h
+
+install-stdint.h: stmp-int-hdrs
+   cp -p $(srcdir)/config/vxworks/stdint.h include/stdint.h
+   chmod a+r include/stdint.h
+
+$(INSTALL_HEADERS_DIR): install-stdint.h
+
 # Both the kernel and RTP headers provide limits.h.  They embed VxWorks
 # specificities and are dated on some configurations so we both need to
 # provide our own version and make sure the system one gets exposed.
diff --git a/gcc/config/vxworks/stdint.h b/gcc/config/vxworks/stdint.h
new file mode 100644
index 000..5e0dbdfaabd
--- /dev/null
+++ b/gcc/config/vxworks/stdint.h
@@ -0,0 +1,28 @@
+/* This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+.  */
+
+#ifndef __GCC_STDINT_H
+#define __GCC_STDINT_H
+
+#include <_yvals.h>
+#include 
+
+#endif
-- 
2.17.1



Re: [PATCH 11/49] Add diagnostic_metadata and CWE support

2019-12-13 Thread Martin Sebor

On 12/12/19 7:59 PM, David Malcolm wrote:

On Wed, 2019-12-04 at 10:36 -0700, Martin Sebor wrote:

On 11/15/19 6:22 PM, David Malcolm wrote:

This patch adds support for associating a diagnostic with an
optional
diagnostic_metadata object, so that plugins can add extra data to
their
diagnostics (e.g. mapping a diagnostic to a taxonomy or coding
standard
such as from CERT or MISRA).

Currently this only supports associating a CWE identifier with a
diagnostic (which is what I'm using for the analyzer warnings later
in
the patch kit), but adding a diagnostic_metadata class allows for
future
growth in this area without an explosion of further "warning_at"
overloads
for all of the different kinds of custom data that a plugin might
want to
add.


We discussed this in the past so I'll be repeating some of my
comments from that thread.  I like the feature at a high level,
but I'm not sure I see how to make it work in a robust way.

There is no one-to-one mapping between GCC warnings and any of
these classifications.  A single GCC warning might map to several
CERT or MISRA guidelines, and a single guideline might map to two
or more different GCC warnings.  This is an M to N mapping times
the number of coding standards/classifications.  I haven't looked
at the patch kit in enough detail to understand how it tries to
handle it.  Can you explain?


The patch kit gives the ability to (optionally) specify a single CWE
identifier when emitting a diagnostic.

The patch kit uses this in various places for its new warnings for the
cases where there is a well-defined CWE weakness identifier (and
doesn't otherwise).

It doesn't attempt to classify any existing warnings.

It doesn't attempt to support other classifications in this patch, but
it does introduce a diagnostic_metadata object that could gain this
functionality at some later time, if we come up with a scheme we're
happy with (a slight violation of YAGNI, but it's such a pain touching
all the diagnostic fns that I prefer to do it once).


I wasn't necessarily asking about any classifications in particular,
or even about pre-existing warnings.  I think it would be nice to be
able to eventually make it work for them but I obviously realize that
will take quite a bit retrofitting.

What I'd like to understand how the warning X classification-id
mapping for the new analyzer warnings is supported in the design
of the (new) diagnostic infrastructure (or how you envision it
will be when it's more complete).

You said the analyzer currently only supports associating a CWE
identifier with a diagnostic.  By "diagnostic" do you mean
a particular instance of a given warning or all its instances?

Picking an uninitialized use as an example, there are three CWE's
that discuss it:

  CWE-457: Use of Uninitialized Variable
  CWE-824: Access of Uninitialized Pointer
  CWE-908: Use of Uninitialized Resource

but only one -Wanalyzer-use-of-uninitialized-value.  I'd like to
see how the mapping works (or will work) between these three CWE's
and instances of this analyzer option/warning.

I see on Goldbolt that for either the use of an uninitialized
pointer (CWE-457) or for its dereference (CWE-824) the analyzer
issues the same warning with the same CWE ID:

  use of uninitialized value 'p' [CWE-457] 
[-Wanalyzer-use-of-uninitialized-value]


It doesn't differentiate between the two CWE's.

If this limitation is baked into the design of the infrastructure
then that's an obvious flaw that needs to be fixed.  There is no
point in issuing warnings with the wrong CWE's.  Anyone who cares
about CWE's would view those as bugs, and those who don't care
don't need to see them.


My other concern here is that these guidelines evolve.  New ones
are being added, existing ones moved or broken up, etc.  Does
the infrastructure cope with this evolution (e.g., by reading
the mapping from a file)?


Let's cross that bridge when we come to it.  If it becomes a problem,
then we can come up with a fix (e.g. a command-line option to specify
the CWE version).

I agree that dealing with evolving classifications is a secondary
goal that can probably be fairly easily met.  I wanted to know if
there already was a solution for it now.

But referencing the right IDs in the diagnostics seems like a basic
design requirement.  Unless the above example is due to the mapping
not being fully populated yet it seems clear that issuing a warning
with one CWE ID for a bug described under another CWE ID is
a problem.

Martin



Dave


Martin


gcc/ChangeLog:
* common.opt (fdiagnostics-show-metadata): New option.
* diagnostic-core.h (class diagnostic_metadata): New forward
decl.
(warning_at): Add overload taking a const diagnostic_metadata
&.
(emit_diagnostic_valist): Add overload taking a
const diagnostic_metadata *.
* diagnostic-format-json.cc: Include "diagnostic-metadata.h".
(json_from_metadata): New function.
(json_end_diagnostic): Call it to add "metadata" 

[committed, amdgcn] Add sub-dword vector multiply

2019-12-13 Thread Andrew Stubbs

I've committed this patch to add v64qi and v64hi multiply patterns.

This is slowly working toward full char and short vectorization.

Andrew
Sub-dword vector multiply for amdgcn

2019-12-13  Andrew Stubbs  

	gcc/
	* config/gcn/gcn-valu.md (mulv64si3): Rename to ...
	(mul3): ... this, and implement sub-dword patterns.
	(mulv64si3_dup): Rename to ...
	(mul3_dup): ... this, and implement sub-dword patterns.

diff --git a/gcc/config/gcn/gcn-valu.md b/gcc/config/gcn/gcn-valu.md
index e1b3c71971f..42604466161 100644
--- a/gcc/config/gcn/gcn-valu.md
+++ b/gcc/config/gcn/gcn-valu.md
@@ -1740,22 +1740,22 @@
   [(set_attr "type" "vop3a")
(set_attr "length" "8")])
 
-(define_insn "mulv64si3"
-  [(set (match_operand:V64SI 0 "register_operand"  "=   v")
-	(mult:V64SI
-	  (match_operand:V64SI 1 "gcn_alu_operand" "%vSvA")
-	  (match_operand:V64SI 2 "gcn_alu_operand" " vSvA")))]
+(define_insn "mul3"
+  [(set (match_operand:VEC_ALL1REG_INT_MODE 0 "register_operand"  "=   v")
+	(mult:VEC_ALL1REG_INT_MODE
+	  (match_operand:VEC_ALL1REG_INT_MODE 1 "gcn_alu_operand" "%vSvA")
+	  (match_operand:VEC_ALL1REG_INT_MODE 2 "gcn_alu_operand" " vSvA")))]
   ""
   "v_mul_lo_u32\t%0, %1, %2"
   [(set_attr "type" "vop3a")
(set_attr "length" "8")])
 
-(define_insn "mulv64si3_dup"
-  [(set (match_operand:V64SI 0 "register_operand"  "=   v")
-	(mult:V64SI
-	  (match_operand:V64SI 1 "gcn_alu_operand" "%vSvA")
-	  (vec_duplicate:V64SI
-	(match_operand:SI 2 "gcn_alu_operand"  "  SvA"]
+(define_insn "mul3_dup"
+  [(set (match_operand:VEC_ALL1REG_INT_MODE 0 "register_operand"  "=   v")
+	(mult:VEC_ALL1REG_INT_MODE
+	  (match_operand:VEC_ALL1REG_INT_MODE 1 "gcn_alu_operand" "%vSvA")
+	  (vec_duplicate:VEC_ALL1REG_INT_MODE
+	(match_operand: 2 "gcn_alu_operand"	  "  SvA"]
   ""
   "v_mul_lo_u32\t%0, %1, %2"
   [(set_attr "type" "vop3a")


[patch] Setup system header wrappers for C++ on VxWorks

2019-12-13 Thread Olivier Hainque

Starting from VxWorks 7, the system comes with a Dinkumware
environment which requires the inclusion of "yvals.h" before other
system headers.  We provide wrapped versions of a few headers to
accommodate such constraints.

Initially proposed by Jérôme, this helps fix dozens of build issues
when activating libstdc++ on such environments.

Tested in accordance with the description in
https://gcc.gnu.org/ml/gcc-patches/2019-12/msg00911.html

Committing soon to mainline.

Olivier

2019-12-13  Jerome Lambourg  
Olivier Hainque  

gcc/
* config/vxworks/_yvals.h: New file.
* config/vxworks/_yvals-wrapper.h: New file.
* gcc/config/vxworks/math.h: Use it to wrap the VxWorks
math.h header.
* gcc/config/vxworks/complex.h: Likewise.
* gcc/config/vxworks/setjmp.h: Likewise.
* gcc/config/vxworks/inttypes.h: Likewise.
* config.gcc (*-*-vxworks*): Add system header wrappers
to extra_headers.
(powerpc-*-vxworks*): Reuse the common extra_headers.

 gcc/config.gcc  | 16 +-
 gcc/config/vxworks/_yvals-wrapper.h | 44 
 gcc/config/vxworks/_yvals.h | 45 +
 gcc/config/vxworks/complex.h| 28 ++
 gcc/config/vxworks/inttypes.h   | 28 ++
 gcc/config/vxworks/math.h   | 28 ++
 gcc/config/vxworks/setjmp.h | 34 ++
 7 files changed, 222 insertions(+), 1 deletion(-)
 create mode 100644 gcc/config/vxworks/_yvals-wrapper.h
 create mode 100644 gcc/config/vxworks/_yvals.h
 create mode 100644 gcc/config/vxworks/complex.h
 create mode 100644 gcc/config/vxworks/inttypes.h
 create mode 100644 gcc/config/vxworks/math.h
 create mode 100644 gcc/config/vxworks/setjmp.h

diff --git a/gcc/config.gcc b/gcc/config.gcc
index b09a3656be8..4790247a868 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -953,12 +953,15 @@ case ${target} in
 *-*-vxworks*)
   tmake_file=t-vxworks
   xm_defines=POSIX
+
   extra_options="${extra_options} vxworks.opt"
   extra_objs="$extra_objs vxworks.o"
+
   c_target_objs="${c_target_objs} vxworks-c.o"
   cxx_target_objs="${cxx_target_objs} vxworks-c.o"
   extra_headers="${extra_headers} ../vxworks/vxworks-predef.h"
   target_has_targetcm="yes"
+
   use_gcc_stdint=provide
   tm_file="${tm_file} vxworks-stdint.h"
 
@@ -968,6 +971,17 @@ case ${target} in
 
   extra_headers="${extra_headers} ../vxworks/_vxworks-versions.h"
 
+  # Starting from VxWorks 7, the system comes with a Dinkumware
+  # environment which requires the inclusion of "yvals.h" before other
+  # system headers.  We provide wrapped versions of a few headers to
+  # accomodate such constraints:
+
+  extra_headers="${extra_headers} ../vxworks/_yvals.h"
+  extra_headers="${extra_headers} ../vxworks/_yvals-wrapper.h"
+
+  extra_headers="${extra_headers} ../vxworks/math.h ../vxworks/complex.h"
+  extra_headers="${extra_headers} ../vxworks/inttypes.h ../vxworks/setjmp.h"
+
   case ${enable_threads} in
 no) ;;
 "" | yes | vxworks) thread_file='vxworks' ;;
@@ -2918,7 +2932,7 @@ powerpc-wrs-vxworks*)
tm_file="${tm_file} elfos.h gnu-user.h freebsd-spec.h rs6000/sysv4.h"
tmake_file="${tmake_file} rs6000/t-fprules rs6000/t-ppccomm 
rs6000/t-vxworks"
extra_options="${extra_options} rs6000/sysv4.opt"
-   extra_headers=ppc-asm.h
+extra_headers="${extra_headers} ppc-asm.h"
case ${target} in
   *-vxworksmils*)
 tm_file="${tm_file} vx-common.h vxworksae.h rs6000/vxworks.h 
rs6000/vxworksmils.h"
diff --git a/gcc/config/vxworks/_yvals-wrapper.h 
b/gcc/config/vxworks/_yvals-wrapper.h
new file mode 100644
index 000..e7b84c2174d
--- /dev/null
+++ b/gcc/config/vxworks/_yvals-wrapper.h
@@ -0,0 +1,44 @@
+/* This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+.  */
+
+/* The VxWorks 7 environment for C++ is based on a Dinkumware toolchain,
+   where quite a few configuration parameters are exposed in a yvals.h header
+   file which needs to be included before other standard 

[PATCH, c] all plattforms: support using a CC_REG instead cc0_rtx

2019-12-13 Thread Stefan Franke

Hi there,

I suggest this patch to allow architectures do substitute cc0_rtx with a 
generated cc register.


Why? If you are using a cc register plus your architecture as many 
instructions which may clobber that cc register, some passes (e.g. gcse) 
will reorder the insns. This can lead to the situation that an insn is 
moved between a compare and it' consuming jump insn. Which yields 
invalid code. (Note that at these stages clobbers are not yet tracked as 
CLOBBER insns).


To get around this behaviour you have to fake HAVE_CC0, e.g. by adding 
some dummy code to your md file:


   (define_peephole2 [(set (match_operand 0 "" "") (cc0))] "" 
[(const_int 0)] "")


plus some empty macros. All of this can be handled by the arch 
implementation, but not the check for the cc0 inside of


  int sets_cc0_p(const_rtx x)


Changelog

gcc/jump.c: use rtx_equal do determine the identity of cc0_rtx

==
--- a/gcc/jump.c
+++ b/gcc/jump.c
@@ -1028,7 +1028,7 @@ sets_cc0_p (const_rtx x)
   if (INSN_P (x))
 x = PATTERN (x);

-  if (GET_CODE (x) == SET && SET_DEST (x) == cc0_rtx)
+  if (GET_CODE (x) == SET && rtx_equal_p(SET_DEST (x), cc0_rtx))
 return 1;
   if (GET_CODE (x) == PARALLEL)
 {


[patch] Introduce an internal API for VxWorks version checks

2019-12-13 Thread Olivier Hainque

This changes introduces an internal API for VxWorks version checks
within runtime files, a prerequisite to a few fixes coming up for libstdc++
builds on more recent versions of the OS.

Tested in accordance with the description in
https://gcc.gnu.org/ml/gcc-patches/2019-12/msg00911.html

Committing to mainline.

Olivier

2019-12-13  Olivier Hainque  

gcc/
* config/vxworks/_vxworks-versions.h: New file.
* config.gcc (*-*-vxworks*): Add it to extra_headers.

libgcc/
* config/gthr-vxworks.h: Use _vxworks-versions.h.
* config/gthr-vxworks-tls.c: Likewise.

 gcc/config.gcc |  7 
 gcc/config/vxworks/_vxworks-versions.h | 54 ++
 libgcc/config/gthr-vxworks-tls.c   | 10 +++--
 libgcc/config/gthr-vxworks.h   | 12 ++
 4 files changed, 70 insertions(+), 13 deletions(-)
 create mode 100644 gcc/config/vxworks/_vxworks-versions.h

diff --git a/gcc/config.gcc b/gcc/config.gcc
index cf73a853e11..b09a3656be8 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -961,6 +961,13 @@ case ${target} in
   target_has_targetcm="yes"
   use_gcc_stdint=provide
   tm_file="${tm_file} vxworks-stdint.h"
+
+  # This private header exposes a consistent interface for checks on
+  # the VxWorks version our runtime header files need to perform, based on
+  # what the system headers adverstise:
+
+  extra_headers="${extra_headers} ../vxworks/_vxworks-versions.h"
+
   case ${enable_threads} in
 no) ;;
 "" | yes | vxworks) thread_file='vxworks' ;;
diff --git a/gcc/config/vxworks/_vxworks-versions.h 
b/gcc/config/vxworks/_vxworks-versions.h
new file mode 100644
index 000..728e7262a72
--- /dev/null
+++ b/gcc/config/vxworks/_vxworks-versions.h
@@ -0,0 +1,54 @@
+/* This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+.  */
+
+#ifndef _VXWORKS_VERSIONS_H
+#define _VXWORKS_VERSIONS_H  1
+
+/* All we need is access to the bare _WRS_VXWORKS_MAJOR/MINOR macros
+   exposed by version.h.  Cheat a bit to make sure we don't drag additional
+   header files, which can easily cause #include ordering nightmares.  */
+
+#pragma push_macro("_WRS_KERNEL")
+#undef _WRS_KERNEL
+#include 
+#pragma pop_macro("_WRS_KERNEL")
+
+#if !defined(_WRS_VXWORKS_MAJOR)
+#error "VxWorks version macros needed but not defined"
+#endif
+
+#define _VXWORKS_MAJOR_GT(MAJOR) (_WRS_VXWORKS_MAJOR > (MAJOR))
+#define _VXWORKS_MAJOR_GE(MAJOR) (_WRS_VXWORKS_MAJOR >= (MAJOR))
+#define _VXWORKS_MAJOR_LT(MAJOR) (_WRS_VXWORKS_MAJOR < (MAJOR))
+#define _VXWORKS_MAJOR_LE(MAJOR) (_WRS_VXWORKS_MAJOR <= (MAJOR))
+#define _VXWORKS_MAJOR_EQ(MAJOR) (_WRS_VXWORKS_MAJOR == (MAJOR))
+
+#define _VXWORKS_MINOR_GT(MINOR) (_WRS_VXWORKS_MINOR > (MINOR))
+#define _VXWORKS_MINOR_GE(MINOR) (_WRS_VXWORKS_MINOR >= (MINOR))
+#define _VXWORKS_MINOR_LT(MINOR) (_WRS_VXWORKS_MINOR < (MINOR))
+#define _VXWORKS_MINOR_LE(MINOR) (_WRS_VXWORKS_MINOR <= (MINOR))
+#define _VXWORKS_MINOR_EQ(MINOR) (_WRS_VXWORKS_MINOR == (MINOR))
+
+#define _VXWORKS_PRE(MAJOR,MINOR) \
+  (_VXWORKS_MAJOR_LT(MAJOR) \
+   || (_VXWORKS_MAJOR_EQ(MAJOR) && _VXWORKS_MINOR_LT(MINOR)))
+
+#endif
diff --git a/libgcc/config/gthr-vxworks-tls.c b/libgcc/config/gthr-vxworks-tls.c
index 96b6bfbdbe6..63715e65eb8 100644
--- a/libgcc/config/gthr-vxworks-tls.c
+++ b/libgcc/config/gthr-vxworks-tls.c
@@ -45,6 +45,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If 
not, see
 #include 
 #endif
 
+#include <_vxworks-versions.h>
+
 /* Thread-local storage.
 
A gthread TLS key is simply an offset in an array, the address of which
@@ -91,10 +93,10 @@ static int self_owner;
it is only removed when unloading this module.  */
 static volatile int delete_hook_installed;
 
-/* TLS data access internal API.  A straight __thread variable on VxWorks 7,
-   a pointer returned by kernel provided routines otherwise.  */
+/* TLS data access internal API.  A straight __thread variable starting with
+   VxWorks 7, a pointer returned by kernel provided routines otherwise.  */
 
-#ifdef __VXWORKS7__
+#if _VXWORKS_MAJOR_GE(7)
 
 static __thread struct tls_data *__gthread_tls_data;
 
@@ -118,7 

[patch] Simplify the compilation commands for config/vxworks.c

2019-12-13 Thread Olivier Hainque

The patch by Joel setting up TARGET_C_PREINCLUDE exposed a possibility
to simplify/robustify the compilation commands use for another source in
the t-vxworks Makefile fragment.

We now leverage $(COMPILE) and $(POSTCOMPILE) instead of replicating
them manually for vxworks.c.

Tested in accordance with the description in
https://gcc.gnu.org/ml/gcc-patches/2019-12/msg00911.html

Committing to mainline.

Olivier

2019-12-13  Olivier Hainque  

* config/t-vxworks: Rework the vxworks.o compilation
rules to use $(COMPILE).

 gcc/config/t-vxworks | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/gcc/config/t-vxworks b/gcc/config/t-vxworks
index 69b3a2e3199..ce30338ed13 100644
--- a/gcc/config/t-vxworks
+++ b/gcc/config/t-vxworks
@@ -16,9 +16,9 @@
 # along with GCC; see the file COPYING3.  If not see
 # .
 
-vxworks.o: $(srcdir)/config/vxworks.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
-   $(TARGET_H) output.h $(TM_H)
-   $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
+vxworks.o: $(srcdir)/config/vxworks.c
+   $(COMPILE) $<
+   $(POSTCOMPILE)
 
 vxworks-c.o: $(srcdir)/config/vxworks-c.c
$(COMPILE) $<
-- 
2.17.1



[patch] Setup TARGET_C_PREINCLUDE for VxWorks

2019-12-13 Thread Olivier Hainque

This patch modifies the C & C++ VxWorks compiler to predefine
the __STDC_ macros verified by gcc.dg/c99-predef-1.c in the testsuite.
  
We setup a vxworks-predef.h header file which arranges to define
TARGET_C_PREINCLUDE, in a separate config/vxworks
directory where other runtime header files will be added afterwards for
libstdc++ support.

Tested in accordance with the description in
https://gcc.gnu.org/ml/gcc-patches/2019-12/msg00911.html

Committing to mainline.

Olivier

2019-12-13  Joel Brobecker  

* config.gcc <*-*-vxworks*>: Add vxworks-c.o to c_target_objs
and cxx_target_objs. Set target_has_targetcm to "yes". Add
vxworks-predef.h to extra_headers.
* config/t-vxworks (vxworks-c.o): New target.
* config/vxworks-c.c: New file.
* config/vxworks/vxworks-predef.h: New file.

 gcc/config.gcc  |  4 
 gcc/config/t-vxworks|  4 
 gcc/config/vxworks-c.c  | 37 +
 gcc/config/vxworks/vxworks-predef.h | 32 +
 4 files changed, 77 insertions(+)
 create mode 100644 gcc/config/vxworks-c.c
 create mode 100644 gcc/config/vxworks/vxworks-predef.h

diff --git a/gcc/config.gcc b/gcc/config.gcc
index 5aa0130135f..cf73a853e11 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -955,6 +955,10 @@ case ${target} in
   xm_defines=POSIX
   extra_options="${extra_options} vxworks.opt"
   extra_objs="$extra_objs vxworks.o"
+  c_target_objs="${c_target_objs} vxworks-c.o"
+  cxx_target_objs="${cxx_target_objs} vxworks-c.o"
+  extra_headers="${extra_headers} ../vxworks/vxworks-predef.h"
+  target_has_targetcm="yes"
   use_gcc_stdint=provide
   tm_file="${tm_file} vxworks-stdint.h"
   case ${enable_threads} in
diff --git a/gcc/config/t-vxworks b/gcc/config/t-vxworks
index 86b26cc1ecc..69b3a2e3199 100644
--- a/gcc/config/t-vxworks
+++ b/gcc/config/t-vxworks
@@ -20,6 +20,10 @@ vxworks.o: $(srcdir)/config/vxworks.c $(CONFIG_H) 
$(SYSTEM_H) coretypes.h \
$(TARGET_H) output.h $(TM_H)
$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
 
+vxworks-c.o: $(srcdir)/config/vxworks-c.c
+   $(COMPILE) $<
+   $(POSTCOMPILE)
+
 # Both the kernel and RTP headers provide limits.h.  They embed VxWorks
 # specificities and are dated on some configurations so we both need to
 # provide our own version and make sure the system one gets exposed.
diff --git a/gcc/config/vxworks-c.c b/gcc/config/vxworks-c.c
new file mode 100644
index 000..0de94e5eefc
--- /dev/null
+++ b/gcc/config/vxworks-c.c
@@ -0,0 +1,37 @@
+/* C-family target hooks initializer for VxWorks targets.
+   Copyright (C) 2019 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "c-family/c-target.h"
+#include "c-family/c-target-def.h"
+
+/* Implement TARGET_C_PREINCLUDE for vxworks targets.  */
+
+static const char *
+vxworks_c_preinclude (void)
+{
+  return "vxworks-predef.h";
+}
+
+#undef TARGET_C_PREINCLUDE
+#define TARGET_C_PREINCLUDE vxworks_c_preinclude
+
+struct gcc_targetcm targetcm = TARGETCM_INITIALIZER;
diff --git a/gcc/config/vxworks/vxworks-predef.h 
b/gcc/config/vxworks/vxworks-predef.h
new file mode 100644
index 000..0ea70fb8c73
--- /dev/null
+++ b/gcc/config/vxworks/vxworks-predef.h
@@ -0,0 +1,32 @@
+/* This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+.  */
+
+#ifndef _VXWORKS_PREDEF_H
+#define _VXWORKS_PREDEF_H  1
+
+#define 

[patch] Refine definitions for wchar_t/wint_t on VxWorks

2019-12-13 Thread Olivier Hainque

This change refines the VxWorks macro definitions configuring
wchar_t to accommodate the VxWorks7 environment, where wchar_t
is now typically a 32bit type.

We also ensure that the definitions for wint_t are always based
on those for wchar_t, so the two remain in sync in environments
where WCHAR_TYPE is redefined for a specific CPU architecture.

The patch posted here is a minor variation on a change initially
devised by Alexandre, just moved to an even more common place where
other type related definitions are.

Tested in accordance with the description in
https://gcc.gnu.org/ml/gcc-patches/2019-12/msg00911.html

Committing to mainline.

Olivier

2019-12-13  Alexandre Oliva  
Olivier Hainque  

* config/vx-common.h (WCHAR_TYPE_SIZE): 32 on VxWorks 7.
(WCHAR_TYPE): Pick accordingly.
(WINT_TYPE_SIZE): Define in terms of WCHAR_TYPE_SIZE.
(WINT_TYPE): Define in terms of WCHAR_TYPE.

 gcc/config/vx-common.h | 27 +--
 1 file changed, 21 insertions(+), 6 deletions(-)

diff --git a/gcc/config/vx-common.h b/gcc/config/vx-common.h
index ed3e4254e77..594db5122ac 100644
--- a/gcc/config/vx-common.h
+++ b/gcc/config/vx-common.h
@@ -43,17 +43,32 @@ along with GCC; see the file COPYING3.  If not see
 
 /* --- Common type descriptions ---  */
 
-/* VxWorks uses wchar_t == unsigned short (UCS2) on all architectures.  */
+/* Regardless of the target architecture, VxWorks uses a signed 32bit
+   integer for wchar_t starting with vx7 SR06xx.  An unsigned short
+   otherwise.  */
+#if TARGET_VXWORKS7
+
+#undef WCHAR_TYPE_SIZE
+#define WCHAR_TYPE_SIZE 32
 #undef WCHAR_TYPE
-#define WCHAR_TYPE "short unsigned int"
+#define WCHAR_TYPE (TARGET_VXWORKS64 ? "int" : "long int")
+
+#else
+
 #undef WCHAR_TYPE_SIZE
 #define WCHAR_TYPE_SIZE 16
+#undef WCHAR_TYPE
+#define WCHAR_TYPE "short unsigned int"
 
-/* Likewise wint_t.  */
-#undef WINT_TYPE
-#define WINT_TYPE "short unsigned int"
+#endif
+
+/* The VxWorks headers base wint_t on the definitions used for wchar_t.
+   Do the same here to make sure they remain in sync, in case WCHAR_TYPE
+   gets redefined for a specific CPU architecture.  */
 #undef WINT_TYPE_SIZE
-#define WINT_TYPE_SIZE 16
+#define WINT_TYPE_SIZE WCHAR_TYPE_SIZE
+#undef WINT_TYPE
+#define WINT_TYPE WCHAR_TYPE
 
 /* -- Debug and unwind info formats --  */
 
-- 
2.17.1



[patch] Identify sections in vx-common.h

2019-12-13 Thread Olivier Hainque
This patch simply adds sectioning comments in vx-common.h
and moves the NO_DOLLAR/DOT_IN_LABEL block down, away from the
section now dedicated to SPEC strings.

Goal to improve readability and facilitate future changes to come.

Tested in accordance with the description in
https://gcc.gnu.org/ml/gcc-patches/2019-12/msg00911.html

Committing to mainline.

Olivier

2019-12-13  Olivier Hainque  

* config/vx-common.h: Minor reorganization and add
sectioning comments.

 gcc/config/vx-common.h | 20 ++--
 1 file changed, 14 insertions(+), 6 deletions(-)

diff --git a/gcc/config/vx-common.h b/gcc/config/vx-common.h
index c76dccf2c99..ed3e4254e77 100644
--- a/gcc/config/vx-common.h
+++ b/gcc/config/vx-common.h
@@ -18,6 +18,8 @@ You should have received a copy of the GNU General Public 
License
 along with GCC; see the file COPYING3.  If not see
 .  */
 
+/* - Common SPEC strings -  */
+
 /* Most of these will probably be overridden by subsequent headers.  We
undefine them here just in case, and define VXWORKS_ versions of each,
to be used in port-specific vxworks.h.  */
@@ -39,12 +41,7 @@ along with GCC; see the file COPYING3.  If not see
 #define VXWORKS_ENDFILE_SPEC ""
 #define VXWORKS_CC1_SPEC ""
 
-/* VxWorks cannot have dots in constructor labels, because it uses a
-   mutant variation of collect2 that generates C code instead of
-   assembly.  Thus each constructor label must be a legitimate C
-   symbol.  FIXME: Have VxWorks use real collect2 instead.  */
-#undef NO_DOLLAR_IN_LABEL
-#define NO_DOT_IN_LABEL
+/* --- Common type descriptions ---  */
 
 /* VxWorks uses wchar_t == unsigned short (UCS2) on all architectures.  */
 #undef WCHAR_TYPE
@@ -58,6 +55,8 @@ along with GCC; see the file COPYING3.  If not see
 #undef WINT_TYPE_SIZE
 #define WINT_TYPE_SIZE 16
 
+/* -- Debug and unwind info formats --  */
+
 /* Dwarf2 unwind info is supported, unless overriden by a request for a target
specific format.
 
@@ -83,6 +82,15 @@ along with GCC; see the file COPYING3.  If not see
 #undef XCOFF_DEBUGGING_INFO
 #undef VMS_DEBUGGING_INFO
 
+/*  Misc configuration bits --  */
+
+/* VxWorks cannot have dots in constructor labels, because it uses a
+   mutant variation of collect2 that generates C code instead of
+   assembly.  Thus each constructor label must be a legitimate C
+   symbol.  FIXME: Have VxWorks use real collect2 instead.  */
+#undef NO_DOLLAR_IN_LABEL
+#define NO_DOT_IN_LABEL
+
 /* Kernel mode doesn't have ctors/dtors, but RTP mode does.  */
 #define TARGET_HAVE_CTORS_DTORS false
 #define VXWORKS_OVERRIDE_OPTIONS /* empty */
-- 
2.17.1



Fix merging of common target infos

2019-12-13 Thread Jan Hubicka
Hi,
while looking into Firefox regression compared to gcc9 I noticed that we
often confuse common target infos when profiles get merged.  This patch
adds the missing update bits.

Honza

* ipa-utils.c (ipa_merge_profiles): Improve dumping; merge common
targets.

Index: ipa-utils.c
===
--- ipa-utils.c (revision 279178)
+++ ipa-utils.c (working copy)
@@ -423,11 +423,6 @@ ipa_merge_profiles (struct cgraph_node *
   if (!src->count.initialized_p ()
   || !(src->count.ipa () == src->count))
 return;
-  if (symtab->dump_file)
-{
-  fprintf (symtab->dump_file, "Merging profiles of %s to %s\n",
-  src->dump_name (), dst->dump_name ());
-}
   profile_count orig_count = dst->count;
 
   /* Either sum the profiles if both are IPA and not global0, or
@@ -451,6 +446,19 @@ ipa_merge_profiles (struct cgraph_node *
   if (dst->count == orig_count)
 return;
 
+  if (symtab->dump_file)
+{
+  fprintf (symtab->dump_file, "Merging profiles of %s count:",
+  src->dump_name ());
+  src->count.dump (symtab->dump_file);
+  fprintf (symtab->dump_file, " to %s count:",
+  dst->dump_name ());
+  orig_count.dump (symtab->dump_file);
+  fprintf (symtab->dump_file, " resulting count:");
+  dst->count.dump (symtab->dump_file);
+  fprintf (symtab->dump_file, "\n");
+}
+
   /* First handle functions with no gimple body.  */
   if (dst->thunk.thunk_p || dst->alias
   || src->thunk.thunk_p || src->alias)
@@ -516,45 +524,86 @@ ipa_merge_profiles (struct cgraph_node *
   else 
 {
   basic_block srcbb, dstbb;
+  struct cgraph_edge *e, *e2;
 
-  FOR_ALL_BB_FN (srcbb, srccfun)
+  for (e = dst->callees, e2 = src->callees; e && e2 && match;
+  e2 = e2->next_callee, e = e->next_callee)
{
- unsigned int i;
-
- dstbb = BASIC_BLOCK_FOR_FN (dstcfun, srcbb->index);
- if (dstbb == NULL)
+ if (gimple_bb (e->call_stmt)->index
+ != gimple_bb (e2->call_stmt)->index)
{
  if (symtab->dump_file)
fprintf (symtab->dump_file,
-"No matching block for bb %i.\n",
-srcbb->index);
+"Giving up; call stmt mismatch.\n");
  match = false;
- break;
}
- if (EDGE_COUNT (srcbb->succs) != EDGE_COUNT (dstbb->succs))
+   }
+  if (e || e2)
+   {
+ if (symtab->dump_file)
+   fprintf (symtab->dump_file,
+"Giving up; number of calls differs.\n");
+ match = false;
+   }
+  for (e = dst->indirect_calls, e2 = src->indirect_calls; e && e2 && match;
+  e2 = e2->next_callee, e = e->next_callee)
+   {
+ if (gimple_bb (e->call_stmt)->index
+ != gimple_bb (e2->call_stmt)->index)
{
  if (symtab->dump_file)
fprintf (symtab->dump_file,
-"Edge count mismatch for bb %i.\n",
-srcbb->index);
+"Giving up; indirect call stmt mismatch.\n");
  match = false;
- break;
-   }
- for (i = 0; i < EDGE_COUNT (srcbb->succs); i++)
-   {
- edge srce = EDGE_SUCC (srcbb, i);
- edge dste = EDGE_SUCC (dstbb, i);
- if (srce->dest->index != dste->dest->index)
-   {
- if (symtab->dump_file)
-   fprintf (symtab->dump_file,
-"Succ edge mismatch for bb %i.\n",
-srce->dest->index);
- match = false;
- break;
-   }
}
}
+  if (e || e2)
+   {
+ if (symtab->dump_file)
+   fprintf (symtab->dump_file,
+"Giving up; number of indirect calls differs.\n");
+ match=false;
+   }
+
+  if (match)
+   FOR_ALL_BB_FN (srcbb, srccfun)
+ {
+   unsigned int i;
+
+   dstbb = BASIC_BLOCK_FOR_FN (dstcfun, srcbb->index);
+   if (dstbb == NULL)
+ {
+   if (symtab->dump_file)
+ fprintf (symtab->dump_file,
+  "No matching block for bb %i.\n",
+  srcbb->index);
+   match = false;
+   break;
+ }
+   if (EDGE_COUNT (srcbb->succs) != EDGE_COUNT (dstbb->succs))
+ {
+   if (symtab->dump_file)
+ fprintf (symtab->dump_file,
+  "Edge count mismatch for bb %i.\n",
+  srcbb->index);
+   match = false;
+   break;
+ }
+   for (i = 0; i < EDGE_COUNT (srcbb->succs); i++)
+ {
+   edge srce = EDGE_SUCC (srcbb, i);
+   edge 

[committed, amdgcn] Add sub-dword vector extend and truncate insns

2019-12-13 Thread Andrew Stubbs
I've committed the attached patch to add extend, zero_extend, and trunc 
instructions patterns to, from and between the v64qi and v64hi modes.


The patch adds both normal and the masked "exec" variants of the 
patterns, as per the rest of the machine description.


The FP conversions also had to be adjusted because the iterators were 
creating broken (but disabled) integer conversion patterns which 
conflicted with the new ones. Their function has not been altered at all.


This fixes a number of missed-optimization testcases.

Andrew
Sub-dword vector extend and truncate for amdgcn

2019-12-13  Andrew Stubbs  

	gcc/
	* config/gcn/gcn-valu.md (sdwa): New mode attribute.
	(VCVT_FROM_MODE): Rename to ...
	(VCVT_MODE): ... this.
	(VCVT_TO_MODE): Delete mode iterator.
	(VCVT_FMODE): New mode iterator.
	(VCVT_IMODE): Likewise.
	(2): Change ...
	(2): ... to this.
	(2): New.
	(zero_convert): New code iterator.
	(convop): New code attribute.
	(2)
	: New.
	(extend2)
	: New.
	(vec_truncatev64div64si): Rename to ...
	(truncv64di2): ... this and implement sub-dword patterns.
	(vec_truncatev64div64si_exec): Rename to ...
	(truncv64di2_exec): ... this and implement sub-dword patterns.
	(v64di2): New insn_and_split.
	(v64di2_exec): Likewise.
	(mask_gather_load): Update truncate names.
	(mask_scatter_store): Likewise.
	* config/gcn/gcn.c (gcn_expand_scaled_offsets): Update truncate names.

diff --git a/gcc/config/gcn/gcn-valu.md b/gcc/config/gcn/gcn-valu.md
index 16b37e8daab..e1b3c71971f 100644
--- a/gcc/config/gcn/gcn-valu.md
+++ b/gcc/config/gcn/gcn-valu.md
@@ -53,6 +53,8 @@
   [(V64QI "QI") (V64HI "HI") (V64SI "SI")
(V64HF "HF") (V64SF "SF") (V64DI "DI") (V64DF "DF")])
 
+(define_mode_attr sdwa [(V64QI "BYTE_0") (V64HI "WORD_0") (V64SI "DWORD")])
+
 ;; }}}
 ;; {{{ Substitutions
 
@@ -2392,8 +2394,9 @@
 (define_mode_iterator CVT_FROM_MODE [HI SI HF SF DF])
 (define_mode_iterator CVT_TO_MODE [HI SI HF SF DF])
 
-(define_mode_iterator VCVT_FROM_MODE [V64HI V64SI V64HF V64SF V64DF])
-(define_mode_iterator VCVT_TO_MODE [V64HI V64SI V64HF V64SF V64DF])
+(define_mode_iterator VCVT_MODE [V64HI V64SI V64HF V64SF V64DF])
+(define_mode_iterator VCVT_FMODE [V64HF V64SF V64DF])
+(define_mode_iterator VCVT_IMODE [V64HI V64SI])
 
 (define_code_iterator cvt_op [fix unsigned_fix
 			  float unsigned_float
@@ -2416,11 +2419,21 @@
   [(set_attr "type" "vop1")
(set_attr "length" "8")])
 
-(define_insn "2"
-  [(set (match_operand:VCVT_TO_MODE 0 "register_operand""=  v")
-	(cvt_op:VCVT_TO_MODE
-	  (match_operand:VCVT_FROM_MODE 1 "gcn_alu_operand" "vSvB")))]
-  "gcn_valid_cvt_p (mode, mode,
+(define_insn "2"
+  [(set (match_operand:VCVT_FMODE 0 "register_operand" "=  v")
+	(cvt_op:VCVT_FMODE
+	  (match_operand:VCVT_MODE 1 "gcn_alu_operand" "vSvB")))]
+  "gcn_valid_cvt_p (mode, mode,
+		_cvt)"
+  "v_cvt\t%0, %1"
+  [(set_attr "type" "vop1")
+   (set_attr "length" "8")])
+
+(define_insn "2"
+  [(set (match_operand:VCVT_IMODE 0 "register_operand"  "=  v")
+	(cvt_op:VCVT_IMODE
+	  (match_operand:VCVT_FMODE 1 "gcn_alu_operand" "vSvB")))]
+  "gcn_valid_cvt_p (mode, mode,
 		_cvt)"
   "v_cvt\t%0, %1"
   [(set_attr "type" "vop1")
@@ -2429,42 +2442,137 @@
 ;; }}}
 ;; {{{ Int/int conversions
 
+(define_code_iterator zero_convert [truncate zero_extend])
+(define_code_attr convop [
+	(sign_extend "extend")
+	(zero_extend "zero_extend")
+	(truncate "trunc")])
+
+(define_insn "2"
+  [(set (match_operand:VEC_ALL1REG_INT_MODE 0 "register_operand"  "=v")
+(zero_convert:VEC_ALL1REG_INT_MODE
+	  (match_operand:VEC_ALL1REG_INT_ALT 1 "register_operand" " v")))]
+  ""
+  "v_mov_b32_sdwa\t%0, %1 dst_sel: dst_unused:UNUSED_PAD src0_sel:"
+  [(set_attr "type" "vop_sdwa")
+   (set_attr "length" "8")])
+
+(define_insn "extend2"
+  [(set (match_operand:VEC_ALL1REG_INT_MODE 0 "register_operand"  "=v")
+(sign_extend:VEC_ALL1REG_INT_MODE
+	  (match_operand:VEC_ALL1REG_INT_ALT 1 "register_operand" " v")))]
+  ""
+  "v_mov_b32_sdwa\t%0, sext(%1) src0_sel:"
+  [(set_attr "type" "vop_sdwa")
+   (set_attr "length" "8")])
+
 ;; GCC can already do these for scalar types, but not for vector types.
 ;; Unfortunately you can't just do SUBREG on a vector to select the low part,
 ;; so there must be a few tricks here.
 
-(define_insn_and_split "vec_truncatev64div64si"
-  [(set (match_operand:V64SI 0 "register_operand"   "=v,")
-	(truncate:V64SI
-	  (match_operand:V64DI 1 "register_operand" " 0, v")))]
+(define_insn_and_split "truncv64di2"
+  [(set (match_operand:VEC_ALL1REG_INT_MODE 0 "register_operand" "=v")
+	(truncate:VEC_ALL1REG_INT_MODE
+	  (match_operand:V64DI 1 "register_operand"  " v")))]
   ""
   "#"
   "reload_completed"
-  [(set (match_dup 0) (match_dup 1))]
+  [(const_int 0)]
   {
-operands[1] = gcn_operand_part (V64SImode, operands[1], 0);
+rtx inlo = gcn_operand_part (V64DImode, operands[1], 0);
+rtx out = operands[0];
+
+if (mode != V64SImode)
+  emit_insn (gen_truncv64si2 (out, inlo));
+else

Re: AW: [PATCH] m68k architecture: support ccmode + lra

2019-12-13 Thread Segher Boessenkool
On Sat, Dec 14, 2019 at 12:06:36AM +0900, Oleg Endo wrote:
> On Fri, 2019-12-13 at 15:57 +0100, John Paul Adrian Glaubitz wrote:
> > Hello Segher!

Hi :-)

> > > With LRA, sh builds fine (with the combine2 patches).  I have no idea
> > > if correct code is generated, but it doesn't ICE anymore.
> > 
> > What are the combine2 patches?
> 
> See the other thread that I've linked in my message.
> 
> >  And I would support switching SH to LRA as
> > there are a few cases (Debian packages) where GCC fails with an internal
> > compiler error which I reported to the GCC bugzilla.
> 
> Have you tried rebuilding debian on/for SH with -mlra enabled for
> *everything*?  Do you have an easy way of doing that?  It would be
> interesting to see how it goes.

Right; there probably are some things that fail in LRA (that do not fail
without it), as well.  The question is just if it is good enough to switch
now -- LRA has a bright future, old reload is fossilised, it is clear
which of the two is the way forward.

For Power it took a lng time before we could switch.  Hopefully it is
much less work now (LRA itself has improved a lot since).


Segher


Re: AW: [PATCH] m68k architecture: support ccmode + lra

2019-12-13 Thread Richard Sandiford
John Paul Adrian Glaubitz  writes:
> Hi!
>
> On 12/13/19 4:06 PM, Oleg Endo wrote:
>>> What are the combine2 patches?
>> 
>> See the other thread that I've linked in my message.
>
> I don't see any patch there.

The latest version is: https://gcc.gnu.org/ml/gcc-patches/2019-12/msg00287.html
Original submission: https://gcc.gnu.org/ml/gcc-patches/2019-11/msg01654.html

Thanks,
Richard


Re: AW: [PATCH] m68k architecture: support ccmode + lra

2019-12-13 Thread Oleg Endo
On Fri, 2019-12-13 at 16:09 +0100, John Paul Adrian Glaubitz wrote:
> Hi!
> 
> On 12/13/19 4:06 PM, Oleg Endo wrote:
> > > What are the combine2 patches?
> > 
> > See the other thread that I've linked in my message.
> 
> I don't see any patch there.

You'd have to crawl up the discussion or so.
And I think there were a couple of versions.  Anyway, I don't think it
made it into trunk yet. 

> > 
> > Have you tried rebuilding debian on/for SH with -mlra enabled for
> > *everything*?  Do you have an easy way of doing that?  It would be
> > interesting to see how it goes.
> 
> Yes, that would be possible. We would have to enable -mlra in gcc by
> default and then trigger a rebuild for 10.000 source packages. But
> that would take a while to finish.
> 

Better start now then :)
No hurry though.

Cheers,
Oleg



'find_group_last' (was: [PATCH] OpenACC reference count overhaul)

2019-12-13 Thread Thomas Schwinge
Hi Julian!

On 2019-10-29T12:15:01+, Julian Brown  wrote:
> On Mon, 21 Oct 2019 16:14:11 +0200
> Thomas Schwinge  wrote:
>
>> On 2019-10-03T09:35:04-0700, Julian Brown 
>> wrote:
>> > --- a/libgomp/oacc-parallel.c
>> > +++ b/libgomp/oacc-parallel.c
>> > @@ -56,12 +56,29 @@ find_pointer (int pos, size_t mapnum, unsigned
>> > short *kinds)  
>> 
>> I've always been confused by this function (before known as
>> 'find_pset'); this feels wrong, but I've never gotten to the bottom
>> of it.
>
> This version removes that function in favour of a function that finds
> groups of consecutive mappings that should be kept together for a
> single gomp_map_vars invocation. I think that fits better with my
> findings as written up on the wiki page
> https://gcc.gnu.org/wiki/LibgompPointerMappingKinds.

:-) Please guide my trying to understand the changes there:

> --- a/libgomp/oacc-parallel.c
> +++ b/libgomp/oacc-parallel.c
> @@ -47,23 +47,39 @@ _Static_assert (GOACC_FLAGS_UNMARSHAL 
> (GOMP_DEVICE_HOST_FALLBACK)
>   "legacy GOMP_DEVICE_HOST_FALLBACK broken");
>  
>  
> -/* Returns the number of mappings associated with the pointer or pset. PSET
> -   have three mappings, whereas pointer have two.  */
> +/* Some types of (pointer) variables use several consecutive mappings, which
> +   must be treated as a group for enter/exit data directives.  This function
> +   returns the last mapping in such a group (inclusive), or POS for singleton
> +   mappings.  */
>  
>  static int
> -find_pointer (int pos, size_t mapnum, unsigned short *kinds)
> +find_group_last (int pos, size_t mapnum, unsigned short *kinds)
>  {
> -  if (pos + 1 >= mapnum)
> -return 0;
> +  unsigned char kind0 = kinds[pos] & 0xff;
> +  int first_pos = pos, last_pos = pos;
>  
> -  unsigned char kind = kinds[pos+1] & 0xff;
> -
> -  if (kind == GOMP_MAP_TO_PSET)
> -return 3;
> -  else if (kind == GOMP_MAP_POINTER)
> -return 2;
> +  if (kind0 == GOMP_MAP_TO_PSET)
> +{
> +  while (pos + 1 < mapnum && (kinds[pos + 1] & 0xff) == GOMP_MAP_POINTER)
> + last_pos = ++pos;
> +  /* We expect at least one GOMP_MAP_POINTER after a GOMP_MAP_TO_PSET.  
> */
> +  assert (last_pos > first_pos);
> +}
> +  else
> +{
> +  /* GOMP_MAP_ALWAYS_POINTER can only appear directly after some other
> +  mapping.  */
> +  if (pos + 1 < mapnum
> +   && (kinds[pos + 1] & 0xff) == GOMP_MAP_ALWAYS_POINTER)
> + return pos + 1;
> +
> +  /* We can have one or several GOMP_MAP_POINTER mappings after a to/from
> +  (etc.) mapping.  */
> +  while (pos + 1 < mapnum && (kinds[pos + 1] & 0xff) == GOMP_MAP_POINTER)
> + last_pos = ++pos;
> +}
>  
> -  return 0;
> +  return last_pos;
>  }

So I ran a simple experiment where I did:

assert (find_group_last (i, mapnum, kinds) == i + pointer);

... where 'pointer' is the current 'find_pointer' function.  (That is,
compare that the old and new way are doing the same things, given the
current GCC code generation/test cases.)

This 'assert' triggers for a few test cases:
'libgomp.oacc-fortran/allocatable-array-1.f90',
'libgomp.oacc-fortran/data-2.f90', 'libgomp.oacc-fortran/data-3.f90',
'libgomp.oacc-fortran/data-4-2.f90', 'libgomp.oacc-fortran/data-4.f90',
'libgomp.oacc-fortran/data-5.f90', 'libgomp.oacc-fortran/if-1.f90',
'libgomp.oacc-fortran/optional-data-enter-exit.f90'.  (Maybe those are
the only ones actually using that stuff?)

I looked into the first one
('libgomp.oacc-fortran/allocatable-array-1.f90'), and for:

integer, parameter :: n = 40
integer, allocatable :: ar(:,:,:)

allocate (ar(1:n,0:n-1,0:n-1))
!$acc enter data copyin (ar)

... found:

(gdb) print mapnum
$2 = 3
(gdb) print kinds[0]
$3 = 1 // GOMP_MAP_TO
(gdb) print kinds[1]
$4 = 773
(gdb) print kinds[1] & 0xff
$5 = 5 // GOMP_MAP_TO_PSET
(gdb) print kinds[2]
$6 = 772
(gdb) print kinds[2] & 0xff
$7 = 4 // GOMP_MAP_POINTER

Current behavior: 'find_pointer (0, mapnum, kinds) == 3', so all three
get mapped as one group.

New behavior: 'find_group_last (0, mapnum, kinds) == 0', so the
'GOMP_MAP_TO' gets mapped alone.  Then, 'find_group_last (1, mapnum,
kinds) == 2', so the 'GOMP_MAP_TO_PSET', 'GOMP_MAP_POINTER' get mapped as
one group.

Is that intentional?

Any then, compating that to
'libgomp/target.c:GOMP_target_enter_exit_data', where (aside from
'GOMP_MAP_STRUCT'; not relevant for us right now, yes?) everything always
gets mapped alone:

for (i = 0; i < mapnum; i++)
  if ((kinds[i] & 0xff) == GOMP_MAP_STRUCT)
{ [...] }
  else
gomp_map_vars (devicep, 1, [i], NULL, [i], [i],
   true, GOMP_MAP_VARS_ENTER_DATA);

Is it just an "accident" that for OpenACC we were and still are going to
do this differently, or is there an actual reason?


I'm not objecting to changing any of that, but would like to understand
this better.


Grüße
 Thomas


signature.asc
Description: PGP signature


Re: AW: [PATCH] m68k architecture: support ccmode + lra

2019-12-13 Thread John Paul Adrian Glaubitz
Hi!

On 12/13/19 4:06 PM, Oleg Endo wrote:
>> What are the combine2 patches?
> 
> See the other thread that I've linked in my message.

I don't see any patch there.

>>  And I would support switching SH to LRA as
>> there are a few cases (Debian packages) where GCC fails with an internal
>> compiler error which I reported to the GCC bugzilla.
> 
> Have you tried rebuilding debian on/for SH with -mlra enabled for
> *everything*?  Do you have an easy way of doing that?  It would be
> interesting to see how it goes.

Yes, that would be possible. We would have to enable -mlra in gcc by
default and then trigger a rebuild for 10.000 source packages. But
that would take a while to finish.

Adrian

-- 
 .''`.  John Paul Adrian Glaubitz
: :' :  Debian Developer - glaub...@debian.org
`. `'   Freie Universitaet Berlin - glaub...@physik.fu-berlin.de
  `-GPG: 62FF 8A75 84E0 2956 9546  0006 7426 3B37 F5B5 F913


Re: AW: [PATCH] m68k architecture: support ccmode + lra

2019-12-13 Thread Jeff Law
On Fri, 2019-12-13 at 05:03 -0600, Segher Boessenkool wrote:
> On Thu, Dec 12, 2019 at 09:32:27AM +, Richard Sandiford wrote:
> > I doubt it will be long before we deprecate
> > all targets that require old reload.)
> 
> Do we wait until GCC 12 (to remove old reload completely)?  If not, we
> should deprecate it now.
Well, I think the plan was to deprecate the cc0 targets this cycle,
meaning they disappear for gcc-11 along with all the cc0 specific code.
This was a prerequisite for deprecating reload.

I think it's probably too late to try and deprecate reload targets this
cycle.  So deprecate reload targets in gcc-11 with them disappearing in
gcc-12 along with reload itself.  That gives folks plenty of time to
convert the remaining targets.


jeff



Re: AW: [PATCH] m68k architecture: support ccmode + lra

2019-12-13 Thread Oleg Endo
On Fri, 2019-12-13 at 15:57 +0100, John Paul Adrian Glaubitz wrote:
> Hello Segher!
> 
> > With LRA, sh builds fine (with the combine2 patches).  I have no idea
> > if correct code is generated, but it doesn't ICE anymore.
> 
> What are the combine2 patches?

See the other thread that I've linked in my message.


>  And I would support switching SH to LRA as
> there are a few cases (Debian packages) where GCC fails with an internal
> compiler error which I reported to the GCC bugzilla.

Have you tried rebuilding debian on/for SH with -mlra enabled for
*everything*?  Do you have an easy way of doing that?  It would be
interesting to see how it goes.

Cheers,
Oleg





Re: AW: [PATCH] m68k architecture: support ccmode + lra

2019-12-13 Thread John Paul Adrian Glaubitz
Hello Segher!

> With LRA, sh builds fine (with the combine2 patches).  I have no idea
> if correct code is generated, but it doesn't ICE anymore.

What are the combine2 patches? And I would support switching SH to LRA as
there are a few cases (Debian packages) where GCC fails with an internal
compiler error which I reported to the GCC bugzilla.

Adrian

-- 
 .''`.  John Paul Adrian Glaubitz
: :' :  Debian Developer - glaub...@debian.org
`. `'   Freie Universitaet Berlin - glaub...@physik.fu-berlin.de
  `-GPG: 62FF 8A75 84E0 2956 9546  0006 7426 3B37 F5B5 F913


Re: [PATCH, OpenACC] Fix potential race condition in OpenACC "exit data" operations

2019-12-13 Thread Thomas Schwinge
Hi Julian!

On 2019-12-12T19:01:21+, Julian Brown  wrote:
> This is a fix for PR92881, broken out of the larger "reference counting
> overhaul" patch last posted here:
>
> https://gcc.gnu.org/ml/gcc-patches/2019-11/msg02235.html

Thanks!

> The current implementation (potentially with synchronous unmapping of
> a variable/memory block immediately after an asynchronous copyout which
> might not complete beforehand) is "obviously incorrect" by observation

ACK.

> but does not appear to cause any issues with the current testsuite
> (i.e., there is no test improvement with this patch).

Ah, too bad.  ;-|

> Tested with offloading to AMD GCN. OK for trunk?

Yes, with a tiny change as noted below:

> --- a/libgomp/oacc-mem.c
> +++ b/libgomp/oacc-mem.c
> @@ -660,7 +660,6 @@ static void
>  delete_copyout (unsigned f, void *h, size_t s, int async, const char 
> *libfnname)
>  {
>splay_tree_key n;
> -  void *d;
>struct goacc_thread *thr = goacc_thread ();
>struct gomp_device_descr *acc_dev = thr->dev;
>  
> @@ -689,9 +688,6 @@ delete_copyout (unsigned f, void *h, size_t s, int async, 
> const char *libfnname)
>gomp_fatal ("[%p,%d] is not mapped", (void *)h, (int)s);
>  }
>  
> -  d = (void *) (n->tgt->tgt_start + n->tgt_offset
> - + (uintptr_t) h - n->host_start);
> -
>if ((uintptr_t) h < n->host_start || (uintptr_t) h + s > n->host_end)
>  {
>size_t host_size = n->host_end - n->host_start;
> @@ -723,12 +719,15 @@ delete_copyout (unsigned f, void *h, size_t s, int 
> async, const char *libfnname)
>if (f & FLAG_COPYOUT)
>   {
> -   [...]
> +   void *d = (void *) (n->tgt->tgt_start + n->tgt_offset
> +   + (uintptr_t) h - n->host_start);

Not sure why you're moving 'd' as part of this patch, but OK if you'd
like.  ;-)

> --- a/libgomp/target.c
> +++ b/libgomp/target.c

(For anyone else reading, the diff displays a bit weird; what's really
going on is that 'gomp_remove_var' got moved further down, as is nicely
shown by 'git diff --patience'.)

> +static bool
> +gomp_unref_tgt (void *ptr)
>  {
>bool is_tgt_unmapped = false;
> -  [...]
> +
> +  struct target_mem_desc *tgt = (struct target_mem_desc *) ptr;
> +
> +  assert (tgt->refcount != REFCOUNT_INFINITY);

Please leave out this 'assert': we don't have any of these yet for
'tgt->refcount' (as far as I remember), and fixing that is a separate
change, to generally deal that issue;
<87r22an29u.fsf@euler.schwinge.homeip.net">http://mid.mail-archive.com/87r22an29u.fsf@euler.schwinge.homeip.net>.


Grüße
 Thomas


signature.asc
Description: PGP signature


[LTO] PR 86416 – improve lto1 diagnostic if a mode does not exist (esp. for offloading targets)

2019-12-13 Thread Tobias Burnus

As long as one compiles for a single target, the message is unlikely to appear.

However, when compiling for offloading, the modes supported on the target
'host' and on the target 'device' can be different. In particular,
'long double' (when larger than double) and '__float128' might not be
available on the device.

This gives currently errors like the following (see PR, comment 0):

lto1: fatal error: unsupported mode TF  > > compilation terminated. > mkoffload: fatal error: 

x86_64-pc-linux-gnu-accel-nvptx-none-gcc returned 1 exit status

While the device target is hidden in 'x86_64-pc-linux-gnu-accel-nvptx-none-gcc', it might make more sense to 
add it more prominently. Additionally, an average user does

not understand what 'TF' or 'XF' means.

Solutions:
(A) Add the target to the output
(B) Add a better description for the error

I did both in the attached patch, giving:
lto1: fatal error: nvptx-none - 80-bit floating-point numbers unsupported (mode 
'XF')
lto1: fatal error: nvptx-none - 128-bit floating-point numbers unsupported 
(mode 'TF')

* (A) should be fine, I think.

* But I am not 100% happy with (B). I think as interim solution,
it is acceptable as XF/TF are well defined and probably the most
common problem. — Alternatively, one could only commit (A) or
solve it more properly (how?).

* If, e.g., 'long long' or 'integer(kind=16)' are used, only a
generic message is printed.  A message such as "'__float128' not
supported" or "'real(kind=10)' not supported" is more helpful and
supporting all modes and not cherry picking those two would be
useful as well.

The question is how to pass this information to lto-streamer-in.c;
it is available as TYPE_NAME – and, with debugging turned on, this
also gets passed on, but is also not be readily available in
lto_input_mode_table. – Suggestions?


Build on x86-64-gnu-linux and tested without offloading and with nvptx
offloading.

Tobias

	PR middle-end/86416
	*  Makefile.in (CFLAGS-lto-streamer-in.o): Pass target_noncanonical on.
	* lto-streamer-in.c (lto_input_mode_table): Use it; add special error
	diagnostic for missing XF and TF modes.

	PR middle-end/86416
	* testsuite/libgomp.c/pr86416-1.c: New.
	* testsuite/libgomp.c/pr86416-2.c: New.

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 6b857bd75de..657488d416b 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -2244,6 +2244,8 @@ version.o: $(REVISION) $(DATESTAMP) $(BASEVER) $(DEVPHASE)
 # lto-compress.o needs $(ZLIBINC) added to the include flags.
 CFLAGS-lto-compress.o += $(ZLIBINC)
 
+CFLAGS-lto-streamer-in.o += -DTARGET_MACHINE=\"$(target_noncanonical)\"
+
 bversion.h: s-bversion; @true
 s-bversion: BASE-VER
 	echo "#define BUILDING_GCC_MAJOR `echo $(BASEVER_c) | sed -e 's/^\([0-9]*\).*$$/\1/'`" > bversion.h
diff --git a/gcc/lto-streamer-in.c b/gcc/lto-streamer-in.c
index 128d7640726..f59e8c5363d 100644
--- a/gcc/lto-streamer-in.c
+++ b/gcc/lto-streamer-in.c
@@ -1700,7 +1700,19 @@ lto_input_mode_table (struct lto_file_decl_data *file_data)
 		}
 	  /* FALLTHRU */
 	default:
-	  fatal_error (UNKNOWN_LOCATION, "unsupported mode %qs", mname);
+	  /* For offloading-target compilions, this is a user-facing
+		 message.  See also target.def and machmode.def.  */
+	  if (strcmp (mname, "XF") == 0)
+		fatal_error (UNKNOWN_LOCATION,
+			 "%s - 80-bit floating-point numbers unsupported "
+			 "(mode %qs)", TARGET_MACHINE, mname);
+	  else if (strcmp (mname, "TF") == 0)
+		fatal_error (UNKNOWN_LOCATION,
+			 "%s - 128-bit floating-point numbers unsupported "
+			 "(mode %qs)", TARGET_MACHINE, mname);
+	  else
+		fatal_error (UNKNOWN_LOCATION, "%s - unsupported mode %qs",
+			 TARGET_MACHINE, mname);
 	  break;
 	}
 	}
diff --git a/libgomp/testsuite/libgomp.c/pr86416-1.c b/libgomp/testsuite/libgomp.c/pr86416-1.c
new file mode 100644
index 000..c7a162d2f41
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/pr86416-1.c
@@ -0,0 +1,22 @@
+/* { dg-do link } */
+/* { dg-require-effective-target large_long_double } */
+
+/* PR middle-end/86416  */
+/* { dg-error "80-bit floating-point numbers unsupported .mode 'XF'." "" { target offload_device } 0 }  */
+/* { dg-excess-errors "Follow-up errors from mkoffload and lto-wrapper" { target offload_device } }  */
+
+#include   /* For abort. */
+
+long double foo (long double x)
+{
+  #pragma omp target map(tofrom:x)
+x *= 2.0;
+  return x;
+}
+
+int main()
+{
+  long double v = foo (10.0q) - 20.0q;
+  if (v > 1.0e-5 || v < -1.0e-5) abort();
+  return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/pr86416-2.c b/libgomp/testsuite/libgomp.c/pr86416-2.c
new file mode 100644
index 000..75e9cd773a3
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/pr86416-2.c
@@ -0,0 +1,22 @@
+/* { dg-do link { target __float128 } } */
+/* { dg-add-options __float128 } */
+
+/* PR middle-end/86416  */
+/* { dg-error "128-bit floating-point numbers unsupported .mode 'TF'." "" { target offload_device } 0 } */
+/* { 

[patch] Define STARTFILE_PREFIX_SPEC for powerpc VxWorks < 7

2019-12-13 Thread Olivier Hainque
Prior to VxWorks 7, the path where startfiles and core
libraries are located contains CPU architecture specific name
components. This should normally be expressed through a CPU
specific STARTFILE_PREFIX_SPEC for such versions of VxWorks.

This change adds a definition for the PowerPc family, which
have been using for years now.

Tested in accordance with the description in
https://gcc.gnu.org/ml/gcc-patches/2019-12/msg00911.html

Committing to mainline.

Olivier

2019-12-13  Doug Rupp  

* config/rs6000/vxworks.h (STARTFILE_PREFIX_SPEC): Define.

 gcc/config/rs6000/vxworks.h | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/gcc/config/rs6000/vxworks.h b/gcc/config/rs6000/vxworks.h
index dd9a6a23239..4240dfff548 100644
--- a/gcc/config/rs6000/vxworks.h
+++ b/gcc/config/rs6000/vxworks.h
@@ -43,6 +43,13 @@ along with GCC; see the file COPYING3.  If not see
 }  \
   while (0)
 
+/* vx6 library path.  */
+#if !TARGET_VXWORKS7
+#undef  STARTFILE_PREFIX_SPEC
+#define STARTFILE_PREFIX_SPEC  \
+ "%{mrtp:%{!shared:%:getenv(WIND_BASE /target/lib/usr/lib/ppc/PPC32/common)}}"
+#endif
+
 /* Only big endian PPC is supported by VxWorks.  */
 #undef BYTES_BIG_ENDIAN
 #define BYTES_BIG_ENDIAN 1
-- 
2.17.1



Re: AW: [PATCH] m68k architecture: support ccmode + lra

2019-12-13 Thread Oleg Endo
On Fri, 2019-12-13 at 08:09 -0600, Segher Boessenkool wrote:
> On Fri, Dec 13, 2019 at 10:06:20PM +0900, Oleg Endo wrote:
> > On Fri, 2019-12-13 at 05:03 -0600, Segher Boessenkool wrote:
> > > On Thu, Dec 12, 2019 at 09:32:27AM +, Richard Sandiford
> > > wrote:
> > > > I doubt it will be long before we deprecate
> > > > all targets that require old reload.)
> > > 
> > > Do we wait until GCC 12 (to remove old reload completely)?  If
> > > not, we
> > > should deprecate it now.
> > > 
> > 
> > Segher, could you please re-run your tests on SH with -mlra as
> > mentioned here?
> > https://gcc.gnu.org/ml/gcc-patches/2019-12/msg00133.html
> > 
> > I'm thinking to make -mlra the default on SH.
> 
> With LRA, sh builds fine (with the combine2 patches).  I have no idea
> if correct code is generated, but it doesn't ICE anymore.
> 

Great, thanks for checking.  I'll try to run some more tests.

Cheers,
Oleg



[OpenACC] Elaborate/simplify 'exit data' 'finalize' handling (was: [OpenACC] Update OpenACC data clause semantics to the 2.5 behavior)

2019-12-13 Thread Thomas Schwinge
Hi!

Julian, Tobias, regarding the following OpenACC 'exit data' 'finalize'
handling:

On 2018-05-25T13:01:58-0700, Cesar Philippidis  wrote:
> --- a/gcc/gimplify.c
> +++ b/gcc/gimplify.c

> @@ -10859,6 +10849,53 @@ gimplify_omp_target_update (tree *expr_p, gimple_seq 
> *pre_p)

> +  else if (TREE_CODE (expr) == OACC_EXIT_DATA
> +&& omp_find_clause (OMP_STANDALONE_CLAUSES (expr),
> +OMP_CLAUSE_FINALIZE))
> +{
> +  /* Use GOMP_MAP_DELETE/GOMP_MAP_FORCE_FROM to denote that "finalize"
> +  semantics apply to all mappings of this OpenACC directive.  */
> +  bool finalize_marked = false;
> +  for (tree c = OMP_STANDALONE_CLAUSES (expr); c; c = OMP_CLAUSE_CHAIN 
> (c))
> + if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP)
> +   switch (OMP_CLAUSE_MAP_KIND (c))
> + {
> + case GOMP_MAP_FROM:
> +   OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_FORCE_FROM);
> +   finalize_marked = true;
> +   break;
> + case GOMP_MAP_RELEASE:
> +   OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_DELETE);
> +   finalize_marked = true;
> +   break;
> + default:
> +   /* Check consistency: libgomp relies on the very first data
> +  mapping clause being marked, so make sure we did that before
> +  any other mapping clauses.  */
> +   gcc_assert (finalize_marked);
> +   break;
> + }
> +}

> --- a/libgomp/oacc-parallel.c
> +++ b/libgomp/oacc-parallel.c

> @@ -286,6 +360,17 @@ GOACC_enter_exit_data (int device, size_t mapnum,

> +  /* Determine whether "finalize" semantics apply to all mappings of this
> + OpenACC directive.  */
> +  bool finalize = false;
> +  if (mapnum > 0)
> +{
> +  unsigned char kind = kinds[0] & 0xff;
> +  if (kind == GOMP_MAP_DELETE
> +   || kind == GOMP_MAP_FORCE_FROM)
> + finalize = true;
> +}
> +

> @@ -360,22 +458,28 @@ GOACC_enter_exit_data (int device, size_t mapnum,

>   switch (kind)
> {
> -   case GOMP_MAP_POINTER:
> - gomp_acc_remove_pointer (hostaddrs[i], (kinds[i] & 0xff)
> -  == GOMP_MAP_FORCE_FROM,
> -  async, 1);
> - break;
> +   case GOMP_MAP_RELEASE:
> case GOMP_MAP_DELETE:
> - acc_delete (hostaddrs[i], sizes[i]);
> + if (acc_is_present (hostaddrs[i], sizes[i]))
> +   {
> + if (finalize)
> +   acc_delete_finalize (hostaddrs[i], sizes[i]);
> + else
> +   acc_delete (hostaddrs[i], sizes[i]);
> +   }
>   break;
> +   case GOMP_MAP_FROM:
> case GOMP_MAP_FORCE_FROM:
> - acc_copyout (hostaddrs[i], sizes[i]);
> + if (finalize)
> +   acc_copyout_finalize (hostaddrs[i], sizes[i]);
> + else
> +   acc_copyout (hostaddrs[i], sizes[i]);
>   break;
> default:
>   gomp_fatal (" GOACC_enter_exit_data UNHANDLED kind 0x%.2x",
> @@ -385,10 +489,12 @@ GOACC_enter_exit_data (int device, size_t mapnum,
> }
>   else
> {
> - gomp_acc_remove_pointer (hostaddrs[i], (kinds[i] & 0xff)
> -  == GOMP_MAP_FORCE_FROM, async, 3);
> +[...]
> + gomp_acc_remove_pointer (hostaddrs[i], sizes[i], copyfrom, async,
> +  finalize, pointer);

... does the attached patch "[OpenACC] Elaborate/simplify 'exit data'
'finalize' handling" (with "No functional changes") match your
understanding of what's going on?  If approving this patch, please
respond with "Reviewed-by: NAME " so that your effort will be
recorded in the commit log, see .

(It will be a separate discussion to change the 'GOMP_MAP_POINTER',
'GOMP_MAP_TO_PSET' stuff later on -- thinking about the changes from
Julian's big "OpenACC reference count overhaul" as well as
 "OpenACC/OpenMP 'target' 'exit
data'/'update' optimizations".  That patch here is just meant to document
what's going at present, and simplify things as a preparation for other
changes.)


Grüße
 Thomas


From 283577c63b374c3e368e3c0b68b90e19085f193c Mon Sep 17 00:00:00 2001
From: Thomas Schwinge 
Date: Fri, 13 Dec 2019 13:56:51 +0100
Subject: [PATCH] [OpenACC] Elaborate/simplify 'exit data' 'finalize' handling

No functional changes.
---
 gcc/gimplify.c| 23 +++
 gcc/testsuite/c-c++-common/goacc/finalize-1.c | 11 -
 gcc/testsuite/gfortran.dg/goacc/finalize-1.f  | 10 
 libgomp/oacc-mem.c| 14 +++
 4 files changed, 36 insertions(+), 22 deletions(-)

diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 9073680cb31..60a80cb8098 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ 

Re: AW: [PATCH] m68k architecture: support ccmode + lra

2019-12-13 Thread Segher Boessenkool
On Fri, Dec 13, 2019 at 01:19:55PM +0100, Richard Biener wrote:
> On December 13, 2019 12:03:30 PM GMT+01:00, Segher Boessenkool 
>  wrote:
> >On Thu, Dec 12, 2019 at 09:32:27AM +, Richard Sandiford wrote:
> >> I doubt it will be long before we deprecate
> >> all targets that require old reload.)
> >
> >Do we wait until GCC 12 (to remove old reload completely)?  If not, we
> >should deprecate it now.
> 
> That would be a bit of a short notice (removing from GCC11).

Yes.  Maybe that is what is needed for some targets to even try out LRA,
though :-P

> But yes, if we are willing to remove old reload then deprecate it at the 
> start of next stage 1 for it to be removed in GCC 12 stage 1.

Boring :-)


Segher


Re: AW: [PATCH] m68k architecture: support ccmode + lra

2019-12-13 Thread Segher Boessenkool
On Fri, Dec 13, 2019 at 10:06:20PM +0900, Oleg Endo wrote:
> On Fri, 2019-12-13 at 05:03 -0600, Segher Boessenkool wrote:
> > On Thu, Dec 12, 2019 at 09:32:27AM +, Richard Sandiford wrote:
> > > I doubt it will be long before we deprecate
> > > all targets that require old reload.)
> > 
> > Do we wait until GCC 12 (to remove old reload completely)?  If not, we
> > should deprecate it now.
> > 
> 
> Segher, could you please re-run your tests on SH with -mlra as
> mentioned here?
> https://gcc.gnu.org/ml/gcc-patches/2019-12/msg00133.html
> 
> I'm thinking to make -mlra the default on SH.

With LRA, sh builds fine (with the combine2 patches).  I have no idea
if correct code is generated, but it doesn't ICE anymore.


Segher


[patch] Improve recursion protection for VxWorks limits.h

2019-12-13 Thread Olivier Hainque

This change fixes latent failures actually observed when activating
libstdc++ for VxWorks on aarch46 VxWorks 7 and powerpc VxWorks 6.

The system limits.h is dated on some configurations, so we
provide our own version to expose constants required by more
recent C standards.  Our version includes the system
one nevertheless, which has its own specificities. As the system
version sometimes originates from GCC, we need to be careful
that the two files use distinct macro names to protect against
recursive inclusions. 

We achieve this by setting up an alternate header where we update
the inclusion protection macro name:

Tested in accordance with the description in
https://gcc.gnu.org/ml/gcc-patches/2019-12/msg00911.html

Committing to mainline.

2019-12-13  Olivier Hainque  
Jerome Lambourg  

* config/t-vxworks: Arrange to alter/restore glimits.h
before/after stmp-int-hdrs, so it uses a different macro
name to protect itself against recursive inclusions.

 gcc/config/t-vxworks | 37 ++---
 1 file changed, 34 insertions(+), 3 deletions(-)

diff --git a/gcc/config/t-vxworks b/gcc/config/t-vxworks
index d3a350f5f8a..86b26cc1ecc 100644
--- a/gcc/config/t-vxworks
+++ b/gcc/config/t-vxworks
@@ -16,9 +16,40 @@
 # along with GCC; see the file COPYING3.  If not see
 # .
 
-# Both the kernel and RTP headers provide limits.h.
-LIMITS_H_TEST = true
-
 vxworks.o: $(srcdir)/config/vxworks.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TARGET_H) output.h $(TM_H)
$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
+
+# Both the kernel and RTP headers provide limits.h.  They embed VxWorks
+# specificities and are dated on some configurations so we both need to
+# provide our own version and make sure the system one gets exposed.
+
+LIMITS_H_TEST = true
+STMP_FIXINC = stmp-fixinc
+
+# VxWorks system environments have been GCC based for a long time and we need
+# to make sure that our files and the system ones use distinct macro names to
+# protect against recursive inclusions.  We achieve this by temporarily
+# substituting the headers used by stmp-int-headers with alternative versions
+# where we add some version indication in the inclusion-protection macro
+# names.
+
+# Before the standard stmp-int-headers operations take place, arrange to
+# copy the current version of the relevant header files locally, generate
+# the alternate version and replace the original version with ours:
+
+stmp-int-hdrs: subst-glimits.h
+
+subst-%.h:
+   cp -p $(srcdir)/$*.h orig-$*.h
+   ID=$$(echo $(BASEVER_c) | sed -e 's/\./_/g'); \
+   sed -e "s/_LIMITS_H__/_LIMITS_H_$${ID}_/" < $(srcdir)/$*.h > $@
+   cp $@ $(srcdir)/$*.h
+
+# Then arrange to restore the original versions after the standard
+# operations have taken place:
+
+INSTALL_HEADERS += restore-glimits.h
+
+restore-glimits.h: stmp-int-hdrs
+   cp -p orig-glimits.h $(srcdir)/glimits.h
-- 
2.17.1



[patch] Improve VxWorks GTHREAD_ONCE_INIT

2019-12-13 Thread Olivier Hainque

This change improves the GTHREAD_ONCE_INIT initializer
exposed by gthr-vxworks.h to use a more standard syntax
for a zero-initialization, which fixes build failures
observed when activating libstdc++ builds for aarch64-vxworks.

Tested in accordance with the description in
https://gcc.gnu.org/ml/gcc-patches/2019-12/msg00911.html

Committing to mainline.

Olivier

2019-12-13  Olivier Hainque  

* config/gthr-vxworks.h (GTHREAD_ONCE_INIT): Use
standard zero-initializer syntax.

 libgcc/config/gthr-vxworks.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libgcc/config/gthr-vxworks.h b/libgcc/config/gthr-vxworks.h
index 3a30ce31088..2d2860a36dd 100644
--- a/libgcc/config/gthr-vxworks.h
+++ b/libgcc/config/gthr-vxworks.h
@@ -222,7 +222,7 @@ typedef struct
 #endif
 } __gthread_once_t;
 
-#define __GTHREAD_ONCE_INIT { 0 }
+#define __GTHREAD_ONCE_INIT {}
 
 extern int __gthread_once (__gthread_once_t *__once, void (*__func)(void));
 
-- 
2.17.1



[patch] Fix macro reference in gthr-vxworks-tls.c

2019-12-13 Thread Olivier Hainque

This change fixes a typo in a macro name reference, introduced
by mistake during a refactoring.

Tested in accordance with the description in
https://gcc.gnu.org/ml/gcc-patches/2019-12/msg00911.html

Committing to mainline.

Olivier

2019-12-13  Olivier Hainque  

libgcc/
* config/gthr-vxworks-tls.c (__gthread_getspecific): Fix
reference to the internal VX_GET_TLS_DATA interface.

 libgcc/config/gthr-vxworks-tls.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libgcc/config/gthr-vxworks-tls.c b/libgcc/config/gthr-vxworks-tls.c
index cd5f7ac831c..96b6bfbdbe6 100644
--- a/libgcc/config/gthr-vxworks-tls.c
+++ b/libgcc/config/gthr-vxworks-tls.c
@@ -293,7 +293,7 @@ __gthread_getspecific (__gthread_key_t key)
   if (key >= MAX_KEYS)
 return 0;
 
-  data = GET_VX_TLS_DATA();
+  data = VX_GET_TLS_DATA();
 
   if (!data)
 return 0;
-- 
2.17.1



[patch] Fix typo in macro name guarding conditional in vxcrtstuff.c

2019-12-13 Thread Olivier Hainque
Hello,

This patch fixes an obvious typo in a macro name used to
guard some definitions used later on in vxcrtstuff.c, leading
to an unexpected mix of symbols in a vxcrtbegin variant and
incorrect behavior for the corresponding mode at run time.

Tested in accordance with the description in
https://gcc.gnu.org/ml/gcc-patches/2019-12/msg00911.html

Committing to mainline.

Olivier

2019-12-13  Olivier Hainque  

libgcc/
* config/vxcrtstuff.c: Fix incorrect spelling of
USE_INITFINI_ARRAY in guard.

 libgcc/config/vxcrtstuff.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libgcc/config/vxcrtstuff.c b/libgcc/config/vxcrtstuff.c
index 616ad072cba..87fadda9ac5 100644
--- a/libgcc/config/vxcrtstuff.c
+++ b/libgcc/config/vxcrtstuff.c
@@ -38,7 +38,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If 
not, see
Otherwise, we may rely on ctors/dtors sections for RTPs or expect munch to
be involved for kernel modules.  */
 
-#if !defined(USE_INIT_FINI_ARRAY) && defined(__RTP__)
+#if !defined(USE_INITFINI_ARRAY) && defined(__RTP__)
 #define USE_CDTORS_SECTIONS
 #endif
 
@@ -77,7 +77,7 @@ __attribute__((section(__LIBGCC_EH_FRAME_SECTION_NAME__), 
aligned(4)))
 #define EH_CTOR_ATTRIBUTE __attribute__((constructor (101)))
 #define EH_DTOR_ATTRIBUTE __attribute__((destructor (101)))
 
-#else /* USE_INITFINI_ARRAY  */
+#else /* !USE_INITFINI_ARRAY  */
 
 /* Note: Even in case of .ctors/.dtors sections, we can't use the attribute
(constructor (15)) here as gcc may have been configured with constructors
-- 
2.17.1



Re: Add a compatible_vector_types_p target hook

2019-12-13 Thread Richard Sandiford
Richard Biener  writes:
>>> The frontend are in charge of specifying the actual argument type and
>>> at that point the target may fix the ABI. The ABI can be recorded in
>>> the calls fntype, either via its TYPE_ARG_TYPES or in more awkward
>>> ways for varargs functions (in full generality that would mean
>>> attaching varargs ABI meta to each call).
>>>
>>> The alternative is to have an actual argument type vector associated
>>> with each call.
>>
>>I think multiple pieces of gimple code would then have to cope with
>>that
>>as a special case.  E.g. if:
>>
>>   void foo (int, ...);
>>
>>   type1 a;
>>   b = VIEW_CONVERT_EXPR (a);
>>   if (a)
>> foo (1, a);
>>   else
>> foo (1, b);
>>
>>gets converted to:
>>
>>   if (a)
>> foo (1, a);
>>   else
>> foo (1, a);
>>
>>on the basis that type1 and type2 are "the same" despite having
>>different calling conventions, we have to be sure that the calls
>>are not treated as equivalent:
>>
>>   foo (1, a);
>>
>>Things like IPA clones would also need to handle this specially.
>>Anything that generates new calls based on old ones will need
>>to copy this information too.
>>
>>This also sounds like it would be fragile and seems a bit too
>>invasive for stage 3.
>
> But we are already relying on this to work (fntype non-propagation) because 
> function pointer conversions are dropped on the floor. 
>
> The real change would be introducing (per call) fntype for calls to 
> unprototyped functions and somehow dealing with varargs. 

Hmm, OK.  Any suggestions for how the varargs type should be
represented?  We can't just change (int, ...) to (int, foo, bar),
since varargs can be passed differently from non-varargs.  We'd need
something like "(int, ...) used as (int, foo, bar)" instead.

Currently TYPE_ARG_TYPES ends with void_list_node for non-varargs
and null for varargs.  Perhaps we could instead add a "..." marker, so:

:
  unprototyped function

:
  (type1, ...) prototype

:
  (type1, type2) prototype

:
  unprototyped function called with type1

:
  (type1, ...) prototype called with (type1, type2)

If so, would something like that be OK during stage3?

Richard


Re: [testsuite][arm] Remove xfail for vect-epilogues test

2019-12-13 Thread Andre Vieira (lists)

Consequently whilst looking at the list I noticed these two were missing.

This OK for trunk?

gcc/ChangeLog:
2019-12-13  Andre Vieira  

* doc/sourcebuild.texi (arm_little_endian, arm_nothumb):
Documented existing target checks.

On 13/12/2019 13:05, Andre Vieira (lists) wrote:
Thanks for pointing it out Rainer. Thanks to that reminder I noticed 
there is a different way to achieve this without adding that extra 
target check.


This OK?

gcc/testsuite/ChangeLog:

2019-12-12  Andre Vieira  

     * gcc.dg/vect/vect-epilogues.c: XFAIL for arm big endian.

On 12/12/2019 17:41, Rainer Orth wrote:

Hi Andre,


gcc/testsuite/ChangeLog:

2019-12-12  Andre Vieira  

 * gcc.dg/vect/vect-epilogues.c: XFAIL for arm big endian.
 * lib/target-supports.exp 
(check_effective_target_arm_big_endian):

 New target selector.


as always, this needs documenting in sourcebuild.texi.

Rainer

diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi
index 3950c82c685d55cb8aada0465b5337555fafbd92..42e3cdd6b95931ae21aa88fa7805dccf5b4c1371 100644
--- a/gcc/doc/sourcebuild.texi
+++ b/gcc/doc/sourcebuild.texi
@@ -1721,6 +1721,9 @@ Target generates decimal floating point instructions with current options.
 @item arm32
 ARM target generates 32-bit code.
 
+@item arm_little_endian
+ARM target that generates little-endian code.
+
 @item arm_eabi
 ARM target adheres to the ABI for the ARM Architecture.
 
@@ -1808,6 +1811,9 @@ ARM target generates Thumb-1 code for @code{-mthumb}.
 @item arm_thumb2_ok
 ARM target generates Thumb-2 code for @code{-mthumb}.
 
+@item arm_nothumb
+ARM target that is not using Thumb.
+
 @item arm_vfp_ok
 ARM target supports @code{-mfpu=vfp -mfloat-abi=softfp}.
 Some multilibs may be incompatible with these options.


  1   2   >