[gomp] fix gcc.dg/gomp/block-7.c

Richard Henderson rth@redhat.com
Sat Oct 22 01:19:00 GMT 2005


On Fri, Oct 21, 2005 at 08:46:51PM -0400, Diego Novillo wrote:
> Is this so that we can emit better diagnostics for ill-formed code?  Or to 
> handle weirdly formed loops?  What kind of construct do you have in mind 
> here?

Well, ill-formed code is one, though the sort of static analysis
required for the block-7.C test case could be handled in other ways.

I'm thinking mostly of C++ here.  For instance,

  void bar();
  void foo()
  {
    #pragma omp for
    for (int i = (true ? throw 0 : 0); i < 10; ++i)
      bar();
  }

This test case is illegal because the throw leaves the structured block.
But we wouldn't trap this at runtime with the must-not-throw wrapper
because we'd moved the throw outside the loop during gimplification.

More importantly, I'm thinking that it should be possible to write a
legal test case with copy constructors and firstprivate that could tell
how it is being evaluated.  If you look at .t16.useless dumps before
and after my patch for something like

  void bar();
  void foo()
  {
    int i, j;
    #pragma omp parallel shared(j)
    {
      #pragma omp for firstprivate(j)
      for (i = j - 1; i < j + 1; ++i)
    }
  }

Before the patch you can see D.n and D.m being computing j-1 and j+1
respectively being inserted into the parallel before the for.  Once 
the parallel function is broken out, you can see D.n and D.m being
computed using the version of J.s (shared) instead of J.fp (firstprivate).

Now, for integers this doesn't matter, and you can't tell the difference.
But with classes, *anything* could have happened as J.s is copied to J.fp.
And so using the wrong decl has to be wrong.  I would think that 
something like

  class S
  {
    int counter;
  public:
    S() : counter(0) { }
    S(const S &s) : counter(s.counter+1) { }
    int foo() const { if (counter == 0) abort (); return 10; }
  };

  void foo()
  {
    S s;
    #pragma omp parallel shared(s)
    {
      #pragma omp for firstprivate(s)
      for (i = 0; i < s.foo(); ++i)
	bar();
    }
  }

should be well-formed.  S::foo is invariant, so that's fine.  The
program doesn't depend on when the side effect of evaluating S::foo
happens, so that's fine too.  But if we call S::foo on the wrong
object, we'll abort.



r~



More information about the Gcc-patches mailing list