12

Having read about the most vexing parse, I experimented a bit and found this program. There are two very similar lines. One of them yields warnings in both g++7 and clang++-3.9, another does not.

int main() {
  void(); // no warning
  int(); // warning: statement has no effect
}

In the second line a default-constructed object of type int is created and immediately destroyed, thus unused. But what happens in the first line? If it was parsed the same way, it should be an error because it is illegal to create an object of type void. On the other hand, it does not look like a function declaration as well.

Baum mit Augen
  • 49,044
  • 25
  • 144
  • 182
Ivan Smirnov
  • 4,365
  • 19
  • 30
  • 4
    Hmm, could it possibly be related to this? https://stackoverflow.com/questions/34288844/what-does-casting-to-void-really-do – Andrew Sun Feb 21 '18 at 18:37
  • 1
    [clang ast](https://godbolt.org/g/yJY5T2) -> [docs](https://clang.llvm.org/doxygen/classclang_1_1CXXScalarValueInitExpr.html#details) -> [standard](http://eel.is/c++draft/expr.post#expr.type.conv-2) – Shafik Yaghmour Feb 21 '18 at 18:46
  • @Raindrop7 Try -Wall -Wextra, my results are with those. – Ivan Smirnov Feb 21 '18 at 18:46
  • I knew I saw similar, possible dup of [Returning a void?](https://stackoverflow.com/q/20478193/1708801) – Shafik Yaghmour Feb 21 '18 at 18:54
  • @AndrewSun It is not a cast – Shafik Yaghmour Feb 21 '18 at 18:59
  • i guess `void` is not a data type. It is used to declare different things in arguments `function a(void)` , returns `return void` and, of course, universal pointer `void *`. But it is a completely different thing than `int`. So, no wonder that compiler does different treatment for them. Though i would prefer it gives some warning in the first place as well. – Serge Feb 21 '18 at 19:27
  • 4
    Casting to `void` is used to remove warning about unused variable. They probably treat this expression the same way. – Jarod42 Feb 21 '18 at 22:25
  • 1
    @Jarod42 it is an explicit type conversion it is neeed so that [templated functions do the right thing](https://stackoverflow.com/q/20478193/1708801) I don't know why people look at this like casting. – Shafik Yaghmour Feb 22 '18 at 04:40
  • `void()` might also be used to avoid evil comma operator: `(foo(), void(), 0)...`. – Jarod42 Feb 22 '18 at 14:14

2 Answers2

5

There is no difference in parsing. Both cases are covered by simple-type-specifier followed by optional parenthesized expression-list.

The semantic meaning is specified in C++17 (N4659) [expr.type.conv]/2:

If the type is cv void and the initializer is () , the expression is a prvalue of the specified type that performs no initialization. Otherwise, the expression is a prvalue of the specified type whose result object is direct-initialized with the initializer.

This specifically says that void() is a prvalue of type void.

Now, I'm sure that it is not intended that a prvalue of type void be illegal, as it is a common occurrence, e.g. (void)x; or calling a void function!

But I can't find where in the Standard it says that temporary materialization should be suppressed for void prvalues. The [class.temporary]/2 seems to say that a discarded-value expression always materializes a temporary; and it is an error to materialize a prvalue of incomplete type. Maybe it is a defect in the standard.


The difference in warning about "unused value" is probably because an unused value of type void is a common occurrence and it would not be helpful to warn about.

M.M
  • 138,810
  • 21
  • 208
  • 365
0

It is parsed the same way.

Warnings don't come from the parser. They arise during semantic analysis. The SA noticed that a value was created an destroyed by int(); without being read or written.

In the void case, there is no value, so no warning.

user207421
  • 305,947
  • 44
  • 307
  • 483