From: Gabriel Dos Reis on
Al <two(a)haik.us> writes:

[...]

| > Wouldn't nasal demons be an advantage, in practice?
|
| Well, I don't see how C++'s approach, i.e., anything can happen,
| including expressly crashing the plane into the ground, or launching all
| the nukes available intentionally, is _at all_ better than Java's
| approach, i.e., one undefined numerical quantity with zero memory
| corruption.

I don't claim C++'s approach is better. But I do dispute that the
Java alternative is better. I suspect we're here in a territory where
there is no (unconditional) total order of behaviour.

--
Gabriel Dos Reis
gdr(a)integrable-solutions.net

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Andrei Alexandrescu (See Website For Email) on
James Kanze wrote:
> Andrei Alexandrescu (See Website For Email) wrote:
>>I guess the set of "all hell breaks loose" is much larger, and includes,
>>the set "there is one incorrect value". I am sitting here in amazement I
>>have so much trouble getting this point across.
>
>
> Certainly. The only point I'm trying to make (here---there seem
> to be multiple issues being discussed in parallel) is that even
> with Java's "defined behavior", all hell can break loose. That
> both are really "undefined behavior".
>
> Except that we're not really discussing the undefined behavior I
> find in Java. I agree that requiring error checking is a good
> thing. And that C++ has too much undefined behavior, especially
> in a lot of cases where there's absolutely no need for it.
> Somehow, the argument has gotten away from my statement that all
> languages have some forms of undefined behavior.

And I disagree with that statement - as simple as that. There are
definitely languages (Haskell, ML) that do not have undefined behavior.
So you'd need at least to qualify your statement with "all non-academic
languages have some forms of undefined behavior".

Even after that qualification, I still disagree with you, subject on how
you define "undefined behavior". If you define "undefined behavior" as
in C++, then I flat out disagree with you. If you defined "undefined
behavior = produces undefined numbers", then I'd agree. The fact that
we're in a C++ forum suggests that "undefined behavior" carries the C++
conotation of the phrase, which is "there is no guarantee about this
program henceforth". So I want to clear that out.

To summarize so far: (1) I find your statement "all languages have some
forms of undefined behavior" wrong because there are languages, be they
academic or of limited market penetration, that do not have undefined
behavior; (2) Even after we restrict the statement to industrial
languages, the statement is still wrong because it uses "undefined
behavior" with its implicit C++ meaning.

> On the other hand, it's impossible to eliminate it entirely;
> some of it comes directly from the hardware we run on, and
> eliminating other cases (e.g. some of the threading issues)
> really does impose unacceptably high run-time costs.

IMHO the whole non-deterministic hardware branch of discussion is a big
smelly red herring pulled on the trail. This is not a hardware forum. We
discuss the whole issue within the confines of a hardware model, and
artificially taking the discussion to metaphysical levels would only
lead to purpose-of-life kind of questions.

> Try doing any multithreaded programming without proper
> synchronization, and you'll get unpredictable results. The
> language standard doesn't specify what happens globally, even if
> it tries to specify most individual accesses. And if what
> happens isn't defined, how can you say that it isn't
> "undefined".

I Java, I'll get wrong numbers but never violated objects. The program
remains well-defined, only the numbers subject to races have undefined
content.


Andrei

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Walter Bright on
Gabriel Dos Reis wrote:
> Walter Bright <walter(a)digitalmars-nospamm.com> writes:
>
> | Gabriel Dos Reis wrote:
> | > Fortunately, not all compilers out there made the decision to actively
> | > unsupport abstractions like the Digital Mars compiler.
> |
> | Name one that returns std::complex values in a register pair.
>
> I did in the part that was consciously left out from your reply.
>
> GCC/g++.

