При реализации моего собственного компилятора C11 я пытаюсь выяснить, как именно обрабатывать ключевое слово/оператор _Pragma. C11 §6.10.9 описывает _Pragma как оператор, поэтому представляется возможным переопределить его с помощью макросов, т.е. #define _Pragma(x) SOME_OTHER_MACRO(x). Кроме того, утверждение #undef _Pragma не должно иметь эффекта (если не считать предшествующего #define of _Pragma). Это похоже на то, как ключевые слова могут быть #define d, например старый VС++ hack #define for if (0) ; else for. Однако, поскольку оператор _Pragma оценивается во время фазы 3 перевода, на той же фазе, что и при выполнении директив препроцессора, неясно, является ли это исключением; в стандарте не упоминается, использовать ли его undefined поведение _Pragma как имя макроса.
Я провел некоторое тестирование с помощью GCC, используя следующий код:
#define PRAGMA _Pragma
PRAGMA("message \"hi\"")
_Pragma ("message \"sup\"")
#undef PRAGMA
#undef _Pragma
//#define _Pragma(x)
_Pragma("message \"hello\"")
Компиляция с выводами gcc -std=c11 -pedantic -Wall -Wextra -c:
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\"")
^
Если я добавлю строку #undef _Alignof, GCC не будет жаловаться на нее.
Это говорит о том, что GCC реализует _Pragma через макрос (через предупреждающее сообщение), а это не определяет его, что приводит к ошибке компиляции. Если я раскомментирую #define _Pragma(x), ошибка исчезнет (поскольку литерал строки исчезнет).
Итак, мои вопросы:
- Можно ли реализовать
_Pragmaв реализациях как просто макрос, а не реализовать его как оператор? - Если это не так, GCC ошибается в этом?
- Если
_Pragmaдолжен быть оператором, является ли поведение undefined определять_Pragmaкак макрос? - Есть ли порядок между оценкой
_Pragmaи другими директивами препроцессора? Или они имеют одинаковый "приоритет" (т.е. Оцениваются в порядке)?
Опять же, просмотр стандарта C11 не упоминает ничего о _Pragma, кроме него, оператора, который может использоваться для директив #pragma.