blob: 0ecd11ec97fcd49468c7d5a39b34e9976502ec1c [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"
Tareq A. Siraj6afcf882013-04-16 19:37:38 +000018#include "clang/Sema/Scope.h"
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000019using namespace clang;
20
Argyrios Kyrtzidisb918d0f2011-01-17 18:58:44 +000021/// \brief Handle the annotation token produced for #pragma unused(...)
22///
23/// Each annot_pragma_unused is followed by the argument token so e.g.
24/// "#pragma unused(x,y)" becomes:
25/// annot_pragma_unused 'x' annot_pragma_unused 'y'
26void Parser::HandlePragmaUnused() {
27 assert(Tok.is(tok::annot_pragma_unused));
28 SourceLocation UnusedLoc = ConsumeToken();
29 Actions.ActOnPragmaUnused(Tok, getCurScope(), UnusedLoc);
30 ConsumeToken(); // The argument token.
31}
Eli Friedmanaa8b0d12010-08-05 06:57:20 +000032
Rafael Espindola426fc942012-01-26 02:02:57 +000033void Parser::HandlePragmaVisibility() {
34 assert(Tok.is(tok::annot_pragma_vis));
35 const IdentifierInfo *VisType =
36 static_cast<IdentifierInfo *>(Tok.getAnnotationValue());
37 SourceLocation VisLoc = ConsumeToken();
38 Actions.ActOnPragmaVisibility(VisType, VisLoc);
39}
40
Eli Friedmanaa5ab262012-02-23 23:47:16 +000041struct PragmaPackInfo {
42 Sema::PragmaPackKind Kind;
43 IdentifierInfo *Name;
Eli Friedman9595c7e2012-10-04 02:36:51 +000044 Token Alignment;
Eli Friedmanaa5ab262012-02-23 23:47:16 +000045 SourceLocation LParenLoc;
46 SourceLocation RParenLoc;
47};
48
49void Parser::HandlePragmaPack() {
50 assert(Tok.is(tok::annot_pragma_pack));
51 PragmaPackInfo *Info =
52 static_cast<PragmaPackInfo *>(Tok.getAnnotationValue());
53 SourceLocation PragmaLoc = ConsumeToken();
Eli Friedman9595c7e2012-10-04 02:36:51 +000054 ExprResult Alignment;
55 if (Info->Alignment.is(tok::numeric_constant)) {
56 Alignment = Actions.ActOnNumericConstant(Info->Alignment);
57 if (Alignment.isInvalid())
58 return;
59 }
60 Actions.ActOnPragmaPack(Info->Kind, Info->Name, Alignment.get(), PragmaLoc,
Eli Friedmanaa5ab262012-02-23 23:47:16 +000061 Info->LParenLoc, Info->RParenLoc);
Eli Friedmanaa5ab262012-02-23 23:47:16 +000062}
63
Eli Friedman9595c7e2012-10-04 02:36:51 +000064void Parser::HandlePragmaMSStruct() {
65 assert(Tok.is(tok::annot_pragma_msstruct));
66 Sema::PragmaMSStructKind Kind =
67 static_cast<Sema::PragmaMSStructKind>(
68 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
69 Actions.ActOnPragmaMSStruct(Kind);
70 ConsumeToken(); // The annotation token.
71}
72
73void Parser::HandlePragmaAlign() {
74 assert(Tok.is(tok::annot_pragma_align));
75 Sema::PragmaOptionsAlignKind Kind =
76 static_cast<Sema::PragmaOptionsAlignKind>(
77 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
78 SourceLocation PragmaLoc = ConsumeToken();
79 Actions.ActOnPragmaOptionsAlign(Kind, PragmaLoc);
80}
81
82void Parser::HandlePragmaWeak() {
83 assert(Tok.is(tok::annot_pragma_weak));
84 SourceLocation PragmaLoc = ConsumeToken();
85 Actions.ActOnPragmaWeakID(Tok.getIdentifierInfo(), PragmaLoc,
86 Tok.getLocation());
87 ConsumeToken(); // The weak name.
88}
89
90void Parser::HandlePragmaWeakAlias() {
91 assert(Tok.is(tok::annot_pragma_weakalias));
92 SourceLocation PragmaLoc = ConsumeToken();
93 IdentifierInfo *WeakName = Tok.getIdentifierInfo();
94 SourceLocation WeakNameLoc = Tok.getLocation();
95 ConsumeToken();
96 IdentifierInfo *AliasName = Tok.getIdentifierInfo();
97 SourceLocation AliasNameLoc = Tok.getLocation();
98 ConsumeToken();
99 Actions.ActOnPragmaWeakAlias(WeakName, AliasName, PragmaLoc,
100 WeakNameLoc, AliasNameLoc);
101
102}
103
104void Parser::HandlePragmaRedefineExtname() {
105 assert(Tok.is(tok::annot_pragma_redefine_extname));
106 SourceLocation RedefLoc = ConsumeToken();
107 IdentifierInfo *RedefName = Tok.getIdentifierInfo();
108 SourceLocation RedefNameLoc = Tok.getLocation();
109 ConsumeToken();
110 IdentifierInfo *AliasName = Tok.getIdentifierInfo();
111 SourceLocation AliasNameLoc = Tok.getLocation();
112 ConsumeToken();
113 Actions.ActOnPragmaRedefineExtname(RedefName, AliasName, RedefLoc,
114 RedefNameLoc, AliasNameLoc);
115}
116
117void Parser::HandlePragmaFPContract() {
118 assert(Tok.is(tok::annot_pragma_fp_contract));
119 tok::OnOffSwitch OOS =
120 static_cast<tok::OnOffSwitch>(
121 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
122 Actions.ActOnPragmaFPContract(OOS);
123 ConsumeToken(); // The annotation token.
124}
125
Tareq A. Siraj85192c72013-04-16 18:41:26 +0000126StmtResult Parser::HandlePragmaCaptured()
127{
128 assert(Tok.is(tok::annot_pragma_captured));
129 ConsumeToken();
130
131 if (Tok.isNot(tok::l_brace)) {
132 PP.Diag(Tok, diag::err_expected_lbrace);
133 return StmtError();
134 }
135
Tareq A. Siraj6afcf882013-04-16 19:37:38 +0000136 SourceLocation Loc = Tok.getLocation();
137
138 ParseScope CapturedRegionScope(this, Scope::FnScope | Scope::DeclScope);
Ben Langmuir3a2f9122013-04-29 13:32:41 +0000139 Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_Default);
Tareq A. Siraj6afcf882013-04-16 19:37:38 +0000140
141 StmtResult R = ParseCompoundStatement();
142 CapturedRegionScope.Exit();
143
144 if (R.isInvalid()) {
145 Actions.ActOnCapturedRegionError();
146 return StmtError();
147 }
148
149 return Actions.ActOnCapturedRegionEnd(R.get());
Tareq A. Siraj85192c72013-04-16 18:41:26 +0000150}
151
Eli Friedman9595c7e2012-10-04 02:36:51 +0000152namespace {
153 typedef llvm::PointerIntPair<IdentifierInfo *, 1, bool> OpenCLExtData;
154}
155
156void Parser::HandlePragmaOpenCLExtension() {
157 assert(Tok.is(tok::annot_pragma_opencl_extension));
158 OpenCLExtData data =
159 OpenCLExtData::getFromOpaqueValue(Tok.getAnnotationValue());
160 unsigned state = data.getInt();
161 IdentifierInfo *ename = data.getPointer();
162 SourceLocation NameLoc = Tok.getLocation();
163 ConsumeToken(); // The annotation token.
164
165 OpenCLOptions &f = Actions.getOpenCLOptions();
166 // OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions,
167 // overriding all previously issued extension directives, but only if the
168 // behavior is set to disable."
169 if (state == 0 && ename->isStr("all")) {
170#define OPENCLEXT(nm) f.nm = 0;
171#include "clang/Basic/OpenCLExtensions.def"
172 }
173#define OPENCLEXT(nm) else if (ename->isStr(#nm)) { f.nm = state; }
174#include "clang/Basic/OpenCLExtensions.def"
175 else {
176 PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << ename;
177 return;
178 }
179}
180
Tareq A. Siraj85192c72013-04-16 18:41:26 +0000181
182
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000183// #pragma GCC visibility comes in two variants:
184// 'push' '(' [visibility] ')'
185// 'pop'
Douglas Gregor80c60f72010-09-09 22:45:38 +0000186void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,
187 PragmaIntroducerKind Introducer,
188 Token &VisTok) {
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000189 SourceLocation VisLoc = VisTok.getLocation();
190
191 Token Tok;
Joerg Sonnenbergere23af2a2011-07-20 01:03:50 +0000192 PP.LexUnexpandedToken(Tok);
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000193
194 const IdentifierInfo *PushPop = Tok.getIdentifierInfo();
195
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000196 const IdentifierInfo *VisType;
197 if (PushPop && PushPop->isStr("pop")) {
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000198 VisType = 0;
199 } else if (PushPop && PushPop->isStr("push")) {
Joerg Sonnenbergere23af2a2011-07-20 01:03:50 +0000200 PP.LexUnexpandedToken(Tok);
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000201 if (Tok.isNot(tok::l_paren)) {
202 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
203 << "visibility";
204 return;
205 }
Joerg Sonnenbergere23af2a2011-07-20 01:03:50 +0000206 PP.LexUnexpandedToken(Tok);
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000207 VisType = Tok.getIdentifierInfo();
208 if (!VisType) {
209 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
210 << "visibility";
211 return;
212 }
Joerg Sonnenbergere23af2a2011-07-20 01:03:50 +0000213 PP.LexUnexpandedToken(Tok);
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000214 if (Tok.isNot(tok::r_paren)) {
215 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
216 << "visibility";
217 return;
218 }
219 } else {
220 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
221 << "visibility";
222 return;
223 }
Joerg Sonnenbergere23af2a2011-07-20 01:03:50 +0000224 PP.LexUnexpandedToken(Tok);
Peter Collingbourne84021552011-02-28 02:37:51 +0000225 if (Tok.isNot(tok::eod)) {
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000226 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
227 << "visibility";
228 return;
229 }
230
Rafael Espindola426fc942012-01-26 02:02:57 +0000231 Token *Toks = new Token[1];
232 Toks[0].startToken();
233 Toks[0].setKind(tok::annot_pragma_vis);
234 Toks[0].setLocation(VisLoc);
235 Toks[0].setAnnotationValue(
236 const_cast<void*>(static_cast<const void*>(VisType)));
237 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
238 /*OwnsTokens=*/true);
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000239}
240
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000241// #pragma pack(...) comes in the following delicious flavors:
242// pack '(' [integer] ')'
243// pack '(' 'show' ')'
244// pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'
Douglas Gregor80c60f72010-09-09 22:45:38 +0000245void PragmaPackHandler::HandlePragma(Preprocessor &PP,
246 PragmaIntroducerKind Introducer,
247 Token &PackTok) {
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000248 SourceLocation PackLoc = PackTok.getLocation();
249
250 Token Tok;
251 PP.Lex(Tok);
252 if (Tok.isNot(tok::l_paren)) {
Ted Kremenek4726d032009-03-23 22:28:25 +0000253 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack";
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000254 return;
255 }
256
John McCallf312b1e2010-08-26 23:41:50 +0000257 Sema::PragmaPackKind Kind = Sema::PPK_Default;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000258 IdentifierInfo *Name = 0;
Eli Friedman9595c7e2012-10-04 02:36:51 +0000259 Token Alignment;
260 Alignment.startToken();
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000261 SourceLocation LParenLoc = Tok.getLocation();
Mike Stump1eb44332009-09-09 15:08:12 +0000262 PP.Lex(Tok);
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);
Eli Friedman19bda3a2011-11-02 01:53:16 +0000267
268 // In MSVC/gcc, #pragma pack(4) sets the alignment without affecting
269 // the push/pop stack.
270 // In Apple gcc, #pragma pack(4) is equivalent to #pragma pack(push, 4)
David Blaikie4e4d0842012-03-11 07:00:24 +0000271 if (PP.getLangOpts().ApplePragmaPack)
Eli Friedman19bda3a2011-11-02 01:53:16 +0000272 Kind = Sema::PPK_Push;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000273 } else if (Tok.is(tok::identifier)) {
274 const IdentifierInfo *II = Tok.getIdentifierInfo();
Chris Lattner08631c52008-11-23 21:45:46 +0000275 if (II->isStr("show")) {
John McCallf312b1e2010-08-26 23:41:50 +0000276 Kind = Sema::PPK_Show;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000277 PP.Lex(Tok);
278 } else {
Chris Lattner08631c52008-11-23 21:45:46 +0000279 if (II->isStr("push")) {
John McCallf312b1e2010-08-26 23:41:50 +0000280 Kind = Sema::PPK_Push;
Chris Lattner08631c52008-11-23 21:45:46 +0000281 } else if (II->isStr("pop")) {
John McCallf312b1e2010-08-26 23:41:50 +0000282 Kind = Sema::PPK_Pop;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000283 } else {
284 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_invalid_action);
285 return;
Mike Stump1eb44332009-09-09 15:08:12 +0000286 }
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000287 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000288
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000289 if (Tok.is(tok::comma)) {
290 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000291
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000292 if (Tok.is(tok::numeric_constant)) {
Eli Friedman9595c7e2012-10-04 02:36:51 +0000293 Alignment = Tok;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000294
295 PP.Lex(Tok);
296 } else if (Tok.is(tok::identifier)) {
297 Name = Tok.getIdentifierInfo();
298 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000299
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000300 if (Tok.is(tok::comma)) {
301 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000302
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000303 if (Tok.isNot(tok::numeric_constant)) {
Chris Lattner08631c52008-11-23 21:45:46 +0000304 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000305 return;
306 }
Mike Stump1eb44332009-09-09 15:08:12 +0000307
Eli Friedman9595c7e2012-10-04 02:36:51 +0000308 Alignment = Tok;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000309
310 PP.Lex(Tok);
311 }
312 } else {
Chris Lattner08631c52008-11-23 21:45:46 +0000313 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000314 return;
315 }
316 }
317 }
David Blaikie4e4d0842012-03-11 07:00:24 +0000318 } else if (PP.getLangOpts().ApplePragmaPack) {
Eli Friedman19bda3a2011-11-02 01:53:16 +0000319 // In MSVC/gcc, #pragma pack() resets the alignment without affecting
320 // the push/pop stack.
321 // In Apple gcc #pragma pack() is equivalent to #pragma pack(pop).
322 Kind = Sema::PPK_Pop;
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000323 }
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000324
325 if (Tok.isNot(tok::r_paren)) {
Ted Kremenek4726d032009-03-23 22:28:25 +0000326 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack";
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000327 return;
328 }
329
Daniel Dunbar861800c2010-05-26 23:29:06 +0000330 SourceLocation RParenLoc = Tok.getLocation();
Eli Friedman99914792009-06-05 00:49:58 +0000331 PP.Lex(Tok);
Peter Collingbourne84021552011-02-28 02:37:51 +0000332 if (Tok.isNot(tok::eod)) {
Eli Friedman99914792009-06-05 00:49:58 +0000333 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack";
334 return;
335 }
336
Daniel Dunbarb0939552012-02-29 01:38:22 +0000337 PragmaPackInfo *Info =
338 (PragmaPackInfo*) PP.getPreprocessorAllocator().Allocate(
339 sizeof(PragmaPackInfo), llvm::alignOf<PragmaPackInfo>());
340 new (Info) PragmaPackInfo();
Eli Friedmanaa5ab262012-02-23 23:47:16 +0000341 Info->Kind = Kind;
342 Info->Name = Name;
Eli Friedman9595c7e2012-10-04 02:36:51 +0000343 Info->Alignment = Alignment;
Eli Friedmanaa5ab262012-02-23 23:47:16 +0000344 Info->LParenLoc = LParenLoc;
345 Info->RParenLoc = RParenLoc;
346
Daniel Dunbarb0939552012-02-29 01:38:22 +0000347 Token *Toks =
348 (Token*) PP.getPreprocessorAllocator().Allocate(
349 sizeof(Token) * 1, llvm::alignOf<Token>());
350 new (Toks) Token();
Eli Friedmanaa5ab262012-02-23 23:47:16 +0000351 Toks[0].startToken();
352 Toks[0].setKind(tok::annot_pragma_pack);
353 Toks[0].setLocation(PackLoc);
354 Toks[0].setAnnotationValue(static_cast<void*>(Info));
355 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
Daniel Dunbarb0939552012-02-29 01:38:22 +0000356 /*OwnsTokens=*/false);
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000357}
358
Fariborz Jahanian62c92582011-04-25 18:49:15 +0000359// #pragma ms_struct on
360// #pragma ms_struct off
361void PragmaMSStructHandler::HandlePragma(Preprocessor &PP,
362 PragmaIntroducerKind Introducer,
363 Token &MSStructTok) {
364 Sema::PragmaMSStructKind Kind = Sema::PMSST_OFF;
365
366 Token Tok;
367 PP.Lex(Tok);
368 if (Tok.isNot(tok::identifier)) {
369 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
370 return;
371 }
372 const IdentifierInfo *II = Tok.getIdentifierInfo();
373 if (II->isStr("on")) {
374 Kind = Sema::PMSST_ON;
375 PP.Lex(Tok);
376 }
377 else if (II->isStr("off") || II->isStr("reset"))
378 PP.Lex(Tok);
379 else {
380 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
381 return;
382 }
383
384 if (Tok.isNot(tok::eod)) {
Daniel Dunbarb0939552012-02-29 01:38:22 +0000385 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
386 << "ms_struct";
Fariborz Jahanian62c92582011-04-25 18:49:15 +0000387 return;
388 }
Eli Friedman9595c7e2012-10-04 02:36:51 +0000389
390 Token *Toks =
391 (Token*) PP.getPreprocessorAllocator().Allocate(
392 sizeof(Token) * 1, llvm::alignOf<Token>());
393 new (Toks) Token();
394 Toks[0].startToken();
395 Toks[0].setKind(tok::annot_pragma_msstruct);
396 Toks[0].setLocation(MSStructTok.getLocation());
397 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
398 static_cast<uintptr_t>(Kind)));
399 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
400 /*OwnsTokens=*/false);
Fariborz Jahanian62c92582011-04-25 18:49:15 +0000401}
402
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000403// #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
404// #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
Eli Friedman9595c7e2012-10-04 02:36:51 +0000405static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok,
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000406 bool IsOptions) {
Daniel Dunbar861800c2010-05-26 23:29:06 +0000407 Token Tok;
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000408
409 if (IsOptions) {
410 PP.Lex(Tok);
411 if (Tok.isNot(tok::identifier) ||
412 !Tok.getIdentifierInfo()->isStr("align")) {
413 PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align);
414 return;
415 }
Daniel Dunbar861800c2010-05-26 23:29:06 +0000416 }
Daniel Dunbar638e7cf2010-05-27 18:42:09 +0000417
Daniel Dunbar861800c2010-05-26 23:29:06 +0000418 PP.Lex(Tok);
419 if (Tok.isNot(tok::equal)) {
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000420 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal)
421 << IsOptions;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000422 return;
423 }
424
425 PP.Lex(Tok);
426 if (Tok.isNot(tok::identifier)) {
427 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000428 << (IsOptions ? "options" : "align");
Daniel Dunbar861800c2010-05-26 23:29:06 +0000429 return;
430 }
431
John McCallf312b1e2010-08-26 23:41:50 +0000432 Sema::PragmaOptionsAlignKind Kind = Sema::POAK_Natural;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000433 const IdentifierInfo *II = Tok.getIdentifierInfo();
Daniel Dunbar638e7cf2010-05-27 18:42:09 +0000434 if (II->isStr("native"))
John McCallf312b1e2010-08-26 23:41:50 +0000435 Kind = Sema::POAK_Native;
Daniel Dunbar638e7cf2010-05-27 18:42:09 +0000436 else if (II->isStr("natural"))
John McCallf312b1e2010-08-26 23:41:50 +0000437 Kind = Sema::POAK_Natural;
Daniel Dunbar6f739142010-05-27 18:42:17 +0000438 else if (II->isStr("packed"))
John McCallf312b1e2010-08-26 23:41:50 +0000439 Kind = Sema::POAK_Packed;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000440 else if (II->isStr("power"))
John McCallf312b1e2010-08-26 23:41:50 +0000441 Kind = Sema::POAK_Power;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000442 else if (II->isStr("mac68k"))
John McCallf312b1e2010-08-26 23:41:50 +0000443 Kind = Sema::POAK_Mac68k;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000444 else if (II->isStr("reset"))
John McCallf312b1e2010-08-26 23:41:50 +0000445 Kind = Sema::POAK_Reset;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000446 else {
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000447 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option)
448 << IsOptions;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000449 return;
450 }
451
Daniel Dunbar861800c2010-05-26 23:29:06 +0000452 PP.Lex(Tok);
Peter Collingbourne84021552011-02-28 02:37:51 +0000453 if (Tok.isNot(tok::eod)) {
Daniel Dunbar861800c2010-05-26 23:29:06 +0000454 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000455 << (IsOptions ? "options" : "align");
Daniel Dunbar861800c2010-05-26 23:29:06 +0000456 return;
457 }
458
Eli Friedman9595c7e2012-10-04 02:36:51 +0000459 Token *Toks =
460 (Token*) PP.getPreprocessorAllocator().Allocate(
461 sizeof(Token) * 1, llvm::alignOf<Token>());
462 new (Toks) Token();
463 Toks[0].startToken();
464 Toks[0].setKind(tok::annot_pragma_align);
465 Toks[0].setLocation(FirstTok.getLocation());
466 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
467 static_cast<uintptr_t>(Kind)));
468 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
469 /*OwnsTokens=*/false);
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000470}
471
Douglas Gregor80c60f72010-09-09 22:45:38 +0000472void PragmaAlignHandler::HandlePragma(Preprocessor &PP,
473 PragmaIntroducerKind Introducer,
474 Token &AlignTok) {
Eli Friedman9595c7e2012-10-04 02:36:51 +0000475 ParseAlignPragma(PP, AlignTok, /*IsOptions=*/false);
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000476}
477
Douglas Gregor80c60f72010-09-09 22:45:38 +0000478void PragmaOptionsHandler::HandlePragma(Preprocessor &PP,
479 PragmaIntroducerKind Introducer,
480 Token &OptionsTok) {
Eli Friedman9595c7e2012-10-04 02:36:51 +0000481 ParseAlignPragma(PP, OptionsTok, /*IsOptions=*/true);
Daniel Dunbar861800c2010-05-26 23:29:06 +0000482}
483
Ted Kremenek4726d032009-03-23 22:28:25 +0000484// #pragma unused(identifier)
Douglas Gregor80c60f72010-09-09 22:45:38 +0000485void PragmaUnusedHandler::HandlePragma(Preprocessor &PP,
486 PragmaIntroducerKind Introducer,
487 Token &UnusedTok) {
Ted Kremenek4726d032009-03-23 22:28:25 +0000488 // FIXME: Should we be expanding macros here? My guess is no.
489 SourceLocation UnusedLoc = UnusedTok.getLocation();
Mike Stump1eb44332009-09-09 15:08:12 +0000490
Ted Kremenek4726d032009-03-23 22:28:25 +0000491 // Lex the left '('.
492 Token Tok;
493 PP.Lex(Tok);
494 if (Tok.isNot(tok::l_paren)) {
495 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
496 return;
497 }
Mike Stump1eb44332009-09-09 15:08:12 +0000498
Ted Kremenek4726d032009-03-23 22:28:25 +0000499 // Lex the declaration reference(s).
Chris Lattner5f9e2722011-07-23 10:55:15 +0000500 SmallVector<Token, 5> Identifiers;
Ted Kremenek4726d032009-03-23 22:28:25 +0000501 SourceLocation RParenLoc;
502 bool LexID = true;
Mike Stump1eb44332009-09-09 15:08:12 +0000503
Ted Kremenek4726d032009-03-23 22:28:25 +0000504 while (true) {
505 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000506
Ted Kremenek4726d032009-03-23 22:28:25 +0000507 if (LexID) {
Mike Stump1eb44332009-09-09 15:08:12 +0000508 if (Tok.is(tok::identifier)) {
Ted Kremenek7a02a372009-08-03 23:24:57 +0000509 Identifiers.push_back(Tok);
Ted Kremenek4726d032009-03-23 22:28:25 +0000510 LexID = false;
511 continue;
512 }
513
Ted Kremenek7a02a372009-08-03 23:24:57 +0000514 // Illegal token!
Ted Kremenek4726d032009-03-23 22:28:25 +0000515 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
516 return;
517 }
Mike Stump1eb44332009-09-09 15:08:12 +0000518
Ted Kremenek4726d032009-03-23 22:28:25 +0000519 // We are execting a ')' or a ','.
520 if (Tok.is(tok::comma)) {
521 LexID = true;
522 continue;
523 }
Mike Stump1eb44332009-09-09 15:08:12 +0000524
Ted Kremenek4726d032009-03-23 22:28:25 +0000525 if (Tok.is(tok::r_paren)) {
526 RParenLoc = Tok.getLocation();
527 break;
528 }
Mike Stump1eb44332009-09-09 15:08:12 +0000529
Ted Kremenek7a02a372009-08-03 23:24:57 +0000530 // Illegal token!
Ted Kremenek4726d032009-03-23 22:28:25 +0000531 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_punc);
532 return;
533 }
Eli Friedman99914792009-06-05 00:49:58 +0000534
535 PP.Lex(Tok);
Peter Collingbourne84021552011-02-28 02:37:51 +0000536 if (Tok.isNot(tok::eod)) {
Eli Friedman99914792009-06-05 00:49:58 +0000537 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
538 "unused";
539 return;
540 }
541
Ted Kremenek4726d032009-03-23 22:28:25 +0000542 // Verify that we have a location for the right parenthesis.
543 assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
Ted Kremenek7a02a372009-08-03 23:24:57 +0000544 assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
Ted Kremenek4726d032009-03-23 22:28:25 +0000545
Argyrios Kyrtzidisb918d0f2011-01-17 18:58:44 +0000546 // For each identifier token, insert into the token stream a
547 // annot_pragma_unused token followed by the identifier token.
548 // This allows us to cache a "#pragma unused" that occurs inside an inline
549 // C++ member function.
550
Daniel Dunbarb0939552012-02-29 01:38:22 +0000551 Token *Toks =
552 (Token*) PP.getPreprocessorAllocator().Allocate(
553 sizeof(Token) * 2 * Identifiers.size(), llvm::alignOf<Token>());
Argyrios Kyrtzidisb918d0f2011-01-17 18:58:44 +0000554 for (unsigned i=0; i != Identifiers.size(); i++) {
555 Token &pragmaUnusedTok = Toks[2*i], &idTok = Toks[2*i+1];
556 pragmaUnusedTok.startToken();
557 pragmaUnusedTok.setKind(tok::annot_pragma_unused);
558 pragmaUnusedTok.setLocation(UnusedLoc);
559 idTok = Identifiers[i];
560 }
Daniel Dunbarb0939552012-02-29 01:38:22 +0000561 PP.EnterTokenStream(Toks, 2*Identifiers.size(),
562 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
Ted Kremenek4726d032009-03-23 22:28:25 +0000563}
Eli Friedman99914792009-06-05 00:49:58 +0000564
565// #pragma weak identifier
566// #pragma weak identifier '=' identifier
Douglas Gregor80c60f72010-09-09 22:45:38 +0000567void PragmaWeakHandler::HandlePragma(Preprocessor &PP,
568 PragmaIntroducerKind Introducer,
569 Token &WeakTok) {
Eli Friedman99914792009-06-05 00:49:58 +0000570 SourceLocation WeakLoc = WeakTok.getLocation();
571
572 Token Tok;
573 PP.Lex(Tok);
574 if (Tok.isNot(tok::identifier)) {
575 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";
576 return;
577 }
578
Eli Friedman9595c7e2012-10-04 02:36:51 +0000579 Token WeakName = Tok;
580 bool HasAlias = false;
581 Token AliasName;
Eli Friedman99914792009-06-05 00:49:58 +0000582
583 PP.Lex(Tok);
584 if (Tok.is(tok::equal)) {
Eli Friedman9595c7e2012-10-04 02:36:51 +0000585 HasAlias = true;
Eli Friedman99914792009-06-05 00:49:58 +0000586 PP.Lex(Tok);
587 if (Tok.isNot(tok::identifier)) {
Mike Stump1eb44332009-09-09 15:08:12 +0000588 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Eli Friedman99914792009-06-05 00:49:58 +0000589 << "weak";
590 return;
591 }
Eli Friedman9595c7e2012-10-04 02:36:51 +0000592 AliasName = Tok;
Eli Friedman99914792009-06-05 00:49:58 +0000593 PP.Lex(Tok);
594 }
595
Peter Collingbourne84021552011-02-28 02:37:51 +0000596 if (Tok.isNot(tok::eod)) {
Eli Friedman99914792009-06-05 00:49:58 +0000597 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";
598 return;
599 }
600
Eli Friedman9595c7e2012-10-04 02:36:51 +0000601 if (HasAlias) {
602 Token *Toks =
603 (Token*) PP.getPreprocessorAllocator().Allocate(
604 sizeof(Token) * 3, llvm::alignOf<Token>());
605 Token &pragmaUnusedTok = Toks[0];
606 pragmaUnusedTok.startToken();
607 pragmaUnusedTok.setKind(tok::annot_pragma_weakalias);
608 pragmaUnusedTok.setLocation(WeakLoc);
609 Toks[1] = WeakName;
610 Toks[2] = AliasName;
611 PP.EnterTokenStream(Toks, 3,
612 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
Eli Friedman99914792009-06-05 00:49:58 +0000613 } else {
Eli Friedman9595c7e2012-10-04 02:36:51 +0000614 Token *Toks =
615 (Token*) PP.getPreprocessorAllocator().Allocate(
616 sizeof(Token) * 2, llvm::alignOf<Token>());
617 Token &pragmaUnusedTok = Toks[0];
618 pragmaUnusedTok.startToken();
619 pragmaUnusedTok.setKind(tok::annot_pragma_weak);
620 pragmaUnusedTok.setLocation(WeakLoc);
621 Toks[1] = WeakName;
622 PP.EnterTokenStream(Toks, 2,
623 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
Eli Friedman99914792009-06-05 00:49:58 +0000624 }
625}
Peter Collingbourne321b8172011-02-14 01:42:35 +0000626
David Chisnall5f3c1632012-02-18 16:12:34 +0000627// #pragma redefine_extname identifier identifier
628void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP,
629 PragmaIntroducerKind Introducer,
630 Token &RedefToken) {
631 SourceLocation RedefLoc = RedefToken.getLocation();
632
633 Token Tok;
634 PP.Lex(Tok);
635 if (Tok.isNot(tok::identifier)) {
636 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
637 "redefine_extname";
638 return;
639 }
640
Eli Friedman9595c7e2012-10-04 02:36:51 +0000641 Token RedefName = Tok;
David Chisnall5f3c1632012-02-18 16:12:34 +0000642 PP.Lex(Tok);
Eli Friedman9595c7e2012-10-04 02:36:51 +0000643
David Chisnall5f3c1632012-02-18 16:12:34 +0000644 if (Tok.isNot(tok::identifier)) {
645 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
646 << "redefine_extname";
647 return;
648 }
Eli Friedman9595c7e2012-10-04 02:36:51 +0000649
650 Token AliasName = Tok;
David Chisnall5f3c1632012-02-18 16:12:34 +0000651 PP.Lex(Tok);
652
653 if (Tok.isNot(tok::eod)) {
654 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
655 "redefine_extname";
656 return;
657 }
658
Eli Friedman9595c7e2012-10-04 02:36:51 +0000659 Token *Toks =
660 (Token*) PP.getPreprocessorAllocator().Allocate(
661 sizeof(Token) * 3, llvm::alignOf<Token>());
662 Token &pragmaRedefTok = Toks[0];
663 pragmaRedefTok.startToken();
664 pragmaRedefTok.setKind(tok::annot_pragma_redefine_extname);
665 pragmaRedefTok.setLocation(RedefLoc);
666 Toks[1] = RedefName;
667 Toks[2] = AliasName;
668 PP.EnterTokenStream(Toks, 3,
669 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
David Chisnall5f3c1632012-02-18 16:12:34 +0000670}
671
672
Peter Collingbourne321b8172011-02-14 01:42:35 +0000673void
674PragmaFPContractHandler::HandlePragma(Preprocessor &PP,
675 PragmaIntroducerKind Introducer,
676 Token &Tok) {
677 tok::OnOffSwitch OOS;
678 if (PP.LexOnOffSwitch(OOS))
679 return;
680
Eli Friedman9595c7e2012-10-04 02:36:51 +0000681 Token *Toks =
682 (Token*) PP.getPreprocessorAllocator().Allocate(
683 sizeof(Token) * 1, llvm::alignOf<Token>());
684 new (Toks) Token();
685 Toks[0].startToken();
686 Toks[0].setKind(tok::annot_pragma_fp_contract);
687 Toks[0].setLocation(Tok.getLocation());
688 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
689 static_cast<uintptr_t>(OOS)));
690 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
691 /*OwnsTokens=*/false);
Peter Collingbourne321b8172011-02-14 01:42:35 +0000692}
Peter Collingbournef315fa82011-02-14 01:42:53 +0000693
694void
695PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
696 PragmaIntroducerKind Introducer,
697 Token &Tok) {
Tanya Lattnerb38b6a72011-04-14 23:35:31 +0000698 PP.LexUnexpandedToken(Tok);
Peter Collingbournef315fa82011-02-14 01:42:53 +0000699 if (Tok.isNot(tok::identifier)) {
700 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
701 "OPENCL";
702 return;
703 }
704 IdentifierInfo *ename = Tok.getIdentifierInfo();
705 SourceLocation NameLoc = Tok.getLocation();
706
707 PP.Lex(Tok);
708 if (Tok.isNot(tok::colon)) {
709 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << ename;
710 return;
711 }
712
713 PP.Lex(Tok);
714 if (Tok.isNot(tok::identifier)) {
715 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
716 return;
717 }
718 IdentifierInfo *op = Tok.getIdentifierInfo();
719
720 unsigned state;
721 if (op->isStr("enable")) {
722 state = 1;
723 } else if (op->isStr("disable")) {
724 state = 0;
725 } else {
726 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
727 return;
728 }
729
Eli Friedman9595c7e2012-10-04 02:36:51 +0000730 PP.Lex(Tok);
731 if (Tok.isNot(tok::eod)) {
732 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
733 "OPENCL EXTENSION";
Peter Collingbournef315fa82011-02-14 01:42:53 +0000734 return;
735 }
Eli Friedman9595c7e2012-10-04 02:36:51 +0000736
737 OpenCLExtData data(ename, state);
738 Token *Toks =
739 (Token*) PP.getPreprocessorAllocator().Allocate(
740 sizeof(Token) * 1, llvm::alignOf<Token>());
741 new (Toks) Token();
742 Toks[0].startToken();
743 Toks[0].setKind(tok::annot_pragma_opencl_extension);
744 Toks[0].setLocation(NameLoc);
745 Toks[0].setAnnotationValue(data.getOpaqueValue());
746 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
747 /*OwnsTokens=*/false);
Peter Collingbournef315fa82011-02-14 01:42:53 +0000748}
749
Alexey Bataevc6400582013-03-22 06:34:35 +0000750/// \brief Handle '#pragma omp ...' when OpenMP is disabled.
751///
752void
753PragmaNoOpenMPHandler::HandlePragma(Preprocessor &PP,
754 PragmaIntroducerKind Introducer,
755 Token &FirstTok) {
756 if (PP.getDiagnostics().getDiagnosticLevel(diag::warn_pragma_omp_ignored,
757 FirstTok.getLocation()) !=
758 DiagnosticsEngine::Ignored) {
759 PP.Diag(FirstTok, diag::warn_pragma_omp_ignored);
760 PP.getDiagnostics().setDiagnosticMapping(diag::warn_pragma_omp_ignored,
761 diag::MAP_IGNORE,
762 SourceLocation());
763 }
764 PP.DiscardUntilEndOfDirective();
765}
766
767/// \brief Handle '#pragma omp ...' when OpenMP is enabled.
768///
769void
770PragmaOpenMPHandler::HandlePragma(Preprocessor &PP,
771 PragmaIntroducerKind Introducer,
772 Token &FirstTok) {
773 SmallVector<Token, 16> Pragma;
774 Token Tok;
775 Tok.startToken();
776 Tok.setKind(tok::annot_pragma_openmp);
777 Tok.setLocation(FirstTok.getLocation());
778
779 while (Tok.isNot(tok::eod)) {
780 Pragma.push_back(Tok);
781 PP.Lex(Tok);
782 }
783 SourceLocation EodLoc = Tok.getLocation();
784 Tok.startToken();
785 Tok.setKind(tok::annot_pragma_openmp_end);
786 Tok.setLocation(EodLoc);
787 Pragma.push_back(Tok);
788
789 Token *Toks = new Token[Pragma.size()];
790 std::copy(Pragma.begin(), Pragma.end(), Toks);
791 PP.EnterTokenStream(Toks, Pragma.size(),
792 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/true);
793}