blob: fef3af249c545e778e9a8c647686e4044c1c1d09 [file] [log] [blame]
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +00001//===--- ParsePragma.cpp - Language specific pragma parsing ---------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the language specific #pragma handlers.
11//
12//===----------------------------------------------------------------------===//
13
14#include "ParsePragma.h"
Chris Lattner500d3292009-01-29 05:15:15 +000015#include "clang/Parse/ParseDiagnostic.h"
Ted Kremenek4726d032009-03-23 22:28:25 +000016#include "clang/Parse/Parser.h"
John McCall19510852010-08-20 18:27:03 +000017#include "clang/Lex/Preprocessor.h"
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000018using namespace clang;
19
Argyrios Kyrtzidisb918d0f2011-01-17 18:58:44 +000020/// \brief Handle the annotation token produced for #pragma unused(...)
21///
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'
25void 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.
30}
Eli Friedmanaa8b0d12010-08-05 06:57:20 +000031
Rafael Espindola426fc942012-01-26 02:02:57 +000032void 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);
38}
39
Eli Friedmanaa5ab262012-02-23 23:47:16 +000040struct PragmaPackInfo {
41 Sema::PragmaPackKind Kind;
42 IdentifierInfo *Name;
43 Expr *Alignment;
44 SourceLocation LParenLoc;
45 SourceLocation RParenLoc;
46};
47
48void 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);
Eli Friedmanaa5ab262012-02-23 23:47:16 +000055}
56
Eli Friedmanaa8b0d12010-08-05 06:57:20 +000057// #pragma GCC visibility comes in two variants:
58// 'push' '(' [visibility] ')'
59// 'pop'
Douglas Gregor80c60f72010-09-09 22:45:38 +000060void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,
61 PragmaIntroducerKind Introducer,
62 Token &VisTok) {
Eli Friedmanaa8b0d12010-08-05 06:57:20 +000063 SourceLocation VisLoc = VisTok.getLocation();
64
65 Token Tok;
Joerg Sonnenbergere23af2a2011-07-20 01:03:50 +000066 PP.LexUnexpandedToken(Tok);
Eli Friedmanaa8b0d12010-08-05 06:57:20 +000067
68 const IdentifierInfo *PushPop = Tok.getIdentifierInfo();
69
Eli Friedmanaa8b0d12010-08-05 06:57:20 +000070 const IdentifierInfo *VisType;
71 if (PushPop && PushPop->isStr("pop")) {
Eli Friedmanaa8b0d12010-08-05 06:57:20 +000072 VisType = 0;
73 } else if (PushPop && PushPop->isStr("push")) {
Joerg Sonnenbergere23af2a2011-07-20 01:03:50 +000074 PP.LexUnexpandedToken(Tok);
Eli Friedmanaa8b0d12010-08-05 06:57:20 +000075 if (Tok.isNot(tok::l_paren)) {
76 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
77 << "visibility";
78 return;
79 }
Joerg Sonnenbergere23af2a2011-07-20 01:03:50 +000080 PP.LexUnexpandedToken(Tok);
Eli Friedmanaa8b0d12010-08-05 06:57:20 +000081 VisType = Tok.getIdentifierInfo();
82 if (!VisType) {
83 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
84 << "visibility";
85 return;
86 }
Joerg Sonnenbergere23af2a2011-07-20 01:03:50 +000087 PP.LexUnexpandedToken(Tok);
Eli Friedmanaa8b0d12010-08-05 06:57:20 +000088 if (Tok.isNot(tok::r_paren)) {
89 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
90 << "visibility";
91 return;
92 }
93 } else {
94 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
95 << "visibility";
96 return;
97 }
Joerg Sonnenbergere23af2a2011-07-20 01:03:50 +000098 PP.LexUnexpandedToken(Tok);
Peter Collingbourne84021552011-02-28 02:37:51 +000099 if (Tok.isNot(tok::eod)) {
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000100 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
101 << "visibility";
102 return;
103 }
104
Rafael Espindola426fc942012-01-26 02:02:57 +0000105 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);
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000113}
114
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000115// #pragma pack(...) comes in the following delicious flavors:
116// pack '(' [integer] ')'
117// pack '(' 'show' ')'
118// pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'
Douglas Gregor80c60f72010-09-09 22:45:38 +0000119void PragmaPackHandler::HandlePragma(Preprocessor &PP,
120 PragmaIntroducerKind Introducer,
121 Token &PackTok) {
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000122 SourceLocation PackLoc = PackTok.getLocation();
123
124 Token Tok;
125 PP.Lex(Tok);
126 if (Tok.isNot(tok::l_paren)) {
Ted Kremenek4726d032009-03-23 22:28:25 +0000127 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack";
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000128 return;
129 }
130
John McCallf312b1e2010-08-26 23:41:50 +0000131 Sema::PragmaPackKind Kind = Sema::PPK_Default;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000132 IdentifierInfo *Name = 0;
John McCall60d7b3a2010-08-24 06:29:42 +0000133 ExprResult Alignment;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000134 SourceLocation LParenLoc = Tok.getLocation();
Mike Stump1eb44332009-09-09 15:08:12 +0000135 PP.Lex(Tok);
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000136 if (Tok.is(tok::numeric_constant)) {
137 Alignment = Actions.ActOnNumericConstant(Tok);
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000138 if (Alignment.isInvalid())
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000139 return;
140
141 PP.Lex(Tok);
Eli Friedman19bda3a2011-11-02 01:53:16 +0000142
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.getLangOptions().ApplePragmaPack)
147 Kind = Sema::PPK_Push;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000148 } else if (Tok.is(tok::identifier)) {
149 const IdentifierInfo *II = Tok.getIdentifierInfo();
Chris Lattner08631c52008-11-23 21:45:46 +0000150 if (II->isStr("show")) {
John McCallf312b1e2010-08-26 23:41:50 +0000151 Kind = Sema::PPK_Show;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000152 PP.Lex(Tok);
153 } else {
Chris Lattner08631c52008-11-23 21:45:46 +0000154 if (II->isStr("push")) {
John McCallf312b1e2010-08-26 23:41:50 +0000155 Kind = Sema::PPK_Push;
Chris Lattner08631c52008-11-23 21:45:46 +0000156 } else if (II->isStr("pop")) {
John McCallf312b1e2010-08-26 23:41:50 +0000157 Kind = Sema::PPK_Pop;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000158 } else {
159 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_invalid_action);
160 return;
Mike Stump1eb44332009-09-09 15:08:12 +0000161 }
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000162 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000163
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000164 if (Tok.is(tok::comma)) {
165 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000166
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000167 if (Tok.is(tok::numeric_constant)) {
168 Alignment = Actions.ActOnNumericConstant(Tok);
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000169 if (Alignment.isInvalid())
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000170 return;
171
172 PP.Lex(Tok);
173 } else if (Tok.is(tok::identifier)) {
174 Name = Tok.getIdentifierInfo();
175 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000176
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000177 if (Tok.is(tok::comma)) {
178 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000179
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000180 if (Tok.isNot(tok::numeric_constant)) {
Chris Lattner08631c52008-11-23 21:45:46 +0000181 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000182 return;
183 }
Mike Stump1eb44332009-09-09 15:08:12 +0000184
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000185 Alignment = Actions.ActOnNumericConstant(Tok);
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000186 if (Alignment.isInvalid())
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000187 return;
188
189 PP.Lex(Tok);
190 }
191 } else {
Chris Lattner08631c52008-11-23 21:45:46 +0000192 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000193 return;
194 }
195 }
196 }
Eli Friedman19bda3a2011-11-02 01:53:16 +0000197 } else if (PP.getLangOptions().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;
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000202 }
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000203
204 if (Tok.isNot(tok::r_paren)) {
Ted Kremenek4726d032009-03-23 22:28:25 +0000205 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack";
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000206 return;
207 }
208
Daniel Dunbar861800c2010-05-26 23:29:06 +0000209 SourceLocation RParenLoc = Tok.getLocation();
Eli Friedman99914792009-06-05 00:49:58 +0000210 PP.Lex(Tok);
Peter Collingbourne84021552011-02-28 02:37:51 +0000211 if (Tok.isNot(tok::eod)) {
Eli Friedman99914792009-06-05 00:49:58 +0000212 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack";
213 return;
214 }
215
Daniel Dunbarb0939552012-02-29 01:38:22 +0000216 PragmaPackInfo *Info =
217 (PragmaPackInfo*) PP.getPreprocessorAllocator().Allocate(
218 sizeof(PragmaPackInfo), llvm::alignOf<PragmaPackInfo>());
219 new (Info) PragmaPackInfo();
Eli Friedmanaa5ab262012-02-23 23:47:16 +0000220 Info->Kind = Kind;
221 Info->Name = Name;
222 Info->Alignment = Alignment.release();
223 Info->LParenLoc = LParenLoc;
224 Info->RParenLoc = RParenLoc;
225
Daniel Dunbarb0939552012-02-29 01:38:22 +0000226 Token *Toks =
227 (Token*) PP.getPreprocessorAllocator().Allocate(
228 sizeof(Token) * 1, llvm::alignOf<Token>());
229 new (Toks) Token();
Eli Friedmanaa5ab262012-02-23 23:47:16 +0000230 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,
Daniel Dunbarb0939552012-02-29 01:38:22 +0000235 /*OwnsTokens=*/false);
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000236}
237
Fariborz Jahanian62c92582011-04-25 18:49:15 +0000238// #pragma ms_struct on
239// #pragma ms_struct off
240void PragmaMSStructHandler::HandlePragma(Preprocessor &PP,
241 PragmaIntroducerKind Introducer,
242 Token &MSStructTok) {
243 Sema::PragmaMSStructKind Kind = Sema::PMSST_OFF;
244
245 Token Tok;
246 PP.Lex(Tok);
247 if (Tok.isNot(tok::identifier)) {
248 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
249 return;
250 }
251 const IdentifierInfo *II = Tok.getIdentifierInfo();
252 if (II->isStr("on")) {
253 Kind = Sema::PMSST_ON;
254 PP.Lex(Tok);
255 }
256 else if (II->isStr("off") || II->isStr("reset"))
257 PP.Lex(Tok);
258 else {
259 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
260 return;
261 }
262
263 if (Tok.isNot(tok::eod)) {
Daniel Dunbarb0939552012-02-29 01:38:22 +0000264 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
265 << "ms_struct";
Fariborz Jahanian62c92582011-04-25 18:49:15 +0000266 return;
267 }
268 Actions.ActOnPragmaMSStruct(Kind);
269}
270
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000271// #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
272// #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
John McCallf312b1e2010-08-26 23:41:50 +0000273static void ParseAlignPragma(Sema &Actions, Preprocessor &PP, Token &FirstTok,
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000274 bool IsOptions) {
Daniel Dunbar861800c2010-05-26 23:29:06 +0000275 Token Tok;
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000276
277 if (IsOptions) {
278 PP.Lex(Tok);
279 if (Tok.isNot(tok::identifier) ||
280 !Tok.getIdentifierInfo()->isStr("align")) {
281 PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align);
282 return;
283 }
Daniel Dunbar861800c2010-05-26 23:29:06 +0000284 }
Daniel Dunbar638e7cf2010-05-27 18:42:09 +0000285
Daniel Dunbar861800c2010-05-26 23:29:06 +0000286 PP.Lex(Tok);
287 if (Tok.isNot(tok::equal)) {
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000288 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal)
289 << IsOptions;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000290 return;
291 }
292
293 PP.Lex(Tok);
294 if (Tok.isNot(tok::identifier)) {
295 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000296 << (IsOptions ? "options" : "align");
Daniel Dunbar861800c2010-05-26 23:29:06 +0000297 return;
298 }
299
John McCallf312b1e2010-08-26 23:41:50 +0000300 Sema::PragmaOptionsAlignKind Kind = Sema::POAK_Natural;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000301 const IdentifierInfo *II = Tok.getIdentifierInfo();
Daniel Dunbar638e7cf2010-05-27 18:42:09 +0000302 if (II->isStr("native"))
John McCallf312b1e2010-08-26 23:41:50 +0000303 Kind = Sema::POAK_Native;
Daniel Dunbar638e7cf2010-05-27 18:42:09 +0000304 else if (II->isStr("natural"))
John McCallf312b1e2010-08-26 23:41:50 +0000305 Kind = Sema::POAK_Natural;
Daniel Dunbar6f739142010-05-27 18:42:17 +0000306 else if (II->isStr("packed"))
John McCallf312b1e2010-08-26 23:41:50 +0000307 Kind = Sema::POAK_Packed;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000308 else if (II->isStr("power"))
John McCallf312b1e2010-08-26 23:41:50 +0000309 Kind = Sema::POAK_Power;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000310 else if (II->isStr("mac68k"))
John McCallf312b1e2010-08-26 23:41:50 +0000311 Kind = Sema::POAK_Mac68k;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000312 else if (II->isStr("reset"))
John McCallf312b1e2010-08-26 23:41:50 +0000313 Kind = Sema::POAK_Reset;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000314 else {
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000315 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option)
316 << IsOptions;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000317 return;
318 }
319
320 SourceLocation KindLoc = Tok.getLocation();
321 PP.Lex(Tok);
Peter Collingbourne84021552011-02-28 02:37:51 +0000322 if (Tok.isNot(tok::eod)) {
Daniel Dunbar861800c2010-05-26 23:29:06 +0000323 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000324 << (IsOptions ? "options" : "align");
Daniel Dunbar861800c2010-05-26 23:29:06 +0000325 return;
326 }
327
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000328 Actions.ActOnPragmaOptionsAlign(Kind, FirstTok.getLocation(), KindLoc);
329}
330
Douglas Gregor80c60f72010-09-09 22:45:38 +0000331void PragmaAlignHandler::HandlePragma(Preprocessor &PP,
332 PragmaIntroducerKind Introducer,
333 Token &AlignTok) {
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000334 ParseAlignPragma(Actions, PP, AlignTok, /*IsOptions=*/false);
335}
336
Douglas Gregor80c60f72010-09-09 22:45:38 +0000337void PragmaOptionsHandler::HandlePragma(Preprocessor &PP,
338 PragmaIntroducerKind Introducer,
339 Token &OptionsTok) {
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000340 ParseAlignPragma(Actions, PP, OptionsTok, /*IsOptions=*/true);
Daniel Dunbar861800c2010-05-26 23:29:06 +0000341}
342
Ted Kremenek4726d032009-03-23 22:28:25 +0000343// #pragma unused(identifier)
Douglas Gregor80c60f72010-09-09 22:45:38 +0000344void PragmaUnusedHandler::HandlePragma(Preprocessor &PP,
345 PragmaIntroducerKind Introducer,
346 Token &UnusedTok) {
Ted Kremenek4726d032009-03-23 22:28:25 +0000347 // FIXME: Should we be expanding macros here? My guess is no.
348 SourceLocation UnusedLoc = UnusedTok.getLocation();
Mike Stump1eb44332009-09-09 15:08:12 +0000349
Ted Kremenek4726d032009-03-23 22:28:25 +0000350 // Lex the left '('.
351 Token Tok;
352 PP.Lex(Tok);
353 if (Tok.isNot(tok::l_paren)) {
354 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
355 return;
356 }
Mike Stump1eb44332009-09-09 15:08:12 +0000357
Ted Kremenek4726d032009-03-23 22:28:25 +0000358 // Lex the declaration reference(s).
Chris Lattner5f9e2722011-07-23 10:55:15 +0000359 SmallVector<Token, 5> Identifiers;
Ted Kremenek4726d032009-03-23 22:28:25 +0000360 SourceLocation RParenLoc;
361 bool LexID = true;
Mike Stump1eb44332009-09-09 15:08:12 +0000362
Ted Kremenek4726d032009-03-23 22:28:25 +0000363 while (true) {
364 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000365
Ted Kremenek4726d032009-03-23 22:28:25 +0000366 if (LexID) {
Mike Stump1eb44332009-09-09 15:08:12 +0000367 if (Tok.is(tok::identifier)) {
Ted Kremenek7a02a372009-08-03 23:24:57 +0000368 Identifiers.push_back(Tok);
Ted Kremenek4726d032009-03-23 22:28:25 +0000369 LexID = false;
370 continue;
371 }
372
Ted Kremenek7a02a372009-08-03 23:24:57 +0000373 // Illegal token!
Ted Kremenek4726d032009-03-23 22:28:25 +0000374 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
375 return;
376 }
Mike Stump1eb44332009-09-09 15:08:12 +0000377
Ted Kremenek4726d032009-03-23 22:28:25 +0000378 // We are execting a ')' or a ','.
379 if (Tok.is(tok::comma)) {
380 LexID = true;
381 continue;
382 }
Mike Stump1eb44332009-09-09 15:08:12 +0000383
Ted Kremenek4726d032009-03-23 22:28:25 +0000384 if (Tok.is(tok::r_paren)) {
385 RParenLoc = Tok.getLocation();
386 break;
387 }
Mike Stump1eb44332009-09-09 15:08:12 +0000388
Ted Kremenek7a02a372009-08-03 23:24:57 +0000389 // Illegal token!
Ted Kremenek4726d032009-03-23 22:28:25 +0000390 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_punc);
391 return;
392 }
Eli Friedman99914792009-06-05 00:49:58 +0000393
394 PP.Lex(Tok);
Peter Collingbourne84021552011-02-28 02:37:51 +0000395 if (Tok.isNot(tok::eod)) {
Eli Friedman99914792009-06-05 00:49:58 +0000396 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
397 "unused";
398 return;
399 }
400
Ted Kremenek4726d032009-03-23 22:28:25 +0000401 // Verify that we have a location for the right parenthesis.
402 assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
Ted Kremenek7a02a372009-08-03 23:24:57 +0000403 assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
Ted Kremenek4726d032009-03-23 22:28:25 +0000404
Argyrios Kyrtzidisb918d0f2011-01-17 18:58:44 +0000405 // 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.
409
Daniel Dunbarb0939552012-02-29 01:38:22 +0000410 Token *Toks =
411 (Token*) PP.getPreprocessorAllocator().Allocate(
412 sizeof(Token) * 2 * Identifiers.size(), llvm::alignOf<Token>());
Argyrios Kyrtzidisb918d0f2011-01-17 18:58:44 +0000413 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];
419 }
Daniel Dunbarb0939552012-02-29 01:38:22 +0000420 PP.EnterTokenStream(Toks, 2*Identifiers.size(),
421 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
Ted Kremenek4726d032009-03-23 22:28:25 +0000422}
Eli Friedman99914792009-06-05 00:49:58 +0000423
424// #pragma weak identifier
425// #pragma weak identifier '=' identifier
Douglas Gregor80c60f72010-09-09 22:45:38 +0000426void PragmaWeakHandler::HandlePragma(Preprocessor &PP,
427 PragmaIntroducerKind Introducer,
428 Token &WeakTok) {
Eli Friedman99914792009-06-05 00:49:58 +0000429 // FIXME: Should we be expanding macros here? My guess is no.
430 SourceLocation WeakLoc = WeakTok.getLocation();
431
432 Token Tok;
433 PP.Lex(Tok);
434 if (Tok.isNot(tok::identifier)) {
435 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";
436 return;
437 }
438
439 IdentifierInfo *WeakName = Tok.getIdentifierInfo(), *AliasName = 0;
440 SourceLocation WeakNameLoc = Tok.getLocation(), AliasNameLoc;
441
442 PP.Lex(Tok);
443 if (Tok.is(tok::equal)) {
444 PP.Lex(Tok);
445 if (Tok.isNot(tok::identifier)) {
Mike Stump1eb44332009-09-09 15:08:12 +0000446 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Eli Friedman99914792009-06-05 00:49:58 +0000447 << "weak";
448 return;
449 }
450 AliasName = Tok.getIdentifierInfo();
451 AliasNameLoc = Tok.getLocation();
452 PP.Lex(Tok);
453 }
454
Peter Collingbourne84021552011-02-28 02:37:51 +0000455 if (Tok.isNot(tok::eod)) {
Eli Friedman99914792009-06-05 00:49:58 +0000456 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";
457 return;
458 }
459
460 if (AliasName) {
461 Actions.ActOnPragmaWeakAlias(WeakName, AliasName, WeakLoc, WeakNameLoc,
462 AliasNameLoc);
463 } else {
464 Actions.ActOnPragmaWeakID(WeakName, WeakLoc, WeakNameLoc);
465 }
466}
Peter Collingbourne321b8172011-02-14 01:42:35 +0000467
David Chisnall5f3c1632012-02-18 16:12:34 +0000468// #pragma redefine_extname identifier identifier
469void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP,
470 PragmaIntroducerKind Introducer,
471 Token &RedefToken) {
472 SourceLocation RedefLoc = RedefToken.getLocation();
473
474 Token Tok;
475 PP.Lex(Tok);
476 if (Tok.isNot(tok::identifier)) {
477 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
478 "redefine_extname";
479 return;
480 }
481
482 IdentifierInfo *RedefName = Tok.getIdentifierInfo(), *AliasName = 0;
483 SourceLocation RedefNameLoc = Tok.getLocation(), AliasNameLoc;
484
485 PP.Lex(Tok);
486 if (Tok.isNot(tok::identifier)) {
487 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
488 << "redefine_extname";
489 return;
490 }
491 AliasName = Tok.getIdentifierInfo();
492 AliasNameLoc = Tok.getLocation();
493 PP.Lex(Tok);
494
495 if (Tok.isNot(tok::eod)) {
496 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
497 "redefine_extname";
498 return;
499 }
500
501 Actions.ActOnPragmaRedefineExtname(RedefName, AliasName, RedefLoc,
502 RedefNameLoc, AliasNameLoc);
503}
504
505
Peter Collingbourne321b8172011-02-14 01:42:35 +0000506void
507PragmaFPContractHandler::HandlePragma(Preprocessor &PP,
508 PragmaIntroducerKind Introducer,
509 Token &Tok) {
510 tok::OnOffSwitch OOS;
511 if (PP.LexOnOffSwitch(OOS))
512 return;
513
514 Actions.ActOnPragmaFPContract(OOS);
515}
Peter Collingbournef315fa82011-02-14 01:42:53 +0000516
517void
518PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
519 PragmaIntroducerKind Introducer,
520 Token &Tok) {
Tanya Lattnerb38b6a72011-04-14 23:35:31 +0000521 PP.LexUnexpandedToken(Tok);
Peter Collingbournef315fa82011-02-14 01:42:53 +0000522 if (Tok.isNot(tok::identifier)) {
523 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
524 "OPENCL";
525 return;
526 }
527 IdentifierInfo *ename = Tok.getIdentifierInfo();
528 SourceLocation NameLoc = Tok.getLocation();
529
530 PP.Lex(Tok);
531 if (Tok.isNot(tok::colon)) {
532 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << ename;
533 return;
534 }
535
536 PP.Lex(Tok);
537 if (Tok.isNot(tok::identifier)) {
538 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
539 return;
540 }
541 IdentifierInfo *op = Tok.getIdentifierInfo();
542
543 unsigned state;
544 if (op->isStr("enable")) {
545 state = 1;
546 } else if (op->isStr("disable")) {
547 state = 0;
548 } else {
549 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
550 return;
551 }
552
553 OpenCLOptions &f = Actions.getOpenCLOptions();
Peter Collingbourne41c8d6f2011-10-06 03:00:50 +0000554 // 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;
Peter Collingbournef315fa82011-02-14 01:42:53 +0000559#include "clang/Basic/OpenCLExtensions.def"
560 }
561#define OPENCLEXT(nm) else if (ename->isStr(#nm)) { f.nm = state; }
562#include "clang/Basic/OpenCLExtensions.def"
563 else {
564 PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << ename;
565 return;
566 }
567}
568