blob: 2fe2f3bdf3caa3a1dfcec10ed56906a453fc3baa [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
32// #pragma GCC visibility comes in two variants:
33// 'push' '(' [visibility] ')'
34// 'pop'
Douglas Gregor80c60f72010-09-09 22:45:38 +000035void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,
36 PragmaIntroducerKind Introducer,
37 Token &VisTok) {
Eli Friedmanaa8b0d12010-08-05 06:57:20 +000038 SourceLocation VisLoc = VisTok.getLocation();
39
40 Token Tok;
Joerg Sonnenbergere23af2a2011-07-20 01:03:50 +000041 PP.LexUnexpandedToken(Tok);
Eli Friedmanaa8b0d12010-08-05 06:57:20 +000042
43 const IdentifierInfo *PushPop = Tok.getIdentifierInfo();
44
Eli Friedmanaa8b0d12010-08-05 06:57:20 +000045 const IdentifierInfo *VisType;
46 if (PushPop && PushPop->isStr("pop")) {
Eli Friedmanaa8b0d12010-08-05 06:57:20 +000047 VisType = 0;
48 } else if (PushPop && PushPop->isStr("push")) {
Joerg Sonnenbergere23af2a2011-07-20 01:03:50 +000049 PP.LexUnexpandedToken(Tok);
Eli Friedmanaa8b0d12010-08-05 06:57:20 +000050 if (Tok.isNot(tok::l_paren)) {
51 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
52 << "visibility";
53 return;
54 }
Joerg Sonnenbergere23af2a2011-07-20 01:03:50 +000055 PP.LexUnexpandedToken(Tok);
Eli Friedmanaa8b0d12010-08-05 06:57:20 +000056 VisType = Tok.getIdentifierInfo();
57 if (!VisType) {
58 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
59 << "visibility";
60 return;
61 }
Joerg Sonnenbergere23af2a2011-07-20 01:03:50 +000062 PP.LexUnexpandedToken(Tok);
Eli Friedmanaa8b0d12010-08-05 06:57:20 +000063 if (Tok.isNot(tok::r_paren)) {
64 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
65 << "visibility";
66 return;
67 }
68 } else {
69 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
70 << "visibility";
71 return;
72 }
Joerg Sonnenbergere23af2a2011-07-20 01:03:50 +000073 PP.LexUnexpandedToken(Tok);
Peter Collingbourne84021552011-02-28 02:37:51 +000074 if (Tok.isNot(tok::eod)) {
Eli Friedmanaa8b0d12010-08-05 06:57:20 +000075 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
76 << "visibility";
77 return;
78 }
79
Rafael Espindola3fc809d2012-01-21 05:43:40 +000080 Actions.ActOnPragmaVisibility(VisType, VisLoc);
Eli Friedmanaa8b0d12010-08-05 06:57:20 +000081}
82
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000083// #pragma pack(...) comes in the following delicious flavors:
84// pack '(' [integer] ')'
85// pack '(' 'show' ')'
86// pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'
Douglas Gregor80c60f72010-09-09 22:45:38 +000087void PragmaPackHandler::HandlePragma(Preprocessor &PP,
88 PragmaIntroducerKind Introducer,
89 Token &PackTok) {
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000090 SourceLocation PackLoc = PackTok.getLocation();
91
92 Token Tok;
93 PP.Lex(Tok);
94 if (Tok.isNot(tok::l_paren)) {
Ted Kremenek4726d032009-03-23 22:28:25 +000095 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack";
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000096 return;
97 }
98
John McCallf312b1e2010-08-26 23:41:50 +000099 Sema::PragmaPackKind Kind = Sema::PPK_Default;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000100 IdentifierInfo *Name = 0;
John McCall60d7b3a2010-08-24 06:29:42 +0000101 ExprResult Alignment;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000102 SourceLocation LParenLoc = Tok.getLocation();
Mike Stump1eb44332009-09-09 15:08:12 +0000103 PP.Lex(Tok);
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000104 if (Tok.is(tok::numeric_constant)) {
105 Alignment = Actions.ActOnNumericConstant(Tok);
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000106 if (Alignment.isInvalid())
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000107 return;
108
109 PP.Lex(Tok);
Eli Friedman19bda3a2011-11-02 01:53:16 +0000110
111 // In MSVC/gcc, #pragma pack(4) sets the alignment without affecting
112 // the push/pop stack.
113 // In Apple gcc, #pragma pack(4) is equivalent to #pragma pack(push, 4)
114 if (PP.getLangOptions().ApplePragmaPack)
115 Kind = Sema::PPK_Push;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000116 } else if (Tok.is(tok::identifier)) {
117 const IdentifierInfo *II = Tok.getIdentifierInfo();
Chris Lattner08631c52008-11-23 21:45:46 +0000118 if (II->isStr("show")) {
John McCallf312b1e2010-08-26 23:41:50 +0000119 Kind = Sema::PPK_Show;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000120 PP.Lex(Tok);
121 } else {
Chris Lattner08631c52008-11-23 21:45:46 +0000122 if (II->isStr("push")) {
John McCallf312b1e2010-08-26 23:41:50 +0000123 Kind = Sema::PPK_Push;
Chris Lattner08631c52008-11-23 21:45:46 +0000124 } else if (II->isStr("pop")) {
John McCallf312b1e2010-08-26 23:41:50 +0000125 Kind = Sema::PPK_Pop;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000126 } else {
127 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_invalid_action);
128 return;
Mike Stump1eb44332009-09-09 15:08:12 +0000129 }
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000130 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000131
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000132 if (Tok.is(tok::comma)) {
133 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000134
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000135 if (Tok.is(tok::numeric_constant)) {
136 Alignment = Actions.ActOnNumericConstant(Tok);
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000137 if (Alignment.isInvalid())
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000138 return;
139
140 PP.Lex(Tok);
141 } else if (Tok.is(tok::identifier)) {
142 Name = Tok.getIdentifierInfo();
143 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000144
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000145 if (Tok.is(tok::comma)) {
146 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000147
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000148 if (Tok.isNot(tok::numeric_constant)) {
Chris Lattner08631c52008-11-23 21:45:46 +0000149 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000150 return;
151 }
Mike Stump1eb44332009-09-09 15:08:12 +0000152
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000153 Alignment = Actions.ActOnNumericConstant(Tok);
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000154 if (Alignment.isInvalid())
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000155 return;
156
157 PP.Lex(Tok);
158 }
159 } else {
Chris Lattner08631c52008-11-23 21:45:46 +0000160 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000161 return;
162 }
163 }
164 }
Eli Friedman19bda3a2011-11-02 01:53:16 +0000165 } else if (PP.getLangOptions().ApplePragmaPack) {
166 // In MSVC/gcc, #pragma pack() resets the alignment without affecting
167 // the push/pop stack.
168 // In Apple gcc #pragma pack() is equivalent to #pragma pack(pop).
169 Kind = Sema::PPK_Pop;
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000170 }
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000171
172 if (Tok.isNot(tok::r_paren)) {
Ted Kremenek4726d032009-03-23 22:28:25 +0000173 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack";
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000174 return;
175 }
176
Daniel Dunbar861800c2010-05-26 23:29:06 +0000177 SourceLocation RParenLoc = Tok.getLocation();
Eli Friedman99914792009-06-05 00:49:58 +0000178 PP.Lex(Tok);
Peter Collingbourne84021552011-02-28 02:37:51 +0000179 if (Tok.isNot(tok::eod)) {
Eli Friedman99914792009-06-05 00:49:58 +0000180 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack";
181 return;
182 }
183
Sebastian Redleffa8d12008-12-10 00:02:53 +0000184 Actions.ActOnPragmaPack(Kind, Name, Alignment.release(), PackLoc,
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000185 LParenLoc, RParenLoc);
186}
187
Fariborz Jahanian62c92582011-04-25 18:49:15 +0000188// #pragma ms_struct on
189// #pragma ms_struct off
190void PragmaMSStructHandler::HandlePragma(Preprocessor &PP,
191 PragmaIntroducerKind Introducer,
192 Token &MSStructTok) {
193 Sema::PragmaMSStructKind Kind = Sema::PMSST_OFF;
194
195 Token Tok;
196 PP.Lex(Tok);
197 if (Tok.isNot(tok::identifier)) {
198 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
199 return;
200 }
201 const IdentifierInfo *II = Tok.getIdentifierInfo();
202 if (II->isStr("on")) {
203 Kind = Sema::PMSST_ON;
204 PP.Lex(Tok);
205 }
206 else if (II->isStr("off") || II->isStr("reset"))
207 PP.Lex(Tok);
208 else {
209 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
210 return;
211 }
212
213 if (Tok.isNot(tok::eod)) {
214 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "ms_struct";
215 return;
216 }
217 Actions.ActOnPragmaMSStruct(Kind);
218}
219
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000220// #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
221// #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
John McCallf312b1e2010-08-26 23:41:50 +0000222static void ParseAlignPragma(Sema &Actions, Preprocessor &PP, Token &FirstTok,
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000223 bool IsOptions) {
Daniel Dunbar861800c2010-05-26 23:29:06 +0000224 Token Tok;
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000225
226 if (IsOptions) {
227 PP.Lex(Tok);
228 if (Tok.isNot(tok::identifier) ||
229 !Tok.getIdentifierInfo()->isStr("align")) {
230 PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align);
231 return;
232 }
Daniel Dunbar861800c2010-05-26 23:29:06 +0000233 }
Daniel Dunbar638e7cf2010-05-27 18:42:09 +0000234
Daniel Dunbar861800c2010-05-26 23:29:06 +0000235 PP.Lex(Tok);
236 if (Tok.isNot(tok::equal)) {
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000237 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal)
238 << IsOptions;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000239 return;
240 }
241
242 PP.Lex(Tok);
243 if (Tok.isNot(tok::identifier)) {
244 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000245 << (IsOptions ? "options" : "align");
Daniel Dunbar861800c2010-05-26 23:29:06 +0000246 return;
247 }
248
John McCallf312b1e2010-08-26 23:41:50 +0000249 Sema::PragmaOptionsAlignKind Kind = Sema::POAK_Natural;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000250 const IdentifierInfo *II = Tok.getIdentifierInfo();
Daniel Dunbar638e7cf2010-05-27 18:42:09 +0000251 if (II->isStr("native"))
John McCallf312b1e2010-08-26 23:41:50 +0000252 Kind = Sema::POAK_Native;
Daniel Dunbar638e7cf2010-05-27 18:42:09 +0000253 else if (II->isStr("natural"))
John McCallf312b1e2010-08-26 23:41:50 +0000254 Kind = Sema::POAK_Natural;
Daniel Dunbar6f739142010-05-27 18:42:17 +0000255 else if (II->isStr("packed"))
John McCallf312b1e2010-08-26 23:41:50 +0000256 Kind = Sema::POAK_Packed;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000257 else if (II->isStr("power"))
John McCallf312b1e2010-08-26 23:41:50 +0000258 Kind = Sema::POAK_Power;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000259 else if (II->isStr("mac68k"))
John McCallf312b1e2010-08-26 23:41:50 +0000260 Kind = Sema::POAK_Mac68k;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000261 else if (II->isStr("reset"))
John McCallf312b1e2010-08-26 23:41:50 +0000262 Kind = Sema::POAK_Reset;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000263 else {
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000264 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option)
265 << IsOptions;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000266 return;
267 }
268
269 SourceLocation KindLoc = Tok.getLocation();
270 PP.Lex(Tok);
Peter Collingbourne84021552011-02-28 02:37:51 +0000271 if (Tok.isNot(tok::eod)) {
Daniel Dunbar861800c2010-05-26 23:29:06 +0000272 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000273 << (IsOptions ? "options" : "align");
Daniel Dunbar861800c2010-05-26 23:29:06 +0000274 return;
275 }
276
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000277 Actions.ActOnPragmaOptionsAlign(Kind, FirstTok.getLocation(), KindLoc);
278}
279
Douglas Gregor80c60f72010-09-09 22:45:38 +0000280void PragmaAlignHandler::HandlePragma(Preprocessor &PP,
281 PragmaIntroducerKind Introducer,
282 Token &AlignTok) {
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000283 ParseAlignPragma(Actions, PP, AlignTok, /*IsOptions=*/false);
284}
285
Douglas Gregor80c60f72010-09-09 22:45:38 +0000286void PragmaOptionsHandler::HandlePragma(Preprocessor &PP,
287 PragmaIntroducerKind Introducer,
288 Token &OptionsTok) {
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000289 ParseAlignPragma(Actions, PP, OptionsTok, /*IsOptions=*/true);
Daniel Dunbar861800c2010-05-26 23:29:06 +0000290}
291
Ted Kremenek4726d032009-03-23 22:28:25 +0000292// #pragma unused(identifier)
Douglas Gregor80c60f72010-09-09 22:45:38 +0000293void PragmaUnusedHandler::HandlePragma(Preprocessor &PP,
294 PragmaIntroducerKind Introducer,
295 Token &UnusedTok) {
Ted Kremenek4726d032009-03-23 22:28:25 +0000296 // FIXME: Should we be expanding macros here? My guess is no.
297 SourceLocation UnusedLoc = UnusedTok.getLocation();
Mike Stump1eb44332009-09-09 15:08:12 +0000298
Ted Kremenek4726d032009-03-23 22:28:25 +0000299 // Lex the left '('.
300 Token Tok;
301 PP.Lex(Tok);
302 if (Tok.isNot(tok::l_paren)) {
303 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
304 return;
305 }
Mike Stump1eb44332009-09-09 15:08:12 +0000306
Ted Kremenek4726d032009-03-23 22:28:25 +0000307 // Lex the declaration reference(s).
Chris Lattner5f9e2722011-07-23 10:55:15 +0000308 SmallVector<Token, 5> Identifiers;
Ted Kremenek4726d032009-03-23 22:28:25 +0000309 SourceLocation RParenLoc;
310 bool LexID = true;
Mike Stump1eb44332009-09-09 15:08:12 +0000311
Ted Kremenek4726d032009-03-23 22:28:25 +0000312 while (true) {
313 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000314
Ted Kremenek4726d032009-03-23 22:28:25 +0000315 if (LexID) {
Mike Stump1eb44332009-09-09 15:08:12 +0000316 if (Tok.is(tok::identifier)) {
Ted Kremenek7a02a372009-08-03 23:24:57 +0000317 Identifiers.push_back(Tok);
Ted Kremenek4726d032009-03-23 22:28:25 +0000318 LexID = false;
319 continue;
320 }
321
Ted Kremenek7a02a372009-08-03 23:24:57 +0000322 // Illegal token!
Ted Kremenek4726d032009-03-23 22:28:25 +0000323 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
324 return;
325 }
Mike Stump1eb44332009-09-09 15:08:12 +0000326
Ted Kremenek4726d032009-03-23 22:28:25 +0000327 // We are execting a ')' or a ','.
328 if (Tok.is(tok::comma)) {
329 LexID = true;
330 continue;
331 }
Mike Stump1eb44332009-09-09 15:08:12 +0000332
Ted Kremenek4726d032009-03-23 22:28:25 +0000333 if (Tok.is(tok::r_paren)) {
334 RParenLoc = Tok.getLocation();
335 break;
336 }
Mike Stump1eb44332009-09-09 15:08:12 +0000337
Ted Kremenek7a02a372009-08-03 23:24:57 +0000338 // Illegal token!
Ted Kremenek4726d032009-03-23 22:28:25 +0000339 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_punc);
340 return;
341 }
Eli Friedman99914792009-06-05 00:49:58 +0000342
343 PP.Lex(Tok);
Peter Collingbourne84021552011-02-28 02:37:51 +0000344 if (Tok.isNot(tok::eod)) {
Eli Friedman99914792009-06-05 00:49:58 +0000345 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
346 "unused";
347 return;
348 }
349
Ted Kremenek4726d032009-03-23 22:28:25 +0000350 // Verify that we have a location for the right parenthesis.
351 assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
Ted Kremenek7a02a372009-08-03 23:24:57 +0000352 assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
Ted Kremenek4726d032009-03-23 22:28:25 +0000353
Argyrios Kyrtzidisb918d0f2011-01-17 18:58:44 +0000354 // For each identifier token, insert into the token stream a
355 // annot_pragma_unused token followed by the identifier token.
356 // This allows us to cache a "#pragma unused" that occurs inside an inline
357 // C++ member function.
358
359 Token *Toks = new Token[2*Identifiers.size()];
360 for (unsigned i=0; i != Identifiers.size(); i++) {
361 Token &pragmaUnusedTok = Toks[2*i], &idTok = Toks[2*i+1];
362 pragmaUnusedTok.startToken();
363 pragmaUnusedTok.setKind(tok::annot_pragma_unused);
364 pragmaUnusedTok.setLocation(UnusedLoc);
365 idTok = Identifiers[i];
366 }
367 PP.EnterTokenStream(Toks, 2*Identifiers.size(), /*DisableMacroExpansion=*/true, /*OwnsTokens=*/true);
Ted Kremenek4726d032009-03-23 22:28:25 +0000368}
Eli Friedman99914792009-06-05 00:49:58 +0000369
370// #pragma weak identifier
371// #pragma weak identifier '=' identifier
Douglas Gregor80c60f72010-09-09 22:45:38 +0000372void PragmaWeakHandler::HandlePragma(Preprocessor &PP,
373 PragmaIntroducerKind Introducer,
374 Token &WeakTok) {
Eli Friedman99914792009-06-05 00:49:58 +0000375 // FIXME: Should we be expanding macros here? My guess is no.
376 SourceLocation WeakLoc = WeakTok.getLocation();
377
378 Token Tok;
379 PP.Lex(Tok);
380 if (Tok.isNot(tok::identifier)) {
381 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";
382 return;
383 }
384
385 IdentifierInfo *WeakName = Tok.getIdentifierInfo(), *AliasName = 0;
386 SourceLocation WeakNameLoc = Tok.getLocation(), AliasNameLoc;
387
388 PP.Lex(Tok);
389 if (Tok.is(tok::equal)) {
390 PP.Lex(Tok);
391 if (Tok.isNot(tok::identifier)) {
Mike Stump1eb44332009-09-09 15:08:12 +0000392 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Eli Friedman99914792009-06-05 00:49:58 +0000393 << "weak";
394 return;
395 }
396 AliasName = Tok.getIdentifierInfo();
397 AliasNameLoc = Tok.getLocation();
398 PP.Lex(Tok);
399 }
400
Peter Collingbourne84021552011-02-28 02:37:51 +0000401 if (Tok.isNot(tok::eod)) {
Eli Friedman99914792009-06-05 00:49:58 +0000402 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";
403 return;
404 }
405
406 if (AliasName) {
407 Actions.ActOnPragmaWeakAlias(WeakName, AliasName, WeakLoc, WeakNameLoc,
408 AliasNameLoc);
409 } else {
410 Actions.ActOnPragmaWeakID(WeakName, WeakLoc, WeakNameLoc);
411 }
412}
Peter Collingbourne321b8172011-02-14 01:42:35 +0000413
414void
415PragmaFPContractHandler::HandlePragma(Preprocessor &PP,
416 PragmaIntroducerKind Introducer,
417 Token &Tok) {
418 tok::OnOffSwitch OOS;
419 if (PP.LexOnOffSwitch(OOS))
420 return;
421
422 Actions.ActOnPragmaFPContract(OOS);
423}
Peter Collingbournef315fa82011-02-14 01:42:53 +0000424
425void
426PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
427 PragmaIntroducerKind Introducer,
428 Token &Tok) {
Tanya Lattnerb38b6a72011-04-14 23:35:31 +0000429 PP.LexUnexpandedToken(Tok);
Peter Collingbournef315fa82011-02-14 01:42:53 +0000430 if (Tok.isNot(tok::identifier)) {
431 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
432 "OPENCL";
433 return;
434 }
435 IdentifierInfo *ename = Tok.getIdentifierInfo();
436 SourceLocation NameLoc = Tok.getLocation();
437
438 PP.Lex(Tok);
439 if (Tok.isNot(tok::colon)) {
440 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << ename;
441 return;
442 }
443
444 PP.Lex(Tok);
445 if (Tok.isNot(tok::identifier)) {
446 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
447 return;
448 }
449 IdentifierInfo *op = Tok.getIdentifierInfo();
450
451 unsigned state;
452 if (op->isStr("enable")) {
453 state = 1;
454 } else if (op->isStr("disable")) {
455 state = 0;
456 } else {
457 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
458 return;
459 }
460
461 OpenCLOptions &f = Actions.getOpenCLOptions();
Peter Collingbourne41c8d6f2011-10-06 03:00:50 +0000462 // OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions,
463 // overriding all previously issued extension directives, but only if the
464 // behavior is set to disable."
465 if (state == 0 && ename->isStr("all")) {
466#define OPENCLEXT(nm) f.nm = 0;
Peter Collingbournef315fa82011-02-14 01:42:53 +0000467#include "clang/Basic/OpenCLExtensions.def"
468 }
469#define OPENCLEXT(nm) else if (ename->isStr(#nm)) { f.nm = state; }
470#include "clang/Basic/OpenCLExtensions.def"
471 else {
472 PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << ename;
473 return;
474 }
475}
476