14

to describe the problem simply, please have a look at the code below:

int main()
{
    int a=123;
    ({if (a) a=0;});
    return 0;
}

I got this warning from [-Wsequence-point]

Line 4: warning: operation on 'a' may be undefined

my g++ version is 4.4.5

I'll appreciate whoever would explain this simple problem.

btw you could find my original program and original problem in #7 in this Chinese site (not necessary)

UPD1:

though to change the code into ({if(a) a=0; a;}) can avoid the warning, but I recognized that the real reason of the problem may not be The last thing in the compound statement should be an expression followed by a semicolon.

because the documentary also said If you use some other kind of statement last within the braces, the construct has type void, and thus effectively no value.

an example can show it:

int main()
{
    int a=123, b;
    ({;});
    ({if (a) b=0;});
    return 0;
}

and this code got no warnings! so I think the real reason is something about sequence point.

please help!

UPD2:

sorry to @AndyProwl for having unaccept his answer which was accepted before UPD1. following his advise I may ask a new question (UPD1 is a new question different from the original one). I'll accept his answer again because it surely avoids warnings anyhow.:)

If I decided to ask a new question, I'll update this question to add a link.

FLanS39
  • 143
  • 1
  • 6
  • There's no sequence point inside the statement expression, yet you are modifying `a` in there. That's UB. –  May 30 '13 at 14:32
  • @H2CO3 inside the statement expression full expressions exist. why no sequence points? hoping you would elaborate on your comment – FLanS39 Jun 01 '13 at 09:36

1 Answers1

5

According to the C++ grammar, expressions (apart from lambda expressions perhaps, but that's a different story) cannot contain statements - including block statements. Therefore, I would say your code is ill-formed, and if GCC compiles it, it means this is a (strange) compiler extension.

You should consult the compiler's reference to figure out what semantics it is given (or not given, as the error message seems to suggest) to it.

EDIT:

As pointed out by Shafik Yaghmour in the comments, this appears to be a GNU extension. According to the documentation, the value of this "statement expression" is supposed to be the value of the last statement in the block, which should be an expression statement:

The last thing in the compound statement should be an expression followed by a semicolon; the value of this subexpression serves as the value of the entire construct. (If you use some other kind of statement last within the braces, the construct has type void, and thus effectively no value.)

Since the block in your example does not contain an expression statement as the last statement, GCC does not know how to evaluate that "statement expression" (not to be confused with "expression statement" - that's what should appear last in a statement expression).

To prevent GCC from complaining, therefore, you should do something like:

({if (a) a=0; a;});
//            ^^

But honestly, I do not understand why one would ever need this thing in C++.

Community
  • 1
  • 1
Andy Prowl
  • 124,023
  • 23
  • 387
  • 451
  • 2
    It is a gcc extension: http://stackoverflow.com/questions/3079721/are-statement-and-declarations-in-expressions-specific-to-gnu-c although the docs are a minimal: http://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html ... I was hoping H2C03 would elaborate on his comment. – Shafik Yaghmour May 30 '13 at 14:57
  • Just compiled the sample with `gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3`, with `gcc -Wall -Wsequence-point`... no errors, no warnings. Quite strange. – Matthieu Rouget May 30 '13 at 14:58
  • @MatthieuM.: So this was basically meant to initialize `const` variables before we had lambdas, right? – Andy Prowl May 30 '13 at 15:05
  • @MatthieuRouget 's fact is very useful. I also doubt that's a bug on specific gcc version because you can see Normal(ans) gots a warning but Normal(a[i][j]) did not in my original code. – FLanS39 May 30 '13 at 15:07
  • @MatthieuM.: Is this supposed to be enabled in GCC by default ? I got a `error: void value not ignored as it ought to be`with your line. – Matthieu Rouget May 30 '13 at 15:07
  • @MatthieuM.: Still, I don't think that would work: the spec says that the last thing in the block statement has to be an expression followed by a semicolon. Moreover, why not `x ? 0 : 123`? – Andy Prowl May 30 '13 at 15:08
  • @AndyProwl: it's a stand-in for lambdas as far as local anonymous functions go, yes. I like the usage in the gcc example page as well (using it in a macro to avoid evaluating macro arguments multiple times). – Matthieu M. May 30 '13 at 15:09
  • @MatthieuRouget: you are right, slight mistake on my part (deleted my comment, I could not edit it), the real proper usage is: `int a = ({ int _z; if (...) _z = 0; else _z = 123; _z; });`. – Matthieu M. May 30 '13 at 15:11
  • @AndyProwl: Well, in this case the ternary operator would indeed be called for, but you can have as many statements as necessary in an expression statement so you can perform multiple operations not just a single `if` branching. – Matthieu M. May 30 '13 at 15:12
  • @MatthieuM.: OK thanks. Interesting, didn't know this feature. – Matthieu Rouget May 30 '13 at 15:13
  • @MatthieuM.: I see, but still - with respect to your last example - why not doing: ` int _z; if (...) _z = 0; else _z = 123; int a = _z`? Perhaps because we would not want to have `_z` in the scope of `a`? – Andy Prowl May 30 '13 at 15:14
  • @AndyProwl: Yes, I guess so. Anyway it's moot for C++11 users thanks to lambdas now :) – Matthieu M. May 30 '13 at 15:16
  • Cool! according to @AndyProwl 's code, **no warnings anymore**! I'll read the documentation more carefully. BTW, statement expression is an important gcc extension which is widely used in linux kernel source (for "macro function") – FLanS39 May 30 '13 at 15:28
  • @FLanS39: Why did you unaccept this answer? Does it not solve your problem? – Andy Prowl Jun 01 '13 at 09:51
  • @AndyProwl very sorry for that. I'd tried to sent a message to you to explain why I unaccept it but I didn't find out how to sent a message. – FLanS39 Jun 01 '13 at 13:03
  • @AndyProwl I updated my question. sorry again for my impolite. – FLanS39 Jun 01 '13 at 13:04
  • @FLanS39: Don't worry about unaccepting (you left an explanation, so that's OK). Honestly, I think the problem is with GCC issuing a wrong message. AFAICT, there is nothing in your code that may lead to undefined behavior. However, if you want this question to receive more attention, you will probably have to ask another question and link it to this one, or offer a bounty - otherwise, nobody will be able to notice that your question has been edited (except for me, because I got notified that my answer was unaccepted). – Andy Prowl Jun 01 '13 at 13:07
  • @AndyProwl your advise is very helpful for me stackoverflow new comer! thank you very much! I may edit my question soon – FLanS39 Jun 01 '13 at 13:11