Main Content

CERT C++: DCL53-CPP

Do not write syntactically ambiguous declarations

Description

Rule Definition

Do not write syntactically ambiguous declarations.1

Polyspace Implementation

The rule checker checks for Ambiguous Declaration Syntax.

Examples

expand all

Issue

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 aResource is a function returning a variable of type ResourceType or an object of type ResourceType.

  • TimeKeeper aTimeKeeper(Timer());

    It is not immediately clear if aTimeKeeper is an object constructed with an unnamed object of type Timer or a function with an unnamed function pointer type as parameter. The function pointer refers to a function with no argument and return type Timer.

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:

  • ResourceType aResource();
    is interpreted as a declaration of a function aResource.

  • TimeKeeper aTimeKeeper(Timer());
    is interpreted as a declaration of a function aTimeKeeper with 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:

    ResourceType aResource;
    prior to C++11, or as:
    ResourceType aResource{};
    after C++11.

    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 aTimeKeeper initialized with an unnamed object of class Timer, add an extra pair of parenthesis:

    TimeKeeper aTimeKeeper( (Timer()) );
    prior to C++11, or use braces:
    TimeKeeper aTimeKeeper{Timer{}};
    after C++11.

    Function declaration:

    If the declaration refers to a function aTimeKeeper with a unnamed parameter of function pointer type, use a named parameter instead.

    typedef Timer(*timerType)();
    TimeKeeper aTimeKeeper(timerType aTimer);

Example – Function or Object Declaration
class ResourceType {
      int aMember;
    public:
      int getMember();
};

void getResource() {
    ResourceType aResource(); //Noncompliant
}

In this example, aResource might be used as an object but the declaration syntax indicates a function declaration.

Correction — Use {} for Object Declaration

One possible correction (after C++11) is to use braces for object declaration.

class ResourceType {
      int aMember;
    public:
      int getMember();
};

void getResource() {
    ResourceType aResource{};
}
Example – Unnamed Object or Unnamed Function Parameter Declaration
class MemberType {};

class ResourceType {
      MemberType aMember;
    public:
      ResourceType(MemberType m) {aMember = m;}
      int getMember();
};

void getResource() {
    ResourceType aResource(MemberType());  //Noncompliant
}

In this example, aResource might be used as an object initialized with an unnamed object of type MemberType but the declaration syntax indicates a function with an unnamed parameter of function pointer type. The function pointer points to a function with no arguments and type MemberType.

Correction — Use {} for Object Declaration

One possible correction (after C++11) is to use braces for object declaration.

class MemberType {};

class ResourceType {
      MemberType aMember;
    public:
      ResourceType(MemberType m) {aMember = m;}
      int getMember();
};

void getResource() {
    ResourceType aResource{MemberType()};
}
Example – Unnamed Object or Named Function Parameter Declaration
class Integer {
	int aMember;
public:
	Integer(int d) {aMember = d;}
	int getMember();
};

int aInt = 0;
void foo(){
	Integer aInteger(Integer(aInt)); //Noncompliant
}

In this example, aInteger might be an object constructed with an unnamed object Integer(aInt) (an object of class Integer which itself is constructed using the variable aInt). However, the declaration syntax indicates that aInteger is a function with a named parameter aInt of type Integer (the superfluous parenthesis is ignored).

Correction — Use of {} for Object Declaration

One possible correction (after C++11) is to use {} for object declaration.

class Integer {
	int aMember;
public:
	Integer(int d) {aMember = d;}
	int getMember();
};

int aInt = 0;
void foo(){
	Integer aInteger(Integer{aInt});
}
Correction — Remove Superfluous Parenthesis for Named Parameter Declaration

If aInteger is a function with a named parameter aInt, remove the superfluous () around aInt.

class Integer {
       int aMember;
    public:
       Integer(int d) {aMember = d;}
       int getMember();
};

Integer aInteger(Integer aInt);

Check Information

Group: 01. Declarations and Initialization (DCL)

Version History

Introduced in R2019a


1 This software has been created by MathWorks incorporating portions of: the “SEI CERT-C Website,” © 2017 Carnegie Mellon University, the SEI CERT-C++ Web site © 2017 Carnegie Mellon University, ”SEI CERT C Coding Standard – Rules for Developing safe, Reliable and Secure systems – 2016 Edition,” © 2016 Carnegie Mellon University, and “SEI CERT C++ Coding Standard – Rules for Developing safe, Reliable and Secure systems in C++ – 2016 Edition” © 2016 Carnegie Mellon University, with special permission from its Software Engineering Institute.

ANY MATERIAL OF CARNEGIE MELLON UNIVERSITY AND/OR ITS SOFTWARE ENGINEERING INSTITUTE CONTAINED HEREIN IS FURNISHED ON AN "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY KIND, EITHER EXPRESSED OR IMPLIED, AS TO ANY MATTER INCLUDING, BUT NOT LIMITED TO, WARRANTY OF FITNESS FOR PURPOSE OR MERCHANTABILITY, EXCLUSIVITY, OR RESULTS OBTAINED FROM USE OF THE MATERIAL. CARNEGIE MELLON UNIVERSITY DOES NOT MAKE ANY WARRANTY OF ANY KIND WITH RESPECT TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT.

This software and associated documentation has not been reviewed nor is it endorsed by Carnegie Mellon University or its Software Engineering Institute.