2014-07-23 13 views
10

Nell'attuare il mio compilatore C11, sto cercando di capire come esattamente per gestire il _Pragma parola/operatore. C11 §6.10.9 descrive _Pragma come operatore, quindi sembra possibile ridefinirlo con macro, ovvero #define _Pragma(x) SOME_OTHER_MACRO(x). Inoltre, la dichiarazione #undef _Pragma non dovrebbe avere alcun effetto (supponendo che non sia anteriore a #define di _Pragma). Questo è simile al modo in cui le parole chiave possono essere #define d, come il vecchio hack VC++ #define for if (0) ; else for. Tuttavia, poiché l'operatore _Pragma viene valutato durante la fase di traduzione 3, nella stessa fase dell'esecuzione delle direttive del preprocessore, non è chiaro se si tratti di un'eccezione; lo standard non indica se il suo comportamento non definito utilizza _Pragma come nome di macro._Pragma e sostituzione di macro

ho fatto alcuni test con GCC utilizzando il seguente codice:

#define PRAGMA _Pragma 
PRAGMA("message \"hi\"") 

_Pragma ("message \"sup\"") 

#undef PRAGMA 

#undef _Pragma 
//#define _Pragma(x) 
_Pragma("message \"hello\"") 

compilazione con gcc -std=c11 -pedantic -Wall -Wextra -c uscite:

tmp.c:2:1: note: #pragma message: hi 
PRAGMA("message \"hi\"") 
^ 
tmp.c:4:1: note: #pragma message: sup 
_Pragma ("message \"sup\"") 
^ 
tmp.c:8:8: warning: undefining "_Pragma" [enabled by default] 
#undef _Pragma 
     ^
tmp.c:10:9: error: expected declaration specifiers or ‘...’ before string constant 
_Pragma("message \"hello\"") 
     ^

Se aggiungo la linea #undef _Alignof, GCC non si lamenta a questo proposito.

Ciò suggerisce che GCC implementa _Pragma tramite una macro (tramite il messaggio di avviso), e che indefiniti si traduce in un errore di compilazione. Se taccio il commento a #define _Pragma(x), l'errore scompare (quando la stringa letterale scompare).

Quindi, le mie domande sono:

  1. sono implementazioni permesso di definire _Pragma come solo un macro, e non implementarlo come un operatore?
  2. In caso contrario, GCC ha torto nel farlo?
  3. se _Pragma si doveva essere un operatore, è un comportamento indefinito di definire _Pragma come macro?
  4. Esiste un ordine tra la valutazione _Pragma e altre direttive del preprocessore? O hanno la stessa "precedenza" (cioè sono valutati in ordine)?

Ancora una volta, guardando attraverso lo standard C11 non menziona nulla _Pragma diverso da quello che è un operatore che può essere utilizzato per #pragma direttive.

+2

anticipare alcune sostanziale livello di opinione giocherà un rotolo nelle risposte si arriva a questa domanda, (come il void main (void ')' discussioni), tuttavia, la vostra ricerca è evidente, e la vostra le domande sono ben presentate Dovrebbe portare a risposte interessanti.(+1) – ryyker

+0

Non sono sicuro, se capisco correttamente lo standard qui, ma penso, si applica C11 7.1.3 p3: "Se il programma rimuove (con #undef) qualsiasi definizione di macro di un identificatore nel primo gruppo elencato sopra, il comportamento non è definito. "dove il" primo gruppo "menzionato sono identificatori che iniziano con un trattino basso seguito da un altro carattere di sottolineatura o da una lettera maiuscola. – mafso

+0

@mafso che sembra applicarsi solo se c'è una definizione di macro, in primo luogo, in modo da codice come '#ifndef _Pragma #undef _Pragma # endif' non sarebbe invocare UB –

risposta

5

Non v'è alcun bisogno di una regola speciale che non voglia _Pragma essere un nome di macro. Avendo una sottolineatura principale e una lettera maiuscola, è tra gli identificatori riservati che non dovresti usare, comunque. L'uso di identificatori riservati porta a un comportamento indefinito del tuo programma, un compilatore può fare qualsiasi cosa.

L'attuazione può implementarlo come una macro, ma che dovrebbe essere trasparente per l'utente, a patto che lo si utilizza in modo corretto, cioè finché non si scherza con esso. L'unica cosa importante che un'implementazione deve garantire è che il "destringization" e "tokeninzation" dell'argomento al _Pragma è fatta come se nella fase 3 (che è difficile se è "solo" una macro) e che la risultante #pragma direttiva viene elaborato in fase di 4.

+0

Non è quasi chiaro cosa significhi lo standard con "riservato per qualsiasi uso" - sicuramente, un'istruzione come "int ln = __LINE __;" potrebbe essere considerata un uso dell'identificatore "__LINE__" (a meno che "riservato per qualsiasi uso" non includa identificatori obbligatori). –

+0

@DrewMcGowen: "riservato per qualsiasi uso" significa che l'utente non può dichiarare o definire identificatori di tale modulo per alcun uso (dal momento che è riservato). Contrasto a quello con i moduli identificativi riservati solo agli identificatori con scope di file o solo se è inclusa un'intestazione specifica. –

+1

@DrewMcGowen, questo ha un significato molto preciso che è fornito in 7.1.3. Il paragrafo 2 dice cosa non si dovrebbe fare con esso: * Se il programma dichiara o definisce un identificatore in un contesto in cui è riservato (diverso da quanto consentito dalla 7.1.4), o definisce un identificatore riservato come nome macro, il comportamento è indefinito. * –