You didn't mention GCC/g++ or x86-64. You mentioned the PowerPC and the
Itanium. It's hard to elide something that wasn't there. Furthermore,
the ABI quotes you gave in one place say the size has to be 8 bytes or
less (won't work for complex types), and another quote only talks about
single values, not multiple values (in register pairs).

> Given
>
> #include <complex>
>
> std::complex<double>
> add(std::complex<double> x, std::complex<double> y)
> {
> return x + y;
> }
>
> It produces, for a target that identifies itself as x86_64-suse-linux,
>
> _Z3addSt7complexIdES0_:
> .LFB1756:
> addsd %xmm3, %xmm1
> addsd %xmm2, %xmm0
> ret
>

Good for g++ on the X86_64. g++ for the x86 does not do this (I checked
it), although there are floating point registers available. The asm
output of g++ is cut and pasted from actual g++ output.

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Gabriel Dos Reis on
"Jeffrey Yasskin" <jyasskin(a)gmail.com> writes:

| On Nov 30, 7:27 am, Gabriel Dos Reis <g...(a)integrable-solutions.net>
| wrote:
| > The Itanium Software Conventions and Runtime Architecture Guide
| > specifies (page 8-13) that certain aggregates are returned in
| > registers. That is lift to C++ UDT if they don't have non-trivial
| > *copy-constructor* or *destructor*. See the "common C++ ABI"
| > specification
| >
| > http://www.codesourcery.com/cxx-abi/abi.html#calls
| >
| > In general, C++ return values are handled just like C return
| > values. This includes class type results returned in
| > registers. However, if the return value type has a non-trivial copy
| > constructor or destructor, the caller allocates space for a
| > temporary, and passes a pointer to the temporary as an implicit
first
| > parameter preceding both the this parameter and user parameters. The
| > callee constructs the return value into this temporary.
|
| Since std::complex has a non-trivial copy constructor

Not with any version of GCC/g++ I've been using for more than half a
decade now.

| (well, actually it can be trivial;

Not just it can; it *is* trivial. I carefully implemented that library
component that way.

| libstdc++ in gcc 4.0.0 does it...), it can't be returned in
| registers on the Itanium.

What if you tried and it did, would you call it a miracle? :-)
I already posted this example, but I'll produce it again:

#include <complex>

std::complex<double>
add(std::complex<double> x, std::complex<double> y)
{
return x + y;
}

For the target x86_64-suse-linux, GCC/g++ generates:

_Z3addSt7complexIdES0_:
.LFB1756:
addsd %xmm3, %xmm1
addsd %xmm2, %xmm0
ret

| Are there any ABIs that allow it?

Yes, but apparently you don't want to believe.

| I know very little about ABI design, but I'd guess that it's very
| tricky to specify that a compiler must implement a particular level of
| optimizations on an interface boundary.

The ABI specification in binding. Therefore, it does not become an
optimization anymore -- by definition, an optimization does not change
the observable behaviour. If you have an ABI that says, the compiler
must return in register in particular circumstances, then the
compiler has no choice, it must do it. Otherwise it miscompiles
programs. If you have an ABI that says the compiler must return in
memory, the compiler must do it that way.

| Walter's opportunity is to
| define a language feature that would let a library writer help the
| compiler pass and return UDTs in registers even when the copy
| constructor is non-trivial, and do it uniformly enough to specify in
| the ABI.

I'm disputing very specific claims, not vapor language features.

--
Gabriel Dos Reis
gdr(a)integrable-solutions.net

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Gabriel Dos Reis on
Walter Bright <walter(a)digitalmars-nospamm.com> writes:


[...]

| For example (I think we can agree that Foo doesn't get any more trivial!):

Sure!

| ------------- C++ ------------------
| struct Foo { int x; };
|
| Foo bar(int i)
| {
| Foo f;
| f.x = i;
| return f;
| }
| ------------- g++ ------------------
| _Z3bari:
| pushl %ebp
| movl %esp, %ebp
| movl 8(%ebp), %edx
| movl 12(%ebp), %eax
| movl %eax, (%edx)
| movl %edx, %eax
| leave
| ret $4
| ----------- DMC++ ------------------
| ?bar@@YA?AUFoo@@H@Z:
| mov EAX,4[ESP]
| ret
| ------------------------------------
| g++ is returning f on the stack, DMC++ in register EAX.

I don't know which g++ you're using as g++ and which platform
you're compiling for, but an old version of g++ (4.1.0) I have on a
machine that identifies itself as x86_64-suse-linux compiles your
function bar to:

_Z3bari:
.LFB2:
movl %edi, %eax
ret

--
Gabriel Dos Reis
gdr(a)integrable-solutions.net

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]