Main Content

CERT C++: MSC38-C

Do not treat a predefined identifier as an object if it might only be implemented as a macro

Description

Rule Definition

Do not treat a predefined identifier as an object if it might only be implemented as a macro.1

Polyspace Implementation

The rule checker checks for Predefined macro used as an object.

Examples

expand all

Issue

Predefined macro used as an object occurs when you use certain identifiers in a way that requires an underlying object to be present. These identifiers are defined as macros. The C Standard does not allow you to redefine them as objects. You use the identifiers in such a way that macro expansion of the identifiers cannot occur.

For instance, you refer to an external variable errno:

extern int errno;
However, errno does not occur as a variable but a macro.

The defect applies to these macros: assert, errno, math_errhandling, setjmp, va_arg, va_copy, va_end, and va_start. The checker looks for the defect only in source files (not header files).

Risk

The C11 Standard (Sec. 7.1.4) allows you to redefine most macros as objects. To access the object and not the macro in a source file, you do one of these:

  • Redeclare the identifier as an external variable or function.

  • For function-like macros, enclose the identifier name in parentheses.

If you try to use these strategies for macros that cannot be redefined as objects, an error occurs.

Fix

Do not use the identifiers in such a way that a macro expansion is suppressed.

  • Do not redeclare the identifiers as external variables or functions.

  • For function-like macros, do not enclose the macro name in parentheses.

Example - Use of assert as Function
#include<assert.h>
typedef void (*err_handler_func)(int);

extern void demo_handle_err(err_handler_func, int);

void func(int err_code) {
    extern void assert(int);    //Noncompliant
    demo_handle_err(&(assert), err_code); //Noncompliant
}

In this example, the assert macro is redefined as an external function. When passed as an argument to demo_handle_err, the identifier assert is enclosed in parentheses, which suppresses use of the assert macro.

Correction — Use assert as Macro

One possible correction is to directly use the assert macro from assert.h. A different implementation of the function demo_handle_err directly uses the assert macro instead of taking the address of an assert function.

#include<assert.h>
void demo_handle_err(int err_code) {
    assert(err_code == 0);                   
}

void func(int err_code) {
    demo_handle_err(err_code);          
}

Check Information

Group: 49. Miscellaneous (MSC)

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.