Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

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

 PRQA QA-C++

Include Page
PRQA QA-C++_V
PRQA QA-C++_V

2510

 
Clang
Include Page
Clang_V
Clang_V
-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"

...