1 //===--- ParsePragma.cpp - Language specific pragma parsing ---------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file implements the language specific #pragma handlers.
12 //===----------------------------------------------------------------------===//
14 #include "ParsePragma.h"
15 #include "clang/Parse/ParseDiagnostic.h"
16 #include "clang/Parse/Parser.h"
17 #include "clang/Lex/Preprocessor.h"
18 using namespace clang;
20 /// \brief Handle the annotation token produced for #pragma unused(...)
22 /// Each annot_pragma_unused is followed by the argument token so e.g.
23 /// "#pragma unused(x,y)" becomes:
24 /// annot_pragma_unused 'x' annot_pragma_unused 'y'
25 void Parser::HandlePragmaUnused() {
26 assert(Tok.is(tok::annot_pragma_unused));
27 SourceLocation UnusedLoc = ConsumeToken();
28 Actions.ActOnPragmaUnused(Tok, getCurScope(), UnusedLoc);
29 ConsumeToken(); // The argument token.
32 void Parser::HandlePragmaVisibility() {
33 assert(Tok.is(tok::annot_pragma_vis));
34 const IdentifierInfo *VisType =
35 static_cast<IdentifierInfo *>(Tok.getAnnotationValue());
36 SourceLocation VisLoc = ConsumeToken();
37 Actions.ActOnPragmaVisibility(VisType, VisLoc);
40 struct PragmaPackInfo {
41 Sema::PragmaPackKind Kind;
44 SourceLocation LParenLoc;
45 SourceLocation RParenLoc;
48 void Parser::HandlePragmaPack() {
49 assert(Tok.is(tok::annot_pragma_pack));
50 PragmaPackInfo *Info =
51 static_cast<PragmaPackInfo *>(Tok.getAnnotationValue());
52 SourceLocation PragmaLoc = ConsumeToken();
53 Actions.ActOnPragmaPack(Info->Kind, Info->Name, Info->Alignment, PragmaLoc,
54 Info->LParenLoc, Info->RParenLoc);
57 // #pragma GCC visibility comes in two variants:
58 // 'push' '(' [visibility] ')'
60 void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,
61 PragmaIntroducerKind Introducer,
63 SourceLocation VisLoc = VisTok.getLocation();
66 PP.LexUnexpandedToken(Tok);
68 const IdentifierInfo *PushPop = Tok.getIdentifierInfo();
70 const IdentifierInfo *VisType;
71 if (PushPop && PushPop->isStr("pop")) {
73 } else if (PushPop && PushPop->isStr("push")) {
74 PP.LexUnexpandedToken(Tok);
75 if (Tok.isNot(tok::l_paren)) {
76 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
80 PP.LexUnexpandedToken(Tok);
81 VisType = Tok.getIdentifierInfo();
83 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
87 PP.LexUnexpandedToken(Tok);
88 if (Tok.isNot(tok::r_paren)) {
89 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
94 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
98 PP.LexUnexpandedToken(Tok);
99 if (Tok.isNot(tok::eod)) {
100 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
105 Token *Toks = new Token[1];
106 Toks[0].startToken();
107 Toks[0].setKind(tok::annot_pragma_vis);
108 Toks[0].setLocation(VisLoc);
109 Toks[0].setAnnotationValue(
110 const_cast<void*>(static_cast<const void*>(VisType)));
111 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
112 /*OwnsTokens=*/true);
115 // #pragma pack(...) comes in the following delicious flavors:
116 // pack '(' [integer] ')'
117 // pack '(' 'show' ')'
118 // pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'
119 void PragmaPackHandler::HandlePragma(Preprocessor &PP,
120 PragmaIntroducerKind Introducer,
122 SourceLocation PackLoc = PackTok.getLocation();
126 if (Tok.isNot(tok::l_paren)) {
127 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack";
131 Sema::PragmaPackKind Kind = Sema::PPK_Default;
132 IdentifierInfo *Name = 0;
133 ExprResult Alignment;
134 SourceLocation LParenLoc = Tok.getLocation();
136 if (Tok.is(tok::numeric_constant)) {
137 Alignment = Actions.ActOnNumericConstant(Tok);
138 if (Alignment.isInvalid())
143 // In MSVC/gcc, #pragma pack(4) sets the alignment without affecting
144 // the push/pop stack.
145 // In Apple gcc, #pragma pack(4) is equivalent to #pragma pack(push, 4)
146 if (PP.getLangOpts().ApplePragmaPack)
147 Kind = Sema::PPK_Push;
148 } else if (Tok.is(tok::identifier)) {
149 const IdentifierInfo *II = Tok.getIdentifierInfo();
150 if (II->isStr("show")) {
151 Kind = Sema::PPK_Show;
154 if (II->isStr("push")) {
155 Kind = Sema::PPK_Push;
156 } else if (II->isStr("pop")) {
157 Kind = Sema::PPK_Pop;
159 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_invalid_action);
164 if (Tok.is(tok::comma)) {
167 if (Tok.is(tok::numeric_constant)) {
168 Alignment = Actions.ActOnNumericConstant(Tok);
169 if (Alignment.isInvalid())
173 } else if (Tok.is(tok::identifier)) {
174 Name = Tok.getIdentifierInfo();
177 if (Tok.is(tok::comma)) {
180 if (Tok.isNot(tok::numeric_constant)) {
181 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
185 Alignment = Actions.ActOnNumericConstant(Tok);
186 if (Alignment.isInvalid())
192 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
197 } else if (PP.getLangOpts().ApplePragmaPack) {
198 // In MSVC/gcc, #pragma pack() resets the alignment without affecting
199 // the push/pop stack.
200 // In Apple gcc #pragma pack() is equivalent to #pragma pack(pop).
201 Kind = Sema::PPK_Pop;
204 if (Tok.isNot(tok::r_paren)) {
205 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack";
209 SourceLocation RParenLoc = Tok.getLocation();
211 if (Tok.isNot(tok::eod)) {
212 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack";
216 PragmaPackInfo *Info =
217 (PragmaPackInfo*) PP.getPreprocessorAllocator().Allocate(
218 sizeof(PragmaPackInfo), llvm::alignOf<PragmaPackInfo>());
219 new (Info) PragmaPackInfo();
222 Info->Alignment = Alignment.release();
223 Info->LParenLoc = LParenLoc;
224 Info->RParenLoc = RParenLoc;
227 (Token*) PP.getPreprocessorAllocator().Allocate(
228 sizeof(Token) * 1, llvm::alignOf<Token>());
230 Toks[0].startToken();
231 Toks[0].setKind(tok::annot_pragma_pack);
232 Toks[0].setLocation(PackLoc);
233 Toks[0].setAnnotationValue(static_cast<void*>(Info));
234 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
235 /*OwnsTokens=*/false);
238 // #pragma ms_struct on
239 // #pragma ms_struct off
240 void PragmaMSStructHandler::HandlePragma(Preprocessor &PP,
241 PragmaIntroducerKind Introducer,
242 Token &MSStructTok) {
243 Sema::PragmaMSStructKind Kind = Sema::PMSST_OFF;
247 if (Tok.isNot(tok::identifier)) {
248 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
251 const IdentifierInfo *II = Tok.getIdentifierInfo();
252 if (II->isStr("on")) {
253 Kind = Sema::PMSST_ON;
256 else if (II->isStr("off") || II->isStr("reset"))
259 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
263 if (Tok.isNot(tok::eod)) {
264 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
268 Actions.ActOnPragmaMSStruct(Kind);
271 // #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
272 // #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
273 static void ParseAlignPragma(Sema &Actions, Preprocessor &PP, Token &FirstTok,
279 if (Tok.isNot(tok::identifier) ||
280 !Tok.getIdentifierInfo()->isStr("align")) {
281 PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align);
287 if (Tok.isNot(tok::equal)) {
288 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal)
294 if (Tok.isNot(tok::identifier)) {
295 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
296 << (IsOptions ? "options" : "align");
300 Sema::PragmaOptionsAlignKind Kind = Sema::POAK_Natural;
301 const IdentifierInfo *II = Tok.getIdentifierInfo();
302 if (II->isStr("native"))
303 Kind = Sema::POAK_Native;
304 else if (II->isStr("natural"))
305 Kind = Sema::POAK_Natural;
306 else if (II->isStr("packed"))
307 Kind = Sema::POAK_Packed;
308 else if (II->isStr("power"))
309 Kind = Sema::POAK_Power;
310 else if (II->isStr("mac68k"))
311 Kind = Sema::POAK_Mac68k;
312 else if (II->isStr("reset"))
313 Kind = Sema::POAK_Reset;
315 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option)
320 SourceLocation KindLoc = Tok.getLocation();
322 if (Tok.isNot(tok::eod)) {
323 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
324 << (IsOptions ? "options" : "align");
328 Actions.ActOnPragmaOptionsAlign(Kind, FirstTok.getLocation(), KindLoc);
331 void PragmaAlignHandler::HandlePragma(Preprocessor &PP,
332 PragmaIntroducerKind Introducer,
334 ParseAlignPragma(Actions, PP, AlignTok, /*IsOptions=*/false);
337 void PragmaOptionsHandler::HandlePragma(Preprocessor &PP,
338 PragmaIntroducerKind Introducer,
340 ParseAlignPragma(Actions, PP, OptionsTok, /*IsOptions=*/true);
343 // #pragma unused(identifier)
344 void PragmaUnusedHandler::HandlePragma(Preprocessor &PP,
345 PragmaIntroducerKind Introducer,
347 // FIXME: Should we be expanding macros here? My guess is no.
348 SourceLocation UnusedLoc = UnusedTok.getLocation();
353 if (Tok.isNot(tok::l_paren)) {
354 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
358 // Lex the declaration reference(s).
359 SmallVector<Token, 5> Identifiers;
360 SourceLocation RParenLoc;
367 if (Tok.is(tok::identifier)) {
368 Identifiers.push_back(Tok);
374 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
378 // We are execting a ')' or a ','.
379 if (Tok.is(tok::comma)) {
384 if (Tok.is(tok::r_paren)) {
385 RParenLoc = Tok.getLocation();
390 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_punc);
395 if (Tok.isNot(tok::eod)) {
396 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
401 // Verify that we have a location for the right parenthesis.
402 assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
403 assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
405 // For each identifier token, insert into the token stream a
406 // annot_pragma_unused token followed by the identifier token.
407 // This allows us to cache a "#pragma unused" that occurs inside an inline
408 // C++ member function.
411 (Token*) PP.getPreprocessorAllocator().Allocate(
412 sizeof(Token) * 2 * Identifiers.size(), llvm::alignOf<Token>());
413 for (unsigned i=0; i != Identifiers.size(); i++) {
414 Token &pragmaUnusedTok = Toks[2*i], &idTok = Toks[2*i+1];
415 pragmaUnusedTok.startToken();
416 pragmaUnusedTok.setKind(tok::annot_pragma_unused);
417 pragmaUnusedTok.setLocation(UnusedLoc);
418 idTok = Identifiers[i];
420 PP.EnterTokenStream(Toks, 2*Identifiers.size(),
421 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
424 // #pragma weak identifier
425 // #pragma weak identifier '=' identifier
426 void PragmaWeakHandler::HandlePragma(Preprocessor &PP,
427 PragmaIntroducerKind Introducer,
429 // FIXME: Should we be expanding macros here? My guess is no.
430 SourceLocation WeakLoc = WeakTok.getLocation();
434 if (Tok.isNot(tok::identifier)) {
435 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";
439 IdentifierInfo *WeakName = Tok.getIdentifierInfo(), *AliasName = 0;
440 SourceLocation WeakNameLoc = Tok.getLocation(), AliasNameLoc;
443 if (Tok.is(tok::equal)) {
445 if (Tok.isNot(tok::identifier)) {
446 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
450 AliasName = Tok.getIdentifierInfo();
451 AliasNameLoc = Tok.getLocation();
455 if (Tok.isNot(tok::eod)) {
456 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";
461 Actions.ActOnPragmaWeakAlias(WeakName, AliasName, WeakLoc, WeakNameLoc,
464 Actions.ActOnPragmaWeakID(WeakName, WeakLoc, WeakNameLoc);
468 // #pragma redefine_extname identifier identifier
469 void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP,
470 PragmaIntroducerKind Introducer,
472 SourceLocation RedefLoc = RedefToken.getLocation();
476 if (Tok.isNot(tok::identifier)) {
477 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
482 IdentifierInfo *RedefName = Tok.getIdentifierInfo(), *AliasName = 0;
483 SourceLocation RedefNameLoc = Tok.getLocation(), AliasNameLoc;
486 if (Tok.isNot(tok::identifier)) {
487 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
488 << "redefine_extname";
491 AliasName = Tok.getIdentifierInfo();
492 AliasNameLoc = Tok.getLocation();
495 if (Tok.isNot(tok::eod)) {
496 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
501 Actions.ActOnPragmaRedefineExtname(RedefName, AliasName, RedefLoc,
502 RedefNameLoc, AliasNameLoc);
507 PragmaFPContractHandler::HandlePragma(Preprocessor &PP,
508 PragmaIntroducerKind Introducer,
510 tok::OnOffSwitch OOS;
511 if (PP.LexOnOffSwitch(OOS))
514 Actions.ActOnPragmaFPContract(OOS);
518 PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
519 PragmaIntroducerKind Introducer,
521 PP.LexUnexpandedToken(Tok);
522 if (Tok.isNot(tok::identifier)) {
523 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
527 IdentifierInfo *ename = Tok.getIdentifierInfo();
528 SourceLocation NameLoc = Tok.getLocation();
531 if (Tok.isNot(tok::colon)) {
532 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << ename;
537 if (Tok.isNot(tok::identifier)) {
538 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
541 IdentifierInfo *op = Tok.getIdentifierInfo();
544 if (op->isStr("enable")) {
546 } else if (op->isStr("disable")) {
549 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
553 OpenCLOptions &f = Actions.getOpenCLOptions();
554 // OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions,
555 // overriding all previously issued extension directives, but only if the
556 // behavior is set to disable."
557 if (state == 0 && ename->isStr("all")) {
558 #define OPENCLEXT(nm) f.nm = 0;
559 #include "clang/Basic/OpenCLExtensions.def"
561 #define OPENCLEXT(nm) else if (ename->isStr(#nm)) { f.nm = state; }
562 #include "clang/Basic/OpenCLExtensions.def"
564 PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << ename;