This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Do C++ signed types have modulo semantics?


Nathan Sidwell <nathan@codesourcery.com> writes:

| Gabriel Dos Reis wrote:
| 
| > But a compiler could define them to be modulo -- that is the whole
| > point.  The paragraph does not say they don't "modulo".
| 
| of course it could do so, but then to be useful it should document it,
| and it would be an extension.

We're in violent agreement there.

| > | 18.2.1.2/57 claims is_modulo is true 'for signed types on most
| > | machines'.  Such an assertion is false when optimizations rely the
| > | undefinedness of signed overflow.  A DR should probably be filed
| > | (maybe one is, I'm not at all familiar with library DRs).
| > Well, undefined behaviour does not mean unconditional hell or  evil.
| > It is just behaviour left up to the compiler to whatever it wants.
| 
| correct.  However the std *itself* says in one place 'this is
| undefined' and in another place 'this is usually modulo'. I find that
| confusing at best.

well, you could send a message to -lib.  The standard does not
prescribe "this is always true", so saying "it is usually true" does
not contradict previous statement that it is undefined -- it is just
as vague.

| > And all useful programs we write rely on undefined behaviour of one
| > sort or the other, starting with GCC.  In the case of
| 
| They do?

Well, just check out GCC for starters :-)

| I thought they usually relied on implementation defined,
| documented extensions or were part of the implementation.  Now I'm
| sure you'll prove me wrong in some way or other, but please stick to
| the point -- do real important programs that must not break and cannot
| be changed rely on signed modulo behaviour?

I don't think that is a useful question, because first we would need
to agree on what is considered "real important programs" when and
where they could or should be changed.

I think what we should address is 

  (1) Can we make it useful, not just left to random blue moon?
  (2) can it be done in a reasonable way?

Just saying, "ah but the standard sys it is undefined behaviour" does
nto sound to me as a satisfying answer.  It one takes the standards
literally, then GCC is not required to be useful; just conformant.
But then you just need "cp /bin/sh gcc" and appropriate documentation.

| > When RTH helped cleanup the numeric_limits implementation in September
| > 2002, he made a very good point (which I held to be true, since
| > obviously he is The Middle-end and Back-end Guy)
| >    http://gcc.gnu.org/ml/libstdc++/2002-09/msg00207.html
| 
| thanks for that.  I was under the impression that some of the loop
| optimizers relied on the fact that iterating over a signed type did
| not do odd modulo related things. 

yes, but in the case of the *concrete* targets supported by GCC, do
you know of any that "do odd modulo related things"?  
GCC's documentation GCC/gcc/doc/implement-c.texi says:

   GCC supports only two's complement integer types, and all bit patterns
   are ordinary values.

And, in the case of 2's complement, the relation between the min, max of
signed integer type is well-defined.  It is not left up to the will of
the Go'aulds.

|  Indeed this comment in loop.c
| concerning BIVs leads me to believe we already fail to honor the
| is_modulo value
| 
|     Note that treating the entire pseudo as a BIV will result in making
|     simple increments to any GIVs based on it.  However, if the variable
|     overflows in its declared mode but not its promoted mode, the result will
|     be incorrect.  This is acceptable if the variable is signed, since
|     overflows in such cases are undefined, but not if it is unsigned, since
|     those overflows are defined.  So we only check for SIGN_EXTEND and
|     not ZERO_EXTEND.

As I said earlier, we do have a consistency problem in GCC and this is
an area where we would be nore useful in improving things.  I do not
consider lengthy discussions exemplified bt late VRP thing very
useful.  It does not really help much arguing "but it is undefined
behaviour".  Yes, we can define it to something useful when we can
(and we should).

| Anyway, this doesn't answer Michael's question.  He asked whether C
| and C++ differ in this regard.  The answer is the standards are the
| same, and the implementation is the same (because it is the same
| backend). 

With the difference that C++ gives users a hook to ask for more information.
And that makes a real difference -- as opposed to a mere "undefined
behaviour".

| So, if whatever optimizations he is turning on change the
| behaviour rth cited, then limits should change too.

As I said, I'm for consistent semantics.  The question remains as
whether we should reflect reality -- the arithmetic is modulo -- or
just leave in the abstract tower of "standard says it is undefined
behaviour". 

| I don't particularly care what behaviour is chosen, except that
| 
| 1) C and C++ implementations should behave the same way
| 
| 2) we should pick the behaviour that leads to better code generation in real life.

We can generate better code if we don't care about semantics and
usefulness.  Just compile the program as if it was

   int main() { } 

| 3) if modulo behaviour is chosen, it should be well documented in a
| place more prominant than type_traits<int>::is_modulo.

I'm all for more documentation and if you could help there, it would
be appreciated.

-- Gaby


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]