blob: 038636d10801ff440af980339cbc9753ac6bd5fb [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
Tareq A. Siraj85192c72013-04-16 18:41:26 +0000125StmtResult Parser::HandlePragmaCaptured()
126{
127 assert(Tok.is(tok::annot_pragma_captured));
128 ConsumeToken();
129
130 if (Tok.isNot(tok::l_brace)) {
131 PP.Diag(Tok, diag::err_expected_lbrace);
132 return StmtError();
133 }
134
135 return StmtEmpty();
136}
137
Eli Friedman9595c7e2012-10-04 02:36:51 +0000138namespace {
139 typedef llvm::PointerIntPair<IdentifierInfo *, 1, bool> OpenCLExtData;
140}
141
142void Parser::HandlePragmaOpenCLExtension() {
143 assert(Tok.is(tok::annot_pragma_opencl_extension));
144 OpenCLExtData data =
145 OpenCLExtData::getFromOpaqueValue(Tok.getAnnotationValue());
146 unsigned state = data.getInt();
147 IdentifierInfo *ename = data.getPointer();
148 SourceLocation NameLoc = Tok.getLocation();
149 ConsumeToken(); // The annotation token.
150
151 OpenCLOptions &f = Actions.getOpenCLOptions();
152 // OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions,
153 // overriding all previously issued extension directives, but only if the
154 // behavior is set to disable."
155 if (state == 0 && ename->isStr("all")) {
156#define OPENCLEXT(nm) f.nm = 0;
157#include "clang/Basic/OpenCLExtensions.def"
158 }
159#define OPENCLEXT(nm) else if (ename->isStr(#nm)) { f.nm = state; }
160#include "clang/Basic/OpenCLExtensions.def"
161 else {
162 PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << ename;
163 return;
164 }
165}
166
Tareq A. Siraj85192c72013-04-16 18:41:26 +0000167
168
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000169// #pragma GCC visibility comes in two variants:
170// 'push' '(' [visibility] ')'
171// 'pop'
Douglas Gregor80c60f72010-09-09 22:45:38 +0000172void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,
173 PragmaIntroducerKind Introducer,
174 Token &VisTok) {
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000175 SourceLocation VisLoc = VisTok.getLocation();
176
177 Token Tok;
Joerg Sonnenbergere23af2a2011-07-20 01:03:50 +0000178 PP.LexUnexpandedToken(Tok);
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000179
180 const IdentifierInfo *PushPop = Tok.getIdentifierInfo();
181
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000182 const IdentifierInfo *VisType;
183 if (PushPop && PushPop->isStr("pop")) {
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000184 VisType = 0;
185 } else if (PushPop && PushPop->isStr("push")) {
Joerg Sonnenbergere23af2a2011-07-20 01:03:50 +0000186 PP.LexUnexpandedToken(Tok);
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000187 if (Tok.isNot(tok::l_paren)) {
188 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
189 << "visibility";
190 return;
191 }
Joerg Sonnenbergere23af2a2011-07-20 01:03:50 +0000192 PP.LexUnexpandedToken(Tok);
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000193 VisType = Tok.getIdentifierInfo();
194 if (!VisType) {
195 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
196 << "visibility";
197 return;
198 }
Joerg Sonnenbergere23af2a2011-07-20 01:03:50 +0000199 PP.LexUnexpandedToken(Tok);
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000200 if (Tok.isNot(tok::r_paren)) {
201 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
202 << "visibility";
203 return;
204 }
205 } else {
206 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
207 << "visibility";
208 return;
209 }
Joerg Sonnenbergere23af2a2011-07-20 01:03:50 +0000210 PP.LexUnexpandedToken(Tok);
Peter Collingbourne84021552011-02-28 02:37:51 +0000211 if (Tok.isNot(tok::eod)) {
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000212 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
213 << "visibility";
214 return;
215 }
216
Rafael Espindola426fc942012-01-26 02:02:57 +0000217 Token *Toks = new Token[1];
218 Toks[0].startToken();
219 Toks[0].setKind(tok::annot_pragma_vis);
220 Toks[0].setLocation(VisLoc);
221 Toks[0].setAnnotationValue(
222 const_cast<void*>(static_cast<const void*>(VisType)));
223 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
224 /*OwnsTokens=*/true);
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000225}
226
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000227// #pragma pack(...) comes in the following delicious flavors:
228// pack '(' [integer] ')'
229// pack '(' 'show' ')'
230// pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'
Douglas Gregor80c60f72010-09-09 22:45:38 +0000231void PragmaPackHandler::HandlePragma(Preprocessor &PP,
232 PragmaIntroducerKind Introducer,
233 Token &PackTok) {
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000234 SourceLocation PackLoc = PackTok.getLocation();
235
236 Token Tok;
237 PP.Lex(Tok);
238 if (Tok.isNot(tok::l_paren)) {
Ted Kremenek4726d032009-03-23 22:28:25 +0000239 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack";
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000240 return;
241 }
242
John McCallf312b1e2010-08-26 23:41:50 +0000243 Sema::PragmaPackKind Kind = Sema::PPK_Default;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000244 IdentifierInfo *Name = 0;
Eli Friedman9595c7e2012-10-04 02:36:51 +0000245 Token Alignment;
246 Alignment.startToken();
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000247 SourceLocation LParenLoc = Tok.getLocation();
Mike Stump1eb44332009-09-09 15:08:12 +0000248 PP.Lex(Tok);
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000249 if (Tok.is(tok::numeric_constant)) {
Eli Friedman9595c7e2012-10-04 02:36:51 +0000250 Alignment = Tok;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000251
252 PP.Lex(Tok);
Eli Friedman19bda3a2011-11-02 01:53:16 +0000253
254 // In MSVC/gcc, #pragma pack(4) sets the alignment without affecting
255 // the push/pop stack.
256 // In Apple gcc, #pragma pack(4) is equivalent to #pragma pack(push, 4)
David Blaikie4e4d0842012-03-11 07:00:24 +0000257 if (PP.getLangOpts().ApplePragmaPack)
Eli Friedman19bda3a2011-11-02 01:53:16 +0000258 Kind = Sema::PPK_Push;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000259 } else if (Tok.is(tok::identifier)) {
260 const IdentifierInfo *II = Tok.getIdentifierInfo();
Chris Lattner08631c52008-11-23 21:45:46 +0000261 if (II->isStr("show")) {
John McCallf312b1e2010-08-26 23:41:50 +0000262 Kind = Sema::PPK_Show;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000263 PP.Lex(Tok);
264 } else {
Chris Lattner08631c52008-11-23 21:45:46 +0000265 if (II->isStr("push")) {
John McCallf312b1e2010-08-26 23:41:50 +0000266 Kind = Sema::PPK_Push;
Chris Lattner08631c52008-11-23 21:45:46 +0000267 } else if (II->isStr("pop")) {
John McCallf312b1e2010-08-26 23:41:50 +0000268 Kind = Sema::PPK_Pop;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000269 } else {
270 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_invalid_action);
271 return;
Mike Stump1eb44332009-09-09 15:08:12 +0000272 }
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000273 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000274
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000275 if (Tok.is(tok::comma)) {
276 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000277
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000278 if (Tok.is(tok::numeric_constant)) {
Eli Friedman9595c7e2012-10-04 02:36:51 +0000279 Alignment = Tok;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000280
281 PP.Lex(Tok);
282 } else if (Tok.is(tok::identifier)) {
283 Name = Tok.getIdentifierInfo();
284 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000285
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000286 if (Tok.is(tok::comma)) {
287 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000288
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000289 if (Tok.isNot(tok::numeric_constant)) {
Chris Lattner08631c52008-11-23 21:45:46 +0000290 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000291 return;
292 }
Mike Stump1eb44332009-09-09 15:08:12 +0000293
Eli Friedman9595c7e2012-10-04 02:36:51 +0000294 Alignment = Tok;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000295
296 PP.Lex(Tok);
297 }
298 } else {
Chris Lattner08631c52008-11-23 21:45:46 +0000299 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000300 return;
301 }
302 }
303 }
David Blaikie4e4d0842012-03-11 07:00:24 +0000304 } else if (PP.getLangOpts().ApplePragmaPack) {
Eli Friedman19bda3a2011-11-02 01:53:16 +0000305 // In MSVC/gcc, #pragma pack() resets the alignment without affecting
306 // the push/pop stack.
307 // In Apple gcc #pragma pack() is equivalent to #pragma pack(pop).
308 Kind = Sema::PPK_Pop;
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000309 }
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000310
311 if (Tok.isNot(tok::r_paren)) {
Ted Kremenek4726d032009-03-23 22:28:25 +0000312 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack";
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000313 return;
314 }
315
Daniel Dunbar861800c2010-05-26 23:29:06 +0000316 SourceLocation RParenLoc = Tok.getLocation();
Eli Friedman99914792009-06-05 00:49:58 +0000317 PP.Lex(Tok);
Peter Collingbourne84021552011-02-28 02:37:51 +0000318 if (Tok.isNot(tok::eod)) {
Eli Friedman99914792009-06-05 00:49:58 +0000319 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack";
320 return;
321 }
322
Daniel Dunbarb0939552012-02-29 01:38:22 +0000323 PragmaPackInfo *Info =
324 (PragmaPackInfo*) PP.getPreprocessorAllocator().Allocate(
325 sizeof(PragmaPackInfo), llvm::alignOf<PragmaPackInfo>());
326 new (Info) PragmaPackInfo();
Eli Friedmanaa5ab262012-02-23 23:47:16 +0000327 Info->Kind = Kind;
328 Info->Name = Name;
Eli Friedman9595c7e2012-10-04 02:36:51 +0000329 Info->Alignment = Alignment;
Eli Friedmanaa5ab262012-02-23 23:47:16 +0000330 Info->LParenLoc = LParenLoc;
331 Info->RParenLoc = RParenLoc;
332
Daniel Dunbarb0939552012-02-29 01:38:22 +0000333 Token *Toks =
334 (Token*) PP.getPreprocessorAllocator().Allocate(
335 sizeof(Token) * 1, llvm::alignOf<Token>());
336 new (Toks) Token();
Eli Friedmanaa5ab262012-02-23 23:47:16 +0000337 Toks[0].startToken();
338 Toks[0].setKind(tok::annot_pragma_pack);
339 Toks[0].setLocation(PackLoc);
340 Toks[0].setAnnotationValue(static_cast<void*>(Info));
341 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
Daniel Dunbarb0939552012-02-29 01:38:22 +0000342 /*OwnsTokens=*/false);
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000343}
344
Fariborz Jahanian62c92582011-04-25 18:49:15 +0000345// #pragma ms_struct on
346// #pragma ms_struct off
347void PragmaMSStructHandler::HandlePragma(Preprocessor &PP,
348 PragmaIntroducerKind Introducer,
349 Token &MSStructTok) {
350 Sema::PragmaMSStructKind Kind = Sema::PMSST_OFF;
351
352 Token Tok;
353 PP.Lex(Tok);
354 if (Tok.isNot(tok::identifier)) {
355 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
356 return;
357 }
358 const IdentifierInfo *II = Tok.getIdentifierInfo();
359 if (II->isStr("on")) {
360 Kind = Sema::PMSST_ON;
361 PP.Lex(Tok);
362 }
363 else if (II->isStr("off") || II->isStr("reset"))
364 PP.Lex(Tok);
365 else {
366 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
367 return;
368 }
369
370 if (Tok.isNot(tok::eod)) {
Daniel Dunbarb0939552012-02-29 01:38:22 +0000371 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
372 << "ms_struct";
Fariborz Jahanian62c92582011-04-25 18:49:15 +0000373 return;
374 }
Eli Friedman9595c7e2012-10-04 02:36:51 +0000375
376 Token *Toks =
377 (Token*) PP.getPreprocessorAllocator().Allocate(
378 sizeof(Token) * 1, llvm::alignOf<Token>());
379 new (Toks) Token();
380 Toks[0].startToken();
381 Toks[0].setKind(tok::annot_pragma_msstruct);
382 Toks[0].setLocation(MSStructTok.getLocation());
383 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
384 static_cast<uintptr_t>(Kind)));
385 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
386 /*OwnsTokens=*/false);
Fariborz Jahanian62c92582011-04-25 18:49:15 +0000387}
388
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000389// #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
390// #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
Eli Friedman9595c7e2012-10-04 02:36:51 +0000391static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok,
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000392 bool IsOptions) {
Daniel Dunbar861800c2010-05-26 23:29:06 +0000393 Token Tok;
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000394
395 if (IsOptions) {
396 PP.Lex(Tok);
397 if (Tok.isNot(tok::identifier) ||
398 !Tok.getIdentifierInfo()->isStr("align")) {
399 PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align);
400 return;
401 }
Daniel Dunbar861800c2010-05-26 23:29:06 +0000402 }
Daniel Dunbar638e7cf2010-05-27 18:42:09 +0000403
Daniel Dunbar861800c2010-05-26 23:29:06 +0000404 PP.Lex(Tok);
405 if (Tok.isNot(tok::equal)) {
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000406 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal)
407 << IsOptions;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000408 return;
409 }
410
411 PP.Lex(Tok);
412 if (Tok.isNot(tok::identifier)) {
413 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000414 << (IsOptions ? "options" : "align");
Daniel Dunbar861800c2010-05-26 23:29:06 +0000415 return;
416 }
417
John McCallf312b1e2010-08-26 23:41:50 +0000418 Sema::PragmaOptionsAlignKind Kind = Sema::POAK_Natural;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000419 const IdentifierInfo *II = Tok.getIdentifierInfo();
Daniel Dunbar638e7cf2010-05-27 18:42:09 +0000420 if (II->isStr("native"))
John McCallf312b1e2010-08-26 23:41:50 +0000421 Kind = Sema::POAK_Native;
Daniel Dunbar638e7cf2010-05-27 18:42:09 +0000422 else if (II->isStr("natural"))
John McCallf312b1e2010-08-26 23:41:50 +0000423 Kind = Sema::POAK_Natural;
Daniel Dunbar6f739142010-05-27 18:42:17 +0000424 else if (II->isStr("packed"))
John McCallf312b1e2010-08-26 23:41:50 +0000425 Kind = Sema::POAK_Packed;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000426 else if (II->isStr("power"))
John McCallf312b1e2010-08-26 23:41:50 +0000427 Kind = Sema::POAK_Power;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000428 else if (II->isStr("mac68k"))
John McCallf312b1e2010-08-26 23:41:50 +0000429 Kind = Sema::POAK_Mac68k;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000430 else if (II->isStr("reset"))
John McCallf312b1e2010-08-26 23:41:50 +0000431 Kind = Sema::POAK_Reset;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000432 else {
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000433 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option)
434 << IsOptions;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000435 return;
436 }
437
Daniel Dunbar861800c2010-05-26 23:29:06 +0000438 PP.Lex(Tok);
Peter Collingbourne84021552011-02-28 02:37:51 +0000439 if (Tok.isNot(tok::eod)) {
Daniel Dunbar861800c2010-05-26 23:29:06 +0000440 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000441 << (IsOptions ? "options" : "align");
Daniel Dunbar861800c2010-05-26 23:29:06 +0000442 return;
443 }
444
Eli Friedman9595c7e2012-10-04 02:36:51 +0000445 Token *Toks =
446 (Token*) PP.getPreprocessorAllocator().Allocate(
447 sizeof(Token) * 1, llvm::alignOf<Token>());
448 new (Toks) Token();
449 Toks[0].startToken();
450 Toks[0].setKind(tok::annot_pragma_align);
451 Toks[0].setLocation(FirstTok.getLocation());
452 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
453 static_cast<uintptr_t>(Kind)));
454 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
455 /*OwnsTokens=*/false);
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000456}
457
Douglas Gregor80c60f72010-09-09 22:45:38 +0000458void PragmaAlignHandler::HandlePragma(Preprocessor &PP,
459 PragmaIntroducerKind Introducer,
460 Token &AlignTok) {
Eli Friedman9595c7e2012-10-04 02:36:51 +0000461 ParseAlignPragma(PP, AlignTok, /*IsOptions=*/false);
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000462}
463
Douglas Gregor80c60f72010-09-09 22:45:38 +0000464void PragmaOptionsHandler::HandlePragma(Preprocessor &PP,
465 PragmaIntroducerKind Introducer,
466 Token &OptionsTok) {
Eli Friedman9595c7e2012-10-04 02:36:51 +0000467 ParseAlignPragma(PP, OptionsTok, /*IsOptions=*/true);
Daniel Dunbar861800c2010-05-26 23:29:06 +0000468}
469
Ted Kremenek4726d032009-03-23 22:28:25 +0000470// #pragma unused(identifier)
Douglas Gregor80c60f72010-09-09 22:45:38 +0000471void PragmaUnusedHandler::HandlePragma(Preprocessor &PP,
472 PragmaIntroducerKind Introducer,
473 Token &UnusedTok) {
Ted Kremenek4726d032009-03-23 22:28:25 +0000474 // FIXME: Should we be expanding macros here? My guess is no.
475 SourceLocation UnusedLoc = UnusedTok.getLocation();
Mike Stump1eb44332009-09-09 15:08:12 +0000476
Ted Kremenek4726d032009-03-23 22:28:25 +0000477 // Lex the left '('.
478 Token Tok;
479 PP.Lex(Tok);
480 if (Tok.isNot(tok::l_paren)) {
481 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
482 return;
483 }
Mike Stump1eb44332009-09-09 15:08:12 +0000484
Ted Kremenek4726d032009-03-23 22:28:25 +0000485 // Lex the declaration reference(s).
Chris Lattner5f9e2722011-07-23 10:55:15 +0000486 SmallVector<Token, 5> Identifiers;
Ted Kremenek4726d032009-03-23 22:28:25 +0000487 SourceLocation RParenLoc;
488 bool LexID = true;
Mike Stump1eb44332009-09-09 15:08:12 +0000489
Ted Kremenek4726d032009-03-23 22:28:25 +0000490 while (true) {
491 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000492
Ted Kremenek4726d032009-03-23 22:28:25 +0000493 if (LexID) {
Mike Stump1eb44332009-09-09 15:08:12 +0000494 if (Tok.is(tok::identifier)) {
Ted Kremenek7a02a372009-08-03 23:24:57 +0000495 Identifiers.push_back(Tok);
Ted Kremenek4726d032009-03-23 22:28:25 +0000496 LexID = false;
497 continue;
498 }
499
Ted Kremenek7a02a372009-08-03 23:24:57 +0000500 // Illegal token!
Ted Kremenek4726d032009-03-23 22:28:25 +0000501 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
502 return;
503 }
Mike Stump1eb44332009-09-09 15:08:12 +0000504
Ted Kremenek4726d032009-03-23 22:28:25 +0000505 // We are execting a ')' or a ','.
506 if (Tok.is(tok::comma)) {
507 LexID = true;
508 continue;
509 }
Mike Stump1eb44332009-09-09 15:08:12 +0000510
Ted Kremenek4726d032009-03-23 22:28:25 +0000511 if (Tok.is(tok::r_paren)) {
512 RParenLoc = Tok.getLocation();
513 break;
514 }
Mike Stump1eb44332009-09-09 15:08:12 +0000515
Ted Kremenek7a02a372009-08-03 23:24:57 +0000516 // Illegal token!
Ted Kremenek4726d032009-03-23 22:28:25 +0000517 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_punc);
518 return;
519 }
Eli Friedman99914792009-06-05 00:49:58 +0000520
521 PP.Lex(Tok);
Peter Collingbourne84021552011-02-28 02:37:51 +0000522 if (Tok.isNot(tok::eod)) {
Eli Friedman99914792009-06-05 00:49:58 +0000523 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
524 "unused";
525 return;
526 }
527
Ted Kremenek4726d032009-03-23 22:28:25 +0000528 // Verify that we have a location for the right parenthesis.
529 assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
Ted Kremenek7a02a372009-08-03 23:24:57 +0000530 assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
Ted Kremenek4726d032009-03-23 22:28:25 +0000531
Argyrios Kyrtzidisb918d0f2011-01-17 18:58:44 +0000532 // For each identifier token, insert into the token stream a
533 // annot_pragma_unused token followed by the identifier token.
534 // This allows us to cache a "#pragma unused" that occurs inside an inline
535 // C++ member function.
536
Daniel Dunbarb0939552012-02-29 01:38:22 +0000537 Token *Toks =
538 (Token*) PP.getPreprocessorAllocator().Allocate(
539 sizeof(Token) * 2 * Identifiers.size(), llvm::alignOf<Token>());
Argyrios Kyrtzidisb918d0f2011-01-17 18:58:44 +0000540 for (unsigned i=0; i != Identifiers.size(); i++) {
541 Token &pragmaUnusedTok = Toks[2*i], &idTok = Toks[2*i+1];
542 pragmaUnusedTok.startToken();
543 pragmaUnusedTok.setKind(tok::annot_pragma_unused);
544 pragmaUnusedTok.setLocation(UnusedLoc);
545 idTok = Identifiers[i];
546 }
Daniel Dunbarb0939552012-02-29 01:38:22 +0000547 PP.EnterTokenStream(Toks, 2*Identifiers.size(),
548 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
Ted Kremenek4726d032009-03-23 22:28:25 +0000549}
Eli Friedman99914792009-06-05 00:49:58 +0000550
551// #pragma weak identifier
552// #pragma weak identifier '=' identifier
Douglas Gregor80c60f72010-09-09 22:45:38 +0000553void PragmaWeakHandler::HandlePragma(Preprocessor &PP,
554 PragmaIntroducerKind Introducer,
555 Token &WeakTok) {
Eli Friedman99914792009-06-05 00:49:58 +0000556 SourceLocation WeakLoc = WeakTok.getLocation();
557
558 Token Tok;
559 PP.Lex(Tok);
560 if (Tok.isNot(tok::identifier)) {
561 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";
562 return;
563 }
564
Eli Friedman9595c7e2012-10-04 02:36:51 +0000565 Token WeakName = Tok;
566 bool HasAlias = false;
567 Token AliasName;
Eli Friedman99914792009-06-05 00:49:58 +0000568
569 PP.Lex(Tok);
570 if (Tok.is(tok::equal)) {
Eli Friedman9595c7e2012-10-04 02:36:51 +0000571 HasAlias = true;
Eli Friedman99914792009-06-05 00:49:58 +0000572 PP.Lex(Tok);
573 if (Tok.isNot(tok::identifier)) {
Mike Stump1eb44332009-09-09 15:08:12 +0000574 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Eli Friedman99914792009-06-05 00:49:58 +0000575 << "weak";
576 return;
577 }
Eli Friedman9595c7e2012-10-04 02:36:51 +0000578 AliasName = Tok;
Eli Friedman99914792009-06-05 00:49:58 +0000579 PP.Lex(Tok);
580 }
581
Peter Collingbourne84021552011-02-28 02:37:51 +0000582 if (Tok.isNot(tok::eod)) {
Eli Friedman99914792009-06-05 00:49:58 +0000583 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";
584 return;
585 }
586
Eli Friedman9595c7e2012-10-04 02:36:51 +0000587 if (HasAlias) {
588 Token *Toks =
589 (Token*) PP.getPreprocessorAllocator().Allocate(
590 sizeof(Token) * 3, llvm::alignOf<Token>());
591 Token &pragmaUnusedTok = Toks[0];
592 pragmaUnusedTok.startToken();
593 pragmaUnusedTok.setKind(tok::annot_pragma_weakalias);
594 pragmaUnusedTok.setLocation(WeakLoc);
595 Toks[1] = WeakName;
596 Toks[2] = AliasName;
597 PP.EnterTokenStream(Toks, 3,
598 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
Eli Friedman99914792009-06-05 00:49:58 +0000599 } else {
Eli Friedman9595c7e2012-10-04 02:36:51 +0000600 Token *Toks =
601 (Token*) PP.getPreprocessorAllocator().Allocate(
602 sizeof(Token) * 2, llvm::alignOf<Token>());
603 Token &pragmaUnusedTok = Toks[0];
604 pragmaUnusedTok.startToken();
605 pragmaUnusedTok.setKind(tok::annot_pragma_weak);
606 pragmaUnusedTok.setLocation(WeakLoc);
607 Toks[1] = WeakName;
608 PP.EnterTokenStream(Toks, 2,
609 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
Eli Friedman99914792009-06-05 00:49:58 +0000610 }
611}
Peter Collingbourne321b8172011-02-14 01:42:35 +0000612
David Chisnall5f3c1632012-02-18 16:12:34 +0000613// #pragma redefine_extname identifier identifier
614void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP,
615 PragmaIntroducerKind Introducer,
616 Token &RedefToken) {
617 SourceLocation RedefLoc = RedefToken.getLocation();
618
619 Token Tok;
620 PP.Lex(Tok);
621 if (Tok.isNot(tok::identifier)) {
622 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
623 "redefine_extname";
624 return;
625 }
626
Eli Friedman9595c7e2012-10-04 02:36:51 +0000627 Token RedefName = Tok;
David Chisnall5f3c1632012-02-18 16:12:34 +0000628 PP.Lex(Tok);
Eli Friedman9595c7e2012-10-04 02:36:51 +0000629
David Chisnall5f3c1632012-02-18 16:12:34 +0000630 if (Tok.isNot(tok::identifier)) {
631 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
632 << "redefine_extname";
633 return;
634 }
Eli Friedman9595c7e2012-10-04 02:36:51 +0000635
636 Token AliasName = Tok;
David Chisnall5f3c1632012-02-18 16:12:34 +0000637 PP.Lex(Tok);
638
639 if (Tok.isNot(tok::eod)) {
640 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
641 "redefine_extname";
642 return;
643 }
644
Eli Friedman9595c7e2012-10-04 02:36:51 +0000645 Token *Toks =
646 (Token*) PP.getPreprocessorAllocator().Allocate(
647 sizeof(Token) * 3, llvm::alignOf<Token>());
648 Token &pragmaRedefTok = Toks[0];
649 pragmaRedefTok.startToken();
650 pragmaRedefTok.setKind(tok::annot_pragma_redefine_extname);
651 pragmaRedefTok.setLocation(RedefLoc);
652 Toks[1] = RedefName;
653 Toks[2] = AliasName;
654 PP.EnterTokenStream(Toks, 3,
655 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
David Chisnall5f3c1632012-02-18 16:12:34 +0000656}
657
658
Peter Collingbourne321b8172011-02-14 01:42:35 +0000659void
660PragmaFPContractHandler::HandlePragma(Preprocessor &PP,
661 PragmaIntroducerKind Introducer,
662 Token &Tok) {
663 tok::OnOffSwitch OOS;
664 if (PP.LexOnOffSwitch(OOS))
665 return;
666
Eli Friedman9595c7e2012-10-04 02:36:51 +0000667 Token *Toks =
668 (Token*) PP.getPreprocessorAllocator().Allocate(
669 sizeof(Token) * 1, llvm::alignOf<Token>());
670 new (Toks) Token();
671 Toks[0].startToken();
672 Toks[0].setKind(tok::annot_pragma_fp_contract);
673 Toks[0].setLocation(Tok.getLocation());
674 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
675 static_cast<uintptr_t>(OOS)));
676 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
677 /*OwnsTokens=*/false);
Peter Collingbourne321b8172011-02-14 01:42:35 +0000678}
Peter Collingbournef315fa82011-02-14 01:42:53 +0000679
680void
681PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
682 PragmaIntroducerKind Introducer,
683 Token &Tok) {
Tanya Lattnerb38b6a72011-04-14 23:35:31 +0000684 PP.LexUnexpandedToken(Tok);
Peter Collingbournef315fa82011-02-14 01:42:53 +0000685 if (Tok.isNot(tok::identifier)) {
686 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
687 "OPENCL";
688 return;
689 }
690 IdentifierInfo *ename = Tok.getIdentifierInfo();
691 SourceLocation NameLoc = Tok.getLocation();
692
693 PP.Lex(Tok);
694 if (Tok.isNot(tok::colon)) {
695 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << ename;
696 return;
697 }
698
699 PP.Lex(Tok);
700 if (Tok.isNot(tok::identifier)) {
701 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
702 return;
703 }
704 IdentifierInfo *op = Tok.getIdentifierInfo();
705
706 unsigned state;
707 if (op->isStr("enable")) {
708 state = 1;
709 } else if (op->isStr("disable")) {
710 state = 0;
711 } else {
712 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
713 return;
714 }
715
Eli Friedman9595c7e2012-10-04 02:36:51 +0000716 PP.Lex(Tok);
717 if (Tok.isNot(tok::eod)) {
718 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
719 "OPENCL EXTENSION";
Peter Collingbournef315fa82011-02-14 01:42:53 +0000720 return;
721 }
Eli Friedman9595c7e2012-10-04 02:36:51 +0000722
723 OpenCLExtData data(ename, state);
724 Token *Toks =
725 (Token*) PP.getPreprocessorAllocator().Allocate(
726 sizeof(Token) * 1, llvm::alignOf<Token>());
727 new (Toks) Token();
728 Toks[0].startToken();
729 Toks[0].setKind(tok::annot_pragma_opencl_extension);
730 Toks[0].setLocation(NameLoc);
731 Toks[0].setAnnotationValue(data.getOpaqueValue());
732 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
733 /*OwnsTokens=*/false);
Peter Collingbournef315fa82011-02-14 01:42:53 +0000734}
735
Alexey Bataevc6400582013-03-22 06:34:35 +0000736/// \brief Handle '#pragma omp ...' when OpenMP is disabled.
737///
738void
739PragmaNoOpenMPHandler::HandlePragma(Preprocessor &PP,
740 PragmaIntroducerKind Introducer,
741 Token &FirstTok) {
742 if (PP.getDiagnostics().getDiagnosticLevel(diag::warn_pragma_omp_ignored,
743 FirstTok.getLocation()) !=
744 DiagnosticsEngine::Ignored) {
745 PP.Diag(FirstTok, diag::warn_pragma_omp_ignored);
746 PP.getDiagnostics().setDiagnosticMapping(diag::warn_pragma_omp_ignored,
747 diag::MAP_IGNORE,
748 SourceLocation());
749 }
750 PP.DiscardUntilEndOfDirective();
751}
752
753/// \brief Handle '#pragma omp ...' when OpenMP is enabled.
754///
755void
756PragmaOpenMPHandler::HandlePragma(Preprocessor &PP,
757 PragmaIntroducerKind Introducer,
758 Token &FirstTok) {
759 SmallVector<Token, 16> Pragma;
760 Token Tok;
761 Tok.startToken();
762 Tok.setKind(tok::annot_pragma_openmp);
763 Tok.setLocation(FirstTok.getLocation());
764
765 while (Tok.isNot(tok::eod)) {
766 Pragma.push_back(Tok);
767 PP.Lex(Tok);
768 }
769 SourceLocation EodLoc = Tok.getLocation();
770 Tok.startToken();
771 Tok.setKind(tok::annot_pragma_openmp_end);
772 Tok.setLocation(EodLoc);
773 Pragma.push_back(Tok);
774
775 Token *Toks = new Token[Pragma.size()];
776 std::copy(Pragma.begin(), Pragma.end(), Toks);
777 PP.EnterTokenStream(Toks, Pragma.size(),
778 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/true);
779}