9

Mentre la produzione di un MCVE per this problema sono incappato, ho trovato il seguente discrepanza tra i compilatori:Inoltra dichiarazione di una funzione `constexpr` all'interno di un'altra funzione - Bug del compilatore?

Si consideri il seguente codice:

// constexpr int f(); // 1 

constexpr int g() { 
    constexpr int f(); // 2 
    return f(); 
} 

constexpr int f() { 
    return 42; 
} 

int main() { 
    constexpr int i = g(); 
    return i; 
} 

Questo codice viene compilato in Clang 3.8.0, ma fallisce il GCC 6.1.0 con:

error: 'constexpr int f()' used before its definition 

Commentando // 2 e decommentando // 1 lavori su entrambi i compilatori.

È interessante notare che, spostando f 's definizione al posto di // 1 compila, ma innesca un avvertimento a // 2:

warning: inline function 'constexpr int f()' used but never defined 

quale compilatore è giusto?

+1

Lo standard non sembra essere abbastanza chiaro su questo. Abbiamo bisogno di un avvocato forte qui :) – Arunmu

risposta

2

Sostituzione delle constexpr funzioni con inline funzioni conserva lo stesso identico problema (che va bene con la dichiarazione globale 1, ma non con la dichiarazione di funzione-ambito 2.) Dal momento che implica constexprinline questa sembra la causa.

In questo caso, con la dichiarazione 2, GCC si lamenta: warning: 'inline' specifier invalid for function 'f' declared out of global scope e warning: inline function 'int f()' used but never defined. Non riesce a collegare ("undefined reference to 'f()'").

Quindi sembra che si arrenda all'inlining, effettui una chiamata, ma non si preoccupa di emettere il codice per f() perché tutti gli usi sono in linea (?), Quindi il collegamento fallisce.

e Clang lamenta: error: inline declaration of 'f' not allowed in block scope

Dal constexpr implica inline, sembra che questa regola che le dichiarazioni non ancorati non siano ammessi in ambito blocco dovrebbe valere anche per constexpr, e così GCC è corretto. Ma lo standard non sembra uscire e dire questo. Nella bozza che ho esaminato, la regola su inline si trova in §7.1.2 [dcl.fct.spec], parte 3: "Lo specificatore in linea non deve apparire in una dichiarazione di funzione di ambito blocco", ma non appare nulla di simile a constexpr.