blob: ef43c5b4b752eb2bf9a8c506d529bf6c4d9f5e69 [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 Langmuir8c045ac2013-05-03 19:00:33 +0000139 Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_Default,
140 /*NumParams=*/1);
Tareq A. Siraj6afcf882013-04-16 19:37:38 +0000141
142 StmtResult R = ParseCompoundStatement();
143 CapturedRegionScope.Exit();
144
145 if (R.isInvalid()) {
146 Actions.ActOnCapturedRegionError();
147 return StmtError();
148 }
149
150 return Actions.ActOnCapturedRegionEnd(R.get());
Tareq A. Siraj85192c72013-04-16 18:41:26 +0000151}
152
Eli Friedman9595c7e2012-10-04 02:36:51 +0000153namespace {
154 typedef llvm::PointerIntPair<IdentifierInfo *, 1, bool> OpenCLExtData;
155}
156
157void Parser::HandlePragmaOpenCLExtension() {
158 assert(Tok.is(tok::annot_pragma_opencl_extension));
159 OpenCLExtData data =
160 OpenCLExtData::getFromOpaqueValue(Tok.getAnnotationValue());
161 unsigned state = data.getInt();
162 IdentifierInfo *ename = data.getPointer();
163 SourceLocation NameLoc = Tok.getLocation();
164 ConsumeToken(); // The annotation token.
165
166 OpenCLOptions &f = Actions.getOpenCLOptions();
167 // OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions,
168 // overriding all previously issued extension directives, but only if the
169 // behavior is set to disable."
170 if (state == 0 && ename->isStr("all")) {
171#define OPENCLEXT(nm) f.nm = 0;
172#include "clang/Basic/OpenCLExtensions.def"
173 }
174#define OPENCLEXT(nm) else if (ename->isStr(#nm)) { f.nm = state; }
175#include "clang/Basic/OpenCLExtensions.def"
176 else {
177 PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << ename;
178 return;
179 }
180}
181
Tareq A. Siraj85192c72013-04-16 18:41:26 +0000182
183
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000184// #pragma GCC visibility comes in two variants:
185// 'push' '(' [visibility] ')'
186// 'pop'
Douglas Gregor80c60f72010-09-09 22:45:38 +0000187void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,
188 PragmaIntroducerKind Introducer,
189 Token &VisTok) {
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000190 SourceLocation VisLoc = VisTok.getLocation();
191
192 Token Tok;
Joerg Sonnenbergere23af2a2011-07-20 01:03:50 +0000193 PP.LexUnexpandedToken(Tok);
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000194
195 const IdentifierInfo *PushPop = Tok.getIdentifierInfo();
196
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000197 const IdentifierInfo *VisType;
198 if (PushPop && PushPop->isStr("pop")) {
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000199 VisType = 0;
200 } else if (PushPop && PushPop->isStr("push")) {
Joerg Sonnenbergere23af2a2011-07-20 01:03:50 +0000201 PP.LexUnexpandedToken(Tok);
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000202 if (Tok.isNot(tok::l_paren)) {
203 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
204 << "visibility";
205 return;
206 }
Joerg Sonnenbergere23af2a2011-07-20 01:03:50 +0000207 PP.LexUnexpandedToken(Tok);
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000208 VisType = Tok.getIdentifierInfo();
209 if (!VisType) {
210 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
211 << "visibility";
212 return;
213 }
Joerg Sonnenbergere23af2a2011-07-20 01:03:50 +0000214 PP.LexUnexpandedToken(Tok);
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000215 if (Tok.isNot(tok::r_paren)) {
216 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
217 << "visibility";
218 return;
219 }
220 } else {
221 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
222 << "visibility";
223 return;
224 }
Joerg Sonnenbergere23af2a2011-07-20 01:03:50 +0000225 PP.LexUnexpandedToken(Tok);
Peter Collingbourne84021552011-02-28 02:37:51 +0000226 if (Tok.isNot(tok::eod)) {
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000227 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
228 << "visibility";
229 return;
230 }
231
Rafael Espindola426fc942012-01-26 02:02:57 +0000232 Token *Toks = new Token[1];
233 Toks[0].startToken();
234 Toks[0].setKind(tok::annot_pragma_vis);
235 Toks[0].setLocation(VisLoc);
236 Toks[0].setAnnotationValue(
237 const_cast<void*>(static_cast<const void*>(VisType)));
238 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
239 /*OwnsTokens=*/true);
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000240}
241
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000242// #pragma pack(...) comes in the following delicious flavors:
243// pack '(' [integer] ')'
244// pack '(' 'show' ')'
245// pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'
Douglas Gregor80c60f72010-09-09 22:45:38 +0000246void PragmaPackHandler::HandlePragma(Preprocessor &PP,
247 PragmaIntroducerKind Introducer,
248 Token &PackTok) {
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000249 SourceLocation PackLoc = PackTok.getLocation();
250
251 Token Tok;
252 PP.Lex(Tok);
253 if (Tok.isNot(tok::l_paren)) {
Ted Kremenek4726d032009-03-23 22:28:25 +0000254 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack";
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000255 return;
256 }
257
John McCallf312b1e2010-08-26 23:41:50 +0000258 Sema::PragmaPackKind Kind = Sema::PPK_Default;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000259 IdentifierInfo *Name = 0;
Eli Friedman9595c7e2012-10-04 02:36:51 +0000260 Token Alignment;
261 Alignment.startToken();
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000262 SourceLocation LParenLoc = Tok.getLocation();
Mike Stump1eb44332009-09-09 15:08:12 +0000263 PP.Lex(Tok);
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000264 if (Tok.is(tok::numeric_constant)) {
Eli Friedman9595c7e2012-10-04 02:36:51 +0000265 Alignment = Tok;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000266
267 PP.Lex(Tok);
Eli Friedman19bda3a2011-11-02 01:53:16 +0000268
269 // In MSVC/gcc, #pragma pack(4) sets the alignment without affecting
270 // the push/pop stack.
271 // In Apple gcc, #pragma pack(4) is equivalent to #pragma pack(push, 4)
David Blaikie4e4d0842012-03-11 07:00:24 +0000272 if (PP.getLangOpts().ApplePragmaPack)
Eli Friedman19bda3a2011-11-02 01:53:16 +0000273 Kind = Sema::PPK_Push;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000274 } else if (Tok.is(tok::identifier)) {
275 const IdentifierInfo *II = Tok.getIdentifierInfo();
Chris Lattner08631c52008-11-23 21:45:46 +0000276 if (II->isStr("show")) {
John McCallf312b1e2010-08-26 23:41:50 +0000277 Kind = Sema::PPK_Show;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000278 PP.Lex(Tok);
279 } else {
Chris Lattner08631c52008-11-23 21:45:46 +0000280 if (II->isStr("push")) {
John McCallf312b1e2010-08-26 23:41:50 +0000281 Kind = Sema::PPK_Push;
Chris Lattner08631c52008-11-23 21:45:46 +0000282 } else if (II->isStr("pop")) {
John McCallf312b1e2010-08-26 23:41:50 +0000283 Kind = Sema::PPK_Pop;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000284 } else {
285 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_invalid_action);
286 return;
Mike Stump1eb44332009-09-09 15:08:12 +0000287 }
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000288 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000289
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000290 if (Tok.is(tok::comma)) {
291 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000292
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000293 if (Tok.is(tok::numeric_constant)) {
Eli Friedman9595c7e2012-10-04 02:36:51 +0000294 Alignment = Tok;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000295
296 PP.Lex(Tok);
297 } else if (Tok.is(tok::identifier)) {
298 Name = Tok.getIdentifierInfo();
299 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000300
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000301 if (Tok.is(tok::comma)) {
302 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000303
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000304 if (Tok.isNot(tok::numeric_constant)) {
Chris Lattner08631c52008-11-23 21:45:46 +0000305 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000306 return;
307 }
Mike Stump1eb44332009-09-09 15:08:12 +0000308
Eli Friedman9595c7e2012-10-04 02:36:51 +0000309 Alignment = Tok;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000310
311 PP.Lex(Tok);
312 }
313 } else {
Chris Lattner08631c52008-11-23 21:45:46 +0000314 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000315 return;
316 }
317 }
318 }
David Blaikie4e4d0842012-03-11 07:00:24 +0000319 } else if (PP.getLangOpts().ApplePragmaPack) {
Eli Friedman19bda3a2011-11-02 01:53:16 +0000320 // In MSVC/gcc, #pragma pack() resets the alignment without affecting
321 // the push/pop stack.
322 // In Apple gcc #pragma pack() is equivalent to #pragma pack(pop).
323 Kind = Sema::PPK_Pop;
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000324 }
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000325
326 if (Tok.isNot(tok::r_paren)) {
Ted Kremenek4726d032009-03-23 22:28:25 +0000327 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack";
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000328 return;
329 }
330
Daniel Dunbar861800c2010-05-26 23:29:06 +0000331 SourceLocation RParenLoc = Tok.getLocation();
Eli Friedman99914792009-06-05 00:49:58 +0000332 PP.Lex(Tok);
Peter Collingbourne84021552011-02-28 02:37:51 +0000333 if (Tok.isNot(tok::eod)) {
Eli Friedman99914792009-06-05 00:49:58 +0000334 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack";
335 return;
336 }
337
Daniel Dunbarb0939552012-02-29 01:38:22 +0000338 PragmaPackInfo *Info =
339 (PragmaPackInfo*) PP.getPreprocessorAllocator().Allocate(
340 sizeof(PragmaPackInfo), llvm::alignOf<PragmaPackInfo>());
341 new (Info) PragmaPackInfo();
Eli Friedmanaa5ab262012-02-23 23:47:16 +0000342 Info->Kind = Kind;
343 Info->Name = Name;
Eli Friedman9595c7e2012-10-04 02:36:51 +0000344 Info->Alignment = Alignment;
Eli Friedmanaa5ab262012-02-23 23:47:16 +0000345 Info->LParenLoc = LParenLoc;
346 Info->RParenLoc = RParenLoc;
347
Daniel Dunbarb0939552012-02-29 01:38:22 +0000348 Token *Toks =
349 (Token*) PP.getPreprocessorAllocator().Allocate(
350 sizeof(Token) * 1, llvm::alignOf<Token>());
351 new (Toks) Token();
Eli Friedmanaa5ab262012-02-23 23:47:16 +0000352 Toks[0].startToken();
353 Toks[0].setKind(tok::annot_pragma_pack);
354 Toks[0].setLocation(PackLoc);
355 Toks[0].setAnnotationValue(static_cast<void*>(Info));
356 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
Daniel Dunbarb0939552012-02-29 01:38:22 +0000357 /*OwnsTokens=*/false);
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000358}
359
Fariborz Jahanian62c92582011-04-25 18:49:15 +0000360// #pragma ms_struct on
361// #pragma ms_struct off
362void PragmaMSStructHandler::HandlePragma(Preprocessor &PP,
363 PragmaIntroducerKind Introducer,
364 Token &MSStructTok) {
365 Sema::PragmaMSStructKind Kind = Sema::PMSST_OFF;
366
367 Token Tok;
368 PP.Lex(Tok);
369 if (Tok.isNot(tok::identifier)) {
370 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
371 return;
372 }
373 const IdentifierInfo *II = Tok.getIdentifierInfo();
374 if (II->isStr("on")) {
375 Kind = Sema::PMSST_ON;
376 PP.Lex(Tok);
377 }
378 else if (II->isStr("off") || II->isStr("reset"))
379 PP.Lex(Tok);
380 else {
381 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
382 return;
383 }
384
385 if (Tok.isNot(tok::eod)) {
Daniel Dunbarb0939552012-02-29 01:38:22 +0000386 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
387 << "ms_struct";
Fariborz Jahanian62c92582011-04-25 18:49:15 +0000388 return;
389 }
Eli Friedman9595c7e2012-10-04 02:36:51 +0000390
391 Token *Toks =
392 (Token*) PP.getPreprocessorAllocator().Allocate(
393 sizeof(Token) * 1, llvm::alignOf<Token>());
394 new (Toks) Token();
395 Toks[0].startToken();
396 Toks[0].setKind(tok::annot_pragma_msstruct);
397 Toks[0].setLocation(MSStructTok.getLocation());
398 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
399 static_cast<uintptr_t>(Kind)));
400 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
401 /*OwnsTokens=*/false);
Fariborz Jahanian62c92582011-04-25 18:49:15 +0000402}
403
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000404// #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
405// #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
Eli Friedman9595c7e2012-10-04 02:36:51 +0000406static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok,
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000407 bool IsOptions) {
Daniel Dunbar861800c2010-05-26 23:29:06 +0000408 Token Tok;
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000409
410 if (IsOptions) {
411 PP.Lex(Tok);
412 if (Tok.isNot(tok::identifier) ||
413 !Tok.getIdentifierInfo()->isStr("align")) {
414 PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align);
415 return;
416 }
Daniel Dunbar861800c2010-05-26 23:29:06 +0000417 }
Daniel Dunbar638e7cf2010-05-27 18:42:09 +0000418
Daniel Dunbar861800c2010-05-26 23:29:06 +0000419 PP.Lex(Tok);
420 if (Tok.isNot(tok::equal)) {
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000421 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal)
422 << IsOptions;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000423 return;
424 }
425
426 PP.Lex(Tok);
427 if (Tok.isNot(tok::identifier)) {
428 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000429 << (IsOptions ? "options" : "align");
Daniel Dunbar861800c2010-05-26 23:29:06 +0000430 return;
431 }
432
John McCallf312b1e2010-08-26 23:41:50 +0000433 Sema::PragmaOptionsAlignKind Kind = Sema::POAK_Natural;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000434 const IdentifierInfo *II = Tok.getIdentifierInfo();
Daniel Dunbar638e7cf2010-05-27 18:42:09 +0000435 if (II->isStr("native"))
John McCallf312b1e2010-08-26 23:41:50 +0000436 Kind = Sema::POAK_Native;
Daniel Dunbar638e7cf2010-05-27 18:42:09 +0000437 else if (II->isStr("natural"))
John McCallf312b1e2010-08-26 23:41:50 +0000438 Kind = Sema::POAK_Natural;
Daniel Dunbar6f739142010-05-27 18:42:17 +0000439 else if (II->isStr("packed"))
John McCallf312b1e2010-08-26 23:41:50 +0000440 Kind = Sema::POAK_Packed;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000441 else if (II->isStr("power"))
John McCallf312b1e2010-08-26 23:41:50 +0000442 Kind = Sema::POAK_Power;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000443 else if (II->isStr("mac68k"))
John McCallf312b1e2010-08-26 23:41:50 +0000444 Kind = Sema::POAK_Mac68k;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000445 else if (II->isStr("reset"))
John McCallf312b1e2010-08-26 23:41:50 +0000446 Kind = Sema::POAK_Reset;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000447 else {
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000448 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option)
449 << IsOptions;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000450 return;
451 }
452
Daniel Dunbar861800c2010-05-26 23:29:06 +0000453 PP.Lex(Tok);
Peter Collingbourne84021552011-02-28 02:37:51 +0000454 if (Tok.isNot(tok::eod)) {
Daniel Dunbar861800c2010-05-26 23:29:06 +0000455 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000456 << (IsOptions ? "options" : "align");
Daniel Dunbar861800c2010-05-26 23:29:06 +0000457 return;
458 }
459
Eli Friedman9595c7e2012-10-04 02:36:51 +0000460 Token *Toks =
461 (Token*) PP.getPreprocessorAllocator().Allocate(
462 sizeof(Token) * 1, llvm::alignOf<Token>());
463 new (Toks) Token();
464 Toks[0].startToken();
465 Toks[0].setKind(tok::annot_pragma_align);
466 Toks[0].setLocation(FirstTok.getLocation());
467 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
468 static_cast<uintptr_t>(Kind)));
469 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
470 /*OwnsTokens=*/false);
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000471}
472
Douglas Gregor80c60f72010-09-09 22:45:38 +0000473void PragmaAlignHandler::HandlePragma(Preprocessor &PP,
474 PragmaIntroducerKind Introducer,
475 Token &AlignTok) {
Eli Friedman9595c7e2012-10-04 02:36:51 +0000476 ParseAlignPragma(PP, AlignTok, /*IsOptions=*/false);
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000477}
478
Douglas Gregor80c60f72010-09-09 22:45:38 +0000479void PragmaOptionsHandler::HandlePragma(Preprocessor &PP,
480 PragmaIntroducerKind Introducer,
481 Token &OptionsTok) {
Eli Friedman9595c7e2012-10-04 02:36:51 +0000482 ParseAlignPragma(PP, OptionsTok, /*IsOptions=*/true);
Daniel Dunbar861800c2010-05-26 23:29:06 +0000483}
484
Ted Kremenek4726d032009-03-23 22:28:25 +0000485// #pragma unused(identifier)
Douglas Gregor80c60f72010-09-09 22:45:38 +0000486void PragmaUnusedHandler::HandlePragma(Preprocessor &PP,
487 PragmaIntroducerKind Introducer,
488 Token &UnusedTok) {
Ted Kremenek4726d032009-03-23 22:28:25 +0000489 // FIXME: Should we be expanding macros here? My guess is no.
490 SourceLocation UnusedLoc = UnusedTok.getLocation();
Mike Stump1eb44332009-09-09 15:08:12 +0000491
Ted Kremenek4726d032009-03-23 22:28:25 +0000492 // Lex the left '('.
493 Token Tok;
494 PP.Lex(Tok);
495 if (Tok.isNot(tok::l_paren)) {
496 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
497 return;
498 }
Mike Stump1eb44332009-09-09 15:08:12 +0000499
Ted Kremenek4726d032009-03-23 22:28:25 +0000500 // Lex the declaration reference(s).
Chris Lattner5f9e2722011-07-23 10:55:15 +0000501 SmallVector<Token, 5> Identifiers;
Ted Kremenek4726d032009-03-23 22:28:25 +0000502 SourceLocation RParenLoc;
503 bool LexID = true;
Mike Stump1eb44332009-09-09 15:08:12 +0000504
Ted Kremenek4726d032009-03-23 22:28:25 +0000505 while (true) {
506 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000507
Ted Kremenek4726d032009-03-23 22:28:25 +0000508 if (LexID) {
Mike Stump1eb44332009-09-09 15:08:12 +0000509 if (Tok.is(tok::identifier)) {
Ted Kremenek7a02a372009-08-03 23:24:57 +0000510 Identifiers.push_back(Tok);
Ted Kremenek4726d032009-03-23 22:28:25 +0000511 LexID = false;
512 continue;
513 }
514
Ted Kremenek7a02a372009-08-03 23:24:57 +0000515 // Illegal token!
Ted Kremenek4726d032009-03-23 22:28:25 +0000516 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
517 return;
518 }
Mike Stump1eb44332009-09-09 15:08:12 +0000519
Ted Kremenek4726d032009-03-23 22:28:25 +0000520 // We are execting a ')' or a ','.
521 if (Tok.is(tok::comma)) {
522 LexID = true;
523 continue;
524 }
Mike Stump1eb44332009-09-09 15:08:12 +0000525
Ted Kremenek4726d032009-03-23 22:28:25 +0000526 if (Tok.is(tok::r_paren)) {
527 RParenLoc = Tok.getLocation();
528 break;
529 }
Mike Stump1eb44332009-09-09 15:08:12 +0000530
Ted Kremenek7a02a372009-08-03 23:24:57 +0000531 // Illegal token!
Ted Kremenek4726d032009-03-23 22:28:25 +0000532 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_punc);
533 return;
534 }
Eli Friedman99914792009-06-05 00:49:58 +0000535
536 PP.Lex(Tok);
Peter Collingbourne84021552011-02-28 02:37:51 +0000537 if (Tok.isNot(tok::eod)) {
Eli Friedman99914792009-06-05 00:49:58 +0000538 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
539 "unused";
540 return;
541 }
542
Ted Kremenek4726d032009-03-23 22:28:25 +0000543 // Verify that we have a location for the right parenthesis.
544 assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
Ted Kremenek7a02a372009-08-03 23:24:57 +0000545 assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
Ted Kremenek4726d032009-03-23 22:28:25 +0000546
Argyrios Kyrtzidisb918d0f2011-01-17 18:58:44 +0000547 // For each identifier token, insert into the token stream a
548 // annot_pragma_unused token followed by the identifier token.
549 // This allows us to cache a "#pragma unused" that occurs inside an inline
550 // C++ member function.
551
Daniel Dunbarb0939552012-02-29 01:38:22 +0000552 Token *Toks =
553 (Token*) PP.getPreprocessorAllocator().Allocate(
554 sizeof(Token) * 2 * Identifiers.size(), llvm::alignOf<Token>());
Argyrios Kyrtzidisb918d0f2011-01-17 18:58:44 +0000555 for (unsigned i=0; i != Identifiers.size(); i++) {
556 Token &pragmaUnusedTok = Toks[2*i], &idTok = Toks[2*i+1];
557 pragmaUnusedTok.startToken();
558 pragmaUnusedTok.setKind(tok::annot_pragma_unused);
559 pragmaUnusedTok.setLocation(UnusedLoc);
560 idTok = Identifiers[i];
561 }
Daniel Dunbarb0939552012-02-29 01:38:22 +0000562 PP.EnterTokenStream(Toks, 2*Identifiers.size(),
563 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
Ted Kremenek4726d032009-03-23 22:28:25 +0000564}
Eli Friedman99914792009-06-05 00:49:58 +0000565
566// #pragma weak identifier
567// #pragma weak identifier '=' identifier
Douglas Gregor80c60f72010-09-09 22:45:38 +0000568void PragmaWeakHandler::HandlePragma(Preprocessor &PP,
569 PragmaIntroducerKind Introducer,
570 Token &WeakTok) {
Eli Friedman99914792009-06-05 00:49:58 +0000571 SourceLocation WeakLoc = WeakTok.getLocation();
572
573 Token Tok;
574 PP.Lex(Tok);
575 if (Tok.isNot(tok::identifier)) {
576 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";
577 return;
578 }
579
Eli Friedman9595c7e2012-10-04 02:36:51 +0000580 Token WeakName = Tok;
581 bool HasAlias = false;
582 Token AliasName;
Eli Friedman99914792009-06-05 00:49:58 +0000583
584 PP.Lex(Tok);
585 if (Tok.is(tok::equal)) {
Eli Friedman9595c7e2012-10-04 02:36:51 +0000586 HasAlias = true;
Eli Friedman99914792009-06-05 00:49:58 +0000587 PP.Lex(Tok);
588 if (Tok.isNot(tok::identifier)) {
Mike Stump1eb44332009-09-09 15:08:12 +0000589 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Eli Friedman99914792009-06-05 00:49:58 +0000590 << "weak";
591 return;
592 }
Eli Friedman9595c7e2012-10-04 02:36:51 +0000593 AliasName = Tok;
Eli Friedman99914792009-06-05 00:49:58 +0000594 PP.Lex(Tok);
595 }
596
Peter Collingbourne84021552011-02-28 02:37:51 +0000597 if (Tok.isNot(tok::eod)) {
Eli Friedman99914792009-06-05 00:49:58 +0000598 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";
599 return;
600 }
601
Eli Friedman9595c7e2012-10-04 02:36:51 +0000602 if (HasAlias) {
603 Token *Toks =
604 (Token*) PP.getPreprocessorAllocator().Allocate(
605 sizeof(Token) * 3, llvm::alignOf<Token>());
606 Token &pragmaUnusedTok = Toks[0];
607 pragmaUnusedTok.startToken();
608 pragmaUnusedTok.setKind(tok::annot_pragma_weakalias);
609 pragmaUnusedTok.setLocation(WeakLoc);
610 Toks[1] = WeakName;
611 Toks[2] = AliasName;
612 PP.EnterTokenStream(Toks, 3,
613 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
Eli Friedman99914792009-06-05 00:49:58 +0000614 } else {
Eli Friedman9595c7e2012-10-04 02:36:51 +0000615 Token *Toks =
616 (Token*) PP.getPreprocessorAllocator().Allocate(
617 sizeof(Token) * 2, llvm::alignOf<Token>());
618 Token &pragmaUnusedTok = Toks[0];
619 pragmaUnusedTok.startToken();
620 pragmaUnusedTok.setKind(tok::annot_pragma_weak);
621 pragmaUnusedTok.setLocation(WeakLoc);
622 Toks[1] = WeakName;
623 PP.EnterTokenStream(Toks, 2,
624 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
Eli Friedman99914792009-06-05 00:49:58 +0000625 }
626}
Peter Collingbourne321b8172011-02-14 01:42:35 +0000627
David Chisnall5f3c1632012-02-18 16:12:34 +0000628// #pragma redefine_extname identifier identifier
629void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP,
630 PragmaIntroducerKind Introducer,
631 Token &RedefToken) {
632 SourceLocation RedefLoc = RedefToken.getLocation();
633
634 Token Tok;
635 PP.Lex(Tok);
636 if (Tok.isNot(tok::identifier)) {
637 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
638 "redefine_extname";
639 return;
640 }
641
Eli Friedman9595c7e2012-10-04 02:36:51 +0000642 Token RedefName = Tok;
David Chisnall5f3c1632012-02-18 16:12:34 +0000643 PP.Lex(Tok);
Eli Friedman9595c7e2012-10-04 02:36:51 +0000644
David Chisnall5f3c1632012-02-18 16:12:34 +0000645 if (Tok.isNot(tok::identifier)) {
646 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
647 << "redefine_extname";
648 return;
649 }
Eli Friedman9595c7e2012-10-04 02:36:51 +0000650
651 Token AliasName = Tok;
David Chisnall5f3c1632012-02-18 16:12:34 +0000652 PP.Lex(Tok);
653
654 if (Tok.isNot(tok::eod)) {
655 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
656 "redefine_extname";
657 return;
658 }
659
Eli Friedman9595c7e2012-10-04 02:36:51 +0000660 Token *Toks =
661 (Token*) PP.getPreprocessorAllocator().Allocate(
662 sizeof(Token) * 3, llvm::alignOf<Token>());
663 Token &pragmaRedefTok = Toks[0];
664 pragmaRedefTok.startToken();
665 pragmaRedefTok.setKind(tok::annot_pragma_redefine_extname);
666 pragmaRedefTok.setLocation(RedefLoc);
667 Toks[1] = RedefName;
668 Toks[2] = AliasName;
669 PP.EnterTokenStream(Toks, 3,
670 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
David Chisnall5f3c1632012-02-18 16:12:34 +0000671}
672
673
Peter Collingbourne321b8172011-02-14 01:42:35 +0000674void
675PragmaFPContractHandler::HandlePragma(Preprocessor &PP,
676 PragmaIntroducerKind Introducer,
677 Token &Tok) {
678 tok::OnOffSwitch OOS;
679 if (PP.LexOnOffSwitch(OOS))
680 return;
681
Eli Friedman9595c7e2012-10-04 02:36:51 +0000682 Token *Toks =
683 (Token*) PP.getPreprocessorAllocator().Allocate(
684 sizeof(Token) * 1, llvm::alignOf<Token>());
685 new (Toks) Token();
686 Toks[0].startToken();
687 Toks[0].setKind(tok::annot_pragma_fp_contract);
688 Toks[0].setLocation(Tok.getLocation());
689 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
690 static_cast<uintptr_t>(OOS)));
691 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
692 /*OwnsTokens=*/false);
Peter Collingbourne321b8172011-02-14 01:42:35 +0000693}
Peter Collingbournef315fa82011-02-14 01:42:53 +0000694
695void
696PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
697 PragmaIntroducerKind Introducer,
698 Token &Tok) {
Tanya Lattnerb38b6a72011-04-14 23:35:31 +0000699 PP.LexUnexpandedToken(Tok);
Peter Collingbournef315fa82011-02-14 01:42:53 +0000700 if (Tok.isNot(tok::identifier)) {
701 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
702 "OPENCL";
703 return;
704 }
705 IdentifierInfo *ename = Tok.getIdentifierInfo();
706 SourceLocation NameLoc = Tok.getLocation();
707
708 PP.Lex(Tok);
709 if (Tok.isNot(tok::colon)) {
710 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << ename;
711 return;
712 }
713
714 PP.Lex(Tok);
715 if (Tok.isNot(tok::identifier)) {
716 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
717 return;
718 }
719 IdentifierInfo *op = Tok.getIdentifierInfo();
720
721 unsigned state;
722 if (op->isStr("enable")) {
723 state = 1;
724 } else if (op->isStr("disable")) {
725 state = 0;
726 } else {
727 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
728 return;
729 }
730
Eli Friedman9595c7e2012-10-04 02:36:51 +0000731 PP.Lex(Tok);
732 if (Tok.isNot(tok::eod)) {
733 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
734 "OPENCL EXTENSION";
Peter Collingbournef315fa82011-02-14 01:42:53 +0000735 return;
736 }
Eli Friedman9595c7e2012-10-04 02:36:51 +0000737
738 OpenCLExtData data(ename, state);
739 Token *Toks =
740 (Token*) PP.getPreprocessorAllocator().Allocate(
741 sizeof(Token) * 1, llvm::alignOf<Token>());
742 new (Toks) Token();
743 Toks[0].startToken();
744 Toks[0].setKind(tok::annot_pragma_opencl_extension);
745 Toks[0].setLocation(NameLoc);
746 Toks[0].setAnnotationValue(data.getOpaqueValue());
747 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
748 /*OwnsTokens=*/false);
Peter Collingbournef315fa82011-02-14 01:42:53 +0000749}
750
Alexey Bataevc6400582013-03-22 06:34:35 +0000751/// \brief Handle '#pragma omp ...' when OpenMP is disabled.
752///
753void
754PragmaNoOpenMPHandler::HandlePragma(Preprocessor &PP,
755 PragmaIntroducerKind Introducer,
756 Token &FirstTok) {
757 if (PP.getDiagnostics().getDiagnosticLevel(diag::warn_pragma_omp_ignored,
758 FirstTok.getLocation()) !=
759 DiagnosticsEngine::Ignored) {
760 PP.Diag(FirstTok, diag::warn_pragma_omp_ignored);
761 PP.getDiagnostics().setDiagnosticMapping(diag::warn_pragma_omp_ignored,
762 diag::MAP_IGNORE,
763 SourceLocation());
764 }
765 PP.DiscardUntilEndOfDirective();
766}
767
768/// \brief Handle '#pragma omp ...' when OpenMP is enabled.
769///
770void
771PragmaOpenMPHandler::HandlePragma(Preprocessor &PP,
772 PragmaIntroducerKind Introducer,
773 Token &FirstTok) {
774 SmallVector<Token, 16> Pragma;
775 Token Tok;
776 Tok.startToken();
777 Tok.setKind(tok::annot_pragma_openmp);
778 Tok.setLocation(FirstTok.getLocation());
779
780 while (Tok.isNot(tok::eod)) {
781 Pragma.push_back(Tok);
782 PP.Lex(Tok);
783 }
784 SourceLocation EodLoc = Tok.getLocation();
785 Tok.startToken();
786 Tok.setKind(tok::annot_pragma_openmp_end);
787 Tok.setLocation(EodLoc);
788 Pragma.push_back(Tok);
789
790 Token *Toks = new Token[Pragma.size()];
791 std::copy(Pragma.begin(), Pragma.end(), Toks);
792 PP.EnterTokenStream(Toks, Pragma.size(),
793 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/true);
794}