blob: 96a4f3af76ca69908d62b51b3b71183dca759f2a [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);
55 delete Info;
56}
57
Eli Friedmanaa8b0d12010-08-05 06:57:20 +000058// #pragma GCC visibility comes in two variants:
59// 'push' '(' [visibility] ')'
60// 'pop'
Douglas Gregor80c60f72010-09-09 22:45:38 +000061void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,
62 PragmaIntroducerKind Introducer,
63 Token &VisTok) {
Eli Friedmanaa8b0d12010-08-05 06:57:20 +000064 SourceLocation VisLoc = VisTok.getLocation();
65
66 Token Tok;
Joerg Sonnenbergere23af2a2011-07-20 01:03:50 +000067 PP.LexUnexpandedToken(Tok);
Eli Friedmanaa8b0d12010-08-05 06:57:20 +000068
69 const IdentifierInfo *PushPop = Tok.getIdentifierInfo();
70
Eli Friedmanaa8b0d12010-08-05 06:57:20 +000071 const IdentifierInfo *VisType;
72 if (PushPop && PushPop->isStr("pop")) {
Eli Friedmanaa8b0d12010-08-05 06:57:20 +000073 VisType = 0;
74 } else if (PushPop && PushPop->isStr("push")) {
Joerg Sonnenbergere23af2a2011-07-20 01:03:50 +000075 PP.LexUnexpandedToken(Tok);
Eli Friedmanaa8b0d12010-08-05 06:57:20 +000076 if (Tok.isNot(tok::l_paren)) {
77 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
78 << "visibility";
79 return;
80 }
Joerg Sonnenbergere23af2a2011-07-20 01:03:50 +000081 PP.LexUnexpandedToken(Tok);
Eli Friedmanaa8b0d12010-08-05 06:57:20 +000082 VisType = Tok.getIdentifierInfo();
83 if (!VisType) {
84 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
85 << "visibility";
86 return;
87 }
Joerg Sonnenbergere23af2a2011-07-20 01:03:50 +000088 PP.LexUnexpandedToken(Tok);
Eli Friedmanaa8b0d12010-08-05 06:57:20 +000089 if (Tok.isNot(tok::r_paren)) {
90 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
91 << "visibility";
92 return;
93 }
94 } else {
95 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
96 << "visibility";
97 return;
98 }
Joerg Sonnenbergere23af2a2011-07-20 01:03:50 +000099 PP.LexUnexpandedToken(Tok);
Peter Collingbourne84021552011-02-28 02:37:51 +0000100 if (Tok.isNot(tok::eod)) {
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000101 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
102 << "visibility";
103 return;
104 }
105
Rafael Espindola426fc942012-01-26 02:02:57 +0000106 Token *Toks = new Token[1];
107 Toks[0].startToken();
108 Toks[0].setKind(tok::annot_pragma_vis);
109 Toks[0].setLocation(VisLoc);
110 Toks[0].setAnnotationValue(
111 const_cast<void*>(static_cast<const void*>(VisType)));
112 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
113 /*OwnsTokens=*/true);
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000114}
115
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000116// #pragma pack(...) comes in the following delicious flavors:
117// pack '(' [integer] ')'
118// pack '(' 'show' ')'
119// pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'
Douglas Gregor80c60f72010-09-09 22:45:38 +0000120void PragmaPackHandler::HandlePragma(Preprocessor &PP,
121 PragmaIntroducerKind Introducer,
122 Token &PackTok) {
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000123 SourceLocation PackLoc = PackTok.getLocation();
124
125 Token Tok;
126 PP.Lex(Tok);
127 if (Tok.isNot(tok::l_paren)) {
Ted Kremenek4726d032009-03-23 22:28:25 +0000128 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack";
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000129 return;
130 }
131
John McCallf312b1e2010-08-26 23:41:50 +0000132 Sema::PragmaPackKind Kind = Sema::PPK_Default;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000133 IdentifierInfo *Name = 0;
John McCall60d7b3a2010-08-24 06:29:42 +0000134 ExprResult Alignment;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000135 SourceLocation LParenLoc = Tok.getLocation();
Mike Stump1eb44332009-09-09 15:08:12 +0000136 PP.Lex(Tok);
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000137 if (Tok.is(tok::numeric_constant)) {
138 Alignment = Actions.ActOnNumericConstant(Tok);
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000139 if (Alignment.isInvalid())
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000140 return;
141
142 PP.Lex(Tok);
Eli Friedman19bda3a2011-11-02 01:53:16 +0000143
144 // In MSVC/gcc, #pragma pack(4) sets the alignment without affecting
145 // the push/pop stack.
146 // In Apple gcc, #pragma pack(4) is equivalent to #pragma pack(push, 4)
147 if (PP.getLangOptions().ApplePragmaPack)
148 Kind = Sema::PPK_Push;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000149 } else if (Tok.is(tok::identifier)) {
150 const IdentifierInfo *II = Tok.getIdentifierInfo();
Chris Lattner08631c52008-11-23 21:45:46 +0000151 if (II->isStr("show")) {
John McCallf312b1e2010-08-26 23:41:50 +0000152 Kind = Sema::PPK_Show;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000153 PP.Lex(Tok);
154 } else {
Chris Lattner08631c52008-11-23 21:45:46 +0000155 if (II->isStr("push")) {
John McCallf312b1e2010-08-26 23:41:50 +0000156 Kind = Sema::PPK_Push;
Chris Lattner08631c52008-11-23 21:45:46 +0000157 } else if (II->isStr("pop")) {
John McCallf312b1e2010-08-26 23:41:50 +0000158 Kind = Sema::PPK_Pop;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000159 } else {
160 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_invalid_action);
161 return;
Mike Stump1eb44332009-09-09 15:08:12 +0000162 }
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000163 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000164
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000165 if (Tok.is(tok::comma)) {
166 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000167
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000168 if (Tok.is(tok::numeric_constant)) {
169 Alignment = Actions.ActOnNumericConstant(Tok);
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000170 if (Alignment.isInvalid())
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000171 return;
172
173 PP.Lex(Tok);
174 } else if (Tok.is(tok::identifier)) {
175 Name = Tok.getIdentifierInfo();
176 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000177
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000178 if (Tok.is(tok::comma)) {
179 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000180
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000181 if (Tok.isNot(tok::numeric_constant)) {
Chris Lattner08631c52008-11-23 21:45:46 +0000182 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000183 return;
184 }
Mike Stump1eb44332009-09-09 15:08:12 +0000185
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000186 Alignment = Actions.ActOnNumericConstant(Tok);
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000187 if (Alignment.isInvalid())
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000188 return;
189
190 PP.Lex(Tok);
191 }
192 } else {
Chris Lattner08631c52008-11-23 21:45:46 +0000193 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000194 return;
195 }
196 }
197 }
Eli Friedman19bda3a2011-11-02 01:53:16 +0000198 } else if (PP.getLangOptions().ApplePragmaPack) {
199 // In MSVC/gcc, #pragma pack() resets the alignment without affecting
200 // the push/pop stack.
201 // In Apple gcc #pragma pack() is equivalent to #pragma pack(pop).
202 Kind = Sema::PPK_Pop;
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000203 }
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000204
205 if (Tok.isNot(tok::r_paren)) {
Ted Kremenek4726d032009-03-23 22:28:25 +0000206 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack";
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000207 return;
208 }
209
Daniel Dunbar861800c2010-05-26 23:29:06 +0000210 SourceLocation RParenLoc = Tok.getLocation();
Eli Friedman99914792009-06-05 00:49:58 +0000211 PP.Lex(Tok);
Peter Collingbourne84021552011-02-28 02:37:51 +0000212 if (Tok.isNot(tok::eod)) {
Eli Friedman99914792009-06-05 00:49:58 +0000213 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack";
214 return;
215 }
216
Eli Friedmanaa5ab262012-02-23 23:47:16 +0000217 PragmaPackInfo *Info = new PragmaPackInfo;
218 Info->Kind = Kind;
219 Info->Name = Name;
220 Info->Alignment = Alignment.release();
221 Info->LParenLoc = LParenLoc;
222 Info->RParenLoc = RParenLoc;
223
224 Token *Toks = new Token[1];
225 Toks[0].startToken();
226 Toks[0].setKind(tok::annot_pragma_pack);
227 Toks[0].setLocation(PackLoc);
228 Toks[0].setAnnotationValue(static_cast<void*>(Info));
229 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
230 /*OwnsTokens=*/true);
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000231}
232
Fariborz Jahanian62c92582011-04-25 18:49:15 +0000233// #pragma ms_struct on
234// #pragma ms_struct off
235void PragmaMSStructHandler::HandlePragma(Preprocessor &PP,
236 PragmaIntroducerKind Introducer,
237 Token &MSStructTok) {
238 Sema::PragmaMSStructKind Kind = Sema::PMSST_OFF;
239
240 Token Tok;
241 PP.Lex(Tok);
242 if (Tok.isNot(tok::identifier)) {
243 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
244 return;
245 }
246 const IdentifierInfo *II = Tok.getIdentifierInfo();
247 if (II->isStr("on")) {
248 Kind = Sema::PMSST_ON;
249 PP.Lex(Tok);
250 }
251 else if (II->isStr("off") || II->isStr("reset"))
252 PP.Lex(Tok);
253 else {
254 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
255 return;
256 }
257
258 if (Tok.isNot(tok::eod)) {
259 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "ms_struct";
260 return;
261 }
262 Actions.ActOnPragmaMSStruct(Kind);
263}
264
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000265// #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
266// #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
John McCallf312b1e2010-08-26 23:41:50 +0000267static void ParseAlignPragma(Sema &Actions, Preprocessor &PP, Token &FirstTok,
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000268 bool IsOptions) {
Daniel Dunbar861800c2010-05-26 23:29:06 +0000269 Token Tok;
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000270
271 if (IsOptions) {
272 PP.Lex(Tok);
273 if (Tok.isNot(tok::identifier) ||
274 !Tok.getIdentifierInfo()->isStr("align")) {
275 PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align);
276 return;
277 }
Daniel Dunbar861800c2010-05-26 23:29:06 +0000278 }
Daniel Dunbar638e7cf2010-05-27 18:42:09 +0000279
Daniel Dunbar861800c2010-05-26 23:29:06 +0000280 PP.Lex(Tok);
281 if (Tok.isNot(tok::equal)) {
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000282 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal)
283 << IsOptions;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000284 return;
285 }
286
287 PP.Lex(Tok);
288 if (Tok.isNot(tok::identifier)) {
289 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000290 << (IsOptions ? "options" : "align");
Daniel Dunbar861800c2010-05-26 23:29:06 +0000291 return;
292 }
293
John McCallf312b1e2010-08-26 23:41:50 +0000294 Sema::PragmaOptionsAlignKind Kind = Sema::POAK_Natural;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000295 const IdentifierInfo *II = Tok.getIdentifierInfo();
Daniel Dunbar638e7cf2010-05-27 18:42:09 +0000296 if (II->isStr("native"))
John McCallf312b1e2010-08-26 23:41:50 +0000297 Kind = Sema::POAK_Native;
Daniel Dunbar638e7cf2010-05-27 18:42:09 +0000298 else if (II->isStr("natural"))
John McCallf312b1e2010-08-26 23:41:50 +0000299 Kind = Sema::POAK_Natural;
Daniel Dunbar6f739142010-05-27 18:42:17 +0000300 else if (II->isStr("packed"))
John McCallf312b1e2010-08-26 23:41:50 +0000301 Kind = Sema::POAK_Packed;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000302 else if (II->isStr("power"))
John McCallf312b1e2010-08-26 23:41:50 +0000303 Kind = Sema::POAK_Power;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000304 else if (II->isStr("mac68k"))
John McCallf312b1e2010-08-26 23:41:50 +0000305 Kind = Sema::POAK_Mac68k;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000306 else if (II->isStr("reset"))
John McCallf312b1e2010-08-26 23:41:50 +0000307 Kind = Sema::POAK_Reset;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000308 else {
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000309 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option)
310 << IsOptions;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000311 return;
312 }
313
314 SourceLocation KindLoc = Tok.getLocation();
315 PP.Lex(Tok);
Peter Collingbourne84021552011-02-28 02:37:51 +0000316 if (Tok.isNot(tok::eod)) {
Daniel Dunbar861800c2010-05-26 23:29:06 +0000317 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000318 << (IsOptions ? "options" : "align");
Daniel Dunbar861800c2010-05-26 23:29:06 +0000319 return;
320 }
321
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000322 Actions.ActOnPragmaOptionsAlign(Kind, FirstTok.getLocation(), KindLoc);
323}
324
Douglas Gregor80c60f72010-09-09 22:45:38 +0000325void PragmaAlignHandler::HandlePragma(Preprocessor &PP,
326 PragmaIntroducerKind Introducer,
327 Token &AlignTok) {
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000328 ParseAlignPragma(Actions, PP, AlignTok, /*IsOptions=*/false);
329}
330
Douglas Gregor80c60f72010-09-09 22:45:38 +0000331void PragmaOptionsHandler::HandlePragma(Preprocessor &PP,
332 PragmaIntroducerKind Introducer,
333 Token &OptionsTok) {
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000334 ParseAlignPragma(Actions, PP, OptionsTok, /*IsOptions=*/true);
Daniel Dunbar861800c2010-05-26 23:29:06 +0000335}
336
Ted Kremenek4726d032009-03-23 22:28:25 +0000337// #pragma unused(identifier)
Douglas Gregor80c60f72010-09-09 22:45:38 +0000338void PragmaUnusedHandler::HandlePragma(Preprocessor &PP,
339 PragmaIntroducerKind Introducer,
340 Token &UnusedTok) {
Ted Kremenek4726d032009-03-23 22:28:25 +0000341 // FIXME: Should we be expanding macros here? My guess is no.
342 SourceLocation UnusedLoc = UnusedTok.getLocation();
Mike Stump1eb44332009-09-09 15:08:12 +0000343
Ted Kremenek4726d032009-03-23 22:28:25 +0000344 // Lex the left '('.
345 Token Tok;
346 PP.Lex(Tok);
347 if (Tok.isNot(tok::l_paren)) {
348 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
349 return;
350 }
Mike Stump1eb44332009-09-09 15:08:12 +0000351
Ted Kremenek4726d032009-03-23 22:28:25 +0000352 // Lex the declaration reference(s).
Chris Lattner5f9e2722011-07-23 10:55:15 +0000353 SmallVector<Token, 5> Identifiers;
Ted Kremenek4726d032009-03-23 22:28:25 +0000354 SourceLocation RParenLoc;
355 bool LexID = true;
Mike Stump1eb44332009-09-09 15:08:12 +0000356
Ted Kremenek4726d032009-03-23 22:28:25 +0000357 while (true) {
358 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000359
Ted Kremenek4726d032009-03-23 22:28:25 +0000360 if (LexID) {
Mike Stump1eb44332009-09-09 15:08:12 +0000361 if (Tok.is(tok::identifier)) {
Ted Kremenek7a02a372009-08-03 23:24:57 +0000362 Identifiers.push_back(Tok);
Ted Kremenek4726d032009-03-23 22:28:25 +0000363 LexID = false;
364 continue;
365 }
366
Ted Kremenek7a02a372009-08-03 23:24:57 +0000367 // Illegal token!
Ted Kremenek4726d032009-03-23 22:28:25 +0000368 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
369 return;
370 }
Mike Stump1eb44332009-09-09 15:08:12 +0000371
Ted Kremenek4726d032009-03-23 22:28:25 +0000372 // We are execting a ')' or a ','.
373 if (Tok.is(tok::comma)) {
374 LexID = true;
375 continue;
376 }
Mike Stump1eb44332009-09-09 15:08:12 +0000377
Ted Kremenek4726d032009-03-23 22:28:25 +0000378 if (Tok.is(tok::r_paren)) {
379 RParenLoc = Tok.getLocation();
380 break;
381 }
Mike Stump1eb44332009-09-09 15:08:12 +0000382
Ted Kremenek7a02a372009-08-03 23:24:57 +0000383 // Illegal token!
Ted Kremenek4726d032009-03-23 22:28:25 +0000384 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_punc);
385 return;
386 }
Eli Friedman99914792009-06-05 00:49:58 +0000387
388 PP.Lex(Tok);
Peter Collingbourne84021552011-02-28 02:37:51 +0000389 if (Tok.isNot(tok::eod)) {
Eli Friedman99914792009-06-05 00:49:58 +0000390 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
391 "unused";
392 return;
393 }
394
Ted Kremenek4726d032009-03-23 22:28:25 +0000395 // Verify that we have a location for the right parenthesis.
396 assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
Ted Kremenek7a02a372009-08-03 23:24:57 +0000397 assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
Ted Kremenek4726d032009-03-23 22:28:25 +0000398
Argyrios Kyrtzidisb918d0f2011-01-17 18:58:44 +0000399 // For each identifier token, insert into the token stream a
400 // annot_pragma_unused token followed by the identifier token.
401 // This allows us to cache a "#pragma unused" that occurs inside an inline
402 // C++ member function.
403
404 Token *Toks = new Token[2*Identifiers.size()];
405 for (unsigned i=0; i != Identifiers.size(); i++) {
406 Token &pragmaUnusedTok = Toks[2*i], &idTok = Toks[2*i+1];
407 pragmaUnusedTok.startToken();
408 pragmaUnusedTok.setKind(tok::annot_pragma_unused);
409 pragmaUnusedTok.setLocation(UnusedLoc);
410 idTok = Identifiers[i];
411 }
412 PP.EnterTokenStream(Toks, 2*Identifiers.size(), /*DisableMacroExpansion=*/true, /*OwnsTokens=*/true);
Ted Kremenek4726d032009-03-23 22:28:25 +0000413}
Eli Friedman99914792009-06-05 00:49:58 +0000414
415// #pragma weak identifier
416// #pragma weak identifier '=' identifier
Douglas Gregor80c60f72010-09-09 22:45:38 +0000417void PragmaWeakHandler::HandlePragma(Preprocessor &PP,
418 PragmaIntroducerKind Introducer,
419 Token &WeakTok) {
Eli Friedman99914792009-06-05 00:49:58 +0000420 // FIXME: Should we be expanding macros here? My guess is no.
421 SourceLocation WeakLoc = WeakTok.getLocation();
422
423 Token Tok;
424 PP.Lex(Tok);
425 if (Tok.isNot(tok::identifier)) {
426 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";
427 return;
428 }
429
430 IdentifierInfo *WeakName = Tok.getIdentifierInfo(), *AliasName = 0;
431 SourceLocation WeakNameLoc = Tok.getLocation(), AliasNameLoc;
432
433 PP.Lex(Tok);
434 if (Tok.is(tok::equal)) {
435 PP.Lex(Tok);
436 if (Tok.isNot(tok::identifier)) {
Mike Stump1eb44332009-09-09 15:08:12 +0000437 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Eli Friedman99914792009-06-05 00:49:58 +0000438 << "weak";
439 return;
440 }
441 AliasName = Tok.getIdentifierInfo();
442 AliasNameLoc = Tok.getLocation();
443 PP.Lex(Tok);
444 }
445
Peter Collingbourne84021552011-02-28 02:37:51 +0000446 if (Tok.isNot(tok::eod)) {
Eli Friedman99914792009-06-05 00:49:58 +0000447 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";
448 return;
449 }
450
451 if (AliasName) {
452 Actions.ActOnPragmaWeakAlias(WeakName, AliasName, WeakLoc, WeakNameLoc,
453 AliasNameLoc);
454 } else {
455 Actions.ActOnPragmaWeakID(WeakName, WeakLoc, WeakNameLoc);
456 }
457}
Peter Collingbourne321b8172011-02-14 01:42:35 +0000458
David Chisnall5f3c1632012-02-18 16:12:34 +0000459// #pragma redefine_extname identifier identifier
460void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP,
461 PragmaIntroducerKind Introducer,
462 Token &RedefToken) {
463 SourceLocation RedefLoc = RedefToken.getLocation();
464
465 Token Tok;
466 PP.Lex(Tok);
467 if (Tok.isNot(tok::identifier)) {
468 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
469 "redefine_extname";
470 return;
471 }
472
473 IdentifierInfo *RedefName = Tok.getIdentifierInfo(), *AliasName = 0;
474 SourceLocation RedefNameLoc = Tok.getLocation(), AliasNameLoc;
475
476 PP.Lex(Tok);
477 if (Tok.isNot(tok::identifier)) {
478 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
479 << "redefine_extname";
480 return;
481 }
482 AliasName = Tok.getIdentifierInfo();
483 AliasNameLoc = Tok.getLocation();
484 PP.Lex(Tok);
485
486 if (Tok.isNot(tok::eod)) {
487 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
488 "redefine_extname";
489 return;
490 }
491
492 Actions.ActOnPragmaRedefineExtname(RedefName, AliasName, RedefLoc,
493 RedefNameLoc, AliasNameLoc);
494}
495
496
Peter Collingbourne321b8172011-02-14 01:42:35 +0000497void
498PragmaFPContractHandler::HandlePragma(Preprocessor &PP,
499 PragmaIntroducerKind Introducer,
500 Token &Tok) {
501 tok::OnOffSwitch OOS;
502 if (PP.LexOnOffSwitch(OOS))
503 return;
504
505 Actions.ActOnPragmaFPContract(OOS);
506}
Peter Collingbournef315fa82011-02-14 01:42:53 +0000507
508void
509PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
510 PragmaIntroducerKind Introducer,
511 Token &Tok) {
Tanya Lattnerb38b6a72011-04-14 23:35:31 +0000512 PP.LexUnexpandedToken(Tok);
Peter Collingbournef315fa82011-02-14 01:42:53 +0000513 if (Tok.isNot(tok::identifier)) {
514 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
515 "OPENCL";
516 return;
517 }
518 IdentifierInfo *ename = Tok.getIdentifierInfo();
519 SourceLocation NameLoc = Tok.getLocation();
520
521 PP.Lex(Tok);
522 if (Tok.isNot(tok::colon)) {
523 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << ename;
524 return;
525 }
526
527 PP.Lex(Tok);
528 if (Tok.isNot(tok::identifier)) {
529 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
530 return;
531 }
532 IdentifierInfo *op = Tok.getIdentifierInfo();
533
534 unsigned state;
535 if (op->isStr("enable")) {
536 state = 1;
537 } else if (op->isStr("disable")) {
538 state = 0;
539 } else {
540 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
541 return;
542 }
543
544 OpenCLOptions &f = Actions.getOpenCLOptions();
Peter Collingbourne41c8d6f2011-10-06 03:00:50 +0000545 // OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions,
546 // overriding all previously issued extension directives, but only if the
547 // behavior is set to disable."
548 if (state == 0 && ename->isStr("all")) {
549#define OPENCLEXT(nm) f.nm = 0;
Peter Collingbournef315fa82011-02-14 01:42:53 +0000550#include "clang/Basic/OpenCLExtensions.def"
551 }
552#define OPENCLEXT(nm) else if (ename->isStr(#nm)) { f.nm = state; }
553#include "clang/Basic/OpenCLExtensions.def"
554 else {
555 PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << ename;
556 return;
557 }
558}
559