...
Do not write a syntactically ambiguous declaration, including vexing parses. With the advent of uniform initialization syntax using a 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, initialization using =
, or by removing extraneous parenthesis around the parameter name.
Noncompliant Code Example
In this noncompliant code example, an attempt is made to declare a local variable, w
, of type Widget
while executing the default constructor. However, this is syntactically ambiguous where the code could either be a declaration of a function pointer accepting no arguments and returning a Widget
, or a declaration of a local variable of type Widget
. The syntax used in this example defines the former instead of the latter.
...
As a result, this program compiles and prints no output, because the default constructor is never actually invoked.
Compliant Solution
This compliant solution shows two equally-compliant ways to write the declaration. The first way is to elide the parenthesis after the variable declaration; this ensures the syntax is that of a variable declaration instead of a function declaration. The second way is to use a braced-init-list to direct-initialize the local variable.
...
Running this program produces the output: Constructed
.
Noncompliant Code Example
This noncompliant code example demonstrates a vexing parse. The declaration Gadget g(Widget(i));
is not parsed as declaring a Gadget
object with a single argument, but is instead parsed as a function declaration with a redundant set of parenthesis around a parameter.
...
As a result, this program is well-formed and prints only 3
as output, because no Gadget
or Widget
objects are constructed.
Compliant Solution
This compliant solution demonstrates two equally-compliant ways to write the declaration of g
. The first declaration, g1
, uses an extra set of parenthesis around the argument to the constructor call, forcing the compiler to parse this as a local variable declaration of type Gadget
instead of as a function declaration. The second declaration, g2
, uses direct initialization to similar effect.
...
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 | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
DCL34-CPP | Low | Unlikely | Medium | P2 | L3 |
Automated Detection
Tool | Version | Checker | Description | ||||||
---|---|---|---|---|---|---|---|---|---|
| 2510 | ||||||||
Clang |
| -Wvexing-parse |
Related Vulnerabilities
Search for other vulnerabilities resulting from the violation of this rule on the CERT website.
Related Guidelines
|
Bibliography
[ISO/IEC 14882-2014] | 6.8, "Ambiguity resolution" 8.2, "Ambiguity resolution" |
[Meyers 01] | Item 6, "Be alert for C++'s most vexing parse" |
...