Ambiguous declaration syntax
Declaration syntax can be interpreted as object declaration or part of function declaration
Description
This defect occurs when it is not clear from a declaration whether an object declaration or function/parameter declaration is intended. The ambiguity is often referred to as most vexing parse.
For instance, these declarations are ambiguous:
ResourceType aResource();
It is not immediately clear if
aResourceis a function returning a variable of typeResourceTypeor an object of typeResourceType.TimeKeeper aTimeKeeper(Timer());
It is not immediately clear if
aTimeKeeperis an object constructed with an unnamed object of typeTimeror a function with an unnamed function pointer type as parameter. The function pointer refers to a function with no argument and return typeTimer.
The checker does not flag ambiguous declarations with global scope. For instance, the
analysis does not flag declarations with global scope using the format
Type a() where
Type is a class type with a default constructor. The
analysis interprets a as a function returning the type
Type.
Risk
In case of an ambiguous declaration, the C++ Standard chooses a specific interpretation of the syntax. For instance:
- is interpreted as a declaration of a function
ResourceType aResource();
aResource. - is interpreted as a declaration of a function
TimeKeeper aTimeKeeper(Timer());
aTimeKeeperwith an unnamed parameter of function pointer type.
If you or another developer or code reviewer expects a different interpretation, the results can be unexpected.
For instance, later you might face a compilation error that is difficult to understand. Since the default interpretation indicates a function declaration, if you use the function as an object, compilers might report a compilation error. The compilation error indicates that a conversion from a function to an object is being attempted without a suitable constructor.
Fix
Make the declaration unambiguous. For instance, fix these ambiguous declarations as follows:
ResourceType aResource();
Object declaration:
If the declaration refers to an object initialized with the default constructor, rewrite it as:
prior to C++11, or as:ResourceType aResource;
after C++11.ResourceType aResource{};Function declaration:
If the declaration refers to a function, use a typedef for the function.
typedef ResourceType(*resourceFunctionType)(); resourceFunctionType aResource;
TimeKeeper aTimeKeeper(Timer());
Object declaration:
If the declaration refers to an object
aTimeKeeperinitialized with an unnamed object of classTimer, add an extra pair of parenthesis:prior to C++11, or use braces:TimeKeeper aTimeKeeper( (Timer()) );
after C++11.TimeKeeper aTimeKeeper{Timer{}};Function declaration:
If the declaration refers to a function
aTimeKeeperwith a unnamed parameter of function pointer type, use a named parameter instead.typedef Timer(*timerType)(); TimeKeeper aTimeKeeper(timerType aTimer);
Examples
Result Information
| Group: Good practice |
| Language: C++ |
| Default: Off |
Command-Line Syntax:
MOST_VEXING_PARSE |
| Impact: Low |
Version History
Introduced in R2019a
See Also
Variable shadowing | Non-initialized variable | Write without a further read | Improper array initialization | Find defects (-checkers)
Topics
- Interpret Bug Finder Results in Polyspace Desktop User Interface
- Interpret Bug Finder Results in Polyspace Access Web Interface (Polyspace Access)
- Address Results in Polyspace User Interface Through Bug Fixes or Justifications
- Address Results in Polyspace Access Through Bug Fixes or Justifications (Polyspace Access)