blob: f47b32f513b35f844373caa8de83d34aaa2a51c5 [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 Friedmanaa8b0d12010-08-05 06:57:20 +000040// #pragma GCC visibility comes in two variants:
41// 'push' '(' [visibility] ')'
42// 'pop'
Douglas Gregor80c60f72010-09-09 22:45:38 +000043void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,
44 PragmaIntroducerKind Introducer,
45 Token &VisTok) {
Eli Friedmanaa8b0d12010-08-05 06:57:20 +000046 SourceLocation VisLoc = VisTok.getLocation();
47
48 Token Tok;
Joerg Sonnenbergere23af2a2011-07-20 01:03:50 +000049 PP.LexUnexpandedToken(Tok);
Eli Friedmanaa8b0d12010-08-05 06:57:20 +000050
51 const IdentifierInfo *PushPop = Tok.getIdentifierInfo();
52
Eli Friedmanaa8b0d12010-08-05 06:57:20 +000053 const IdentifierInfo *VisType;
54 if (PushPop && PushPop->isStr("pop")) {
Eli Friedmanaa8b0d12010-08-05 06:57:20 +000055 VisType = 0;
56 } else if (PushPop && PushPop->isStr("push")) {
Joerg Sonnenbergere23af2a2011-07-20 01:03:50 +000057 PP.LexUnexpandedToken(Tok);
Eli Friedmanaa8b0d12010-08-05 06:57:20 +000058 if (Tok.isNot(tok::l_paren)) {
59 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
60 << "visibility";
61 return;
62 }
Joerg Sonnenbergere23af2a2011-07-20 01:03:50 +000063 PP.LexUnexpandedToken(Tok);
Eli Friedmanaa8b0d12010-08-05 06:57:20 +000064 VisType = Tok.getIdentifierInfo();
65 if (!VisType) {
66 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
67 << "visibility";
68 return;
69 }
Joerg Sonnenbergere23af2a2011-07-20 01:03:50 +000070 PP.LexUnexpandedToken(Tok);
Eli Friedmanaa8b0d12010-08-05 06:57:20 +000071 if (Tok.isNot(tok::r_paren)) {
72 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
73 << "visibility";
74 return;
75 }
76 } else {
77 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
78 << "visibility";
79 return;
80 }
Joerg Sonnenbergere23af2a2011-07-20 01:03:50 +000081 PP.LexUnexpandedToken(Tok);
Peter Collingbourne84021552011-02-28 02:37:51 +000082 if (Tok.isNot(tok::eod)) {
Eli Friedmanaa8b0d12010-08-05 06:57:20 +000083 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
84 << "visibility";
85 return;
86 }
87
Rafael Espindola426fc942012-01-26 02:02:57 +000088 Token *Toks = new Token[1];
89 Toks[0].startToken();
90 Toks[0].setKind(tok::annot_pragma_vis);
91 Toks[0].setLocation(VisLoc);
92 Toks[0].setAnnotationValue(
93 const_cast<void*>(static_cast<const void*>(VisType)));
94 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
95 /*OwnsTokens=*/true);
Eli Friedmanaa8b0d12010-08-05 06:57:20 +000096}
97
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000098// #pragma pack(...) comes in the following delicious flavors:
99// pack '(' [integer] ')'
100// pack '(' 'show' ')'
101// pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'
Douglas Gregor80c60f72010-09-09 22:45:38 +0000102void PragmaPackHandler::HandlePragma(Preprocessor &PP,
103 PragmaIntroducerKind Introducer,
104 Token &PackTok) {
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000105 SourceLocation PackLoc = PackTok.getLocation();
106
107 Token Tok;
108 PP.Lex(Tok);
109 if (Tok.isNot(tok::l_paren)) {
Ted Kremenek4726d032009-03-23 22:28:25 +0000110 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack";
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000111 return;
112 }
113
John McCallf312b1e2010-08-26 23:41:50 +0000114 Sema::PragmaPackKind Kind = Sema::PPK_Default;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000115 IdentifierInfo *Name = 0;
John McCall60d7b3a2010-08-24 06:29:42 +0000116 ExprResult Alignment;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000117 SourceLocation LParenLoc = Tok.getLocation();
Mike Stump1eb44332009-09-09 15:08:12 +0000118 PP.Lex(Tok);
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000119 if (Tok.is(tok::numeric_constant)) {
120 Alignment = Actions.ActOnNumericConstant(Tok);
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000121 if (Alignment.isInvalid())
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000122 return;
123
124 PP.Lex(Tok);
Eli Friedman19bda3a2011-11-02 01:53:16 +0000125
126 // In MSVC/gcc, #pragma pack(4) sets the alignment without affecting
127 // the push/pop stack.
128 // In Apple gcc, #pragma pack(4) is equivalent to #pragma pack(push, 4)
129 if (PP.getLangOptions().ApplePragmaPack)
130 Kind = Sema::PPK_Push;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000131 } else if (Tok.is(tok::identifier)) {
132 const IdentifierInfo *II = Tok.getIdentifierInfo();
Chris Lattner08631c52008-11-23 21:45:46 +0000133 if (II->isStr("show")) {
John McCallf312b1e2010-08-26 23:41:50 +0000134 Kind = Sema::PPK_Show;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000135 PP.Lex(Tok);
136 } else {
Chris Lattner08631c52008-11-23 21:45:46 +0000137 if (II->isStr("push")) {
John McCallf312b1e2010-08-26 23:41:50 +0000138 Kind = Sema::PPK_Push;
Chris Lattner08631c52008-11-23 21:45:46 +0000139 } else if (II->isStr("pop")) {
John McCallf312b1e2010-08-26 23:41:50 +0000140 Kind = Sema::PPK_Pop;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000141 } else {
142 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_invalid_action);
143 return;
Mike Stump1eb44332009-09-09 15:08:12 +0000144 }
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000145 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000146
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000147 if (Tok.is(tok::comma)) {
148 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000149
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000150 if (Tok.is(tok::numeric_constant)) {
151 Alignment = Actions.ActOnNumericConstant(Tok);
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000152 if (Alignment.isInvalid())
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000153 return;
154
155 PP.Lex(Tok);
156 } else if (Tok.is(tok::identifier)) {
157 Name = Tok.getIdentifierInfo();
158 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000159
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000160 if (Tok.is(tok::comma)) {
161 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000162
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000163 if (Tok.isNot(tok::numeric_constant)) {
Chris Lattner08631c52008-11-23 21:45:46 +0000164 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000165 return;
166 }
Mike Stump1eb44332009-09-09 15:08:12 +0000167
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000168 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 }
174 } else {
Chris Lattner08631c52008-11-23 21:45:46 +0000175 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000176 return;
177 }
178 }
179 }
Eli Friedman19bda3a2011-11-02 01:53:16 +0000180 } else if (PP.getLangOptions().ApplePragmaPack) {
181 // In MSVC/gcc, #pragma pack() resets the alignment without affecting
182 // the push/pop stack.
183 // In Apple gcc #pragma pack() is equivalent to #pragma pack(pop).
184 Kind = Sema::PPK_Pop;
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000185 }
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000186
187 if (Tok.isNot(tok::r_paren)) {
Ted Kremenek4726d032009-03-23 22:28:25 +0000188 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack";
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000189 return;
190 }
191
Daniel Dunbar861800c2010-05-26 23:29:06 +0000192 SourceLocation RParenLoc = Tok.getLocation();
Eli Friedman99914792009-06-05 00:49:58 +0000193 PP.Lex(Tok);
Peter Collingbourne84021552011-02-28 02:37:51 +0000194 if (Tok.isNot(tok::eod)) {
Eli Friedman99914792009-06-05 00:49:58 +0000195 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack";
196 return;
197 }
198
Sebastian Redleffa8d12008-12-10 00:02:53 +0000199 Actions.ActOnPragmaPack(Kind, Name, Alignment.release(), PackLoc,
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000200 LParenLoc, RParenLoc);
201}
202
Fariborz Jahanian62c92582011-04-25 18:49:15 +0000203// #pragma ms_struct on
204// #pragma ms_struct off
205void PragmaMSStructHandler::HandlePragma(Preprocessor &PP,
206 PragmaIntroducerKind Introducer,
207 Token &MSStructTok) {
208 Sema::PragmaMSStructKind Kind = Sema::PMSST_OFF;
209
210 Token Tok;
211 PP.Lex(Tok);
212 if (Tok.isNot(tok::identifier)) {
213 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
214 return;
215 }
216 const IdentifierInfo *II = Tok.getIdentifierInfo();
217 if (II->isStr("on")) {
218 Kind = Sema::PMSST_ON;
219 PP.Lex(Tok);
220 }
221 else if (II->isStr("off") || II->isStr("reset"))
222 PP.Lex(Tok);
223 else {
224 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
225 return;
226 }
227
228 if (Tok.isNot(tok::eod)) {
229 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "ms_struct";
230 return;
231 }
232 Actions.ActOnPragmaMSStruct(Kind);
233}
234
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000235// #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
236// #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
John McCallf312b1e2010-08-26 23:41:50 +0000237static void ParseAlignPragma(Sema &Actions, Preprocessor &PP, Token &FirstTok,
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000238 bool IsOptions) {
Daniel Dunbar861800c2010-05-26 23:29:06 +0000239 Token Tok;
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000240
241 if (IsOptions) {
242 PP.Lex(Tok);
243 if (Tok.isNot(tok::identifier) ||
244 !Tok.getIdentifierInfo()->isStr("align")) {
245 PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align);
246 return;
247 }
Daniel Dunbar861800c2010-05-26 23:29:06 +0000248 }
Daniel Dunbar638e7cf2010-05-27 18:42:09 +0000249
Daniel Dunbar861800c2010-05-26 23:29:06 +0000250 PP.Lex(Tok);
251 if (Tok.isNot(tok::equal)) {
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000252 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal)
253 << IsOptions;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000254 return;
255 }
256
257 PP.Lex(Tok);
258 if (Tok.isNot(tok::identifier)) {
259 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000260 << (IsOptions ? "options" : "align");
Daniel Dunbar861800c2010-05-26 23:29:06 +0000261 return;
262 }
263
John McCallf312b1e2010-08-26 23:41:50 +0000264 Sema::PragmaOptionsAlignKind Kind = Sema::POAK_Natural;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000265 const IdentifierInfo *II = Tok.getIdentifierInfo();
Daniel Dunbar638e7cf2010-05-27 18:42:09 +0000266 if (II->isStr("native"))
John McCallf312b1e2010-08-26 23:41:50 +0000267 Kind = Sema::POAK_Native;
Daniel Dunbar638e7cf2010-05-27 18:42:09 +0000268 else if (II->isStr("natural"))
John McCallf312b1e2010-08-26 23:41:50 +0000269 Kind = Sema::POAK_Natural;
Daniel Dunbar6f739142010-05-27 18:42:17 +0000270 else if (II->isStr("packed"))
John McCallf312b1e2010-08-26 23:41:50 +0000271 Kind = Sema::POAK_Packed;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000272 else if (II->isStr("power"))
John McCallf312b1e2010-08-26 23:41:50 +0000273 Kind = Sema::POAK_Power;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000274 else if (II->isStr("mac68k"))
John McCallf312b1e2010-08-26 23:41:50 +0000275 Kind = Sema::POAK_Mac68k;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000276 else if (II->isStr("reset"))
John McCallf312b1e2010-08-26 23:41:50 +0000277 Kind = Sema::POAK_Reset;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000278 else {
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000279 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option)
280 << IsOptions;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000281 return;
282 }
283
284 SourceLocation KindLoc = Tok.getLocation();
285 PP.Lex(Tok);
Peter Collingbourne84021552011-02-28 02:37:51 +0000286 if (Tok.isNot(tok::eod)) {
Daniel Dunbar861800c2010-05-26 23:29:06 +0000287 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000288 << (IsOptions ? "options" : "align");
Daniel Dunbar861800c2010-05-26 23:29:06 +0000289 return;
290 }
291
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000292 Actions.ActOnPragmaOptionsAlign(Kind, FirstTok.getLocation(), KindLoc);
293}
294
Douglas Gregor80c60f72010-09-09 22:45:38 +0000295void PragmaAlignHandler::HandlePragma(Preprocessor &PP,
296 PragmaIntroducerKind Introducer,
297 Token &AlignTok) {
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000298 ParseAlignPragma(Actions, PP, AlignTok, /*IsOptions=*/false);
299}
300
Douglas Gregor80c60f72010-09-09 22:45:38 +0000301void PragmaOptionsHandler::HandlePragma(Preprocessor &PP,
302 PragmaIntroducerKind Introducer,
303 Token &OptionsTok) {
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000304 ParseAlignPragma(Actions, PP, OptionsTok, /*IsOptions=*/true);
Daniel Dunbar861800c2010-05-26 23:29:06 +0000305}
306
Ted Kremenek4726d032009-03-23 22:28:25 +0000307// #pragma unused(identifier)
Douglas Gregor80c60f72010-09-09 22:45:38 +0000308void PragmaUnusedHandler::HandlePragma(Preprocessor &PP,
309 PragmaIntroducerKind Introducer,
310 Token &UnusedTok) {
Ted Kremenek4726d032009-03-23 22:28:25 +0000311 // FIXME: Should we be expanding macros here? My guess is no.
312 SourceLocation UnusedLoc = UnusedTok.getLocation();
Mike Stump1eb44332009-09-09 15:08:12 +0000313
Ted Kremenek4726d032009-03-23 22:28:25 +0000314 // Lex the left '('.
315 Token Tok;
316 PP.Lex(Tok);
317 if (Tok.isNot(tok::l_paren)) {
318 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
319 return;
320 }
Mike Stump1eb44332009-09-09 15:08:12 +0000321
Ted Kremenek4726d032009-03-23 22:28:25 +0000322 // Lex the declaration reference(s).
Chris Lattner5f9e2722011-07-23 10:55:15 +0000323 SmallVector<Token, 5> Identifiers;
Ted Kremenek4726d032009-03-23 22:28:25 +0000324 SourceLocation RParenLoc;
325 bool LexID = true;
Mike Stump1eb44332009-09-09 15:08:12 +0000326
Ted Kremenek4726d032009-03-23 22:28:25 +0000327 while (true) {
328 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000329
Ted Kremenek4726d032009-03-23 22:28:25 +0000330 if (LexID) {
Mike Stump1eb44332009-09-09 15:08:12 +0000331 if (Tok.is(tok::identifier)) {
Ted Kremenek7a02a372009-08-03 23:24:57 +0000332 Identifiers.push_back(Tok);
Ted Kremenek4726d032009-03-23 22:28:25 +0000333 LexID = false;
334 continue;
335 }
336
Ted Kremenek7a02a372009-08-03 23:24:57 +0000337 // Illegal token!
Ted Kremenek4726d032009-03-23 22:28:25 +0000338 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
339 return;
340 }
Mike Stump1eb44332009-09-09 15:08:12 +0000341
Ted Kremenek4726d032009-03-23 22:28:25 +0000342 // We are execting a ')' or a ','.
343 if (Tok.is(tok::comma)) {
344 LexID = true;
345 continue;
346 }
Mike Stump1eb44332009-09-09 15:08:12 +0000347
Ted Kremenek4726d032009-03-23 22:28:25 +0000348 if (Tok.is(tok::r_paren)) {
349 RParenLoc = Tok.getLocation();
350 break;
351 }
Mike Stump1eb44332009-09-09 15:08:12 +0000352
Ted Kremenek7a02a372009-08-03 23:24:57 +0000353 // Illegal token!
Ted Kremenek4726d032009-03-23 22:28:25 +0000354 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_punc);
355 return;
356 }
Eli Friedman99914792009-06-05 00:49:58 +0000357
358 PP.Lex(Tok);
Peter Collingbourne84021552011-02-28 02:37:51 +0000359 if (Tok.isNot(tok::eod)) {
Eli Friedman99914792009-06-05 00:49:58 +0000360 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
361 "unused";
362 return;
363 }
364
Ted Kremenek4726d032009-03-23 22:28:25 +0000365 // Verify that we have a location for the right parenthesis.
366 assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
Ted Kremenek7a02a372009-08-03 23:24:57 +0000367 assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
Ted Kremenek4726d032009-03-23 22:28:25 +0000368
Argyrios Kyrtzidisb918d0f2011-01-17 18:58:44 +0000369 // For each identifier token, insert into the token stream a
370 // annot_pragma_unused token followed by the identifier token.
371 // This allows us to cache a "#pragma unused" that occurs inside an inline
372 // C++ member function.
373
374 Token *Toks = new Token[2*Identifiers.size()];
375 for (unsigned i=0; i != Identifiers.size(); i++) {
376 Token &pragmaUnusedTok = Toks[2*i], &idTok = Toks[2*i+1];
377 pragmaUnusedTok.startToken();
378 pragmaUnusedTok.setKind(tok::annot_pragma_unused);
379 pragmaUnusedTok.setLocation(UnusedLoc);
380 idTok = Identifiers[i];
381 }
382 PP.EnterTokenStream(Toks, 2*Identifiers.size(), /*DisableMacroExpansion=*/true, /*OwnsTokens=*/true);
Ted Kremenek4726d032009-03-23 22:28:25 +0000383}
Eli Friedman99914792009-06-05 00:49:58 +0000384
385// #pragma weak identifier
386// #pragma weak identifier '=' identifier
Douglas Gregor80c60f72010-09-09 22:45:38 +0000387void PragmaWeakHandler::HandlePragma(Preprocessor &PP,
388 PragmaIntroducerKind Introducer,
389 Token &WeakTok) {
Eli Friedman99914792009-06-05 00:49:58 +0000390 // FIXME: Should we be expanding macros here? My guess is no.
391 SourceLocation WeakLoc = WeakTok.getLocation();
392
393 Token Tok;
394 PP.Lex(Tok);
395 if (Tok.isNot(tok::identifier)) {
396 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";
397 return;
398 }
399
400 IdentifierInfo *WeakName = Tok.getIdentifierInfo(), *AliasName = 0;
401 SourceLocation WeakNameLoc = Tok.getLocation(), AliasNameLoc;
402
403 PP.Lex(Tok);
404 if (Tok.is(tok::equal)) {
405 PP.Lex(Tok);
406 if (Tok.isNot(tok::identifier)) {
Mike Stump1eb44332009-09-09 15:08:12 +0000407 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Eli Friedman99914792009-06-05 00:49:58 +0000408 << "weak";
409 return;
410 }
411 AliasName = Tok.getIdentifierInfo();
412 AliasNameLoc = Tok.getLocation();
413 PP.Lex(Tok);
414 }
415
Peter Collingbourne84021552011-02-28 02:37:51 +0000416 if (Tok.isNot(tok::eod)) {
Eli Friedman99914792009-06-05 00:49:58 +0000417 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";
418 return;
419 }
420
421 if (AliasName) {
422 Actions.ActOnPragmaWeakAlias(WeakName, AliasName, WeakLoc, WeakNameLoc,
423 AliasNameLoc);
424 } else {
425 Actions.ActOnPragmaWeakID(WeakName, WeakLoc, WeakNameLoc);
426 }
427}
Peter Collingbourne321b8172011-02-14 01:42:35 +0000428
429void
430PragmaFPContractHandler::HandlePragma(Preprocessor &PP,
431 PragmaIntroducerKind Introducer,
432 Token &Tok) {
433 tok::OnOffSwitch OOS;
434 if (PP.LexOnOffSwitch(OOS))
435 return;
436
437 Actions.ActOnPragmaFPContract(OOS);
438}
Peter Collingbournef315fa82011-02-14 01:42:53 +0000439
440void
441PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
442 PragmaIntroducerKind Introducer,
443 Token &Tok) {
Tanya Lattnerb38b6a72011-04-14 23:35:31 +0000444 PP.LexUnexpandedToken(Tok);
Peter Collingbournef315fa82011-02-14 01:42:53 +0000445 if (Tok.isNot(tok::identifier)) {
446 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
447 "OPENCL";
448 return;
449 }
450 IdentifierInfo *ename = Tok.getIdentifierInfo();
451 SourceLocation NameLoc = Tok.getLocation();
452
453 PP.Lex(Tok);
454 if (Tok.isNot(tok::colon)) {
455 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << ename;
456 return;
457 }
458
459 PP.Lex(Tok);
460 if (Tok.isNot(tok::identifier)) {
461 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
462 return;
463 }
464 IdentifierInfo *op = Tok.getIdentifierInfo();
465
466 unsigned state;
467 if (op->isStr("enable")) {
468 state = 1;
469 } else if (op->isStr("disable")) {
470 state = 0;
471 } else {
472 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
473 return;
474 }
475
476 OpenCLOptions &f = Actions.getOpenCLOptions();
Peter Collingbourne41c8d6f2011-10-06 03:00:50 +0000477 // OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions,
478 // overriding all previously issued extension directives, but only if the
479 // behavior is set to disable."
480 if (state == 0 && ename->isStr("all")) {
481#define OPENCLEXT(nm) f.nm = 0;
Peter Collingbournef315fa82011-02-14 01:42:53 +0000482#include "clang/Basic/OpenCLExtensions.def"
483 }
484#define OPENCLEXT(nm) else if (ename->isStr(#nm)) { f.nm = state; }
485#include "clang/Basic/OpenCLExtensions.def"
486 else {
487 PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << ename;
488 return;
489 }
490}
491