blob: 10ad5df629e0389ea646ebe4ac27fdf18c8a82cf [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"
Reid Kleckner7adf79a2013-05-06 21:02:12 +000019#include "llvm/ADT/StringSwitch.h"
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000020using namespace clang;
21
Argyrios Kyrtzidisb918d0f2011-01-17 18:58:44 +000022/// \brief Handle the annotation token produced for #pragma unused(...)
23///
24/// Each annot_pragma_unused is followed by the argument token so e.g.
25/// "#pragma unused(x,y)" becomes:
26/// annot_pragma_unused 'x' annot_pragma_unused 'y'
27void Parser::HandlePragmaUnused() {
28 assert(Tok.is(tok::annot_pragma_unused));
29 SourceLocation UnusedLoc = ConsumeToken();
30 Actions.ActOnPragmaUnused(Tok, getCurScope(), UnusedLoc);
31 ConsumeToken(); // The argument token.
32}
Eli Friedmanaa8b0d12010-08-05 06:57:20 +000033
Rafael Espindola426fc942012-01-26 02:02:57 +000034void Parser::HandlePragmaVisibility() {
35 assert(Tok.is(tok::annot_pragma_vis));
36 const IdentifierInfo *VisType =
37 static_cast<IdentifierInfo *>(Tok.getAnnotationValue());
38 SourceLocation VisLoc = ConsumeToken();
39 Actions.ActOnPragmaVisibility(VisType, VisLoc);
40}
41
Eli Friedmanaa5ab262012-02-23 23:47:16 +000042struct PragmaPackInfo {
43 Sema::PragmaPackKind Kind;
44 IdentifierInfo *Name;
Eli Friedman9595c7e2012-10-04 02:36:51 +000045 Token Alignment;
Eli Friedmanaa5ab262012-02-23 23:47:16 +000046 SourceLocation LParenLoc;
47 SourceLocation RParenLoc;
48};
49
50void Parser::HandlePragmaPack() {
51 assert(Tok.is(tok::annot_pragma_pack));
52 PragmaPackInfo *Info =
53 static_cast<PragmaPackInfo *>(Tok.getAnnotationValue());
54 SourceLocation PragmaLoc = ConsumeToken();
Eli Friedman9595c7e2012-10-04 02:36:51 +000055 ExprResult Alignment;
56 if (Info->Alignment.is(tok::numeric_constant)) {
57 Alignment = Actions.ActOnNumericConstant(Info->Alignment);
58 if (Alignment.isInvalid())
59 return;
60 }
61 Actions.ActOnPragmaPack(Info->Kind, Info->Name, Alignment.get(), PragmaLoc,
Eli Friedmanaa5ab262012-02-23 23:47:16 +000062 Info->LParenLoc, Info->RParenLoc);
Eli Friedmanaa5ab262012-02-23 23:47:16 +000063}
64
Eli Friedman9595c7e2012-10-04 02:36:51 +000065void Parser::HandlePragmaMSStruct() {
66 assert(Tok.is(tok::annot_pragma_msstruct));
67 Sema::PragmaMSStructKind Kind =
68 static_cast<Sema::PragmaMSStructKind>(
69 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
70 Actions.ActOnPragmaMSStruct(Kind);
71 ConsumeToken(); // The annotation token.
72}
73
74void Parser::HandlePragmaAlign() {
75 assert(Tok.is(tok::annot_pragma_align));
76 Sema::PragmaOptionsAlignKind Kind =
77 static_cast<Sema::PragmaOptionsAlignKind>(
78 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
79 SourceLocation PragmaLoc = ConsumeToken();
80 Actions.ActOnPragmaOptionsAlign(Kind, PragmaLoc);
81}
82
83void Parser::HandlePragmaWeak() {
84 assert(Tok.is(tok::annot_pragma_weak));
85 SourceLocation PragmaLoc = ConsumeToken();
86 Actions.ActOnPragmaWeakID(Tok.getIdentifierInfo(), PragmaLoc,
87 Tok.getLocation());
88 ConsumeToken(); // The weak name.
89}
90
91void Parser::HandlePragmaWeakAlias() {
92 assert(Tok.is(tok::annot_pragma_weakalias));
93 SourceLocation PragmaLoc = ConsumeToken();
94 IdentifierInfo *WeakName = Tok.getIdentifierInfo();
95 SourceLocation WeakNameLoc = Tok.getLocation();
96 ConsumeToken();
97 IdentifierInfo *AliasName = Tok.getIdentifierInfo();
98 SourceLocation AliasNameLoc = Tok.getLocation();
99 ConsumeToken();
100 Actions.ActOnPragmaWeakAlias(WeakName, AliasName, PragmaLoc,
101 WeakNameLoc, AliasNameLoc);
102
103}
104
105void Parser::HandlePragmaRedefineExtname() {
106 assert(Tok.is(tok::annot_pragma_redefine_extname));
107 SourceLocation RedefLoc = ConsumeToken();
108 IdentifierInfo *RedefName = Tok.getIdentifierInfo();
109 SourceLocation RedefNameLoc = Tok.getLocation();
110 ConsumeToken();
111 IdentifierInfo *AliasName = Tok.getIdentifierInfo();
112 SourceLocation AliasNameLoc = Tok.getLocation();
113 ConsumeToken();
114 Actions.ActOnPragmaRedefineExtname(RedefName, AliasName, RedefLoc,
115 RedefNameLoc, AliasNameLoc);
116}
117
118void Parser::HandlePragmaFPContract() {
119 assert(Tok.is(tok::annot_pragma_fp_contract));
120 tok::OnOffSwitch OOS =
121 static_cast<tok::OnOffSwitch>(
122 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
123 Actions.ActOnPragmaFPContract(OOS);
124 ConsumeToken(); // The annotation token.
125}
126
Tareq A. Siraj85192c72013-04-16 18:41:26 +0000127StmtResult Parser::HandlePragmaCaptured()
128{
129 assert(Tok.is(tok::annot_pragma_captured));
130 ConsumeToken();
131
132 if (Tok.isNot(tok::l_brace)) {
133 PP.Diag(Tok, diag::err_expected_lbrace);
134 return StmtError();
135 }
136
Tareq A. Siraj6afcf882013-04-16 19:37:38 +0000137 SourceLocation Loc = Tok.getLocation();
138
139 ParseScope CapturedRegionScope(this, Scope::FnScope | Scope::DeclScope);
Ben Langmuir8c045ac2013-05-03 19:00:33 +0000140 Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_Default,
141 /*NumParams=*/1);
Tareq A. Siraj6afcf882013-04-16 19:37:38 +0000142
143 StmtResult R = ParseCompoundStatement();
144 CapturedRegionScope.Exit();
145
146 if (R.isInvalid()) {
147 Actions.ActOnCapturedRegionError();
148 return StmtError();
149 }
150
151 return Actions.ActOnCapturedRegionEnd(R.get());
Tareq A. Siraj85192c72013-04-16 18:41:26 +0000152}
153
Eli Friedman9595c7e2012-10-04 02:36:51 +0000154namespace {
155 typedef llvm::PointerIntPair<IdentifierInfo *, 1, bool> OpenCLExtData;
156}
157
158void Parser::HandlePragmaOpenCLExtension() {
159 assert(Tok.is(tok::annot_pragma_opencl_extension));
160 OpenCLExtData data =
161 OpenCLExtData::getFromOpaqueValue(Tok.getAnnotationValue());
162 unsigned state = data.getInt();
163 IdentifierInfo *ename = data.getPointer();
164 SourceLocation NameLoc = Tok.getLocation();
165 ConsumeToken(); // The annotation token.
166
167 OpenCLOptions &f = Actions.getOpenCLOptions();
168 // OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions,
169 // overriding all previously issued extension directives, but only if the
170 // behavior is set to disable."
171 if (state == 0 && ename->isStr("all")) {
172#define OPENCLEXT(nm) f.nm = 0;
173#include "clang/Basic/OpenCLExtensions.def"
174 }
175#define OPENCLEXT(nm) else if (ename->isStr(#nm)) { f.nm = state; }
176#include "clang/Basic/OpenCLExtensions.def"
177 else {
178 PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << ename;
179 return;
180 }
181}
182
Tareq A. Siraj85192c72013-04-16 18:41:26 +0000183
184
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000185// #pragma GCC visibility comes in two variants:
186// 'push' '(' [visibility] ')'
187// 'pop'
Douglas Gregor80c60f72010-09-09 22:45:38 +0000188void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,
189 PragmaIntroducerKind Introducer,
190 Token &VisTok) {
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000191 SourceLocation VisLoc = VisTok.getLocation();
192
193 Token Tok;
Joerg Sonnenbergere23af2a2011-07-20 01:03:50 +0000194 PP.LexUnexpandedToken(Tok);
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000195
196 const IdentifierInfo *PushPop = Tok.getIdentifierInfo();
197
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000198 const IdentifierInfo *VisType;
199 if (PushPop && PushPop->isStr("pop")) {
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000200 VisType = 0;
201 } else if (PushPop && PushPop->isStr("push")) {
Joerg Sonnenbergere23af2a2011-07-20 01:03:50 +0000202 PP.LexUnexpandedToken(Tok);
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000203 if (Tok.isNot(tok::l_paren)) {
204 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
205 << "visibility";
206 return;
207 }
Joerg Sonnenbergere23af2a2011-07-20 01:03:50 +0000208 PP.LexUnexpandedToken(Tok);
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000209 VisType = Tok.getIdentifierInfo();
210 if (!VisType) {
211 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
212 << "visibility";
213 return;
214 }
Joerg Sonnenbergere23af2a2011-07-20 01:03:50 +0000215 PP.LexUnexpandedToken(Tok);
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000216 if (Tok.isNot(tok::r_paren)) {
217 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
218 << "visibility";
219 return;
220 }
221 } else {
222 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
223 << "visibility";
224 return;
225 }
Joerg Sonnenbergere23af2a2011-07-20 01:03:50 +0000226 PP.LexUnexpandedToken(Tok);
Peter Collingbourne84021552011-02-28 02:37:51 +0000227 if (Tok.isNot(tok::eod)) {
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000228 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
229 << "visibility";
230 return;
231 }
232
Rafael Espindola426fc942012-01-26 02:02:57 +0000233 Token *Toks = new Token[1];
234 Toks[0].startToken();
235 Toks[0].setKind(tok::annot_pragma_vis);
236 Toks[0].setLocation(VisLoc);
237 Toks[0].setAnnotationValue(
238 const_cast<void*>(static_cast<const void*>(VisType)));
239 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
240 /*OwnsTokens=*/true);
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000241}
242
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000243// #pragma pack(...) comes in the following delicious flavors:
244// pack '(' [integer] ')'
245// pack '(' 'show' ')'
246// pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'
Douglas Gregor80c60f72010-09-09 22:45:38 +0000247void PragmaPackHandler::HandlePragma(Preprocessor &PP,
248 PragmaIntroducerKind Introducer,
249 Token &PackTok) {
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000250 SourceLocation PackLoc = PackTok.getLocation();
251
252 Token Tok;
253 PP.Lex(Tok);
254 if (Tok.isNot(tok::l_paren)) {
Ted Kremenek4726d032009-03-23 22:28:25 +0000255 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack";
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000256 return;
257 }
258
John McCallf312b1e2010-08-26 23:41:50 +0000259 Sema::PragmaPackKind Kind = Sema::PPK_Default;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000260 IdentifierInfo *Name = 0;
Eli Friedman9595c7e2012-10-04 02:36:51 +0000261 Token Alignment;
262 Alignment.startToken();
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000263 SourceLocation LParenLoc = Tok.getLocation();
Mike Stump1eb44332009-09-09 15:08:12 +0000264 PP.Lex(Tok);
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000265 if (Tok.is(tok::numeric_constant)) {
Eli Friedman9595c7e2012-10-04 02:36:51 +0000266 Alignment = Tok;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000267
268 PP.Lex(Tok);
Eli Friedman19bda3a2011-11-02 01:53:16 +0000269
270 // In MSVC/gcc, #pragma pack(4) sets the alignment without affecting
271 // the push/pop stack.
272 // In Apple gcc, #pragma pack(4) is equivalent to #pragma pack(push, 4)
David Blaikie4e4d0842012-03-11 07:00:24 +0000273 if (PP.getLangOpts().ApplePragmaPack)
Eli Friedman19bda3a2011-11-02 01:53:16 +0000274 Kind = Sema::PPK_Push;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000275 } else if (Tok.is(tok::identifier)) {
276 const IdentifierInfo *II = Tok.getIdentifierInfo();
Chris Lattner08631c52008-11-23 21:45:46 +0000277 if (II->isStr("show")) {
John McCallf312b1e2010-08-26 23:41:50 +0000278 Kind = Sema::PPK_Show;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000279 PP.Lex(Tok);
280 } else {
Chris Lattner08631c52008-11-23 21:45:46 +0000281 if (II->isStr("push")) {
John McCallf312b1e2010-08-26 23:41:50 +0000282 Kind = Sema::PPK_Push;
Chris Lattner08631c52008-11-23 21:45:46 +0000283 } else if (II->isStr("pop")) {
John McCallf312b1e2010-08-26 23:41:50 +0000284 Kind = Sema::PPK_Pop;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000285 } else {
286 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_invalid_action);
287 return;
Mike Stump1eb44332009-09-09 15:08:12 +0000288 }
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000289 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000290
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000291 if (Tok.is(tok::comma)) {
292 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000293
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000294 if (Tok.is(tok::numeric_constant)) {
Eli Friedman9595c7e2012-10-04 02:36:51 +0000295 Alignment = Tok;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000296
297 PP.Lex(Tok);
298 } else if (Tok.is(tok::identifier)) {
299 Name = Tok.getIdentifierInfo();
300 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000301
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000302 if (Tok.is(tok::comma)) {
303 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000304
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000305 if (Tok.isNot(tok::numeric_constant)) {
Chris Lattner08631c52008-11-23 21:45:46 +0000306 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000307 return;
308 }
Mike Stump1eb44332009-09-09 15:08:12 +0000309
Eli Friedman9595c7e2012-10-04 02:36:51 +0000310 Alignment = Tok;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000311
312 PP.Lex(Tok);
313 }
314 } else {
Chris Lattner08631c52008-11-23 21:45:46 +0000315 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000316 return;
317 }
318 }
319 }
David Blaikie4e4d0842012-03-11 07:00:24 +0000320 } else if (PP.getLangOpts().ApplePragmaPack) {
Eli Friedman19bda3a2011-11-02 01:53:16 +0000321 // In MSVC/gcc, #pragma pack() resets the alignment without affecting
322 // the push/pop stack.
323 // In Apple gcc #pragma pack() is equivalent to #pragma pack(pop).
324 Kind = Sema::PPK_Pop;
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000325 }
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000326
327 if (Tok.isNot(tok::r_paren)) {
Ted Kremenek4726d032009-03-23 22:28:25 +0000328 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack";
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000329 return;
330 }
331
Daniel Dunbar861800c2010-05-26 23:29:06 +0000332 SourceLocation RParenLoc = Tok.getLocation();
Eli Friedman99914792009-06-05 00:49:58 +0000333 PP.Lex(Tok);
Peter Collingbourne84021552011-02-28 02:37:51 +0000334 if (Tok.isNot(tok::eod)) {
Eli Friedman99914792009-06-05 00:49:58 +0000335 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack";
336 return;
337 }
338
Daniel Dunbarb0939552012-02-29 01:38:22 +0000339 PragmaPackInfo *Info =
340 (PragmaPackInfo*) PP.getPreprocessorAllocator().Allocate(
341 sizeof(PragmaPackInfo), llvm::alignOf<PragmaPackInfo>());
342 new (Info) PragmaPackInfo();
Eli Friedmanaa5ab262012-02-23 23:47:16 +0000343 Info->Kind = Kind;
344 Info->Name = Name;
Eli Friedman9595c7e2012-10-04 02:36:51 +0000345 Info->Alignment = Alignment;
Eli Friedmanaa5ab262012-02-23 23:47:16 +0000346 Info->LParenLoc = LParenLoc;
347 Info->RParenLoc = RParenLoc;
348
Daniel Dunbarb0939552012-02-29 01:38:22 +0000349 Token *Toks =
350 (Token*) PP.getPreprocessorAllocator().Allocate(
351 sizeof(Token) * 1, llvm::alignOf<Token>());
352 new (Toks) Token();
Eli Friedmanaa5ab262012-02-23 23:47:16 +0000353 Toks[0].startToken();
354 Toks[0].setKind(tok::annot_pragma_pack);
355 Toks[0].setLocation(PackLoc);
356 Toks[0].setAnnotationValue(static_cast<void*>(Info));
357 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
Daniel Dunbarb0939552012-02-29 01:38:22 +0000358 /*OwnsTokens=*/false);
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000359}
360
Fariborz Jahanian62c92582011-04-25 18:49:15 +0000361// #pragma ms_struct on
362// #pragma ms_struct off
363void PragmaMSStructHandler::HandlePragma(Preprocessor &PP,
364 PragmaIntroducerKind Introducer,
365 Token &MSStructTok) {
366 Sema::PragmaMSStructKind Kind = Sema::PMSST_OFF;
367
368 Token Tok;
369 PP.Lex(Tok);
370 if (Tok.isNot(tok::identifier)) {
371 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
372 return;
373 }
374 const IdentifierInfo *II = Tok.getIdentifierInfo();
375 if (II->isStr("on")) {
376 Kind = Sema::PMSST_ON;
377 PP.Lex(Tok);
378 }
379 else if (II->isStr("off") || II->isStr("reset"))
380 PP.Lex(Tok);
381 else {
382 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
383 return;
384 }
385
386 if (Tok.isNot(tok::eod)) {
Daniel Dunbarb0939552012-02-29 01:38:22 +0000387 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
388 << "ms_struct";
Fariborz Jahanian62c92582011-04-25 18:49:15 +0000389 return;
390 }
Eli Friedman9595c7e2012-10-04 02:36:51 +0000391
392 Token *Toks =
393 (Token*) PP.getPreprocessorAllocator().Allocate(
394 sizeof(Token) * 1, llvm::alignOf<Token>());
395 new (Toks) Token();
396 Toks[0].startToken();
397 Toks[0].setKind(tok::annot_pragma_msstruct);
398 Toks[0].setLocation(MSStructTok.getLocation());
399 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
400 static_cast<uintptr_t>(Kind)));
401 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
402 /*OwnsTokens=*/false);
Fariborz Jahanian62c92582011-04-25 18:49:15 +0000403}
404
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000405// #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
406// #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
Eli Friedman9595c7e2012-10-04 02:36:51 +0000407static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok,
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000408 bool IsOptions) {
Daniel Dunbar861800c2010-05-26 23:29:06 +0000409 Token Tok;
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000410
411 if (IsOptions) {
412 PP.Lex(Tok);
413 if (Tok.isNot(tok::identifier) ||
414 !Tok.getIdentifierInfo()->isStr("align")) {
415 PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align);
416 return;
417 }
Daniel Dunbar861800c2010-05-26 23:29:06 +0000418 }
Daniel Dunbar638e7cf2010-05-27 18:42:09 +0000419
Daniel Dunbar861800c2010-05-26 23:29:06 +0000420 PP.Lex(Tok);
421 if (Tok.isNot(tok::equal)) {
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000422 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal)
423 << IsOptions;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000424 return;
425 }
426
427 PP.Lex(Tok);
428 if (Tok.isNot(tok::identifier)) {
429 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000430 << (IsOptions ? "options" : "align");
Daniel Dunbar861800c2010-05-26 23:29:06 +0000431 return;
432 }
433
John McCallf312b1e2010-08-26 23:41:50 +0000434 Sema::PragmaOptionsAlignKind Kind = Sema::POAK_Natural;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000435 const IdentifierInfo *II = Tok.getIdentifierInfo();
Daniel Dunbar638e7cf2010-05-27 18:42:09 +0000436 if (II->isStr("native"))
John McCallf312b1e2010-08-26 23:41:50 +0000437 Kind = Sema::POAK_Native;
Daniel Dunbar638e7cf2010-05-27 18:42:09 +0000438 else if (II->isStr("natural"))
John McCallf312b1e2010-08-26 23:41:50 +0000439 Kind = Sema::POAK_Natural;
Daniel Dunbar6f739142010-05-27 18:42:17 +0000440 else if (II->isStr("packed"))
John McCallf312b1e2010-08-26 23:41:50 +0000441 Kind = Sema::POAK_Packed;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000442 else if (II->isStr("power"))
John McCallf312b1e2010-08-26 23:41:50 +0000443 Kind = Sema::POAK_Power;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000444 else if (II->isStr("mac68k"))
John McCallf312b1e2010-08-26 23:41:50 +0000445 Kind = Sema::POAK_Mac68k;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000446 else if (II->isStr("reset"))
John McCallf312b1e2010-08-26 23:41:50 +0000447 Kind = Sema::POAK_Reset;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000448 else {
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000449 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option)
450 << IsOptions;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000451 return;
452 }
453
Daniel Dunbar861800c2010-05-26 23:29:06 +0000454 PP.Lex(Tok);
Peter Collingbourne84021552011-02-28 02:37:51 +0000455 if (Tok.isNot(tok::eod)) {
Daniel Dunbar861800c2010-05-26 23:29:06 +0000456 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000457 << (IsOptions ? "options" : "align");
Daniel Dunbar861800c2010-05-26 23:29:06 +0000458 return;
459 }
460
Eli Friedman9595c7e2012-10-04 02:36:51 +0000461 Token *Toks =
462 (Token*) PP.getPreprocessorAllocator().Allocate(
463 sizeof(Token) * 1, llvm::alignOf<Token>());
464 new (Toks) Token();
465 Toks[0].startToken();
466 Toks[0].setKind(tok::annot_pragma_align);
467 Toks[0].setLocation(FirstTok.getLocation());
468 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
469 static_cast<uintptr_t>(Kind)));
470 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
471 /*OwnsTokens=*/false);
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000472}
473
Douglas Gregor80c60f72010-09-09 22:45:38 +0000474void PragmaAlignHandler::HandlePragma(Preprocessor &PP,
475 PragmaIntroducerKind Introducer,
476 Token &AlignTok) {
Eli Friedman9595c7e2012-10-04 02:36:51 +0000477 ParseAlignPragma(PP, AlignTok, /*IsOptions=*/false);
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000478}
479
Douglas Gregor80c60f72010-09-09 22:45:38 +0000480void PragmaOptionsHandler::HandlePragma(Preprocessor &PP,
481 PragmaIntroducerKind Introducer,
482 Token &OptionsTok) {
Eli Friedman9595c7e2012-10-04 02:36:51 +0000483 ParseAlignPragma(PP, OptionsTok, /*IsOptions=*/true);
Daniel Dunbar861800c2010-05-26 23:29:06 +0000484}
485
Ted Kremenek4726d032009-03-23 22:28:25 +0000486// #pragma unused(identifier)
Douglas Gregor80c60f72010-09-09 22:45:38 +0000487void PragmaUnusedHandler::HandlePragma(Preprocessor &PP,
488 PragmaIntroducerKind Introducer,
489 Token &UnusedTok) {
Ted Kremenek4726d032009-03-23 22:28:25 +0000490 // FIXME: Should we be expanding macros here? My guess is no.
491 SourceLocation UnusedLoc = UnusedTok.getLocation();
Mike Stump1eb44332009-09-09 15:08:12 +0000492
Ted Kremenek4726d032009-03-23 22:28:25 +0000493 // Lex the left '('.
494 Token Tok;
495 PP.Lex(Tok);
496 if (Tok.isNot(tok::l_paren)) {
497 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
498 return;
499 }
Mike Stump1eb44332009-09-09 15:08:12 +0000500
Ted Kremenek4726d032009-03-23 22:28:25 +0000501 // Lex the declaration reference(s).
Chris Lattner5f9e2722011-07-23 10:55:15 +0000502 SmallVector<Token, 5> Identifiers;
Ted Kremenek4726d032009-03-23 22:28:25 +0000503 SourceLocation RParenLoc;
504 bool LexID = true;
Mike Stump1eb44332009-09-09 15:08:12 +0000505
Ted Kremenek4726d032009-03-23 22:28:25 +0000506 while (true) {
507 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000508
Ted Kremenek4726d032009-03-23 22:28:25 +0000509 if (LexID) {
Mike Stump1eb44332009-09-09 15:08:12 +0000510 if (Tok.is(tok::identifier)) {
Ted Kremenek7a02a372009-08-03 23:24:57 +0000511 Identifiers.push_back(Tok);
Ted Kremenek4726d032009-03-23 22:28:25 +0000512 LexID = false;
513 continue;
514 }
515
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_var);
518 return;
519 }
Mike Stump1eb44332009-09-09 15:08:12 +0000520
Ted Kremenek4726d032009-03-23 22:28:25 +0000521 // We are execting a ')' or a ','.
522 if (Tok.is(tok::comma)) {
523 LexID = true;
524 continue;
525 }
Mike Stump1eb44332009-09-09 15:08:12 +0000526
Ted Kremenek4726d032009-03-23 22:28:25 +0000527 if (Tok.is(tok::r_paren)) {
528 RParenLoc = Tok.getLocation();
529 break;
530 }
Mike Stump1eb44332009-09-09 15:08:12 +0000531
Ted Kremenek7a02a372009-08-03 23:24:57 +0000532 // Illegal token!
Ted Kremenek4726d032009-03-23 22:28:25 +0000533 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_punc);
534 return;
535 }
Eli Friedman99914792009-06-05 00:49:58 +0000536
537 PP.Lex(Tok);
Peter Collingbourne84021552011-02-28 02:37:51 +0000538 if (Tok.isNot(tok::eod)) {
Eli Friedman99914792009-06-05 00:49:58 +0000539 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
540 "unused";
541 return;
542 }
543
Ted Kremenek4726d032009-03-23 22:28:25 +0000544 // Verify that we have a location for the right parenthesis.
545 assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
Ted Kremenek7a02a372009-08-03 23:24:57 +0000546 assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
Ted Kremenek4726d032009-03-23 22:28:25 +0000547
Argyrios Kyrtzidisb918d0f2011-01-17 18:58:44 +0000548 // For each identifier token, insert into the token stream a
549 // annot_pragma_unused token followed by the identifier token.
550 // This allows us to cache a "#pragma unused" that occurs inside an inline
551 // C++ member function.
552
Daniel Dunbarb0939552012-02-29 01:38:22 +0000553 Token *Toks =
554 (Token*) PP.getPreprocessorAllocator().Allocate(
555 sizeof(Token) * 2 * Identifiers.size(), llvm::alignOf<Token>());
Argyrios Kyrtzidisb918d0f2011-01-17 18:58:44 +0000556 for (unsigned i=0; i != Identifiers.size(); i++) {
557 Token &pragmaUnusedTok = Toks[2*i], &idTok = Toks[2*i+1];
558 pragmaUnusedTok.startToken();
559 pragmaUnusedTok.setKind(tok::annot_pragma_unused);
560 pragmaUnusedTok.setLocation(UnusedLoc);
561 idTok = Identifiers[i];
562 }
Daniel Dunbarb0939552012-02-29 01:38:22 +0000563 PP.EnterTokenStream(Toks, 2*Identifiers.size(),
564 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
Ted Kremenek4726d032009-03-23 22:28:25 +0000565}
Eli Friedman99914792009-06-05 00:49:58 +0000566
567// #pragma weak identifier
568// #pragma weak identifier '=' identifier
Douglas Gregor80c60f72010-09-09 22:45:38 +0000569void PragmaWeakHandler::HandlePragma(Preprocessor &PP,
570 PragmaIntroducerKind Introducer,
571 Token &WeakTok) {
Eli Friedman99914792009-06-05 00:49:58 +0000572 SourceLocation WeakLoc = WeakTok.getLocation();
573
574 Token Tok;
575 PP.Lex(Tok);
576 if (Tok.isNot(tok::identifier)) {
577 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";
578 return;
579 }
580
Eli Friedman9595c7e2012-10-04 02:36:51 +0000581 Token WeakName = Tok;
582 bool HasAlias = false;
583 Token AliasName;
Eli Friedman99914792009-06-05 00:49:58 +0000584
585 PP.Lex(Tok);
586 if (Tok.is(tok::equal)) {
Eli Friedman9595c7e2012-10-04 02:36:51 +0000587 HasAlias = true;
Eli Friedman99914792009-06-05 00:49:58 +0000588 PP.Lex(Tok);
589 if (Tok.isNot(tok::identifier)) {
Mike Stump1eb44332009-09-09 15:08:12 +0000590 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Eli Friedman99914792009-06-05 00:49:58 +0000591 << "weak";
592 return;
593 }
Eli Friedman9595c7e2012-10-04 02:36:51 +0000594 AliasName = Tok;
Eli Friedman99914792009-06-05 00:49:58 +0000595 PP.Lex(Tok);
596 }
597
Peter Collingbourne84021552011-02-28 02:37:51 +0000598 if (Tok.isNot(tok::eod)) {
Eli Friedman99914792009-06-05 00:49:58 +0000599 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";
600 return;
601 }
602
Eli Friedman9595c7e2012-10-04 02:36:51 +0000603 if (HasAlias) {
604 Token *Toks =
605 (Token*) PP.getPreprocessorAllocator().Allocate(
606 sizeof(Token) * 3, llvm::alignOf<Token>());
607 Token &pragmaUnusedTok = Toks[0];
608 pragmaUnusedTok.startToken();
609 pragmaUnusedTok.setKind(tok::annot_pragma_weakalias);
610 pragmaUnusedTok.setLocation(WeakLoc);
611 Toks[1] = WeakName;
612 Toks[2] = AliasName;
613 PP.EnterTokenStream(Toks, 3,
614 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
Eli Friedman99914792009-06-05 00:49:58 +0000615 } else {
Eli Friedman9595c7e2012-10-04 02:36:51 +0000616 Token *Toks =
617 (Token*) PP.getPreprocessorAllocator().Allocate(
618 sizeof(Token) * 2, llvm::alignOf<Token>());
619 Token &pragmaUnusedTok = Toks[0];
620 pragmaUnusedTok.startToken();
621 pragmaUnusedTok.setKind(tok::annot_pragma_weak);
622 pragmaUnusedTok.setLocation(WeakLoc);
623 Toks[1] = WeakName;
624 PP.EnterTokenStream(Toks, 2,
625 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
Eli Friedman99914792009-06-05 00:49:58 +0000626 }
627}
Peter Collingbourne321b8172011-02-14 01:42:35 +0000628
David Chisnall5f3c1632012-02-18 16:12:34 +0000629// #pragma redefine_extname identifier identifier
630void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP,
631 PragmaIntroducerKind Introducer,
632 Token &RedefToken) {
633 SourceLocation RedefLoc = RedefToken.getLocation();
634
635 Token Tok;
636 PP.Lex(Tok);
637 if (Tok.isNot(tok::identifier)) {
638 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
639 "redefine_extname";
640 return;
641 }
642
Eli Friedman9595c7e2012-10-04 02:36:51 +0000643 Token RedefName = Tok;
David Chisnall5f3c1632012-02-18 16:12:34 +0000644 PP.Lex(Tok);
Eli Friedman9595c7e2012-10-04 02:36:51 +0000645
David Chisnall5f3c1632012-02-18 16:12:34 +0000646 if (Tok.isNot(tok::identifier)) {
647 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
648 << "redefine_extname";
649 return;
650 }
Eli Friedman9595c7e2012-10-04 02:36:51 +0000651
652 Token AliasName = Tok;
David Chisnall5f3c1632012-02-18 16:12:34 +0000653 PP.Lex(Tok);
654
655 if (Tok.isNot(tok::eod)) {
656 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
657 "redefine_extname";
658 return;
659 }
660
Eli Friedman9595c7e2012-10-04 02:36:51 +0000661 Token *Toks =
662 (Token*) PP.getPreprocessorAllocator().Allocate(
663 sizeof(Token) * 3, llvm::alignOf<Token>());
664 Token &pragmaRedefTok = Toks[0];
665 pragmaRedefTok.startToken();
666 pragmaRedefTok.setKind(tok::annot_pragma_redefine_extname);
667 pragmaRedefTok.setLocation(RedefLoc);
668 Toks[1] = RedefName;
669 Toks[2] = AliasName;
670 PP.EnterTokenStream(Toks, 3,
671 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
David Chisnall5f3c1632012-02-18 16:12:34 +0000672}
673
674
Peter Collingbourne321b8172011-02-14 01:42:35 +0000675void
676PragmaFPContractHandler::HandlePragma(Preprocessor &PP,
677 PragmaIntroducerKind Introducer,
678 Token &Tok) {
679 tok::OnOffSwitch OOS;
680 if (PP.LexOnOffSwitch(OOS))
681 return;
682
Eli Friedman9595c7e2012-10-04 02:36:51 +0000683 Token *Toks =
684 (Token*) PP.getPreprocessorAllocator().Allocate(
685 sizeof(Token) * 1, llvm::alignOf<Token>());
686 new (Toks) Token();
687 Toks[0].startToken();
688 Toks[0].setKind(tok::annot_pragma_fp_contract);
689 Toks[0].setLocation(Tok.getLocation());
690 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
691 static_cast<uintptr_t>(OOS)));
692 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
693 /*OwnsTokens=*/false);
Peter Collingbourne321b8172011-02-14 01:42:35 +0000694}
Peter Collingbournef315fa82011-02-14 01:42:53 +0000695
696void
697PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
698 PragmaIntroducerKind Introducer,
699 Token &Tok) {
Tanya Lattnerb38b6a72011-04-14 23:35:31 +0000700 PP.LexUnexpandedToken(Tok);
Peter Collingbournef315fa82011-02-14 01:42:53 +0000701 if (Tok.isNot(tok::identifier)) {
702 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
703 "OPENCL";
704 return;
705 }
706 IdentifierInfo *ename = Tok.getIdentifierInfo();
707 SourceLocation NameLoc = Tok.getLocation();
708
709 PP.Lex(Tok);
710 if (Tok.isNot(tok::colon)) {
711 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << ename;
712 return;
713 }
714
715 PP.Lex(Tok);
716 if (Tok.isNot(tok::identifier)) {
717 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
718 return;
719 }
720 IdentifierInfo *op = Tok.getIdentifierInfo();
721
722 unsigned state;
723 if (op->isStr("enable")) {
724 state = 1;
725 } else if (op->isStr("disable")) {
726 state = 0;
727 } else {
728 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
729 return;
730 }
731
Eli Friedman9595c7e2012-10-04 02:36:51 +0000732 PP.Lex(Tok);
733 if (Tok.isNot(tok::eod)) {
734 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
735 "OPENCL EXTENSION";
Peter Collingbournef315fa82011-02-14 01:42:53 +0000736 return;
737 }
Eli Friedman9595c7e2012-10-04 02:36:51 +0000738
739 OpenCLExtData data(ename, state);
740 Token *Toks =
741 (Token*) PP.getPreprocessorAllocator().Allocate(
742 sizeof(Token) * 1, llvm::alignOf<Token>());
743 new (Toks) Token();
744 Toks[0].startToken();
745 Toks[0].setKind(tok::annot_pragma_opencl_extension);
746 Toks[0].setLocation(NameLoc);
747 Toks[0].setAnnotationValue(data.getOpaqueValue());
748 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
749 /*OwnsTokens=*/false);
Peter Collingbournef315fa82011-02-14 01:42:53 +0000750}
751
Alexey Bataevc6400582013-03-22 06:34:35 +0000752/// \brief Handle '#pragma omp ...' when OpenMP is disabled.
753///
754void
755PragmaNoOpenMPHandler::HandlePragma(Preprocessor &PP,
756 PragmaIntroducerKind Introducer,
757 Token &FirstTok) {
758 if (PP.getDiagnostics().getDiagnosticLevel(diag::warn_pragma_omp_ignored,
759 FirstTok.getLocation()) !=
760 DiagnosticsEngine::Ignored) {
761 PP.Diag(FirstTok, diag::warn_pragma_omp_ignored);
762 PP.getDiagnostics().setDiagnosticMapping(diag::warn_pragma_omp_ignored,
763 diag::MAP_IGNORE,
764 SourceLocation());
765 }
766 PP.DiscardUntilEndOfDirective();
767}
768
769/// \brief Handle '#pragma omp ...' when OpenMP is enabled.
770///
771void
772PragmaOpenMPHandler::HandlePragma(Preprocessor &PP,
773 PragmaIntroducerKind Introducer,
774 Token &FirstTok) {
775 SmallVector<Token, 16> Pragma;
776 Token Tok;
777 Tok.startToken();
778 Tok.setKind(tok::annot_pragma_openmp);
779 Tok.setLocation(FirstTok.getLocation());
780
781 while (Tok.isNot(tok::eod)) {
782 Pragma.push_back(Tok);
783 PP.Lex(Tok);
784 }
785 SourceLocation EodLoc = Tok.getLocation();
786 Tok.startToken();
787 Tok.setKind(tok::annot_pragma_openmp_end);
788 Tok.setLocation(EodLoc);
789 Pragma.push_back(Tok);
790
791 Token *Toks = new Token[Pragma.size()];
792 std::copy(Pragma.begin(), Pragma.end(), Toks);
793 PP.EnterTokenStream(Toks, Pragma.size(),
794 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/true);
795}
Reid Kleckner7adf79a2013-05-06 21:02:12 +0000796
Aaron Ballmana7ff62f2013-06-04 02:07:14 +0000797/// \brief Handle the Microsoft \#pragma detect_mismatch extension.
798///
799/// The syntax is:
800/// \code
801/// #pragma detect_mismatch("name", "value")
802/// \endcode
803/// Where 'name' and 'value' are quoted strings. The values are embedded in
804/// the object file and passed along to the linker. If the linker detects a
805/// mismatch in the object file's values for the given name, a LNK2038 error
806/// is emitted. See MSDN for more details.
807void PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP,
808 PragmaIntroducerKind Introducer,
809 Token &Tok) {
810 SourceLocation CommentLoc = Tok.getLocation();
811 PP.Lex(Tok);
812 if (Tok.isNot(tok::l_paren)) {
813 PP.Diag(CommentLoc, diag::err_expected_lparen);
814 return;
815 }
816
817 // Read the name to embed, which must be a string literal.
818 std::string NameString;
819 if (!PP.LexStringLiteral(Tok, NameString,
820 "pragma detect_mismatch",
821 /*MacroExpansion=*/true))
822 return;
823
824 // Read the comma followed by a second string literal.
825 std::string ValueString;
826 if (Tok.isNot(tok::comma)) {
827 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
828 return;
829 }
830
831 if (!PP.LexStringLiteral(Tok, ValueString, "pragma detect_mismatch",
832 /*MacroExpansion=*/true))
833 return;
834
835 if (Tok.isNot(tok::r_paren)) {
836 PP.Diag(Tok.getLocation(), diag::err_expected_rparen);
837 return;
838 }
839 PP.Lex(Tok); // Eat the r_paren.
840
841 if (Tok.isNot(tok::eod)) {
842 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
843 return;
844 }
845
846 // If the pragma is lexically sound, notify any interested PPCallbacks.
847 if (PP.getPPCallbacks())
848 PP.getPPCallbacks()->PragmaDetectMismatch(CommentLoc, NameString,
849 ValueString);
850
851 Actions.ActOnPragmaDetectMismatch(NameString, ValueString);
852}
853
Reid Kleckner7adf79a2013-05-06 21:02:12 +0000854/// \brief Handle the microsoft \#pragma comment extension.
855///
856/// The syntax is:
857/// \code
858/// #pragma comment(linker, "foo")
859/// \endcode
860/// 'linker' is one of five identifiers: compiler, exestr, lib, linker, user.
861/// "foo" is a string, which is fully macro expanded, and permits string
862/// concatenation, embedded escape characters etc. See MSDN for more details.
863void PragmaCommentHandler::HandlePragma(Preprocessor &PP,
864 PragmaIntroducerKind Introducer,
865 Token &Tok) {
866 SourceLocation CommentLoc = Tok.getLocation();
867 PP.Lex(Tok);
868 if (Tok.isNot(tok::l_paren)) {
869 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
870 return;
871 }
872
873 // Read the identifier.
874 PP.Lex(Tok);
875 if (Tok.isNot(tok::identifier)) {
876 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
877 return;
878 }
879
880 // Verify that this is one of the 5 whitelisted options.
Reid Kleckner3190ca92013-05-08 13:44:39 +0000881 IdentifierInfo *II = Tok.getIdentifierInfo();
882 Sema::PragmaMSCommentKind Kind =
883 llvm::StringSwitch<Sema::PragmaMSCommentKind>(II->getName())
884 .Case("linker", Sema::PCK_Linker)
885 .Case("lib", Sema::PCK_Lib)
886 .Case("compiler", Sema::PCK_Compiler)
887 .Case("exestr", Sema::PCK_ExeStr)
888 .Case("user", Sema::PCK_User)
889 .Default(Sema::PCK_Unknown);
890 if (Kind == Sema::PCK_Unknown) {
Reid Kleckner7adf79a2013-05-06 21:02:12 +0000891 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_unknown_kind);
892 return;
893 }
894
895 // Read the optional string if present.
896 PP.Lex(Tok);
897 std::string ArgumentString;
898 if (Tok.is(tok::comma) && !PP.LexStringLiteral(Tok, ArgumentString,
899 "pragma comment",
900 /*MacroExpansion=*/true))
901 return;
902
Reid Kleckner3190ca92013-05-08 13:44:39 +0000903 // FIXME: warn that 'exestr' is deprecated.
Reid Kleckner7adf79a2013-05-06 21:02:12 +0000904 // FIXME: If the kind is "compiler" warn if the string is present (it is
905 // ignored).
Reid Kleckner3190ca92013-05-08 13:44:39 +0000906 // The MSDN docs say that "lib" and "linker" require a string and have a short
907 // whitelist of linker options they support, but in practice MSVC doesn't
908 // issue a diagnostic. Therefore neither does clang.
Reid Kleckner7adf79a2013-05-06 21:02:12 +0000909
910 if (Tok.isNot(tok::r_paren)) {
911 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
912 return;
913 }
914 PP.Lex(Tok); // eat the r_paren.
915
916 if (Tok.isNot(tok::eod)) {
917 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
918 return;
919 }
920
921 // If the pragma is lexically sound, notify any interested PPCallbacks.
922 if (PP.getPPCallbacks())
923 PP.getPPCallbacks()->PragmaComment(CommentLoc, II, ArgumentString);
Reid Kleckner3190ca92013-05-08 13:44:39 +0000924
925 Actions.ActOnPragmaMSComment(Kind, ArgumentString);
Reid Kleckner7adf79a2013-05-06 21:02:12 +0000926}