3

I am a bit confused about the way the changes to C++17 affect the rule that you should not modify one variable 2 times between sequence points.

For example is this specified, unspecified or undefined in C++17?

void func(int x, int y);
int x=47;
func(x++,x++);

My guess would be UB.

edit: extra datapoint: clang HEAD in c++2a mode gives

prog.cc:8:11: warning: multiple unsequenced modifications to 'x' [-Wunsequenced]

edit2: same with gcc HEAD in C++2a mode

prog.cc:8:15: warning: operation on 'x' may be undefined [-Wsequence-point]

edit3: with preincrement gcc and clang give different results

NoSenseEtAl
  • 23,776
  • 22
  • 102
  • 222
  • 1
    Well, the answer you linked says `f(i++, i) was undefined but is now unspecified.` – KamilCuk Apr 09 '19 at 10:19
  • According to your link, the order of the evaluation of the parameters is unspecified, it does not cause UB, when depending on the order. – cmdLP Apr 09 '19 at 10:22
  • In other words, if it helps: There are now sequence points (in unspecified order) between evaluations of each function parameter. – jrok Apr 09 '19 at 10:26
  • We don't have sequence points [since C++11](https://en.cppreference.com/w/cpp/language/eval_order). – HolyBlackCat Apr 09 '19 at 10:42
  • @HolyBlackCat I'm not saying we have, it's just might be easier to understand for some if said that way. – jrok Apr 09 '19 at 10:57
  • @NoSenseEtAl: "*I am a bit confused about the way the changes to C++17 affect the rule that you should not modify one variable 2 times between sequence points.*" It doesn't. Even if that had become well-defined behavior, you *shouldn't* deliberately write code like that. These rules are primarily intended for cases where you have no choice, like parameter pack fold expressions, places where variable changes are not easily visible, and the like. You shouldn't use them as an excuse for more `++` abuse. – Nicol Bolas Apr 09 '19 at 13:30
  • @NicolBolas language lawyer questions get asked all the time... Also if somebody is reading this in future: IMAO this is NOT a duplicate Q. – NoSenseEtAl Apr 09 '19 at 15:13
  • @NoSenseEtAl: First, you didn't use the proper tag for that. Second, you cited a rule that is not just a rule of the language; it is a rule of good coding practices. If you had cited the standard specifically, where it says these things are undefined, that would be a different matter. – Nicol Bolas Apr 09 '19 at 15:15
  • I disagree, but anyway it does not matter now since Q is IMAO wrongly closed, so this is just spam for future readers. So if somebody in the future is reading this: my guess is still that code is UB, but I am not sure. – NoSenseEtAl Apr 09 '19 at 15:18
  • @NoSenseEtAl: "*my guess is still that code is UB, but I am not sure.*" Even ignoring the fact that you can work out your answer entirely from information on the duplicate, you got three answers here, *all of which* say that it not UB (though one of them is flatly wrong as to *why*). So how you came to such a guess is beyond me. – Nicol Bolas Apr 09 '19 at 16:05
  • @NicolBolas well long story short is that I have no reason to explain to you why I do not consider 3 bad answers or unrelated question authoritative. – NoSenseEtAl Apr 10 '19 at 02:19
  • @NoSenseEtAl: I have embellished the main answer on the duplicate in a way that more directly addresses your question. But if you find that deficient in some way, you'll have to explain how if you want an answer ;) – Nicol Bolas Apr 10 '19 at 02:33
  • @NicolBolas tnx, but now you are telling me that 2 different compilers give wrong warning? (I know warnings are not required to be 100% correct, but still seems weird) – NoSenseEtAl Apr 10 '19 at 02:36
  • @NoSenseEtAl: It seems like what you're *really* asking is "if the standard says that this is unspecified, why do GCC and Clang say that they're undefined?" – Nicol Bolas Apr 10 '19 at 02:38
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/191570/discussion-between-nosenseetal-and-nicol-bolas). – NoSenseEtAl Apr 10 '19 at 02:40

2 Answers2

1

The example in your question

int x = 0;
f(x++, x++);

Is now unspecified behavior, rather than undefined behavior. That means that it’s valid code, but what actually happens may differ between compilers.

J. Antonio Perez
  • 8,918
  • 16
  • 37
  • The phrase "unspecified behavior" is essentially meaningless. It would be better to say that an implementation may choose in *unspecified fashion* from among the behaviors that could result from evaluating the arguments, individually, in some arbitrary order. – supercat Apr 09 '19 at 20:28
  • You should propose changing the wording! The standards committee is really open to community input, and they encourage everyone to write up and submit papers. It’s a very democratic process – J. Antonio Perez Apr 09 '19 at 20:34
  • I don't think the Standard ever describes any *particular* action as invoking "unspecified behavior". Rather, it describes various particular choices an implementation may make in unspecified fashion. The only places the Standard uses the phrase "unspecified behavior" are when referring collectively to actions whose behavior isn't fully specified [e.g. saying that a program can be correct without all aspects of its behavior being fully specified]. – supercat Apr 09 '19 at 20:38
  • BTW, I think a bigger "wording" problem is the lack of a term to describe actions which should behave in predictable or at least bounded fashion in cases where that would be useful and practical (based on an implementation's target platform and the purposes for which it claims to be suitable), but need not do so in cases that would be useless or impractical. Unfortunately, I don't see any realistic prospect of consensus on such a thing, since some compiler writers are too heavily invested in the notion that all forms of UB should be allowed to "jump the rails". – supercat Apr 10 '19 at 15:55
0

The order of the evaluation of the parameters is unspecified, it means that the compiler can evaluate the parameter in any order, but should not invoke UB. This is nessecary for parameters with an allocation for example, allocation has itself a sideeffect, but for the semantic of the program, the order of allocation should not matter.

class person;

// consumes 2 persons, needs to delete them later
void use_persons(person* a, person* b);

int main() {
    // Alice can be allocated before or after Bob
    use_persons(new person("Alice"), new person("Bob"));
}
cmdLP
  • 1,375
  • 7
  • 17