It is possible to devise syntax that can ambiguously be interpreted as either an expression statement or a declaration. Syntax of this sort is called a vexing parse because the compiler must use disambiguation rules to determine the semantic results. The C++ Standard, [stmt.ambig], paragraph 1 [ISO/IEC 14882-2014], states in part, states the following:
There is an ambiguity in the grammar involving expression-statements and declarations: An expression-statement with a function-style explicit type conversion as its leftmost subexpression can be indistinguishable from a declaration where the first declarator starts with a
(. In those cases the statement is a declaration. [Note: To disambiguate, the whole statement might have to be examined to determine if it is an expression-statement or a declaration. ...
A similarly vexing parse exists within the context of a declaration where syntax can be ambiguously interpreted as either a function declaration or a declaration with a function-style cast as the initializer. The C++ Standard, [dcl.ambig.res], paragraph 1, states in part, states the following:
The ambiguity arising from the similarity between a function-style cast and a declaration mentioned in 6.8 can also occur in the context of a declaration. In that context, the choice is between a function declaration with a redundant set of parentheses around a parameter name and an object declaration with a function-style cast as the initializer. Just as for the ambiguities mentioned in 6.8, the resolution is to consider any construct that could possibly be a declaration a declaration.
Do not write a vexing parsesyntactically ambiguous declaration. With the advent of uniform initialization syntax using a braceda braced-init-list, there is now syntax that unambiguously specifies a declaration instead of an expression statement. Declarations can also be disambiguated by using nonfunction-style casts, by initializating initializing using =, or by removing extraneous parenthesis around the parameter name.
...
In this compliant solution, the lock object is given an identifier (other than m) and the proper converting constructor is called:.
| Code Block | ||||
|---|---|---|---|---|
| ||||
#include <mutex>
static std::mutex m;
static int shared_resource;
void increment_by_42() {
std::unique_lock<std::mutex> lock(m);
shared_resource += 42;
} |
...
Parentheses around parameter names are optional, so the following is a semantically identical spelling of the declaration:.
| Code Block | ||||
|---|---|---|---|---|
| ||||
Gadget g(Widget i); |
...
This compliant solution demonstrates two equally compliant ways to write the declaration of g. The first declaration, g1, uses an extra set of parentheses around the argument to the constructor call, forcing the compiler to parse this it as a local variable declaration of type Gadget instead of as a function declaration. The second declaration, g2, uses direct initialization to similar effect.
...
Running this program produces the expected output:.
| Code Block | ||
|---|---|---|
| ||
Widget constructed |
...
Gadget constructed |
...
Widget constructed |
...
Gadget constructed |
...
3 |
Risk Assessment
Syntactically ambiguous declarations can lead to unexpected program execution. However, it is likely that rudimentary testing would uncover violations of this rule.
Rule | Severity | Likelihood | Detectable |
|---|
Repairable | Priority | Level | |
|---|---|---|---|
DCL53-CPP | Low | Unlikely | Yes |
No | P2 | L3 |
Automated Detection
Tool | Version | Checker | Description |
|---|
2510
| CodeSonar |
| LANG.STRUCT.DECL.FNEST | Nested Function Declaration | ||||||
| Helix QAC |
| C++1109, C++2510 | |||||||
| Klocwork |
| CERT.DCL.AMBIGUOUS_DECL | |||||||
| LDRA tool suite |
| 296 S | Partially implemented | ||||||
| Parasoft C/C++test |
| CERT_CPP-DCL53-a | Parameter names in function declarations should not be enclosed in parentheses | ||||||
| Polyspace Bug Finder |
| CERT C++: DCL53-CPP | Checks for declarations that can be confused between:
Rule fully covered. |
| Clang |
| -Wvexing-parse |
| SonarQube C/C++ Plugin |
| S3468 |
Related Vulnerabilities
Search for other vulnerabilities resulting from the violation of this rule on the CERT website.
Bibliography
| [ISO/IEC 14882-2014] | Subclause 6.8, "Ambiguity Resolution" Subclause 8.2, "Ambiguity Resolution" |
| [Meyers |
| 2001] | Item 6, "Be Alert for C++'s Most Vexing Parse" |
...
...