blob: 641654b221aea89dd81a9e554d881a4289e1c838 [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"
Chandler Carruth55fc8732012-12-04 09:13:33 +000015#include "clang/Lex/Preprocessor.h"
Chris Lattner500d3292009-01-29 05:15:15 +000016#include "clang/Parse/ParseDiagnostic.h"
Ted Kremenek4726d032009-03-23 22:28:25 +000017#include "clang/Parse/Parser.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;
Eli Friedman9595c7e2012-10-04 02:36:51 +000043 Token Alignment;
Eli Friedmanaa5ab262012-02-23 23:47:16 +000044 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();
Eli Friedman9595c7e2012-10-04 02:36:51 +000053 ExprResult Alignment;
54 if (Info->Alignment.is(tok::numeric_constant)) {
55 Alignment = Actions.ActOnNumericConstant(Info->Alignment);
56 if (Alignment.isInvalid())
57 return;
58 }
59 Actions.ActOnPragmaPack(Info->Kind, Info->Name, Alignment.get(), PragmaLoc,
Eli Friedmanaa5ab262012-02-23 23:47:16 +000060 Info->LParenLoc, Info->RParenLoc);
Eli Friedmanaa5ab262012-02-23 23:47:16 +000061}
62
Eli Friedman9595c7e2012-10-04 02:36:51 +000063void Parser::HandlePragmaMSStruct() {
64 assert(Tok.is(tok::annot_pragma_msstruct));
65 Sema::PragmaMSStructKind Kind =
66 static_cast<Sema::PragmaMSStructKind>(
67 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
68 Actions.ActOnPragmaMSStruct(Kind);
69 ConsumeToken(); // The annotation token.
70}
71
72void Parser::HandlePragmaAlign() {
73 assert(Tok.is(tok::annot_pragma_align));
74 Sema::PragmaOptionsAlignKind Kind =
75 static_cast<Sema::PragmaOptionsAlignKind>(
76 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
77 SourceLocation PragmaLoc = ConsumeToken();
78 Actions.ActOnPragmaOptionsAlign(Kind, PragmaLoc);
79}
80
81void Parser::HandlePragmaWeak() {
82 assert(Tok.is(tok::annot_pragma_weak));
83 SourceLocation PragmaLoc = ConsumeToken();
84 Actions.ActOnPragmaWeakID(Tok.getIdentifierInfo(), PragmaLoc,
85 Tok.getLocation());
86 ConsumeToken(); // The weak name.
87}
88
89void Parser::HandlePragmaWeakAlias() {
90 assert(Tok.is(tok::annot_pragma_weakalias));
91 SourceLocation PragmaLoc = ConsumeToken();
92 IdentifierInfo *WeakName = Tok.getIdentifierInfo();
93 SourceLocation WeakNameLoc = Tok.getLocation();
94 ConsumeToken();
95 IdentifierInfo *AliasName = Tok.getIdentifierInfo();
96 SourceLocation AliasNameLoc = Tok.getLocation();
97 ConsumeToken();
98 Actions.ActOnPragmaWeakAlias(WeakName, AliasName, PragmaLoc,
99 WeakNameLoc, AliasNameLoc);
100
101}
102
103void Parser::HandlePragmaRedefineExtname() {
104 assert(Tok.is(tok::annot_pragma_redefine_extname));
105 SourceLocation RedefLoc = ConsumeToken();
106 IdentifierInfo *RedefName = Tok.getIdentifierInfo();
107 SourceLocation RedefNameLoc = Tok.getLocation();
108 ConsumeToken();
109 IdentifierInfo *AliasName = Tok.getIdentifierInfo();
110 SourceLocation AliasNameLoc = Tok.getLocation();
111 ConsumeToken();
112 Actions.ActOnPragmaRedefineExtname(RedefName, AliasName, RedefLoc,
113 RedefNameLoc, AliasNameLoc);
114}
115
116void Parser::HandlePragmaFPContract() {
117 assert(Tok.is(tok::annot_pragma_fp_contract));
118 tok::OnOffSwitch OOS =
119 static_cast<tok::OnOffSwitch>(
120 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
121 Actions.ActOnPragmaFPContract(OOS);
122 ConsumeToken(); // The annotation token.
123}
124
125namespace {
126 typedef llvm::PointerIntPair<IdentifierInfo *, 1, bool> OpenCLExtData;
127}
128
129void Parser::HandlePragmaOpenCLExtension() {
130 assert(Tok.is(tok::annot_pragma_opencl_extension));
131 OpenCLExtData data =
132 OpenCLExtData::getFromOpaqueValue(Tok.getAnnotationValue());
133 unsigned state = data.getInt();
134 IdentifierInfo *ename = data.getPointer();
135 SourceLocation NameLoc = Tok.getLocation();
136 ConsumeToken(); // The annotation token.
137
138 OpenCLOptions &f = Actions.getOpenCLOptions();
139 // OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions,
140 // overriding all previously issued extension directives, but only if the
141 // behavior is set to disable."
142 if (state == 0 && ename->isStr("all")) {
143#define OPENCLEXT(nm) f.nm = 0;
144#include "clang/Basic/OpenCLExtensions.def"
145 }
146#define OPENCLEXT(nm) else if (ename->isStr(#nm)) { f.nm = state; }
147#include "clang/Basic/OpenCLExtensions.def"
148 else {
149 PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << ename;
150 return;
151 }
152}
153
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000154// #pragma GCC visibility comes in two variants:
155// 'push' '(' [visibility] ')'
156// 'pop'
Douglas Gregor80c60f72010-09-09 22:45:38 +0000157void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,
158 PragmaIntroducerKind Introducer,
159 Token &VisTok) {
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000160 SourceLocation VisLoc = VisTok.getLocation();
161
162 Token Tok;
Joerg Sonnenbergere23af2a2011-07-20 01:03:50 +0000163 PP.LexUnexpandedToken(Tok);
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000164
165 const IdentifierInfo *PushPop = Tok.getIdentifierInfo();
166
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000167 const IdentifierInfo *VisType;
168 if (PushPop && PushPop->isStr("pop")) {
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000169 VisType = 0;
170 } else if (PushPop && PushPop->isStr("push")) {
Joerg Sonnenbergere23af2a2011-07-20 01:03:50 +0000171 PP.LexUnexpandedToken(Tok);
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000172 if (Tok.isNot(tok::l_paren)) {
173 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
174 << "visibility";
175 return;
176 }
Joerg Sonnenbergere23af2a2011-07-20 01:03:50 +0000177 PP.LexUnexpandedToken(Tok);
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000178 VisType = Tok.getIdentifierInfo();
179 if (!VisType) {
180 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
181 << "visibility";
182 return;
183 }
Joerg Sonnenbergere23af2a2011-07-20 01:03:50 +0000184 PP.LexUnexpandedToken(Tok);
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000185 if (Tok.isNot(tok::r_paren)) {
186 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
187 << "visibility";
188 return;
189 }
190 } else {
191 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
192 << "visibility";
193 return;
194 }
Joerg Sonnenbergere23af2a2011-07-20 01:03:50 +0000195 PP.LexUnexpandedToken(Tok);
Peter Collingbourne84021552011-02-28 02:37:51 +0000196 if (Tok.isNot(tok::eod)) {
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000197 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
198 << "visibility";
199 return;
200 }
201
Rafael Espindola426fc942012-01-26 02:02:57 +0000202 Token *Toks = new Token[1];
203 Toks[0].startToken();
204 Toks[0].setKind(tok::annot_pragma_vis);
205 Toks[0].setLocation(VisLoc);
206 Toks[0].setAnnotationValue(
207 const_cast<void*>(static_cast<const void*>(VisType)));
208 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
209 /*OwnsTokens=*/true);
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000210}
211
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000212// #pragma pack(...) comes in the following delicious flavors:
213// pack '(' [integer] ')'
214// pack '(' 'show' ')'
215// pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'
Douglas Gregor80c60f72010-09-09 22:45:38 +0000216void PragmaPackHandler::HandlePragma(Preprocessor &PP,
217 PragmaIntroducerKind Introducer,
218 Token &PackTok) {
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000219 SourceLocation PackLoc = PackTok.getLocation();
220
221 Token Tok;
222 PP.Lex(Tok);
223 if (Tok.isNot(tok::l_paren)) {
Ted Kremenek4726d032009-03-23 22:28:25 +0000224 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack";
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000225 return;
226 }
227
John McCallf312b1e2010-08-26 23:41:50 +0000228 Sema::PragmaPackKind Kind = Sema::PPK_Default;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000229 IdentifierInfo *Name = 0;
Eli Friedman9595c7e2012-10-04 02:36:51 +0000230 Token Alignment;
231 Alignment.startToken();
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000232 SourceLocation LParenLoc = Tok.getLocation();
Mike Stump1eb44332009-09-09 15:08:12 +0000233 PP.Lex(Tok);
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000234 if (Tok.is(tok::numeric_constant)) {
Eli Friedman9595c7e2012-10-04 02:36:51 +0000235 Alignment = Tok;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000236
237 PP.Lex(Tok);
Eli Friedman19bda3a2011-11-02 01:53:16 +0000238
239 // In MSVC/gcc, #pragma pack(4) sets the alignment without affecting
240 // the push/pop stack.
241 // In Apple gcc, #pragma pack(4) is equivalent to #pragma pack(push, 4)
David Blaikie4e4d0842012-03-11 07:00:24 +0000242 if (PP.getLangOpts().ApplePragmaPack)
Eli Friedman19bda3a2011-11-02 01:53:16 +0000243 Kind = Sema::PPK_Push;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000244 } else if (Tok.is(tok::identifier)) {
245 const IdentifierInfo *II = Tok.getIdentifierInfo();
Chris Lattner08631c52008-11-23 21:45:46 +0000246 if (II->isStr("show")) {
John McCallf312b1e2010-08-26 23:41:50 +0000247 Kind = Sema::PPK_Show;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000248 PP.Lex(Tok);
249 } else {
Chris Lattner08631c52008-11-23 21:45:46 +0000250 if (II->isStr("push")) {
John McCallf312b1e2010-08-26 23:41:50 +0000251 Kind = Sema::PPK_Push;
Chris Lattner08631c52008-11-23 21:45:46 +0000252 } else if (II->isStr("pop")) {
John McCallf312b1e2010-08-26 23:41:50 +0000253 Kind = Sema::PPK_Pop;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000254 } else {
255 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_invalid_action);
256 return;
Mike Stump1eb44332009-09-09 15:08:12 +0000257 }
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000258 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000259
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000260 if (Tok.is(tok::comma)) {
261 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000262
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000263 if (Tok.is(tok::numeric_constant)) {
Eli Friedman9595c7e2012-10-04 02:36:51 +0000264 Alignment = Tok;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000265
266 PP.Lex(Tok);
267 } else if (Tok.is(tok::identifier)) {
268 Name = Tok.getIdentifierInfo();
269 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000270
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000271 if (Tok.is(tok::comma)) {
272 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000273
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000274 if (Tok.isNot(tok::numeric_constant)) {
Chris Lattner08631c52008-11-23 21:45:46 +0000275 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000276 return;
277 }
Mike Stump1eb44332009-09-09 15:08:12 +0000278
Eli Friedman9595c7e2012-10-04 02:36:51 +0000279 Alignment = Tok;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000280
281 PP.Lex(Tok);
282 }
283 } else {
Chris Lattner08631c52008-11-23 21:45:46 +0000284 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000285 return;
286 }
287 }
288 }
David Blaikie4e4d0842012-03-11 07:00:24 +0000289 } else if (PP.getLangOpts().ApplePragmaPack) {
Eli Friedman19bda3a2011-11-02 01:53:16 +0000290 // In MSVC/gcc, #pragma pack() resets the alignment without affecting
291 // the push/pop stack.
292 // In Apple gcc #pragma pack() is equivalent to #pragma pack(pop).
293 Kind = Sema::PPK_Pop;
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000294 }
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000295
296 if (Tok.isNot(tok::r_paren)) {
Ted Kremenek4726d032009-03-23 22:28:25 +0000297 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack";
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000298 return;
299 }
300
Daniel Dunbar861800c2010-05-26 23:29:06 +0000301 SourceLocation RParenLoc = Tok.getLocation();
Eli Friedman99914792009-06-05 00:49:58 +0000302 PP.Lex(Tok);
Peter Collingbourne84021552011-02-28 02:37:51 +0000303 if (Tok.isNot(tok::eod)) {
Eli Friedman99914792009-06-05 00:49:58 +0000304 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack";
305 return;
306 }
307
Daniel Dunbarb0939552012-02-29 01:38:22 +0000308 PragmaPackInfo *Info =
309 (PragmaPackInfo*) PP.getPreprocessorAllocator().Allocate(
310 sizeof(PragmaPackInfo), llvm::alignOf<PragmaPackInfo>());
311 new (Info) PragmaPackInfo();
Eli Friedmanaa5ab262012-02-23 23:47:16 +0000312 Info->Kind = Kind;
313 Info->Name = Name;
Eli Friedman9595c7e2012-10-04 02:36:51 +0000314 Info->Alignment = Alignment;
Eli Friedmanaa5ab262012-02-23 23:47:16 +0000315 Info->LParenLoc = LParenLoc;
316 Info->RParenLoc = RParenLoc;
317
Daniel Dunbarb0939552012-02-29 01:38:22 +0000318 Token *Toks =
319 (Token*) PP.getPreprocessorAllocator().Allocate(
320 sizeof(Token) * 1, llvm::alignOf<Token>());
321 new (Toks) Token();
Eli Friedmanaa5ab262012-02-23 23:47:16 +0000322 Toks[0].startToken();
323 Toks[0].setKind(tok::annot_pragma_pack);
324 Toks[0].setLocation(PackLoc);
325 Toks[0].setAnnotationValue(static_cast<void*>(Info));
326 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
Daniel Dunbarb0939552012-02-29 01:38:22 +0000327 /*OwnsTokens=*/false);
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000328}
329
Fariborz Jahanian62c92582011-04-25 18:49:15 +0000330// #pragma ms_struct on
331// #pragma ms_struct off
332void PragmaMSStructHandler::HandlePragma(Preprocessor &PP,
333 PragmaIntroducerKind Introducer,
334 Token &MSStructTok) {
335 Sema::PragmaMSStructKind Kind = Sema::PMSST_OFF;
336
337 Token Tok;
338 PP.Lex(Tok);
339 if (Tok.isNot(tok::identifier)) {
340 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
341 return;
342 }
343 const IdentifierInfo *II = Tok.getIdentifierInfo();
344 if (II->isStr("on")) {
345 Kind = Sema::PMSST_ON;
346 PP.Lex(Tok);
347 }
348 else if (II->isStr("off") || II->isStr("reset"))
349 PP.Lex(Tok);
350 else {
351 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
352 return;
353 }
354
355 if (Tok.isNot(tok::eod)) {
Daniel Dunbarb0939552012-02-29 01:38:22 +0000356 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
357 << "ms_struct";
Fariborz Jahanian62c92582011-04-25 18:49:15 +0000358 return;
359 }
Eli Friedman9595c7e2012-10-04 02:36:51 +0000360
361 Token *Toks =
362 (Token*) PP.getPreprocessorAllocator().Allocate(
363 sizeof(Token) * 1, llvm::alignOf<Token>());
364 new (Toks) Token();
365 Toks[0].startToken();
366 Toks[0].setKind(tok::annot_pragma_msstruct);
367 Toks[0].setLocation(MSStructTok.getLocation());
368 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
369 static_cast<uintptr_t>(Kind)));
370 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
371 /*OwnsTokens=*/false);
Fariborz Jahanian62c92582011-04-25 18:49:15 +0000372}
373
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000374// #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
375// #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
Eli Friedman9595c7e2012-10-04 02:36:51 +0000376static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok,
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000377 bool IsOptions) {
Daniel Dunbar861800c2010-05-26 23:29:06 +0000378 Token Tok;
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000379
380 if (IsOptions) {
381 PP.Lex(Tok);
382 if (Tok.isNot(tok::identifier) ||
383 !Tok.getIdentifierInfo()->isStr("align")) {
384 PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align);
385 return;
386 }
Daniel Dunbar861800c2010-05-26 23:29:06 +0000387 }
Daniel Dunbar638e7cf2010-05-27 18:42:09 +0000388
Daniel Dunbar861800c2010-05-26 23:29:06 +0000389 PP.Lex(Tok);
390 if (Tok.isNot(tok::equal)) {
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000391 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal)
392 << IsOptions;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000393 return;
394 }
395
396 PP.Lex(Tok);
397 if (Tok.isNot(tok::identifier)) {
398 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000399 << (IsOptions ? "options" : "align");
Daniel Dunbar861800c2010-05-26 23:29:06 +0000400 return;
401 }
402
John McCallf312b1e2010-08-26 23:41:50 +0000403 Sema::PragmaOptionsAlignKind Kind = Sema::POAK_Natural;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000404 const IdentifierInfo *II = Tok.getIdentifierInfo();
Daniel Dunbar638e7cf2010-05-27 18:42:09 +0000405 if (II->isStr("native"))
John McCallf312b1e2010-08-26 23:41:50 +0000406 Kind = Sema::POAK_Native;
Daniel Dunbar638e7cf2010-05-27 18:42:09 +0000407 else if (II->isStr("natural"))
John McCallf312b1e2010-08-26 23:41:50 +0000408 Kind = Sema::POAK_Natural;
Daniel Dunbar6f739142010-05-27 18:42:17 +0000409 else if (II->isStr("packed"))
John McCallf312b1e2010-08-26 23:41:50 +0000410 Kind = Sema::POAK_Packed;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000411 else if (II->isStr("power"))
John McCallf312b1e2010-08-26 23:41:50 +0000412 Kind = Sema::POAK_Power;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000413 else if (II->isStr("mac68k"))
John McCallf312b1e2010-08-26 23:41:50 +0000414 Kind = Sema::POAK_Mac68k;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000415 else if (II->isStr("reset"))
John McCallf312b1e2010-08-26 23:41:50 +0000416 Kind = Sema::POAK_Reset;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000417 else {
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000418 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option)
419 << IsOptions;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000420 return;
421 }
422
Daniel Dunbar861800c2010-05-26 23:29:06 +0000423 PP.Lex(Tok);
Peter Collingbourne84021552011-02-28 02:37:51 +0000424 if (Tok.isNot(tok::eod)) {
Daniel Dunbar861800c2010-05-26 23:29:06 +0000425 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000426 << (IsOptions ? "options" : "align");
Daniel Dunbar861800c2010-05-26 23:29:06 +0000427 return;
428 }
429
Eli Friedman9595c7e2012-10-04 02:36:51 +0000430 Token *Toks =
431 (Token*) PP.getPreprocessorAllocator().Allocate(
432 sizeof(Token) * 1, llvm::alignOf<Token>());
433 new (Toks) Token();
434 Toks[0].startToken();
435 Toks[0].setKind(tok::annot_pragma_align);
436 Toks[0].setLocation(FirstTok.getLocation());
437 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
438 static_cast<uintptr_t>(Kind)));
439 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
440 /*OwnsTokens=*/false);
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000441}
442
Douglas Gregor80c60f72010-09-09 22:45:38 +0000443void PragmaAlignHandler::HandlePragma(Preprocessor &PP,
444 PragmaIntroducerKind Introducer,
445 Token &AlignTok) {
Eli Friedman9595c7e2012-10-04 02:36:51 +0000446 ParseAlignPragma(PP, AlignTok, /*IsOptions=*/false);
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000447}
448
Douglas Gregor80c60f72010-09-09 22:45:38 +0000449void PragmaOptionsHandler::HandlePragma(Preprocessor &PP,
450 PragmaIntroducerKind Introducer,
451 Token &OptionsTok) {
Eli Friedman9595c7e2012-10-04 02:36:51 +0000452 ParseAlignPragma(PP, OptionsTok, /*IsOptions=*/true);
Daniel Dunbar861800c2010-05-26 23:29:06 +0000453}
454
Ted Kremenek4726d032009-03-23 22:28:25 +0000455// #pragma unused(identifier)
Douglas Gregor80c60f72010-09-09 22:45:38 +0000456void PragmaUnusedHandler::HandlePragma(Preprocessor &PP,
457 PragmaIntroducerKind Introducer,
458 Token &UnusedTok) {
Ted Kremenek4726d032009-03-23 22:28:25 +0000459 // FIXME: Should we be expanding macros here? My guess is no.
460 SourceLocation UnusedLoc = UnusedTok.getLocation();
Mike Stump1eb44332009-09-09 15:08:12 +0000461
Ted Kremenek4726d032009-03-23 22:28:25 +0000462 // Lex the left '('.
463 Token Tok;
464 PP.Lex(Tok);
465 if (Tok.isNot(tok::l_paren)) {
466 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
467 return;
468 }
Mike Stump1eb44332009-09-09 15:08:12 +0000469
Ted Kremenek4726d032009-03-23 22:28:25 +0000470 // Lex the declaration reference(s).
Chris Lattner5f9e2722011-07-23 10:55:15 +0000471 SmallVector<Token, 5> Identifiers;
Ted Kremenek4726d032009-03-23 22:28:25 +0000472 SourceLocation RParenLoc;
473 bool LexID = true;
Mike Stump1eb44332009-09-09 15:08:12 +0000474
Ted Kremenek4726d032009-03-23 22:28:25 +0000475 while (true) {
476 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000477
Ted Kremenek4726d032009-03-23 22:28:25 +0000478 if (LexID) {
Mike Stump1eb44332009-09-09 15:08:12 +0000479 if (Tok.is(tok::identifier)) {
Ted Kremenek7a02a372009-08-03 23:24:57 +0000480 Identifiers.push_back(Tok);
Ted Kremenek4726d032009-03-23 22:28:25 +0000481 LexID = false;
482 continue;
483 }
484
Ted Kremenek7a02a372009-08-03 23:24:57 +0000485 // Illegal token!
Ted Kremenek4726d032009-03-23 22:28:25 +0000486 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
487 return;
488 }
Mike Stump1eb44332009-09-09 15:08:12 +0000489
Ted Kremenek4726d032009-03-23 22:28:25 +0000490 // We are execting a ')' or a ','.
491 if (Tok.is(tok::comma)) {
492 LexID = true;
493 continue;
494 }
Mike Stump1eb44332009-09-09 15:08:12 +0000495
Ted Kremenek4726d032009-03-23 22:28:25 +0000496 if (Tok.is(tok::r_paren)) {
497 RParenLoc = Tok.getLocation();
498 break;
499 }
Mike Stump1eb44332009-09-09 15:08:12 +0000500
Ted Kremenek7a02a372009-08-03 23:24:57 +0000501 // Illegal token!
Ted Kremenek4726d032009-03-23 22:28:25 +0000502 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_punc);
503 return;
504 }
Eli Friedman99914792009-06-05 00:49:58 +0000505
506 PP.Lex(Tok);
Peter Collingbourne84021552011-02-28 02:37:51 +0000507 if (Tok.isNot(tok::eod)) {
Eli Friedman99914792009-06-05 00:49:58 +0000508 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
509 "unused";
510 return;
511 }
512
Ted Kremenek4726d032009-03-23 22:28:25 +0000513 // Verify that we have a location for the right parenthesis.
514 assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
Ted Kremenek7a02a372009-08-03 23:24:57 +0000515 assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
Ted Kremenek4726d032009-03-23 22:28:25 +0000516
Argyrios Kyrtzidisb918d0f2011-01-17 18:58:44 +0000517 // For each identifier token, insert into the token stream a
518 // annot_pragma_unused token followed by the identifier token.
519 // This allows us to cache a "#pragma unused" that occurs inside an inline
520 // C++ member function.
521
Daniel Dunbarb0939552012-02-29 01:38:22 +0000522 Token *Toks =
523 (Token*) PP.getPreprocessorAllocator().Allocate(
524 sizeof(Token) * 2 * Identifiers.size(), llvm::alignOf<Token>());
Argyrios Kyrtzidisb918d0f2011-01-17 18:58:44 +0000525 for (unsigned i=0; i != Identifiers.size(); i++) {
526 Token &pragmaUnusedTok = Toks[2*i], &idTok = Toks[2*i+1];
527 pragmaUnusedTok.startToken();
528 pragmaUnusedTok.setKind(tok::annot_pragma_unused);
529 pragmaUnusedTok.setLocation(UnusedLoc);
530 idTok = Identifiers[i];
531 }
Daniel Dunbarb0939552012-02-29 01:38:22 +0000532 PP.EnterTokenStream(Toks, 2*Identifiers.size(),
533 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
Ted Kremenek4726d032009-03-23 22:28:25 +0000534}
Eli Friedman99914792009-06-05 00:49:58 +0000535
536// #pragma weak identifier
537// #pragma weak identifier '=' identifier
Douglas Gregor80c60f72010-09-09 22:45:38 +0000538void PragmaWeakHandler::HandlePragma(Preprocessor &PP,
539 PragmaIntroducerKind Introducer,
540 Token &WeakTok) {
Eli Friedman99914792009-06-05 00:49:58 +0000541 SourceLocation WeakLoc = WeakTok.getLocation();
542
543 Token Tok;
544 PP.Lex(Tok);
545 if (Tok.isNot(tok::identifier)) {
546 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";
547 return;
548 }
549
Eli Friedman9595c7e2012-10-04 02:36:51 +0000550 Token WeakName = Tok;
551 bool HasAlias = false;
552 Token AliasName;
Eli Friedman99914792009-06-05 00:49:58 +0000553
554 PP.Lex(Tok);
555 if (Tok.is(tok::equal)) {
Eli Friedman9595c7e2012-10-04 02:36:51 +0000556 HasAlias = true;
Eli Friedman99914792009-06-05 00:49:58 +0000557 PP.Lex(Tok);
558 if (Tok.isNot(tok::identifier)) {
Mike Stump1eb44332009-09-09 15:08:12 +0000559 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Eli Friedman99914792009-06-05 00:49:58 +0000560 << "weak";
561 return;
562 }
Eli Friedman9595c7e2012-10-04 02:36:51 +0000563 AliasName = Tok;
Eli Friedman99914792009-06-05 00:49:58 +0000564 PP.Lex(Tok);
565 }
566
Peter Collingbourne84021552011-02-28 02:37:51 +0000567 if (Tok.isNot(tok::eod)) {
Eli Friedman99914792009-06-05 00:49:58 +0000568 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";
569 return;
570 }
571
Eli Friedman9595c7e2012-10-04 02:36:51 +0000572 if (HasAlias) {
573 Token *Toks =
574 (Token*) PP.getPreprocessorAllocator().Allocate(
575 sizeof(Token) * 3, llvm::alignOf<Token>());
576 Token &pragmaUnusedTok = Toks[0];
577 pragmaUnusedTok.startToken();
578 pragmaUnusedTok.setKind(tok::annot_pragma_weakalias);
579 pragmaUnusedTok.setLocation(WeakLoc);
580 Toks[1] = WeakName;
581 Toks[2] = AliasName;
582 PP.EnterTokenStream(Toks, 3,
583 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
Eli Friedman99914792009-06-05 00:49:58 +0000584 } else {
Eli Friedman9595c7e2012-10-04 02:36:51 +0000585 Token *Toks =
586 (Token*) PP.getPreprocessorAllocator().Allocate(
587 sizeof(Token) * 2, llvm::alignOf<Token>());
588 Token &pragmaUnusedTok = Toks[0];
589 pragmaUnusedTok.startToken();
590 pragmaUnusedTok.setKind(tok::annot_pragma_weak);
591 pragmaUnusedTok.setLocation(WeakLoc);
592 Toks[1] = WeakName;
593 PP.EnterTokenStream(Toks, 2,
594 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
Eli Friedman99914792009-06-05 00:49:58 +0000595 }
596}
Peter Collingbourne321b8172011-02-14 01:42:35 +0000597
David Chisnall5f3c1632012-02-18 16:12:34 +0000598// #pragma redefine_extname identifier identifier
599void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP,
600 PragmaIntroducerKind Introducer,
601 Token &RedefToken) {
602 SourceLocation RedefLoc = RedefToken.getLocation();
603
604 Token Tok;
605 PP.Lex(Tok);
606 if (Tok.isNot(tok::identifier)) {
607 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
608 "redefine_extname";
609 return;
610 }
611
Eli Friedman9595c7e2012-10-04 02:36:51 +0000612 Token RedefName = Tok;
David Chisnall5f3c1632012-02-18 16:12:34 +0000613 PP.Lex(Tok);
Eli Friedman9595c7e2012-10-04 02:36:51 +0000614
David Chisnall5f3c1632012-02-18 16:12:34 +0000615 if (Tok.isNot(tok::identifier)) {
616 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
617 << "redefine_extname";
618 return;
619 }
Eli Friedman9595c7e2012-10-04 02:36:51 +0000620
621 Token AliasName = Tok;
David Chisnall5f3c1632012-02-18 16:12:34 +0000622 PP.Lex(Tok);
623
624 if (Tok.isNot(tok::eod)) {
625 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
626 "redefine_extname";
627 return;
628 }
629
Eli Friedman9595c7e2012-10-04 02:36:51 +0000630 Token *Toks =
631 (Token*) PP.getPreprocessorAllocator().Allocate(
632 sizeof(Token) * 3, llvm::alignOf<Token>());
633 Token &pragmaRedefTok = Toks[0];
634 pragmaRedefTok.startToken();
635 pragmaRedefTok.setKind(tok::annot_pragma_redefine_extname);
636 pragmaRedefTok.setLocation(RedefLoc);
637 Toks[1] = RedefName;
638 Toks[2] = AliasName;
639 PP.EnterTokenStream(Toks, 3,
640 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
David Chisnall5f3c1632012-02-18 16:12:34 +0000641}
642
643
Peter Collingbourne321b8172011-02-14 01:42:35 +0000644void
645PragmaFPContractHandler::HandlePragma(Preprocessor &PP,
646 PragmaIntroducerKind Introducer,
647 Token &Tok) {
648 tok::OnOffSwitch OOS;
649 if (PP.LexOnOffSwitch(OOS))
650 return;
651
Eli Friedman9595c7e2012-10-04 02:36:51 +0000652 Token *Toks =
653 (Token*) PP.getPreprocessorAllocator().Allocate(
654 sizeof(Token) * 1, llvm::alignOf<Token>());
655 new (Toks) Token();
656 Toks[0].startToken();
657 Toks[0].setKind(tok::annot_pragma_fp_contract);
658 Toks[0].setLocation(Tok.getLocation());
659 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
660 static_cast<uintptr_t>(OOS)));
661 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
662 /*OwnsTokens=*/false);
Peter Collingbourne321b8172011-02-14 01:42:35 +0000663}
Peter Collingbournef315fa82011-02-14 01:42:53 +0000664
665void
666PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
667 PragmaIntroducerKind Introducer,
668 Token &Tok) {
Tanya Lattnerb38b6a72011-04-14 23:35:31 +0000669 PP.LexUnexpandedToken(Tok);
Peter Collingbournef315fa82011-02-14 01:42:53 +0000670 if (Tok.isNot(tok::identifier)) {
671 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
672 "OPENCL";
673 return;
674 }
675 IdentifierInfo *ename = Tok.getIdentifierInfo();
676 SourceLocation NameLoc = Tok.getLocation();
677
678 PP.Lex(Tok);
679 if (Tok.isNot(tok::colon)) {
680 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << ename;
681 return;
682 }
683
684 PP.Lex(Tok);
685 if (Tok.isNot(tok::identifier)) {
686 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
687 return;
688 }
689 IdentifierInfo *op = Tok.getIdentifierInfo();
690
691 unsigned state;
692 if (op->isStr("enable")) {
693 state = 1;
694 } else if (op->isStr("disable")) {
695 state = 0;
696 } else {
697 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
698 return;
699 }
700
Eli Friedman9595c7e2012-10-04 02:36:51 +0000701 PP.Lex(Tok);
702 if (Tok.isNot(tok::eod)) {
703 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
704 "OPENCL EXTENSION";
Peter Collingbournef315fa82011-02-14 01:42:53 +0000705 return;
706 }
Eli Friedman9595c7e2012-10-04 02:36:51 +0000707
708 OpenCLExtData data(ename, state);
709 Token *Toks =
710 (Token*) PP.getPreprocessorAllocator().Allocate(
711 sizeof(Token) * 1, llvm::alignOf<Token>());
712 new (Toks) Token();
713 Toks[0].startToken();
714 Toks[0].setKind(tok::annot_pragma_opencl_extension);
715 Toks[0].setLocation(NameLoc);
716 Toks[0].setAnnotationValue(data.getOpaqueValue());
717 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
718 /*OwnsTokens=*/false);
Peter Collingbournef315fa82011-02-14 01:42:53 +0000719}
720