Stream: general

Topic: termination c vs c++


gnzlbg (Feb 11 2019 at 17:41, on Zulip):

@nagisa do you have a link to the differences in whether termination is an effect in C but not in C++ ? AFAIK it is also an effect in C++. At least a pure+noreturn function seems to be UB in both: https://gcc.godbolt.org/z/scPU2t

nagisa (Feb 11 2019 at 17:43, on Zulip):

well, non-termination is an effect in C, but not C++

nagisa (Feb 11 2019 at 17:43, on Zulip):

specifically because C++ allows optimising out empty loops, but not C.

nagisa (Feb 11 2019 at 17:44, on Zulip):

Did I write it wrong on the issue again?

nagisa (Feb 11 2019 at 17:45, on Zulip):

nah, it seems like whatever I wrote is right, given the ccontext.

gnzlbg (Feb 11 2019 at 17:52, on Zulip):

ah yes, that's correct

gnzlbg (Feb 11 2019 at 17:52, on Zulip):

LLVM is broken in that it treats C and Rust as C++

gnzlbg (Feb 11 2019 at 17:53, on Zulip):

I somehow read it the other way around

gnzlbg (Feb 11 2019 at 17:54, on Zulip):

@nagisa i think that's only for for loops

gnzlbg (Feb 11 2019 at 17:55, on Zulip):

as in, in C++ infinite loops are UB, in C they are not, but the implementation can assume that they terminate

nagisa (Feb 11 2019 at 17:55, on Zulip):

In C while(x) is required to be considered a side-effect as long as x is constant-ish

gnzlbg (Feb 11 2019 at 17:55, on Zulip):

that is in C empty loops can be removed

nagisa (Feb 11 2019 at 17:55, on Zulip):

but if it is not [constant], it is fine if it is not considered as such [side-effect].

gnzlbg (Feb 11 2019 at 17:56, on Zulip):

while(x) { } where x is not a constant expression can be assumed to terminate

nagisa (Feb 11 2019 at 17:57, on Zulip):

That’s what I said :slight_smile:

gnzlbg (Feb 11 2019 at 17:57, on Zulip):

this is different from it being undefined behavior

gnzlbg (Feb 11 2019 at 17:57, on Zulip):

which is what you meant, yes

gnzlbg (Feb 11 2019 at 17:58, on Zulip):

@nagisa so I guess the infinite loop example is ok for both C and C++

gnzlbg (Feb 11 2019 at 17:58, on Zulip):

in C++, it is UB, so anything is allowed

gnzlbg (Feb 11 2019 at 17:58, on Zulip):

in C, it can be assumed to terminate, but the function is noreturn

gnzlbg (Feb 11 2019 at 17:58, on Zulip):

so that would mean that it would return, which would be undefined behavior for a noreturn function

nagisa (Feb 11 2019 at 17:58, on Zulip):

side-effect and terminate are two distinct things.

nagisa (Feb 11 2019 at 17:59, on Zulip):

termination is a side-effect, but not the other way around.

gnzlbg (Feb 11 2019 at 17:59, on Zulip):

the function foo is noreturn,pure, that is, it is not allowed to return, and it is not allowed to have side-effects

nagisa (Feb 11 2019 at 18:00, on Zulip):

right, and therefore pure function must not have an infinite loop in it.

gnzlbg (Feb 11 2019 at 18:00, on Zulip):

the question is whether calling it is always UB

gnzlbg (Feb 11 2019 at 18:00, on Zulip):

in both C and C++

gnzlbg (Feb 11 2019 at 18:00, on Zulip):

ah no, only in C

nagisa (Feb 11 2019 at 18:01, on Zulip):

My initial reaction is that it is, but I haven’t thought much about it. It applies to both C and C++.

nagisa (Feb 11 2019 at 18:01, on Zulip):

C++ has a [[noreturn]] attribute which means what you’d expect. And implementing such function requires a side-effect AFAICT.

gnzlbg (Feb 11 2019 at 18:01, on Zulip):

note that you don't have to use while(x) {}, one can also use for(;;) which in C has no effects AFAICT

nagisa (Feb 11 2019 at 18:02, on Zulip):

basically the question is: can a function be noreturn and also have no side-effects?

nagisa (Feb 11 2019 at 18:03, on Zulip):

to which my answer is "probably no, but I haven’t thought about it that much to tell for sure”

gnzlbg (Feb 11 2019 at 18:03, on Zulip):

so what could such a function do? it could loop forever in C, but if it does that without side-effects, the compiler can remove the loop

gnzlbg (Feb 11 2019 at 18:03, on Zulip):

which would make it try to return, which would be UB

gnzlbg (Feb 11 2019 at 18:04, on Zulip):

it has to do something that does not return, even in the absence of side-effects

gnzlbg (Feb 11 2019 at 18:04, on Zulip):

I don't think that's possible in C (either you do something that has side-effects, or the function will return_

nagisa (Feb 11 2019 at 18:04, on Zulip):

right.

Nicole Mazzuca (Feb 11 2019 at 18:30, on Zulip):

I can't tell if this helps, but you can do local side effects while still being pure (see: Haskell, for example). The following is a program without UB in C++:

void do_no_effect() [[noreturn]] __attribute((const)) {
  int volatile x = 0;
  for (;;) {
    x = 0;
  }
}
nagisa (Feb 11 2019 at 18:34, on Zulip):

@Nicole Mazzuca non-escaping “side-effects” are permitted by the LLVM’s definition of "const" and "pure", not sure about C/C++/gcc, though.

Nicole Mazzuca (Feb 11 2019 at 18:35, on Zulip):

@nagisa they must be

Nicole Mazzuca (Feb 11 2019 at 18:36, on Zulip):

The reason that __attribute((const)) and __attribute((pure)) exist is to allow the implementation to remove function calls

Nicole Mazzuca (Feb 11 2019 at 18:36, on Zulip):

removing a function call which doesn't change global state in any way is totally reasonable

Nicole Mazzuca (Feb 11 2019 at 18:37, on Zulip):

hmm...

Nicole Mazzuca (Feb 11 2019 at 18:37, on Zulip):

no, I see what you're saying

nagisa (Feb 11 2019 at 18:39, on Zulip):

I just genuinely don’t know to claim either way. I just know that LLVM specifically is just fine with that.

gnzlbg (Feb 11 2019 at 18:44, on Zulip):

i've posted a summary comment
https://github.com/rust-lang/rust/pull/58327#discussion_r

gnzlbg (Feb 11 2019 at 18:45, on Zulip):

i'm not sure about the last part

gnzlbg (Feb 11 2019 at 18:45, on Zulip):

whether abort, etc. are side-effects, but I think so

nagisa (Feb 11 2019 at 18:46, on Zulip):

abort is definitely considered to be a global side-effect.

Nicole Mazzuca (Feb 11 2019 at 19:54, on Zulip):

https://twitter.com/GyrosGeier/status/1095037097533153280?s=19

RalfJ (Feb 11 2019 at 20:41, on Zulip):

can be assumed to terminate [...] this is different from it being undefined behavior

I don't see the difference. "x is UB" is exactly the same statement as "x can be assumed not to happen"

RalfJ (Feb 11 2019 at 20:41, on Zulip):

so, "can be assumed to terminate" = "non-termination is UB"

Nicole Mazzuca (Feb 11 2019 at 20:53, on Zulip):

This is the reading of the C++ standards committee

Last update: Nov 20 2019 at 12:10UTC