blob: 8cf2b3f1d2678340572b88ea01bdee182937d5d1 [file] [log] [blame]
Daniel Dunbar921b9682008-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 Carruth3a022472012-12-04 09:13:33 +000015#include "clang/Lex/Preprocessor.h"
Chris Lattner60f36222009-01-29 05:15:15 +000016#include "clang/Parse/ParseDiagnostic.h"
Ted Kremenekfd14fad2009-03-23 22:28:25 +000017#include "clang/Parse/Parser.h"
Tareq A. Siraj6dfa25a2013-04-16 19:37:38 +000018#include "clang/Sema/Scope.h"
Reid Kleckner002562a2013-05-06 21:02:12 +000019#include "llvm/ADT/StringSwitch.h"
Daniel Dunbar921b9682008-10-04 19:21:03 +000020using namespace clang;
21
Argyrios Kyrtzidisee569622011-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 Friedman570024a2010-08-05 06:57:20 +000033
Rafael Espindola273fd772012-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 Friedmanec52f922012-02-23 23:47:16 +000042struct PragmaPackInfo {
43 Sema::PragmaPackKind Kind;
44 IdentifierInfo *Name;
Eli Friedman68be1642012-10-04 02:36:51 +000045 Token Alignment;
Eli Friedmanec52f922012-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 Friedman68be1642012-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 Friedmanec52f922012-02-23 23:47:16 +000062 Info->LParenLoc, Info->RParenLoc);
Eli Friedmanec52f922012-02-23 23:47:16 +000063}
64
Eli Friedman68be1642012-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. Siraj0de0dd42013-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)) {
Alp Tokerec543272013-12-24 09:48:30 +0000133 PP.Diag(Tok, diag::err_expected) << tok::l_brace;
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000134 return StmtError();
135 }
136
Tareq A. Siraj6dfa25a2013-04-16 19:37:38 +0000137 SourceLocation Loc = Tok.getLocation();
138
139 ParseScope CapturedRegionScope(this, Scope::FnScope | Scope::DeclScope);
Ben Langmuir37943a72013-05-03 19:00:33 +0000140 Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_Default,
141 /*NumParams=*/1);
Tareq A. Siraj6dfa25a2013-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. Siraj0de0dd42013-04-16 18:41:26 +0000152}
153
Eli Friedman68be1642012-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
David Majnemer4bb09802014-02-10 19:50:15 +0000183void Parser::HandlePragmaMSPointersToMembers() {
184 assert(Tok.is(tok::annot_pragma_ms_pointers_to_members));
David Majnemer86c318f2014-02-11 21:05:00 +0000185 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod =
186 static_cast<LangOptions::PragmaMSPointersToMembersKind>(
David Majnemer4bb09802014-02-10 19:50:15 +0000187 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
188 SourceLocation PragmaLoc = ConsumeToken(); // The annotation token.
189 Actions.ActOnPragmaMSPointersToMembers(RepresentationMethod, PragmaLoc);
190}
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000191
192
Eli Friedman570024a2010-08-05 06:57:20 +0000193// #pragma GCC visibility comes in two variants:
194// 'push' '(' [visibility] ')'
195// 'pop'
Douglas Gregorc7d65762010-09-09 22:45:38 +0000196void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,
197 PragmaIntroducerKind Introducer,
198 Token &VisTok) {
Eli Friedman570024a2010-08-05 06:57:20 +0000199 SourceLocation VisLoc = VisTok.getLocation();
200
201 Token Tok;
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +0000202 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +0000203
204 const IdentifierInfo *PushPop = Tok.getIdentifierInfo();
205
Eli Friedman570024a2010-08-05 06:57:20 +0000206 const IdentifierInfo *VisType;
207 if (PushPop && PushPop->isStr("pop")) {
Eli Friedman570024a2010-08-05 06:57:20 +0000208 VisType = 0;
209 } else if (PushPop && PushPop->isStr("push")) {
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +0000210 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +0000211 if (Tok.isNot(tok::l_paren)) {
212 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
213 << "visibility";
214 return;
215 }
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +0000216 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +0000217 VisType = Tok.getIdentifierInfo();
218 if (!VisType) {
219 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
220 << "visibility";
221 return;
222 }
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +0000223 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +0000224 if (Tok.isNot(tok::r_paren)) {
225 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
226 << "visibility";
227 return;
228 }
229 } else {
230 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
231 << "visibility";
232 return;
233 }
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +0000234 PP.LexUnexpandedToken(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +0000235 if (Tok.isNot(tok::eod)) {
Eli Friedman570024a2010-08-05 06:57:20 +0000236 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
237 << "visibility";
238 return;
239 }
240
Rafael Espindola273fd772012-01-26 02:02:57 +0000241 Token *Toks = new Token[1];
242 Toks[0].startToken();
243 Toks[0].setKind(tok::annot_pragma_vis);
244 Toks[0].setLocation(VisLoc);
245 Toks[0].setAnnotationValue(
246 const_cast<void*>(static_cast<const void*>(VisType)));
247 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
248 /*OwnsTokens=*/true);
Eli Friedman570024a2010-08-05 06:57:20 +0000249}
250
Daniel Dunbar921b9682008-10-04 19:21:03 +0000251// #pragma pack(...) comes in the following delicious flavors:
252// pack '(' [integer] ')'
253// pack '(' 'show' ')'
254// pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'
Douglas Gregorc7d65762010-09-09 22:45:38 +0000255void PragmaPackHandler::HandlePragma(Preprocessor &PP,
256 PragmaIntroducerKind Introducer,
257 Token &PackTok) {
Daniel Dunbar921b9682008-10-04 19:21:03 +0000258 SourceLocation PackLoc = PackTok.getLocation();
259
260 Token Tok;
261 PP.Lex(Tok);
262 if (Tok.isNot(tok::l_paren)) {
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000263 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack";
Daniel Dunbar921b9682008-10-04 19:21:03 +0000264 return;
265 }
266
John McCallfaf5fb42010-08-26 23:41:50 +0000267 Sema::PragmaPackKind Kind = Sema::PPK_Default;
Daniel Dunbar921b9682008-10-04 19:21:03 +0000268 IdentifierInfo *Name = 0;
Eli Friedman68be1642012-10-04 02:36:51 +0000269 Token Alignment;
270 Alignment.startToken();
Daniel Dunbar921b9682008-10-04 19:21:03 +0000271 SourceLocation LParenLoc = Tok.getLocation();
Mike Stump11289f42009-09-09 15:08:12 +0000272 PP.Lex(Tok);
Daniel Dunbar921b9682008-10-04 19:21:03 +0000273 if (Tok.is(tok::numeric_constant)) {
Eli Friedman68be1642012-10-04 02:36:51 +0000274 Alignment = Tok;
Daniel Dunbar921b9682008-10-04 19:21:03 +0000275
276 PP.Lex(Tok);
Eli Friedman055c9702011-11-02 01:53:16 +0000277
278 // In MSVC/gcc, #pragma pack(4) sets the alignment without affecting
279 // the push/pop stack.
280 // In Apple gcc, #pragma pack(4) is equivalent to #pragma pack(push, 4)
David Blaikiebbafb8a2012-03-11 07:00:24 +0000281 if (PP.getLangOpts().ApplePragmaPack)
Eli Friedman055c9702011-11-02 01:53:16 +0000282 Kind = Sema::PPK_Push;
Daniel Dunbar921b9682008-10-04 19:21:03 +0000283 } else if (Tok.is(tok::identifier)) {
284 const IdentifierInfo *II = Tok.getIdentifierInfo();
Chris Lattnere3d20d92008-11-23 21:45:46 +0000285 if (II->isStr("show")) {
John McCallfaf5fb42010-08-26 23:41:50 +0000286 Kind = Sema::PPK_Show;
Daniel Dunbar921b9682008-10-04 19:21:03 +0000287 PP.Lex(Tok);
288 } else {
Chris Lattnere3d20d92008-11-23 21:45:46 +0000289 if (II->isStr("push")) {
John McCallfaf5fb42010-08-26 23:41:50 +0000290 Kind = Sema::PPK_Push;
Chris Lattnere3d20d92008-11-23 21:45:46 +0000291 } else if (II->isStr("pop")) {
John McCallfaf5fb42010-08-26 23:41:50 +0000292 Kind = Sema::PPK_Pop;
Daniel Dunbar921b9682008-10-04 19:21:03 +0000293 } else {
294 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_invalid_action);
295 return;
Mike Stump11289f42009-09-09 15:08:12 +0000296 }
Daniel Dunbar921b9682008-10-04 19:21:03 +0000297 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +0000298
Daniel Dunbar921b9682008-10-04 19:21:03 +0000299 if (Tok.is(tok::comma)) {
300 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +0000301
Daniel Dunbar921b9682008-10-04 19:21:03 +0000302 if (Tok.is(tok::numeric_constant)) {
Eli Friedman68be1642012-10-04 02:36:51 +0000303 Alignment = Tok;
Daniel Dunbar921b9682008-10-04 19:21:03 +0000304
305 PP.Lex(Tok);
306 } else if (Tok.is(tok::identifier)) {
307 Name = Tok.getIdentifierInfo();
308 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +0000309
Daniel Dunbar921b9682008-10-04 19:21:03 +0000310 if (Tok.is(tok::comma)) {
311 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +0000312
Daniel Dunbar921b9682008-10-04 19:21:03 +0000313 if (Tok.isNot(tok::numeric_constant)) {
Chris Lattnere3d20d92008-11-23 21:45:46 +0000314 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbar921b9682008-10-04 19:21:03 +0000315 return;
316 }
Mike Stump11289f42009-09-09 15:08:12 +0000317
Eli Friedman68be1642012-10-04 02:36:51 +0000318 Alignment = Tok;
Daniel Dunbar921b9682008-10-04 19:21:03 +0000319
320 PP.Lex(Tok);
321 }
322 } else {
Chris Lattnere3d20d92008-11-23 21:45:46 +0000323 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbar921b9682008-10-04 19:21:03 +0000324 return;
325 }
326 }
327 }
David Blaikiebbafb8a2012-03-11 07:00:24 +0000328 } else if (PP.getLangOpts().ApplePragmaPack) {
Eli Friedman055c9702011-11-02 01:53:16 +0000329 // In MSVC/gcc, #pragma pack() resets the alignment without affecting
330 // the push/pop stack.
331 // In Apple gcc #pragma pack() is equivalent to #pragma pack(pop).
332 Kind = Sema::PPK_Pop;
Sebastian Redl17f2c7d2008-12-09 13:15:23 +0000333 }
Daniel Dunbar921b9682008-10-04 19:21:03 +0000334
335 if (Tok.isNot(tok::r_paren)) {
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000336 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack";
Daniel Dunbar921b9682008-10-04 19:21:03 +0000337 return;
338 }
339
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000340 SourceLocation RParenLoc = Tok.getLocation();
Eli Friedmanf5867dd2009-06-05 00:49:58 +0000341 PP.Lex(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +0000342 if (Tok.isNot(tok::eod)) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +0000343 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack";
344 return;
345 }
346
Daniel Dunbar340cf242012-02-29 01:38:22 +0000347 PragmaPackInfo *Info =
348 (PragmaPackInfo*) PP.getPreprocessorAllocator().Allocate(
349 sizeof(PragmaPackInfo), llvm::alignOf<PragmaPackInfo>());
350 new (Info) PragmaPackInfo();
Eli Friedmanec52f922012-02-23 23:47:16 +0000351 Info->Kind = Kind;
352 Info->Name = Name;
Eli Friedman68be1642012-10-04 02:36:51 +0000353 Info->Alignment = Alignment;
Eli Friedmanec52f922012-02-23 23:47:16 +0000354 Info->LParenLoc = LParenLoc;
355 Info->RParenLoc = RParenLoc;
356
Daniel Dunbar340cf242012-02-29 01:38:22 +0000357 Token *Toks =
358 (Token*) PP.getPreprocessorAllocator().Allocate(
359 sizeof(Token) * 1, llvm::alignOf<Token>());
360 new (Toks) Token();
Eli Friedmanec52f922012-02-23 23:47:16 +0000361 Toks[0].startToken();
362 Toks[0].setKind(tok::annot_pragma_pack);
363 Toks[0].setLocation(PackLoc);
364 Toks[0].setAnnotationValue(static_cast<void*>(Info));
365 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
Daniel Dunbar340cf242012-02-29 01:38:22 +0000366 /*OwnsTokens=*/false);
Daniel Dunbar921b9682008-10-04 19:21:03 +0000367}
368
Fariborz Jahanian743dda42011-04-25 18:49:15 +0000369// #pragma ms_struct on
370// #pragma ms_struct off
371void PragmaMSStructHandler::HandlePragma(Preprocessor &PP,
372 PragmaIntroducerKind Introducer,
373 Token &MSStructTok) {
374 Sema::PragmaMSStructKind Kind = Sema::PMSST_OFF;
375
376 Token Tok;
377 PP.Lex(Tok);
378 if (Tok.isNot(tok::identifier)) {
379 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
380 return;
381 }
382 const IdentifierInfo *II = Tok.getIdentifierInfo();
383 if (II->isStr("on")) {
384 Kind = Sema::PMSST_ON;
385 PP.Lex(Tok);
386 }
387 else if (II->isStr("off") || II->isStr("reset"))
388 PP.Lex(Tok);
389 else {
390 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
391 return;
392 }
393
394 if (Tok.isNot(tok::eod)) {
Daniel Dunbar340cf242012-02-29 01:38:22 +0000395 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
396 << "ms_struct";
Fariborz Jahanian743dda42011-04-25 18:49:15 +0000397 return;
398 }
Eli Friedman68be1642012-10-04 02:36:51 +0000399
400 Token *Toks =
401 (Token*) PP.getPreprocessorAllocator().Allocate(
402 sizeof(Token) * 1, llvm::alignOf<Token>());
403 new (Toks) Token();
404 Toks[0].startToken();
405 Toks[0].setKind(tok::annot_pragma_msstruct);
406 Toks[0].setLocation(MSStructTok.getLocation());
407 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
408 static_cast<uintptr_t>(Kind)));
409 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
410 /*OwnsTokens=*/false);
Fariborz Jahanian743dda42011-04-25 18:49:15 +0000411}
412
Daniel Dunbarcb82acb2010-07-31 19:17:07 +0000413// #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
414// #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
Eli Friedman68be1642012-10-04 02:36:51 +0000415static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok,
Daniel Dunbarcb82acb2010-07-31 19:17:07 +0000416 bool IsOptions) {
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000417 Token Tok;
Daniel Dunbarcb82acb2010-07-31 19:17:07 +0000418
419 if (IsOptions) {
420 PP.Lex(Tok);
421 if (Tok.isNot(tok::identifier) ||
422 !Tok.getIdentifierInfo()->isStr("align")) {
423 PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align);
424 return;
425 }
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000426 }
Daniel Dunbar663e8092010-05-27 18:42:09 +0000427
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000428 PP.Lex(Tok);
429 if (Tok.isNot(tok::equal)) {
Daniel Dunbarcb82acb2010-07-31 19:17:07 +0000430 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal)
431 << IsOptions;
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000432 return;
433 }
434
435 PP.Lex(Tok);
436 if (Tok.isNot(tok::identifier)) {
437 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Daniel Dunbarcb82acb2010-07-31 19:17:07 +0000438 << (IsOptions ? "options" : "align");
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000439 return;
440 }
441
John McCallfaf5fb42010-08-26 23:41:50 +0000442 Sema::PragmaOptionsAlignKind Kind = Sema::POAK_Natural;
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000443 const IdentifierInfo *II = Tok.getIdentifierInfo();
Daniel Dunbar663e8092010-05-27 18:42:09 +0000444 if (II->isStr("native"))
John McCallfaf5fb42010-08-26 23:41:50 +0000445 Kind = Sema::POAK_Native;
Daniel Dunbar663e8092010-05-27 18:42:09 +0000446 else if (II->isStr("natural"))
John McCallfaf5fb42010-08-26 23:41:50 +0000447 Kind = Sema::POAK_Natural;
Daniel Dunbar9c84d4a2010-05-27 18:42:17 +0000448 else if (II->isStr("packed"))
John McCallfaf5fb42010-08-26 23:41:50 +0000449 Kind = Sema::POAK_Packed;
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000450 else if (II->isStr("power"))
John McCallfaf5fb42010-08-26 23:41:50 +0000451 Kind = Sema::POAK_Power;
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000452 else if (II->isStr("mac68k"))
John McCallfaf5fb42010-08-26 23:41:50 +0000453 Kind = Sema::POAK_Mac68k;
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000454 else if (II->isStr("reset"))
John McCallfaf5fb42010-08-26 23:41:50 +0000455 Kind = Sema::POAK_Reset;
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000456 else {
Daniel Dunbarcb82acb2010-07-31 19:17:07 +0000457 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option)
458 << IsOptions;
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000459 return;
460 }
461
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000462 PP.Lex(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +0000463 if (Tok.isNot(tok::eod)) {
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000464 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
Daniel Dunbarcb82acb2010-07-31 19:17:07 +0000465 << (IsOptions ? "options" : "align");
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000466 return;
467 }
468
Eli Friedman68be1642012-10-04 02:36:51 +0000469 Token *Toks =
470 (Token*) PP.getPreprocessorAllocator().Allocate(
471 sizeof(Token) * 1, llvm::alignOf<Token>());
472 new (Toks) Token();
473 Toks[0].startToken();
474 Toks[0].setKind(tok::annot_pragma_align);
475 Toks[0].setLocation(FirstTok.getLocation());
476 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
477 static_cast<uintptr_t>(Kind)));
478 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
479 /*OwnsTokens=*/false);
Daniel Dunbarcb82acb2010-07-31 19:17:07 +0000480}
481
Douglas Gregorc7d65762010-09-09 22:45:38 +0000482void PragmaAlignHandler::HandlePragma(Preprocessor &PP,
483 PragmaIntroducerKind Introducer,
484 Token &AlignTok) {
Eli Friedman68be1642012-10-04 02:36:51 +0000485 ParseAlignPragma(PP, AlignTok, /*IsOptions=*/false);
Daniel Dunbarcb82acb2010-07-31 19:17:07 +0000486}
487
Douglas Gregorc7d65762010-09-09 22:45:38 +0000488void PragmaOptionsHandler::HandlePragma(Preprocessor &PP,
489 PragmaIntroducerKind Introducer,
490 Token &OptionsTok) {
Eli Friedman68be1642012-10-04 02:36:51 +0000491 ParseAlignPragma(PP, OptionsTok, /*IsOptions=*/true);
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000492}
493
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000494// #pragma unused(identifier)
Douglas Gregorc7d65762010-09-09 22:45:38 +0000495void PragmaUnusedHandler::HandlePragma(Preprocessor &PP,
496 PragmaIntroducerKind Introducer,
497 Token &UnusedTok) {
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000498 // FIXME: Should we be expanding macros here? My guess is no.
499 SourceLocation UnusedLoc = UnusedTok.getLocation();
Mike Stump11289f42009-09-09 15:08:12 +0000500
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000501 // Lex the left '('.
502 Token Tok;
503 PP.Lex(Tok);
504 if (Tok.isNot(tok::l_paren)) {
505 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
506 return;
507 }
Mike Stump11289f42009-09-09 15:08:12 +0000508
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000509 // Lex the declaration reference(s).
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000510 SmallVector<Token, 5> Identifiers;
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000511 SourceLocation RParenLoc;
512 bool LexID = true;
Mike Stump11289f42009-09-09 15:08:12 +0000513
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000514 while (true) {
515 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +0000516
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000517 if (LexID) {
Mike Stump11289f42009-09-09 15:08:12 +0000518 if (Tok.is(tok::identifier)) {
Ted Kremenekfb50bf52009-08-03 23:24:57 +0000519 Identifiers.push_back(Tok);
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000520 LexID = false;
521 continue;
522 }
523
Ted Kremenekfb50bf52009-08-03 23:24:57 +0000524 // Illegal token!
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000525 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
526 return;
527 }
Mike Stump11289f42009-09-09 15:08:12 +0000528
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000529 // We are execting a ')' or a ','.
530 if (Tok.is(tok::comma)) {
531 LexID = true;
532 continue;
533 }
Mike Stump11289f42009-09-09 15:08:12 +0000534
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000535 if (Tok.is(tok::r_paren)) {
536 RParenLoc = Tok.getLocation();
537 break;
538 }
Mike Stump11289f42009-09-09 15:08:12 +0000539
Ted Kremenekfb50bf52009-08-03 23:24:57 +0000540 // Illegal token!
David Majnemer88969812014-02-10 19:06:37 +0000541 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_punc) << "unused";
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000542 return;
543 }
Eli Friedmanf5867dd2009-06-05 00:49:58 +0000544
545 PP.Lex(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +0000546 if (Tok.isNot(tok::eod)) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +0000547 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
548 "unused";
549 return;
550 }
551
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000552 // Verify that we have a location for the right parenthesis.
553 assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
Ted Kremenekfb50bf52009-08-03 23:24:57 +0000554 assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000555
Argyrios Kyrtzidisee569622011-01-17 18:58:44 +0000556 // For each identifier token, insert into the token stream a
557 // annot_pragma_unused token followed by the identifier token.
558 // This allows us to cache a "#pragma unused" that occurs inside an inline
559 // C++ member function.
560
Daniel Dunbar340cf242012-02-29 01:38:22 +0000561 Token *Toks =
562 (Token*) PP.getPreprocessorAllocator().Allocate(
563 sizeof(Token) * 2 * Identifiers.size(), llvm::alignOf<Token>());
Argyrios Kyrtzidisee569622011-01-17 18:58:44 +0000564 for (unsigned i=0; i != Identifiers.size(); i++) {
565 Token &pragmaUnusedTok = Toks[2*i], &idTok = Toks[2*i+1];
566 pragmaUnusedTok.startToken();
567 pragmaUnusedTok.setKind(tok::annot_pragma_unused);
568 pragmaUnusedTok.setLocation(UnusedLoc);
569 idTok = Identifiers[i];
570 }
Daniel Dunbar340cf242012-02-29 01:38:22 +0000571 PP.EnterTokenStream(Toks, 2*Identifiers.size(),
572 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000573}
Eli Friedmanf5867dd2009-06-05 00:49:58 +0000574
575// #pragma weak identifier
576// #pragma weak identifier '=' identifier
Douglas Gregorc7d65762010-09-09 22:45:38 +0000577void PragmaWeakHandler::HandlePragma(Preprocessor &PP,
578 PragmaIntroducerKind Introducer,
579 Token &WeakTok) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +0000580 SourceLocation WeakLoc = WeakTok.getLocation();
581
582 Token Tok;
583 PP.Lex(Tok);
584 if (Tok.isNot(tok::identifier)) {
585 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";
586 return;
587 }
588
Eli Friedman68be1642012-10-04 02:36:51 +0000589 Token WeakName = Tok;
590 bool HasAlias = false;
591 Token AliasName;
Eli Friedmanf5867dd2009-06-05 00:49:58 +0000592
593 PP.Lex(Tok);
594 if (Tok.is(tok::equal)) {
Eli Friedman68be1642012-10-04 02:36:51 +0000595 HasAlias = true;
Eli Friedmanf5867dd2009-06-05 00:49:58 +0000596 PP.Lex(Tok);
597 if (Tok.isNot(tok::identifier)) {
Mike Stump11289f42009-09-09 15:08:12 +0000598 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Eli Friedmanf5867dd2009-06-05 00:49:58 +0000599 << "weak";
600 return;
601 }
Eli Friedman68be1642012-10-04 02:36:51 +0000602 AliasName = Tok;
Eli Friedmanf5867dd2009-06-05 00:49:58 +0000603 PP.Lex(Tok);
604 }
605
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +0000606 if (Tok.isNot(tok::eod)) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +0000607 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";
608 return;
609 }
610
Eli Friedman68be1642012-10-04 02:36:51 +0000611 if (HasAlias) {
612 Token *Toks =
613 (Token*) PP.getPreprocessorAllocator().Allocate(
614 sizeof(Token) * 3, llvm::alignOf<Token>());
615 Token &pragmaUnusedTok = Toks[0];
616 pragmaUnusedTok.startToken();
617 pragmaUnusedTok.setKind(tok::annot_pragma_weakalias);
618 pragmaUnusedTok.setLocation(WeakLoc);
619 Toks[1] = WeakName;
620 Toks[2] = AliasName;
621 PP.EnterTokenStream(Toks, 3,
622 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
Eli Friedmanf5867dd2009-06-05 00:49:58 +0000623 } else {
Eli Friedman68be1642012-10-04 02:36:51 +0000624 Token *Toks =
625 (Token*) PP.getPreprocessorAllocator().Allocate(
626 sizeof(Token) * 2, llvm::alignOf<Token>());
627 Token &pragmaUnusedTok = Toks[0];
628 pragmaUnusedTok.startToken();
629 pragmaUnusedTok.setKind(tok::annot_pragma_weak);
630 pragmaUnusedTok.setLocation(WeakLoc);
631 Toks[1] = WeakName;
632 PP.EnterTokenStream(Toks, 2,
633 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
Eli Friedmanf5867dd2009-06-05 00:49:58 +0000634 }
635}
Peter Collingbourne564c0fa2011-02-14 01:42:35 +0000636
David Chisnall0867d9c2012-02-18 16:12:34 +0000637// #pragma redefine_extname identifier identifier
638void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP,
639 PragmaIntroducerKind Introducer,
640 Token &RedefToken) {
641 SourceLocation RedefLoc = RedefToken.getLocation();
642
643 Token Tok;
644 PP.Lex(Tok);
645 if (Tok.isNot(tok::identifier)) {
646 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
647 "redefine_extname";
648 return;
649 }
650
Eli Friedman68be1642012-10-04 02:36:51 +0000651 Token RedefName = Tok;
David Chisnall0867d9c2012-02-18 16:12:34 +0000652 PP.Lex(Tok);
Eli Friedman68be1642012-10-04 02:36:51 +0000653
David Chisnall0867d9c2012-02-18 16:12:34 +0000654 if (Tok.isNot(tok::identifier)) {
655 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
656 << "redefine_extname";
657 return;
658 }
Eli Friedman68be1642012-10-04 02:36:51 +0000659
660 Token AliasName = Tok;
David Chisnall0867d9c2012-02-18 16:12:34 +0000661 PP.Lex(Tok);
662
663 if (Tok.isNot(tok::eod)) {
664 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
665 "redefine_extname";
666 return;
667 }
668
Eli Friedman68be1642012-10-04 02:36:51 +0000669 Token *Toks =
670 (Token*) PP.getPreprocessorAllocator().Allocate(
671 sizeof(Token) * 3, llvm::alignOf<Token>());
672 Token &pragmaRedefTok = Toks[0];
673 pragmaRedefTok.startToken();
674 pragmaRedefTok.setKind(tok::annot_pragma_redefine_extname);
675 pragmaRedefTok.setLocation(RedefLoc);
676 Toks[1] = RedefName;
677 Toks[2] = AliasName;
678 PP.EnterTokenStream(Toks, 3,
679 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
David Chisnall0867d9c2012-02-18 16:12:34 +0000680}
681
682
Peter Collingbourne564c0fa2011-02-14 01:42:35 +0000683void
684PragmaFPContractHandler::HandlePragma(Preprocessor &PP,
685 PragmaIntroducerKind Introducer,
686 Token &Tok) {
687 tok::OnOffSwitch OOS;
688 if (PP.LexOnOffSwitch(OOS))
689 return;
690
Eli Friedman68be1642012-10-04 02:36:51 +0000691 Token *Toks =
692 (Token*) PP.getPreprocessorAllocator().Allocate(
693 sizeof(Token) * 1, llvm::alignOf<Token>());
694 new (Toks) Token();
695 Toks[0].startToken();
696 Toks[0].setKind(tok::annot_pragma_fp_contract);
697 Toks[0].setLocation(Tok.getLocation());
698 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
699 static_cast<uintptr_t>(OOS)));
700 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
701 /*OwnsTokens=*/false);
Peter Collingbourne564c0fa2011-02-14 01:42:35 +0000702}
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +0000703
704void
705PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
706 PragmaIntroducerKind Introducer,
707 Token &Tok) {
Tanya Lattneree840b82011-04-14 23:35:31 +0000708 PP.LexUnexpandedToken(Tok);
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +0000709 if (Tok.isNot(tok::identifier)) {
710 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
711 "OPENCL";
712 return;
713 }
714 IdentifierInfo *ename = Tok.getIdentifierInfo();
715 SourceLocation NameLoc = Tok.getLocation();
716
717 PP.Lex(Tok);
718 if (Tok.isNot(tok::colon)) {
719 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << ename;
720 return;
721 }
722
723 PP.Lex(Tok);
724 if (Tok.isNot(tok::identifier)) {
725 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
726 return;
727 }
728 IdentifierInfo *op = Tok.getIdentifierInfo();
729
730 unsigned state;
731 if (op->isStr("enable")) {
732 state = 1;
733 } else if (op->isStr("disable")) {
734 state = 0;
735 } else {
736 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
737 return;
738 }
Pekka Jaaskelainen1db1da22013-10-12 09:29:48 +0000739 SourceLocation StateLoc = Tok.getLocation();
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +0000740
Eli Friedman68be1642012-10-04 02:36:51 +0000741 PP.Lex(Tok);
742 if (Tok.isNot(tok::eod)) {
743 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
744 "OPENCL EXTENSION";
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +0000745 return;
746 }
Eli Friedman68be1642012-10-04 02:36:51 +0000747
748 OpenCLExtData data(ename, state);
749 Token *Toks =
750 (Token*) PP.getPreprocessorAllocator().Allocate(
751 sizeof(Token) * 1, llvm::alignOf<Token>());
752 new (Toks) Token();
753 Toks[0].startToken();
754 Toks[0].setKind(tok::annot_pragma_opencl_extension);
755 Toks[0].setLocation(NameLoc);
756 Toks[0].setAnnotationValue(data.getOpaqueValue());
757 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
758 /*OwnsTokens=*/false);
Pekka Jaaskelainen1db1da22013-10-12 09:29:48 +0000759
760 if (PP.getPPCallbacks())
761 PP.getPPCallbacks()->PragmaOpenCLExtension(NameLoc, ename,
762 StateLoc, state);
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +0000763}
764
Alexey Bataeva769e072013-03-22 06:34:35 +0000765/// \brief Handle '#pragma omp ...' when OpenMP is disabled.
766///
767void
768PragmaNoOpenMPHandler::HandlePragma(Preprocessor &PP,
769 PragmaIntroducerKind Introducer,
770 Token &FirstTok) {
771 if (PP.getDiagnostics().getDiagnosticLevel(diag::warn_pragma_omp_ignored,
772 FirstTok.getLocation()) !=
773 DiagnosticsEngine::Ignored) {
774 PP.Diag(FirstTok, diag::warn_pragma_omp_ignored);
775 PP.getDiagnostics().setDiagnosticMapping(diag::warn_pragma_omp_ignored,
776 diag::MAP_IGNORE,
777 SourceLocation());
778 }
779 PP.DiscardUntilEndOfDirective();
780}
781
782/// \brief Handle '#pragma omp ...' when OpenMP is enabled.
783///
784void
785PragmaOpenMPHandler::HandlePragma(Preprocessor &PP,
786 PragmaIntroducerKind Introducer,
787 Token &FirstTok) {
788 SmallVector<Token, 16> Pragma;
789 Token Tok;
790 Tok.startToken();
791 Tok.setKind(tok::annot_pragma_openmp);
792 Tok.setLocation(FirstTok.getLocation());
793
794 while (Tok.isNot(tok::eod)) {
795 Pragma.push_back(Tok);
796 PP.Lex(Tok);
797 }
798 SourceLocation EodLoc = Tok.getLocation();
799 Tok.startToken();
800 Tok.setKind(tok::annot_pragma_openmp_end);
801 Tok.setLocation(EodLoc);
802 Pragma.push_back(Tok);
803
804 Token *Toks = new Token[Pragma.size()];
805 std::copy(Pragma.begin(), Pragma.end(), Toks);
806 PP.EnterTokenStream(Toks, Pragma.size(),
807 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/true);
808}
Reid Kleckner002562a2013-05-06 21:02:12 +0000809
David Majnemer4bb09802014-02-10 19:50:15 +0000810/// \brief Handle '#pragma pointers_to_members'
811// The grammar for this pragma is as follows:
812//
813// <inheritance model> ::= ('single' | 'multiple' | 'virtual') '_inheritance'
814//
815// #pragma pointers_to_members '(' 'best_case' ')'
816// #pragma pointers_to_members '(' 'full_generality' [',' inheritance-model] ')'
817// #pragma pointers_to_members '(' inheritance-model ')'
818void PragmaMSPointersToMembers::HandlePragma(Preprocessor &PP,
819 PragmaIntroducerKind Introducer,
820 Token &Tok) {
821 SourceLocation PointersToMembersLoc = Tok.getLocation();
822 PP.Lex(Tok);
823 if (Tok.isNot(tok::l_paren)) {
824 PP.Diag(PointersToMembersLoc, diag::warn_pragma_expected_lparen)
825 << "pointers_to_members";
826 return;
827 }
828 PP.Lex(Tok);
829 const IdentifierInfo *Arg = Tok.getIdentifierInfo();
830 if (!Arg) {
831 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
832 << "pointers_to_members";
833 return;
834 }
835 PP.Lex(Tok);
836
David Majnemer86c318f2014-02-11 21:05:00 +0000837 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod;
David Majnemer4bb09802014-02-10 19:50:15 +0000838 if (Arg->isStr("best_case")) {
David Majnemer86c318f2014-02-11 21:05:00 +0000839 RepresentationMethod = LangOptions::PPTMK_BestCase;
David Majnemer4bb09802014-02-10 19:50:15 +0000840 } else {
841 if (Arg->isStr("full_generality")) {
842 if (Tok.is(tok::comma)) {
843 PP.Lex(Tok);
844
845 Arg = Tok.getIdentifierInfo();
846 if (!Arg) {
847 PP.Diag(Tok.getLocation(),
848 diag::err_pragma_pointers_to_members_unknown_kind)
849 << Tok.getKind() << /*OnlyInheritanceModels*/ 0;
850 return;
851 }
852 PP.Lex(Tok);
853 } else if (Tok.is(tok::r_paren)) {
854 // #pragma pointers_to_members(full_generality) implicitly specifies
855 // virtual_inheritance.
856 Arg = 0;
David Majnemer86c318f2014-02-11 21:05:00 +0000857 RepresentationMethod = LangOptions::PPTMK_FullGeneralityVirtualInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +0000858 } else {
859 PP.Diag(Tok.getLocation(), diag::err_expected_punc)
860 << "full_generality";
861 return;
862 }
863 }
864
865 if (Arg) {
866 if (Arg->isStr("single_inheritance")) {
David Majnemer86c318f2014-02-11 21:05:00 +0000867 RepresentationMethod =
868 LangOptions::PPTMK_FullGeneralitySingleInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +0000869 } else if (Arg->isStr("multiple_inheritance")) {
David Majnemer86c318f2014-02-11 21:05:00 +0000870 RepresentationMethod =
871 LangOptions::PPTMK_FullGeneralityMultipleInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +0000872 } else if (Arg->isStr("virtual_inheritance")) {
David Majnemer86c318f2014-02-11 21:05:00 +0000873 RepresentationMethod =
874 LangOptions::PPTMK_FullGeneralityVirtualInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +0000875 } else {
876 PP.Diag(Tok.getLocation(),
877 diag::err_pragma_pointers_to_members_unknown_kind)
878 << Arg << /*HasPointerDeclaration*/ 1;
879 return;
880 }
881 }
882 }
883
884 if (Tok.isNot(tok::r_paren)) {
885 PP.Diag(Tok.getLocation(), diag::err_expected_rparen_after)
886 << (Arg ? Arg->getName() : "full_generality");
887 return;
888 }
889
890 PP.Lex(Tok);
891 if (Tok.isNot(tok::eod)) {
892 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
893 << "pointers_to_members";
894 return;
895 }
896
897 Token AnnotTok;
898 AnnotTok.startToken();
899 AnnotTok.setKind(tok::annot_pragma_ms_pointers_to_members);
900 AnnotTok.setLocation(PointersToMembersLoc);
901 AnnotTok.setAnnotationValue(
902 reinterpret_cast<void *>(static_cast<uintptr_t>(RepresentationMethod)));
903 PP.EnterToken(AnnotTok);
904}
905
Aaron Ballman5d041be2013-06-04 02:07:14 +0000906/// \brief Handle the Microsoft \#pragma detect_mismatch extension.
907///
908/// The syntax is:
909/// \code
910/// #pragma detect_mismatch("name", "value")
911/// \endcode
912/// Where 'name' and 'value' are quoted strings. The values are embedded in
913/// the object file and passed along to the linker. If the linker detects a
914/// mismatch in the object file's values for the given name, a LNK2038 error
915/// is emitted. See MSDN for more details.
916void PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP,
917 PragmaIntroducerKind Introducer,
918 Token &Tok) {
919 SourceLocation CommentLoc = Tok.getLocation();
920 PP.Lex(Tok);
921 if (Tok.isNot(tok::l_paren)) {
Alp Tokerec543272013-12-24 09:48:30 +0000922 PP.Diag(CommentLoc, diag::err_expected) << tok::l_paren;
Aaron Ballman5d041be2013-06-04 02:07:14 +0000923 return;
924 }
925
926 // Read the name to embed, which must be a string literal.
927 std::string NameString;
928 if (!PP.LexStringLiteral(Tok, NameString,
929 "pragma detect_mismatch",
930 /*MacroExpansion=*/true))
931 return;
932
933 // Read the comma followed by a second string literal.
934 std::string ValueString;
935 if (Tok.isNot(tok::comma)) {
936 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
937 return;
938 }
939
940 if (!PP.LexStringLiteral(Tok, ValueString, "pragma detect_mismatch",
941 /*MacroExpansion=*/true))
942 return;
943
944 if (Tok.isNot(tok::r_paren)) {
Alp Tokerec543272013-12-24 09:48:30 +0000945 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
Aaron Ballman5d041be2013-06-04 02:07:14 +0000946 return;
947 }
948 PP.Lex(Tok); // Eat the r_paren.
949
950 if (Tok.isNot(tok::eod)) {
951 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
952 return;
953 }
954
955 // If the pragma is lexically sound, notify any interested PPCallbacks.
956 if (PP.getPPCallbacks())
957 PP.getPPCallbacks()->PragmaDetectMismatch(CommentLoc, NameString,
958 ValueString);
959
960 Actions.ActOnPragmaDetectMismatch(NameString, ValueString);
961}
962
Reid Kleckner002562a2013-05-06 21:02:12 +0000963/// \brief Handle the microsoft \#pragma comment extension.
964///
965/// The syntax is:
966/// \code
967/// #pragma comment(linker, "foo")
968/// \endcode
969/// 'linker' is one of five identifiers: compiler, exestr, lib, linker, user.
970/// "foo" is a string, which is fully macro expanded, and permits string
971/// concatenation, embedded escape characters etc. See MSDN for more details.
972void PragmaCommentHandler::HandlePragma(Preprocessor &PP,
973 PragmaIntroducerKind Introducer,
974 Token &Tok) {
975 SourceLocation CommentLoc = Tok.getLocation();
976 PP.Lex(Tok);
977 if (Tok.isNot(tok::l_paren)) {
978 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
979 return;
980 }
981
982 // Read the identifier.
983 PP.Lex(Tok);
984 if (Tok.isNot(tok::identifier)) {
985 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
986 return;
987 }
988
989 // Verify that this is one of the 5 whitelisted options.
Reid Klecknere43f0fe2013-05-08 13:44:39 +0000990 IdentifierInfo *II = Tok.getIdentifierInfo();
991 Sema::PragmaMSCommentKind Kind =
992 llvm::StringSwitch<Sema::PragmaMSCommentKind>(II->getName())
993 .Case("linker", Sema::PCK_Linker)
994 .Case("lib", Sema::PCK_Lib)
995 .Case("compiler", Sema::PCK_Compiler)
996 .Case("exestr", Sema::PCK_ExeStr)
997 .Case("user", Sema::PCK_User)
998 .Default(Sema::PCK_Unknown);
999 if (Kind == Sema::PCK_Unknown) {
Reid Kleckner002562a2013-05-06 21:02:12 +00001000 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_unknown_kind);
1001 return;
1002 }
1003
1004 // Read the optional string if present.
1005 PP.Lex(Tok);
1006 std::string ArgumentString;
1007 if (Tok.is(tok::comma) && !PP.LexStringLiteral(Tok, ArgumentString,
1008 "pragma comment",
1009 /*MacroExpansion=*/true))
1010 return;
1011
Reid Klecknere43f0fe2013-05-08 13:44:39 +00001012 // FIXME: warn that 'exestr' is deprecated.
Reid Kleckner002562a2013-05-06 21:02:12 +00001013 // FIXME: If the kind is "compiler" warn if the string is present (it is
1014 // ignored).
Reid Klecknere43f0fe2013-05-08 13:44:39 +00001015 // The MSDN docs say that "lib" and "linker" require a string and have a short
1016 // whitelist of linker options they support, but in practice MSVC doesn't
1017 // issue a diagnostic. Therefore neither does clang.
Reid Kleckner002562a2013-05-06 21:02:12 +00001018
1019 if (Tok.isNot(tok::r_paren)) {
1020 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
1021 return;
1022 }
1023 PP.Lex(Tok); // eat the r_paren.
1024
1025 if (Tok.isNot(tok::eod)) {
1026 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
1027 return;
1028 }
1029
1030 // If the pragma is lexically sound, notify any interested PPCallbacks.
1031 if (PP.getPPCallbacks())
1032 PP.getPPCallbacks()->PragmaComment(CommentLoc, II, ArgumentString);
Reid Klecknere43f0fe2013-05-08 13:44:39 +00001033
1034 Actions.ActOnPragmaMSComment(Kind, ArgumentString);
Reid Kleckner002562a2013-05-06 21:02:12 +00001035}