Clang error: non-extern declaration of A follows extern declaration (err_non_extern_extern)

From emmtrix Wiki
Jump to navigation Jump to search
Text error: non-extern declaration of A follows extern declaration
Type Error
Category Semantic Issue
Internal Id err_non_extern_extern
Internal Message non-extern declaration of %0 follows extern declaration
Regular Expression (?:error|fatal error)\: non\-extern declaration of (.*?) follows extern declaration
First Commit 2011-01-31 819f61094216 Diagnose if extern local variable is followed by non-extern and vice-versa.

Description

The error is issued by the Clang compiler when it encounters a situation where a non-extern declaration of a variable follows a previous extern declaration of the same variable within the same scope. This typically indicates an attempt to redefine a variable in a way that conflicts with its previous declaration as extern, which is used to specify that a variable has external linkage—meaning it is defined in another translation unit.

In C and C++, an extern declaration enables the declaration of a variable without defining it, allowing it to be defined in another file. This error message is generated when a subsequent declaration in the same scope attempts to redefine the variable without the extern keyword, potentially leading to ambiguous definitions and linkage conflicts.

The correct approach when needing to reference an external variable is to ensure that all declarations specifying extern are consistent, and any definition of the variable (a declaration that allocates storage) does not contradict its initial extern declaration. This ensures that the variable is correctly linked across different translation units without causing redefinition or conflicting linkage problems.

 
AI Generated

Example

In the following example, an extern declaration of a variable v is made, indicating that its definition and storage allocation will occur in another translation unit. This is a common practice for making a variable accessible across different files without redefining it, preserving the linkage and ensuring single instance definitions. Following this, within the function f(), v is declared again as extern, which is permissible and reaffirms its external linkage within a more localized scope. However, the error arises when v is declared without the extern keyword again in the same scope. This action attempts to redefine v with automatic storage duration, conflicting with its previous extern declaration. The Clang compiler detects this discrepancy and issues the error, as such a sequence of declarations could lead to linkage conflicts and ambiguities regarding the variable's definition location and linkage status.  
AI Generated


Flags -xc

[Try out in Compiler Explorer]

Source
extern int v; // extern declaration of v

void f() {
  extern int v; // extern redeclaration is allowed
  int v; // error: non-extern declaration after an extern one
}
Compiler Output
<source>:5:7: error: non-extern declaration of 'v' follows extern declaration
<source>:4:14: note: previous declaration is here


Clang Internals (17.0.6)

Git Commit Message

Diagnose if extern local variable is followed by non-extern and vice-versa.

llvm-svn: 124579

Used in Clang Sources

This section lists all occurrences of the diagnostic within the Clang's codebase. For each occurrence, an auto-extracted snipped from the source code is listed including key elements like control structures, functions, or classes. It should illustrate the conditions under which the diagnostic is activated.

clang/lib/Sema/SemaDecl.cpp (line 4666)

/// MergeVarDecl - We just parsed a variable 'New' which has the same name
/// and scope as a previous declaration 'Old'.  Figure out how to resolve this
/// situation, merging decls or emitting diagnostics as appropriate.
///
/// Tentative definition rules (C99 6.9.2p2) are checked by
/// FinalizeDeclaratorGroup. Unfortunately, we can't analyze tentative
/// definitions here, since the initializer hasn't been attached.
///
void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
  // ...
  if (Old->hasLinkage() && New->isLocalVarDeclOrParm() && !New->hasExternalStorage()) {
    Diag(New->getLocation(), diag::err_non_extern_extern) << New->getDeclName();

Triggered in Clang Tests

This section lists all internal Clang test cases that trigger the diagnostic.

clang/test/Sema/private-extern.c

  • clang/test/Sema/private-extern.c:34:7: error: non-extern declaration of 'g8' follows extern declaration
  • clang/test/Sema/private-extern.c:39:7: error: non-extern declaration of 'g9' follows extern declaration