Main Content

MISRA C:2012 Rule 8.7

Functions and objects should not be defined with external linkage if they are referenced in only one translation unit

Description

This checker is deactivated in a default Polyspace® as You Code analysis. See Checkers Deactivated in Polyspace as You Code Analysis (Polyspace Access).

Rule Definition

Functions and objects should not be defined with external linkage if they are referenced in only one translation unit.

Rationale

Compliance with this rule avoids confusion between your identifier and an identical identifier in another translation unit or library. If you restrict or reduce the visibility of an object by giving it internal linkage or no linkage, you or someone else is less likely to access the object inadvertently.

Polyspace Implementation

The rule checker flags:

  • Objects that are defined at file scope without the static specifier but used only in one file.

  • Functions that are defined without the static specifier but called only in one file.

If you intend to use the object or function in one file only, declare it static.

If your code does not contain a main function and you use options such as Variables to initialize (-main-generator-writes-variables) with value custom to explicitly specify a set of variables to initialize, the checker does not flag those variables. The checker assumes that in a real application, the file containing the main must initialize the variables in addition to any file that currently uses them. Therefore, the variables are used in more than one translation unit.

Troubleshooting

If you expect a rule violation but do not see it, refer to Diagnose Why Coding Standard Violations Do Not Appear as Expected.

Examples

expand all

Header file:

/* file.h */
extern int var;

First source file:

/* file1.c */
#include "file.h"

int var;    /* Compliant */
int var2;   /* Non compliant */
static int var3; /* Compliant */

void reset(void);

void reset(void) {
    var = 0;
    var2 = 0;
    var3 = 0;
}

Second source file:

/* file2.c */
#include "file.h"

void increment(int var2);

void increment(int var2) {
    var++;
    var2++;
}

In this example:

  • The declaration of var is compliant because var is declared with external linkage and used in multiple files.

  • The declaration of var2 is noncompliant because var2 is declared with external linkage but used in one file only.

    It might appear that var2 is defined in both files. However, in the second file, var2 is a parameter with no linkage and is not the same as the var2 in the first file.

  • The declaration of var3 is compliant because var3 is declared with internal linkage (with the static specifier) and used in one file only.

Header file:

/* file.h */
extern int var;
extern void increment1 (void);

First source file:

/* file1.c */
#include "file.h"

int var;

void increment2(void);
static void increment3(void);
void func(void);

void increment2(void) { /* Non compliant */
    var+=2;
}

static void increment3(void) { /* Compliant */
    var+=3;
}

void func(void) {
    increment1();
    increment2();
    increment3();
}

Second source file:

/* file2.c */
#include "file.h"

void increment1(void) { /* Compliant */
    var++;
}

In this example:

  • The definition of increment1 is compliant because increment1 is defined with external linkage and called in a different file.

  • The declaration of increment2 is noncompliant because increment2 is defined with external linkage but called in the same file and nowhere else.

  • The declaration of increment3 is compliant because increment3 is defined with internal linkage (with the static specifier) and called in the same file and nowhere else.

In this example, the function get_pi() is declared as an extern but the function is used in a single translation unit. Polyspace reports a violation.

extern double get_pi(void)
{
    //....
    return 3.1416;
}

void foo(){
    
 get_pi(); // Noncompliant
}
Correction — Declare get_pi() as static

To fix the violation, declare the function get_pi() as a static function.

static double get_pi(void)
{
    //....
    return 3.1416;
}

void foo(){
    
 get_pi(); // Compliant
}

Check Information

Group: Declarations and Definitions
Category: Advisory
AGC Category: Advisory

Version History

Introduced in R2014b