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 // #pragma GCC visibility comes in two variants:
33 // 'push' '(' [visibility] ')'
35 void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,
36 PragmaIntroducerKind Introducer,
38 SourceLocation VisLoc = VisTok.getLocation();
41 PP.LexUnexpandedToken(Tok);
43 const IdentifierInfo *PushPop = Tok.getIdentifierInfo();
46 const IdentifierInfo *VisType;
47 if (PushPop && PushPop->isStr("pop")) {
50 } else if (PushPop && PushPop->isStr("push")) {
52 PP.LexUnexpandedToken(Tok);
53 if (Tok.isNot(tok::l_paren)) {
54 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
58 PP.LexUnexpandedToken(Tok);
59 VisType = Tok.getIdentifierInfo();
61 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
65 PP.LexUnexpandedToken(Tok);
66 if (Tok.isNot(tok::r_paren)) {
67 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
72 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
76 PP.LexUnexpandedToken(Tok);
77 if (Tok.isNot(tok::eod)) {
78 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
83 Actions.ActOnPragmaVisibility(IsPush, VisType, VisLoc);
86 // #pragma pack(...) comes in the following delicious flavors:
87 // pack '(' [integer] ')'
88 // pack '(' 'show' ')'
89 // pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'
90 void PragmaPackHandler::HandlePragma(Preprocessor &PP,
91 PragmaIntroducerKind Introducer,
93 SourceLocation PackLoc = PackTok.getLocation();
97 if (Tok.isNot(tok::l_paren)) {
98 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack";
102 Sema::PragmaPackKind Kind = Sema::PPK_Default;
103 IdentifierInfo *Name = 0;
104 ExprResult Alignment;
105 SourceLocation LParenLoc = Tok.getLocation();
107 if (Tok.is(tok::numeric_constant)) {
108 Alignment = Actions.ActOnNumericConstant(Tok);
109 if (Alignment.isInvalid())
113 } else if (Tok.is(tok::identifier)) {
114 const IdentifierInfo *II = Tok.getIdentifierInfo();
115 if (II->isStr("show")) {
116 Kind = Sema::PPK_Show;
119 if (II->isStr("push")) {
120 Kind = Sema::PPK_Push;
121 } else if (II->isStr("pop")) {
122 Kind = Sema::PPK_Pop;
124 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_invalid_action);
129 if (Tok.is(tok::comma)) {
132 if (Tok.is(tok::numeric_constant)) {
133 Alignment = Actions.ActOnNumericConstant(Tok);
134 if (Alignment.isInvalid())
138 } else if (Tok.is(tok::identifier)) {
139 Name = Tok.getIdentifierInfo();
142 if (Tok.is(tok::comma)) {
145 if (Tok.isNot(tok::numeric_constant)) {
146 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
150 Alignment = Actions.ActOnNumericConstant(Tok);
151 if (Alignment.isInvalid())
157 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
164 if (Tok.isNot(tok::r_paren)) {
165 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack";
169 SourceLocation RParenLoc = Tok.getLocation();
171 if (Tok.isNot(tok::eod)) {
172 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack";
176 Actions.ActOnPragmaPack(Kind, Name, Alignment.release(), PackLoc,
177 LParenLoc, RParenLoc);
180 // #pragma ms_struct on
181 // #pragma ms_struct off
182 void PragmaMSStructHandler::HandlePragma(Preprocessor &PP,
183 PragmaIntroducerKind Introducer,
184 Token &MSStructTok) {
185 Sema::PragmaMSStructKind Kind = Sema::PMSST_OFF;
189 if (Tok.isNot(tok::identifier)) {
190 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
193 const IdentifierInfo *II = Tok.getIdentifierInfo();
194 if (II->isStr("on")) {
195 Kind = Sema::PMSST_ON;
198 else if (II->isStr("off") || II->isStr("reset"))
201 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
205 if (Tok.isNot(tok::eod)) {
206 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "ms_struct";
209 Actions.ActOnPragmaMSStruct(Kind);
212 // #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
213 // #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
214 static void ParseAlignPragma(Sema &Actions, Preprocessor &PP, Token &FirstTok,
220 if (Tok.isNot(tok::identifier) ||
221 !Tok.getIdentifierInfo()->isStr("align")) {
222 PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align);
228 if (Tok.isNot(tok::equal)) {
229 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal)
235 if (Tok.isNot(tok::identifier)) {
236 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
237 << (IsOptions ? "options" : "align");
241 Sema::PragmaOptionsAlignKind Kind = Sema::POAK_Natural;
242 const IdentifierInfo *II = Tok.getIdentifierInfo();
243 if (II->isStr("native"))
244 Kind = Sema::POAK_Native;
245 else if (II->isStr("natural"))
246 Kind = Sema::POAK_Natural;
247 else if (II->isStr("packed"))
248 Kind = Sema::POAK_Packed;
249 else if (II->isStr("power"))
250 Kind = Sema::POAK_Power;
251 else if (II->isStr("mac68k"))
252 Kind = Sema::POAK_Mac68k;
253 else if (II->isStr("reset"))
254 Kind = Sema::POAK_Reset;
256 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option)
261 SourceLocation KindLoc = Tok.getLocation();
263 if (Tok.isNot(tok::eod)) {
264 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
265 << (IsOptions ? "options" : "align");
269 Actions.ActOnPragmaOptionsAlign(Kind, FirstTok.getLocation(), KindLoc);
272 void PragmaAlignHandler::HandlePragma(Preprocessor &PP,
273 PragmaIntroducerKind Introducer,
275 ParseAlignPragma(Actions, PP, AlignTok, /*IsOptions=*/false);
278 void PragmaOptionsHandler::HandlePragma(Preprocessor &PP,
279 PragmaIntroducerKind Introducer,
281 ParseAlignPragma(Actions, PP, OptionsTok, /*IsOptions=*/true);
284 // #pragma unused(identifier)
285 void PragmaUnusedHandler::HandlePragma(Preprocessor &PP,
286 PragmaIntroducerKind Introducer,
288 // FIXME: Should we be expanding macros here? My guess is no.
289 SourceLocation UnusedLoc = UnusedTok.getLocation();
294 if (Tok.isNot(tok::l_paren)) {
295 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
299 // Lex the declaration reference(s).
300 SmallVector<Token, 5> Identifiers;
301 SourceLocation RParenLoc;
308 if (Tok.is(tok::identifier)) {
309 Identifiers.push_back(Tok);
315 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
319 // We are execting a ')' or a ','.
320 if (Tok.is(tok::comma)) {
325 if (Tok.is(tok::r_paren)) {
326 RParenLoc = Tok.getLocation();
331 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_punc);
336 if (Tok.isNot(tok::eod)) {
337 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
342 // Verify that we have a location for the right parenthesis.
343 assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
344 assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
346 // For each identifier token, insert into the token stream a
347 // annot_pragma_unused token followed by the identifier token.
348 // This allows us to cache a "#pragma unused" that occurs inside an inline
349 // C++ member function.
351 Token *Toks = new Token[2*Identifiers.size()];
352 for (unsigned i=0; i != Identifiers.size(); i++) {
353 Token &pragmaUnusedTok = Toks[2*i], &idTok = Toks[2*i+1];
354 pragmaUnusedTok.startToken();
355 pragmaUnusedTok.setKind(tok::annot_pragma_unused);
356 pragmaUnusedTok.setLocation(UnusedLoc);
357 idTok = Identifiers[i];
359 PP.EnterTokenStream(Toks, 2*Identifiers.size(), /*DisableMacroExpansion=*/true, /*OwnsTokens=*/true);
362 // #pragma weak identifier
363 // #pragma weak identifier '=' identifier
364 void PragmaWeakHandler::HandlePragma(Preprocessor &PP,
365 PragmaIntroducerKind Introducer,
367 // FIXME: Should we be expanding macros here? My guess is no.
368 SourceLocation WeakLoc = WeakTok.getLocation();
372 if (Tok.isNot(tok::identifier)) {
373 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";
377 IdentifierInfo *WeakName = Tok.getIdentifierInfo(), *AliasName = 0;
378 SourceLocation WeakNameLoc = Tok.getLocation(), AliasNameLoc;
381 if (Tok.is(tok::equal)) {
383 if (Tok.isNot(tok::identifier)) {
384 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
388 AliasName = Tok.getIdentifierInfo();
389 AliasNameLoc = Tok.getLocation();
393 if (Tok.isNot(tok::eod)) {
394 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";
399 Actions.ActOnPragmaWeakAlias(WeakName, AliasName, WeakLoc, WeakNameLoc,
402 Actions.ActOnPragmaWeakID(WeakName, WeakLoc, WeakNameLoc);
407 PragmaFPContractHandler::HandlePragma(Preprocessor &PP,
408 PragmaIntroducerKind Introducer,
410 tok::OnOffSwitch OOS;
411 if (PP.LexOnOffSwitch(OOS))
414 Actions.ActOnPragmaFPContract(OOS);
418 PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
419 PragmaIntroducerKind Introducer,
421 PP.LexUnexpandedToken(Tok);
422 if (Tok.isNot(tok::identifier)) {
423 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
427 IdentifierInfo *ename = Tok.getIdentifierInfo();
428 SourceLocation NameLoc = Tok.getLocation();
431 if (Tok.isNot(tok::colon)) {
432 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << ename;
437 if (Tok.isNot(tok::identifier)) {
438 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
441 IdentifierInfo *op = Tok.getIdentifierInfo();
444 if (op->isStr("enable")) {
446 } else if (op->isStr("disable")) {
449 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
453 OpenCLOptions &f = Actions.getOpenCLOptions();
454 // OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions,
455 // overriding all previously issued extension directives, but only if the
456 // behavior is set to disable."
457 if (state == 0 && ename->isStr("all")) {
458 #define OPENCLEXT(nm) f.nm = 0;
459 #include "clang/Basic/OpenCLExtensions.def"
461 #define OPENCLEXT(nm) else if (ename->isStr(#nm)) { f.nm = state; }
462 #include "clang/Basic/OpenCLExtensions.def"
464 PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << ename;