2013-03-15 8 views
15

Sto cercando di capire se presentare una segnalazione di bug contro Clang, GCC o entrambi (ho provato contro il tronco di Clang e GCC 4.7 .2: se qualcuno ha potuto verificare questo contro il tronco GCC che sarebbe utile):Clang contro GCC: Friending di una funzione globale tramite nomi qualificati/non qualificati

in sostanza, il file di tre righe seguente codice compila bene con -fsyntax-only, in default e C++ 11 modalità:

class A { 
    friend void f(); 
}; 

Si noti che non esiste una dichiarazione preventiva di f(), ma questo è esplicitamente OK.

Tuttavia, Clang (ma non GCC) respinge il seguente:

class A { 
    friend void ::f(); 
}; 

L'errore da Clang è "nessuna funzione denominata 'f' con il tipo 'void()' è stato trovato nell'ambito specificato", ma non riesco a trovare alcuna giustificazione nello standard per trattare questo caso in modo diverso rispetto al precedente, quindi penso che sia un bug; Potrei avere torto però (sto leggendo da N3242, tuttavia, che AFAIK è l'ultimo progetto pubblico prima di C++ 11).

Questo esempio successivo, però, è respinta da GCC piuttosto che Clang:

void f() { } 

void g() 
{ 
    class A { 
     friend void ::f(); 
    }; 
} 

L'errore da GCC è "amico dichiarazione 'void f()' in classe locale senza previa dichiarazione", che doesn' Sembra che abbia senso dal momento che void ::f() deve fare riferimento allo f() nello spazio dei nomi globale, che è dichiarato. (Non importa che friend -Ing una funzione globale da una classe locale è privo di senso, non sembra essere illegale ...)

Infine, questo ultimo esempio è respinta sia dal Clang e GCC:

void g() 
{ 
    class A { 
     friend void ::f(); 
    }; 
} 

Gli errori sono "friend declaration 'void f()' nella classe locale senza dichiarazione preventiva" e "nessuna funzione denominata 'f' con tipo 'void()' è stata trovata nell'ambito specificato", rispettivamente. Ora, ci sembra di essere un po 'una giustificazione per respingere una dichiarazione amico di una funzione non dichiarati in una classe locale, da 11.4p11, ma il punto in realtà si legge:

Se una dichiarazione amico compare in una classe locale (9.8) e il nome specificato è un nome non qualificato, una dichiarazione precedente viene esaminata senza considerare gli ambiti che non rientrano nell'ambito di applicazione non di classe più interno. Per una dichiarazione di funzione amico, se non v'è alcuna dichiarazione preliminare, il programma è mal formati ...

L'illegalità di questa dichiarazione apparentemente si basa sulla seconda frase in questo paragrafo, ma non è chiaro a me se la frase debba essere applicata anche nel caso di un nome qualificato, come in questo caso. (Probabilmente, potrebbe essere che l'intero paragrafo si applichi al caso della "classe locale" indipendentemente dal fatto che venga usato o meno un "nome non qualificato", e la clausola "e il nome specificato è un nome non qualificato" si applica solo alla ricerca descritta nella prima frase, ma sembra un allungamento ... l'unica ragione per cui immagino questa possibilità è perché entrambi i compilatori la rifiutano.)

In ogni caso, così da quello che posso dire, tutti e quattro di questi i casi (indipendentemente da quanto siano o meno ragionevoli) dovrebbero essere legali; anche se no, almeno uno tra Clang e GCC è sbagliato nel secondo e nel terzo caso. Qualcuno può trovare un errore nella mia logica?

Il terzo e il quarto caso sono dichiaratamente privi di senso; ma posso vedere il secondo caso che rompe il codice valido e utile di qualcuno, quindi sono un po 'sorpreso che non sia mai stato catturato, se è davvero un bug.

risposta

4

Credo che questa frase da 8,3/1 è rilevante:

Quando il dichiaratore-id è qualificato, la dichiarazione si riferisce ad un membro precedentemente dichiarato della classe o spazio dei nomi a cui la qualificazione si riferisce (o, nel caso di uno spazio dei nomi, di un elemento dell'insieme dello spazio dei nomi in linea di tale spazio dei nomi (7.3.1)) o di una sua specializzazione; il membro non deve essere stato semplicemente introdotto da una utilizzando la dichiarazione nell'ambito della classe o dello spazio dei nomi nominato dallo identificatore del nome nidificato del dichiaratore-id.

Il paragrafo parla di dichiaratori in generale, in qualsiasi tipo di dichiarazione. Quindi penso che gli esempi 2 e 4 siano mal formati, che il clang sia corretto e che gcc sia sbagliato.

(L'Esempio 3 potrebbe diventare più realistico se la dichiarazione globale fosse una funzione modello.Potrebbe essere utile un modello di funzione globale o una specializzazione da una classe locale.E se ciò è consentito, il tuo esempio 3 come potrebbe essere legale per coerenza.)

+0

Ah, grazie, ha senso allora. Penso tu abbia ragione. Impara qualcosa di nuovo ogni giorno :) –

+0

Abbastanza interessante, GCC sta bene con il terzo caso questo se 'f' è fatto in un modello ... che è probabilmente l'unico caso d'uso valido comunque ... ma sì, il il terzo caso probabilmente dovrebbe essere permesso per coerenza (a meno che non sia esplicitamente disabilitato da qualche parte) e il secondo dovrebbe probabilmente essere respinto (anche se un compilatore è libero di accettare codice non valido se vuole, suppongo). –

Problemi correlati