blob: 90929d69188eb321d002a874612e5b73085188d7 [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
Reid Klecknerc0dca6d2014-02-12 23:50:26 +0000192void Parser::HandlePragmaMSVtorDisp() {
193 assert(Tok.is(tok::annot_pragma_ms_vtordisp));
194 uintptr_t Value = reinterpret_cast<uintptr_t>(Tok.getAnnotationValue());
195 Sema::PragmaVtorDispKind Kind =
196 static_cast<Sema::PragmaVtorDispKind>((Value >> 16) & 0xFFFF);
197 MSVtorDispAttr::Mode Mode = MSVtorDispAttr::Mode(Value & 0xFFFF);
198 SourceLocation PragmaLoc = ConsumeToken(); // The annotation token.
199 Actions.ActOnPragmaMSVtorDisp(Kind, PragmaLoc, Mode);
200}
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000201
Eli Friedman570024a2010-08-05 06:57:20 +0000202// #pragma GCC visibility comes in two variants:
203// 'push' '(' [visibility] ')'
204// 'pop'
Douglas Gregorc7d65762010-09-09 22:45:38 +0000205void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,
206 PragmaIntroducerKind Introducer,
207 Token &VisTok) {
Eli Friedman570024a2010-08-05 06:57:20 +0000208 SourceLocation VisLoc = VisTok.getLocation();
209
210 Token Tok;
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +0000211 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +0000212
213 const IdentifierInfo *PushPop = Tok.getIdentifierInfo();
214
Eli Friedman570024a2010-08-05 06:57:20 +0000215 const IdentifierInfo *VisType;
216 if (PushPop && PushPop->isStr("pop")) {
Eli Friedman570024a2010-08-05 06:57:20 +0000217 VisType = 0;
218 } else if (PushPop && PushPop->isStr("push")) {
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +0000219 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +0000220 if (Tok.isNot(tok::l_paren)) {
221 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
222 << "visibility";
223 return;
224 }
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +0000225 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +0000226 VisType = Tok.getIdentifierInfo();
227 if (!VisType) {
228 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
229 << "visibility";
230 return;
231 }
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +0000232 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +0000233 if (Tok.isNot(tok::r_paren)) {
234 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
235 << "visibility";
236 return;
237 }
238 } else {
239 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
240 << "visibility";
241 return;
242 }
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +0000243 PP.LexUnexpandedToken(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +0000244 if (Tok.isNot(tok::eod)) {
Eli Friedman570024a2010-08-05 06:57:20 +0000245 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
246 << "visibility";
247 return;
248 }
249
Rafael Espindola273fd772012-01-26 02:02:57 +0000250 Token *Toks = new Token[1];
251 Toks[0].startToken();
252 Toks[0].setKind(tok::annot_pragma_vis);
253 Toks[0].setLocation(VisLoc);
254 Toks[0].setAnnotationValue(
255 const_cast<void*>(static_cast<const void*>(VisType)));
256 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
257 /*OwnsTokens=*/true);
Eli Friedman570024a2010-08-05 06:57:20 +0000258}
259
Daniel Dunbar921b9682008-10-04 19:21:03 +0000260// #pragma pack(...) comes in the following delicious flavors:
261// pack '(' [integer] ')'
262// pack '(' 'show' ')'
263// pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'
Douglas Gregorc7d65762010-09-09 22:45:38 +0000264void PragmaPackHandler::HandlePragma(Preprocessor &PP,
265 PragmaIntroducerKind Introducer,
266 Token &PackTok) {
Daniel Dunbar921b9682008-10-04 19:21:03 +0000267 SourceLocation PackLoc = PackTok.getLocation();
268
269 Token Tok;
270 PP.Lex(Tok);
271 if (Tok.isNot(tok::l_paren)) {
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000272 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack";
Daniel Dunbar921b9682008-10-04 19:21:03 +0000273 return;
274 }
275
John McCallfaf5fb42010-08-26 23:41:50 +0000276 Sema::PragmaPackKind Kind = Sema::PPK_Default;
Daniel Dunbar921b9682008-10-04 19:21:03 +0000277 IdentifierInfo *Name = 0;
Eli Friedman68be1642012-10-04 02:36:51 +0000278 Token Alignment;
279 Alignment.startToken();
Daniel Dunbar921b9682008-10-04 19:21:03 +0000280 SourceLocation LParenLoc = Tok.getLocation();
Mike Stump11289f42009-09-09 15:08:12 +0000281 PP.Lex(Tok);
Daniel Dunbar921b9682008-10-04 19:21:03 +0000282 if (Tok.is(tok::numeric_constant)) {
Eli Friedman68be1642012-10-04 02:36:51 +0000283 Alignment = Tok;
Daniel Dunbar921b9682008-10-04 19:21:03 +0000284
285 PP.Lex(Tok);
Eli Friedman055c9702011-11-02 01:53:16 +0000286
287 // In MSVC/gcc, #pragma pack(4) sets the alignment without affecting
288 // the push/pop stack.
289 // In Apple gcc, #pragma pack(4) is equivalent to #pragma pack(push, 4)
David Blaikiebbafb8a2012-03-11 07:00:24 +0000290 if (PP.getLangOpts().ApplePragmaPack)
Eli Friedman055c9702011-11-02 01:53:16 +0000291 Kind = Sema::PPK_Push;
Daniel Dunbar921b9682008-10-04 19:21:03 +0000292 } else if (Tok.is(tok::identifier)) {
293 const IdentifierInfo *II = Tok.getIdentifierInfo();
Chris Lattnere3d20d92008-11-23 21:45:46 +0000294 if (II->isStr("show")) {
John McCallfaf5fb42010-08-26 23:41:50 +0000295 Kind = Sema::PPK_Show;
Daniel Dunbar921b9682008-10-04 19:21:03 +0000296 PP.Lex(Tok);
297 } else {
Chris Lattnere3d20d92008-11-23 21:45:46 +0000298 if (II->isStr("push")) {
John McCallfaf5fb42010-08-26 23:41:50 +0000299 Kind = Sema::PPK_Push;
Chris Lattnere3d20d92008-11-23 21:45:46 +0000300 } else if (II->isStr("pop")) {
John McCallfaf5fb42010-08-26 23:41:50 +0000301 Kind = Sema::PPK_Pop;
Daniel Dunbar921b9682008-10-04 19:21:03 +0000302 } else {
Reid Klecknerc0dca6d2014-02-12 23:50:26 +0000303 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action) << "pack";
Daniel Dunbar921b9682008-10-04 19:21:03 +0000304 return;
Mike Stump11289f42009-09-09 15:08:12 +0000305 }
Daniel Dunbar921b9682008-10-04 19:21:03 +0000306 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +0000307
Daniel Dunbar921b9682008-10-04 19:21:03 +0000308 if (Tok.is(tok::comma)) {
309 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +0000310
Daniel Dunbar921b9682008-10-04 19:21:03 +0000311 if (Tok.is(tok::numeric_constant)) {
Eli Friedman68be1642012-10-04 02:36:51 +0000312 Alignment = Tok;
Daniel Dunbar921b9682008-10-04 19:21:03 +0000313
314 PP.Lex(Tok);
315 } else if (Tok.is(tok::identifier)) {
316 Name = Tok.getIdentifierInfo();
317 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +0000318
Daniel Dunbar921b9682008-10-04 19:21:03 +0000319 if (Tok.is(tok::comma)) {
320 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +0000321
Daniel Dunbar921b9682008-10-04 19:21:03 +0000322 if (Tok.isNot(tok::numeric_constant)) {
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 }
Mike Stump11289f42009-09-09 15:08:12 +0000326
Eli Friedman68be1642012-10-04 02:36:51 +0000327 Alignment = Tok;
Daniel Dunbar921b9682008-10-04 19:21:03 +0000328
329 PP.Lex(Tok);
330 }
331 } else {
Chris Lattnere3d20d92008-11-23 21:45:46 +0000332 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbar921b9682008-10-04 19:21:03 +0000333 return;
334 }
335 }
336 }
David Blaikiebbafb8a2012-03-11 07:00:24 +0000337 } else if (PP.getLangOpts().ApplePragmaPack) {
Eli Friedman055c9702011-11-02 01:53:16 +0000338 // In MSVC/gcc, #pragma pack() resets the alignment without affecting
339 // the push/pop stack.
340 // In Apple gcc #pragma pack() is equivalent to #pragma pack(pop).
341 Kind = Sema::PPK_Pop;
Sebastian Redl17f2c7d2008-12-09 13:15:23 +0000342 }
Daniel Dunbar921b9682008-10-04 19:21:03 +0000343
344 if (Tok.isNot(tok::r_paren)) {
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000345 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack";
Daniel Dunbar921b9682008-10-04 19:21:03 +0000346 return;
347 }
348
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000349 SourceLocation RParenLoc = Tok.getLocation();
Eli Friedmanf5867dd2009-06-05 00:49:58 +0000350 PP.Lex(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +0000351 if (Tok.isNot(tok::eod)) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +0000352 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack";
353 return;
354 }
355
Daniel Dunbar340cf242012-02-29 01:38:22 +0000356 PragmaPackInfo *Info =
357 (PragmaPackInfo*) PP.getPreprocessorAllocator().Allocate(
358 sizeof(PragmaPackInfo), llvm::alignOf<PragmaPackInfo>());
359 new (Info) PragmaPackInfo();
Eli Friedmanec52f922012-02-23 23:47:16 +0000360 Info->Kind = Kind;
361 Info->Name = Name;
Eli Friedman68be1642012-10-04 02:36:51 +0000362 Info->Alignment = Alignment;
Eli Friedmanec52f922012-02-23 23:47:16 +0000363 Info->LParenLoc = LParenLoc;
364 Info->RParenLoc = RParenLoc;
365
Daniel Dunbar340cf242012-02-29 01:38:22 +0000366 Token *Toks =
367 (Token*) PP.getPreprocessorAllocator().Allocate(
368 sizeof(Token) * 1, llvm::alignOf<Token>());
369 new (Toks) Token();
Eli Friedmanec52f922012-02-23 23:47:16 +0000370 Toks[0].startToken();
371 Toks[0].setKind(tok::annot_pragma_pack);
372 Toks[0].setLocation(PackLoc);
373 Toks[0].setAnnotationValue(static_cast<void*>(Info));
374 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
Daniel Dunbar340cf242012-02-29 01:38:22 +0000375 /*OwnsTokens=*/false);
Daniel Dunbar921b9682008-10-04 19:21:03 +0000376}
377
Fariborz Jahanian743dda42011-04-25 18:49:15 +0000378// #pragma ms_struct on
379// #pragma ms_struct off
380void PragmaMSStructHandler::HandlePragma(Preprocessor &PP,
381 PragmaIntroducerKind Introducer,
382 Token &MSStructTok) {
383 Sema::PragmaMSStructKind Kind = Sema::PMSST_OFF;
384
385 Token Tok;
386 PP.Lex(Tok);
387 if (Tok.isNot(tok::identifier)) {
388 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
389 return;
390 }
391 const IdentifierInfo *II = Tok.getIdentifierInfo();
392 if (II->isStr("on")) {
393 Kind = Sema::PMSST_ON;
394 PP.Lex(Tok);
395 }
396 else if (II->isStr("off") || II->isStr("reset"))
397 PP.Lex(Tok);
398 else {
399 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
400 return;
401 }
402
403 if (Tok.isNot(tok::eod)) {
Daniel Dunbar340cf242012-02-29 01:38:22 +0000404 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
405 << "ms_struct";
Fariborz Jahanian743dda42011-04-25 18:49:15 +0000406 return;
407 }
Eli Friedman68be1642012-10-04 02:36:51 +0000408
409 Token *Toks =
410 (Token*) PP.getPreprocessorAllocator().Allocate(
411 sizeof(Token) * 1, llvm::alignOf<Token>());
412 new (Toks) Token();
413 Toks[0].startToken();
414 Toks[0].setKind(tok::annot_pragma_msstruct);
415 Toks[0].setLocation(MSStructTok.getLocation());
416 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
417 static_cast<uintptr_t>(Kind)));
418 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
419 /*OwnsTokens=*/false);
Fariborz Jahanian743dda42011-04-25 18:49:15 +0000420}
421
Daniel Dunbarcb82acb2010-07-31 19:17:07 +0000422// #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
423// #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
Eli Friedman68be1642012-10-04 02:36:51 +0000424static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok,
Daniel Dunbarcb82acb2010-07-31 19:17:07 +0000425 bool IsOptions) {
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000426 Token Tok;
Daniel Dunbarcb82acb2010-07-31 19:17:07 +0000427
428 if (IsOptions) {
429 PP.Lex(Tok);
430 if (Tok.isNot(tok::identifier) ||
431 !Tok.getIdentifierInfo()->isStr("align")) {
432 PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align);
433 return;
434 }
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000435 }
Daniel Dunbar663e8092010-05-27 18:42:09 +0000436
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000437 PP.Lex(Tok);
438 if (Tok.isNot(tok::equal)) {
Daniel Dunbarcb82acb2010-07-31 19:17:07 +0000439 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal)
440 << IsOptions;
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000441 return;
442 }
443
444 PP.Lex(Tok);
445 if (Tok.isNot(tok::identifier)) {
446 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Daniel Dunbarcb82acb2010-07-31 19:17:07 +0000447 << (IsOptions ? "options" : "align");
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000448 return;
449 }
450
John McCallfaf5fb42010-08-26 23:41:50 +0000451 Sema::PragmaOptionsAlignKind Kind = Sema::POAK_Natural;
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000452 const IdentifierInfo *II = Tok.getIdentifierInfo();
Daniel Dunbar663e8092010-05-27 18:42:09 +0000453 if (II->isStr("native"))
John McCallfaf5fb42010-08-26 23:41:50 +0000454 Kind = Sema::POAK_Native;
Daniel Dunbar663e8092010-05-27 18:42:09 +0000455 else if (II->isStr("natural"))
John McCallfaf5fb42010-08-26 23:41:50 +0000456 Kind = Sema::POAK_Natural;
Daniel Dunbar9c84d4a2010-05-27 18:42:17 +0000457 else if (II->isStr("packed"))
John McCallfaf5fb42010-08-26 23:41:50 +0000458 Kind = Sema::POAK_Packed;
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000459 else if (II->isStr("power"))
John McCallfaf5fb42010-08-26 23:41:50 +0000460 Kind = Sema::POAK_Power;
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000461 else if (II->isStr("mac68k"))
John McCallfaf5fb42010-08-26 23:41:50 +0000462 Kind = Sema::POAK_Mac68k;
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000463 else if (II->isStr("reset"))
John McCallfaf5fb42010-08-26 23:41:50 +0000464 Kind = Sema::POAK_Reset;
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000465 else {
Daniel Dunbarcb82acb2010-07-31 19:17:07 +0000466 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option)
467 << IsOptions;
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000468 return;
469 }
470
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000471 PP.Lex(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +0000472 if (Tok.isNot(tok::eod)) {
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000473 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
Daniel Dunbarcb82acb2010-07-31 19:17:07 +0000474 << (IsOptions ? "options" : "align");
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000475 return;
476 }
477
Eli Friedman68be1642012-10-04 02:36:51 +0000478 Token *Toks =
479 (Token*) PP.getPreprocessorAllocator().Allocate(
480 sizeof(Token) * 1, llvm::alignOf<Token>());
481 new (Toks) Token();
482 Toks[0].startToken();
483 Toks[0].setKind(tok::annot_pragma_align);
484 Toks[0].setLocation(FirstTok.getLocation());
485 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
486 static_cast<uintptr_t>(Kind)));
487 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
488 /*OwnsTokens=*/false);
Daniel Dunbarcb82acb2010-07-31 19:17:07 +0000489}
490
Douglas Gregorc7d65762010-09-09 22:45:38 +0000491void PragmaAlignHandler::HandlePragma(Preprocessor &PP,
492 PragmaIntroducerKind Introducer,
493 Token &AlignTok) {
Eli Friedman68be1642012-10-04 02:36:51 +0000494 ParseAlignPragma(PP, AlignTok, /*IsOptions=*/false);
Daniel Dunbarcb82acb2010-07-31 19:17:07 +0000495}
496
Douglas Gregorc7d65762010-09-09 22:45:38 +0000497void PragmaOptionsHandler::HandlePragma(Preprocessor &PP,
498 PragmaIntroducerKind Introducer,
499 Token &OptionsTok) {
Eli Friedman68be1642012-10-04 02:36:51 +0000500 ParseAlignPragma(PP, OptionsTok, /*IsOptions=*/true);
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000501}
502
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000503// #pragma unused(identifier)
Douglas Gregorc7d65762010-09-09 22:45:38 +0000504void PragmaUnusedHandler::HandlePragma(Preprocessor &PP,
505 PragmaIntroducerKind Introducer,
506 Token &UnusedTok) {
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000507 // FIXME: Should we be expanding macros here? My guess is no.
508 SourceLocation UnusedLoc = UnusedTok.getLocation();
Mike Stump11289f42009-09-09 15:08:12 +0000509
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000510 // Lex the left '('.
511 Token Tok;
512 PP.Lex(Tok);
513 if (Tok.isNot(tok::l_paren)) {
514 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
515 return;
516 }
Mike Stump11289f42009-09-09 15:08:12 +0000517
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000518 // Lex the declaration reference(s).
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000519 SmallVector<Token, 5> Identifiers;
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000520 SourceLocation RParenLoc;
521 bool LexID = true;
Mike Stump11289f42009-09-09 15:08:12 +0000522
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000523 while (true) {
524 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +0000525
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000526 if (LexID) {
Mike Stump11289f42009-09-09 15:08:12 +0000527 if (Tok.is(tok::identifier)) {
Ted Kremenekfb50bf52009-08-03 23:24:57 +0000528 Identifiers.push_back(Tok);
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000529 LexID = false;
530 continue;
531 }
532
Ted Kremenekfb50bf52009-08-03 23:24:57 +0000533 // Illegal token!
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000534 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
535 return;
536 }
Mike Stump11289f42009-09-09 15:08:12 +0000537
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000538 // We are execting a ')' or a ','.
539 if (Tok.is(tok::comma)) {
540 LexID = true;
541 continue;
542 }
Mike Stump11289f42009-09-09 15:08:12 +0000543
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000544 if (Tok.is(tok::r_paren)) {
545 RParenLoc = Tok.getLocation();
546 break;
547 }
Mike Stump11289f42009-09-09 15:08:12 +0000548
Ted Kremenekfb50bf52009-08-03 23:24:57 +0000549 // Illegal token!
David Majnemer88969812014-02-10 19:06:37 +0000550 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_punc) << "unused";
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000551 return;
552 }
Eli Friedmanf5867dd2009-06-05 00:49:58 +0000553
554 PP.Lex(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +0000555 if (Tok.isNot(tok::eod)) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +0000556 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
557 "unused";
558 return;
559 }
560
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000561 // Verify that we have a location for the right parenthesis.
562 assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
Ted Kremenekfb50bf52009-08-03 23:24:57 +0000563 assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000564
Argyrios Kyrtzidisee569622011-01-17 18:58:44 +0000565 // For each identifier token, insert into the token stream a
566 // annot_pragma_unused token followed by the identifier token.
567 // This allows us to cache a "#pragma unused" that occurs inside an inline
568 // C++ member function.
569
Daniel Dunbar340cf242012-02-29 01:38:22 +0000570 Token *Toks =
571 (Token*) PP.getPreprocessorAllocator().Allocate(
572 sizeof(Token) * 2 * Identifiers.size(), llvm::alignOf<Token>());
Argyrios Kyrtzidisee569622011-01-17 18:58:44 +0000573 for (unsigned i=0; i != Identifiers.size(); i++) {
574 Token &pragmaUnusedTok = Toks[2*i], &idTok = Toks[2*i+1];
575 pragmaUnusedTok.startToken();
576 pragmaUnusedTok.setKind(tok::annot_pragma_unused);
577 pragmaUnusedTok.setLocation(UnusedLoc);
578 idTok = Identifiers[i];
579 }
Daniel Dunbar340cf242012-02-29 01:38:22 +0000580 PP.EnterTokenStream(Toks, 2*Identifiers.size(),
581 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000582}
Eli Friedmanf5867dd2009-06-05 00:49:58 +0000583
584// #pragma weak identifier
585// #pragma weak identifier '=' identifier
Douglas Gregorc7d65762010-09-09 22:45:38 +0000586void PragmaWeakHandler::HandlePragma(Preprocessor &PP,
587 PragmaIntroducerKind Introducer,
588 Token &WeakTok) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +0000589 SourceLocation WeakLoc = WeakTok.getLocation();
590
591 Token Tok;
592 PP.Lex(Tok);
593 if (Tok.isNot(tok::identifier)) {
594 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";
595 return;
596 }
597
Eli Friedman68be1642012-10-04 02:36:51 +0000598 Token WeakName = Tok;
599 bool HasAlias = false;
600 Token AliasName;
Eli Friedmanf5867dd2009-06-05 00:49:58 +0000601
602 PP.Lex(Tok);
603 if (Tok.is(tok::equal)) {
Eli Friedman68be1642012-10-04 02:36:51 +0000604 HasAlias = true;
Eli Friedmanf5867dd2009-06-05 00:49:58 +0000605 PP.Lex(Tok);
606 if (Tok.isNot(tok::identifier)) {
Mike Stump11289f42009-09-09 15:08:12 +0000607 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Eli Friedmanf5867dd2009-06-05 00:49:58 +0000608 << "weak";
609 return;
610 }
Eli Friedman68be1642012-10-04 02:36:51 +0000611 AliasName = Tok;
Eli Friedmanf5867dd2009-06-05 00:49:58 +0000612 PP.Lex(Tok);
613 }
614
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +0000615 if (Tok.isNot(tok::eod)) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +0000616 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";
617 return;
618 }
619
Eli Friedman68be1642012-10-04 02:36:51 +0000620 if (HasAlias) {
621 Token *Toks =
622 (Token*) PP.getPreprocessorAllocator().Allocate(
623 sizeof(Token) * 3, llvm::alignOf<Token>());
624 Token &pragmaUnusedTok = Toks[0];
625 pragmaUnusedTok.startToken();
626 pragmaUnusedTok.setKind(tok::annot_pragma_weakalias);
627 pragmaUnusedTok.setLocation(WeakLoc);
628 Toks[1] = WeakName;
629 Toks[2] = AliasName;
630 PP.EnterTokenStream(Toks, 3,
631 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
Eli Friedmanf5867dd2009-06-05 00:49:58 +0000632 } else {
Eli Friedman68be1642012-10-04 02:36:51 +0000633 Token *Toks =
634 (Token*) PP.getPreprocessorAllocator().Allocate(
635 sizeof(Token) * 2, llvm::alignOf<Token>());
636 Token &pragmaUnusedTok = Toks[0];
637 pragmaUnusedTok.startToken();
638 pragmaUnusedTok.setKind(tok::annot_pragma_weak);
639 pragmaUnusedTok.setLocation(WeakLoc);
640 Toks[1] = WeakName;
641 PP.EnterTokenStream(Toks, 2,
642 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
Eli Friedmanf5867dd2009-06-05 00:49:58 +0000643 }
644}
Peter Collingbourne564c0fa2011-02-14 01:42:35 +0000645
David Chisnall0867d9c2012-02-18 16:12:34 +0000646// #pragma redefine_extname identifier identifier
647void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP,
648 PragmaIntroducerKind Introducer,
649 Token &RedefToken) {
650 SourceLocation RedefLoc = RedefToken.getLocation();
651
652 Token Tok;
653 PP.Lex(Tok);
654 if (Tok.isNot(tok::identifier)) {
655 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
656 "redefine_extname";
657 return;
658 }
659
Eli Friedman68be1642012-10-04 02:36:51 +0000660 Token RedefName = Tok;
David Chisnall0867d9c2012-02-18 16:12:34 +0000661 PP.Lex(Tok);
Eli Friedman68be1642012-10-04 02:36:51 +0000662
David Chisnall0867d9c2012-02-18 16:12:34 +0000663 if (Tok.isNot(tok::identifier)) {
664 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
665 << "redefine_extname";
666 return;
667 }
Eli Friedman68be1642012-10-04 02:36:51 +0000668
669 Token AliasName = Tok;
David Chisnall0867d9c2012-02-18 16:12:34 +0000670 PP.Lex(Tok);
671
672 if (Tok.isNot(tok::eod)) {
673 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
674 "redefine_extname";
675 return;
676 }
677
Eli Friedman68be1642012-10-04 02:36:51 +0000678 Token *Toks =
679 (Token*) PP.getPreprocessorAllocator().Allocate(
680 sizeof(Token) * 3, llvm::alignOf<Token>());
681 Token &pragmaRedefTok = Toks[0];
682 pragmaRedefTok.startToken();
683 pragmaRedefTok.setKind(tok::annot_pragma_redefine_extname);
684 pragmaRedefTok.setLocation(RedefLoc);
685 Toks[1] = RedefName;
686 Toks[2] = AliasName;
687 PP.EnterTokenStream(Toks, 3,
688 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
David Chisnall0867d9c2012-02-18 16:12:34 +0000689}
690
691
Peter Collingbourne564c0fa2011-02-14 01:42:35 +0000692void
693PragmaFPContractHandler::HandlePragma(Preprocessor &PP,
694 PragmaIntroducerKind Introducer,
695 Token &Tok) {
696 tok::OnOffSwitch OOS;
697 if (PP.LexOnOffSwitch(OOS))
698 return;
699
Eli Friedman68be1642012-10-04 02:36:51 +0000700 Token *Toks =
701 (Token*) PP.getPreprocessorAllocator().Allocate(
702 sizeof(Token) * 1, llvm::alignOf<Token>());
703 new (Toks) Token();
704 Toks[0].startToken();
705 Toks[0].setKind(tok::annot_pragma_fp_contract);
706 Toks[0].setLocation(Tok.getLocation());
707 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
708 static_cast<uintptr_t>(OOS)));
709 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
710 /*OwnsTokens=*/false);
Peter Collingbourne564c0fa2011-02-14 01:42:35 +0000711}
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +0000712
713void
714PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
715 PragmaIntroducerKind Introducer,
716 Token &Tok) {
Tanya Lattneree840b82011-04-14 23:35:31 +0000717 PP.LexUnexpandedToken(Tok);
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +0000718 if (Tok.isNot(tok::identifier)) {
719 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
720 "OPENCL";
721 return;
722 }
723 IdentifierInfo *ename = Tok.getIdentifierInfo();
724 SourceLocation NameLoc = Tok.getLocation();
725
726 PP.Lex(Tok);
727 if (Tok.isNot(tok::colon)) {
728 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << ename;
729 return;
730 }
731
732 PP.Lex(Tok);
733 if (Tok.isNot(tok::identifier)) {
734 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
735 return;
736 }
737 IdentifierInfo *op = Tok.getIdentifierInfo();
738
739 unsigned state;
740 if (op->isStr("enable")) {
741 state = 1;
742 } else if (op->isStr("disable")) {
743 state = 0;
744 } else {
745 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
746 return;
747 }
Pekka Jaaskelainen1db1da22013-10-12 09:29:48 +0000748 SourceLocation StateLoc = Tok.getLocation();
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +0000749
Eli Friedman68be1642012-10-04 02:36:51 +0000750 PP.Lex(Tok);
751 if (Tok.isNot(tok::eod)) {
752 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
753 "OPENCL EXTENSION";
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +0000754 return;
755 }
Eli Friedman68be1642012-10-04 02:36:51 +0000756
757 OpenCLExtData data(ename, state);
758 Token *Toks =
759 (Token*) PP.getPreprocessorAllocator().Allocate(
760 sizeof(Token) * 1, llvm::alignOf<Token>());
761 new (Toks) Token();
762 Toks[0].startToken();
763 Toks[0].setKind(tok::annot_pragma_opencl_extension);
764 Toks[0].setLocation(NameLoc);
765 Toks[0].setAnnotationValue(data.getOpaqueValue());
766 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
767 /*OwnsTokens=*/false);
Pekka Jaaskelainen1db1da22013-10-12 09:29:48 +0000768
769 if (PP.getPPCallbacks())
770 PP.getPPCallbacks()->PragmaOpenCLExtension(NameLoc, ename,
771 StateLoc, state);
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +0000772}
773
Alexey Bataeva769e072013-03-22 06:34:35 +0000774/// \brief Handle '#pragma omp ...' when OpenMP is disabled.
775///
776void
777PragmaNoOpenMPHandler::HandlePragma(Preprocessor &PP,
778 PragmaIntroducerKind Introducer,
779 Token &FirstTok) {
780 if (PP.getDiagnostics().getDiagnosticLevel(diag::warn_pragma_omp_ignored,
781 FirstTok.getLocation()) !=
782 DiagnosticsEngine::Ignored) {
783 PP.Diag(FirstTok, diag::warn_pragma_omp_ignored);
784 PP.getDiagnostics().setDiagnosticMapping(diag::warn_pragma_omp_ignored,
785 diag::MAP_IGNORE,
786 SourceLocation());
787 }
788 PP.DiscardUntilEndOfDirective();
789}
790
791/// \brief Handle '#pragma omp ...' when OpenMP is enabled.
792///
793void
794PragmaOpenMPHandler::HandlePragma(Preprocessor &PP,
795 PragmaIntroducerKind Introducer,
796 Token &FirstTok) {
797 SmallVector<Token, 16> Pragma;
798 Token Tok;
799 Tok.startToken();
800 Tok.setKind(tok::annot_pragma_openmp);
801 Tok.setLocation(FirstTok.getLocation());
802
803 while (Tok.isNot(tok::eod)) {
804 Pragma.push_back(Tok);
805 PP.Lex(Tok);
806 }
807 SourceLocation EodLoc = Tok.getLocation();
808 Tok.startToken();
809 Tok.setKind(tok::annot_pragma_openmp_end);
810 Tok.setLocation(EodLoc);
811 Pragma.push_back(Tok);
812
813 Token *Toks = new Token[Pragma.size()];
814 std::copy(Pragma.begin(), Pragma.end(), Toks);
815 PP.EnterTokenStream(Toks, Pragma.size(),
816 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/true);
817}
Reid Kleckner002562a2013-05-06 21:02:12 +0000818
David Majnemer4bb09802014-02-10 19:50:15 +0000819/// \brief Handle '#pragma pointers_to_members'
820// The grammar for this pragma is as follows:
821//
822// <inheritance model> ::= ('single' | 'multiple' | 'virtual') '_inheritance'
823//
824// #pragma pointers_to_members '(' 'best_case' ')'
825// #pragma pointers_to_members '(' 'full_generality' [',' inheritance-model] ')'
826// #pragma pointers_to_members '(' inheritance-model ')'
827void PragmaMSPointersToMembers::HandlePragma(Preprocessor &PP,
828 PragmaIntroducerKind Introducer,
829 Token &Tok) {
830 SourceLocation PointersToMembersLoc = Tok.getLocation();
831 PP.Lex(Tok);
832 if (Tok.isNot(tok::l_paren)) {
833 PP.Diag(PointersToMembersLoc, diag::warn_pragma_expected_lparen)
834 << "pointers_to_members";
835 return;
836 }
837 PP.Lex(Tok);
838 const IdentifierInfo *Arg = Tok.getIdentifierInfo();
839 if (!Arg) {
840 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
841 << "pointers_to_members";
842 return;
843 }
844 PP.Lex(Tok);
845
David Majnemer86c318f2014-02-11 21:05:00 +0000846 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod;
David Majnemer4bb09802014-02-10 19:50:15 +0000847 if (Arg->isStr("best_case")) {
David Majnemer86c318f2014-02-11 21:05:00 +0000848 RepresentationMethod = LangOptions::PPTMK_BestCase;
David Majnemer4bb09802014-02-10 19:50:15 +0000849 } else {
850 if (Arg->isStr("full_generality")) {
851 if (Tok.is(tok::comma)) {
852 PP.Lex(Tok);
853
854 Arg = Tok.getIdentifierInfo();
855 if (!Arg) {
856 PP.Diag(Tok.getLocation(),
857 diag::err_pragma_pointers_to_members_unknown_kind)
858 << Tok.getKind() << /*OnlyInheritanceModels*/ 0;
859 return;
860 }
861 PP.Lex(Tok);
862 } else if (Tok.is(tok::r_paren)) {
863 // #pragma pointers_to_members(full_generality) implicitly specifies
864 // virtual_inheritance.
865 Arg = 0;
David Majnemer86c318f2014-02-11 21:05:00 +0000866 RepresentationMethod = LangOptions::PPTMK_FullGeneralityVirtualInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +0000867 } else {
868 PP.Diag(Tok.getLocation(), diag::err_expected_punc)
869 << "full_generality";
870 return;
871 }
872 }
873
874 if (Arg) {
875 if (Arg->isStr("single_inheritance")) {
David Majnemer86c318f2014-02-11 21:05:00 +0000876 RepresentationMethod =
877 LangOptions::PPTMK_FullGeneralitySingleInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +0000878 } else if (Arg->isStr("multiple_inheritance")) {
David Majnemer86c318f2014-02-11 21:05:00 +0000879 RepresentationMethod =
880 LangOptions::PPTMK_FullGeneralityMultipleInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +0000881 } else if (Arg->isStr("virtual_inheritance")) {
David Majnemer86c318f2014-02-11 21:05:00 +0000882 RepresentationMethod =
883 LangOptions::PPTMK_FullGeneralityVirtualInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +0000884 } else {
885 PP.Diag(Tok.getLocation(),
886 diag::err_pragma_pointers_to_members_unknown_kind)
887 << Arg << /*HasPointerDeclaration*/ 1;
888 return;
889 }
890 }
891 }
892
893 if (Tok.isNot(tok::r_paren)) {
894 PP.Diag(Tok.getLocation(), diag::err_expected_rparen_after)
895 << (Arg ? Arg->getName() : "full_generality");
896 return;
897 }
898
899 PP.Lex(Tok);
900 if (Tok.isNot(tok::eod)) {
901 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
902 << "pointers_to_members";
903 return;
904 }
905
906 Token AnnotTok;
907 AnnotTok.startToken();
908 AnnotTok.setKind(tok::annot_pragma_ms_pointers_to_members);
909 AnnotTok.setLocation(PointersToMembersLoc);
910 AnnotTok.setAnnotationValue(
911 reinterpret_cast<void *>(static_cast<uintptr_t>(RepresentationMethod)));
912 PP.EnterToken(AnnotTok);
913}
914
Reid Klecknerc0dca6d2014-02-12 23:50:26 +0000915/// \brief Handle '#pragma vtordisp'
916// The grammar for this pragma is as follows:
917//
918// <vtordisp-mode> ::= ('off' | 'on' | '0' | '1' | '2' )
919//
920// #pragma vtordisp '(' ['push' ','] vtordisp-mode ')'
921// #pragma vtordisp '(' 'pop' ')'
922// #pragma vtordisp '(' ')'
923void PragmaMSVtorDisp::HandlePragma(Preprocessor &PP,
924 PragmaIntroducerKind Introducer,
925 Token &Tok) {
926 SourceLocation VtorDispLoc = Tok.getLocation();
927 PP.Lex(Tok);
928 if (Tok.isNot(tok::l_paren)) {
929 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_lparen) << "vtordisp";
930 return;
931 }
932 PP.Lex(Tok);
933
934 Sema::PragmaVtorDispKind Kind = Sema::PVDK_Set;
935 const IdentifierInfo *II = Tok.getIdentifierInfo();
936 if (II) {
937 if (II->isStr("push")) {
938 // #pragma vtordisp(push, mode)
939 PP.Lex(Tok);
940 if (Tok.isNot(tok::comma)) {
941 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_punc) << "vtordisp";
942 return;
943 }
944 PP.Lex(Tok);
945 Kind = Sema::PVDK_Push;
946 // not push, could be on/off
947 } else if (II->isStr("pop")) {
948 // #pragma vtordisp(pop)
949 PP.Lex(Tok);
950 Kind = Sema::PVDK_Pop;
951 }
952 // not push or pop, could be on/off
953 } else {
954 if (Tok.is(tok::r_paren)) {
955 // #pragma vtordisp()
956 Kind = Sema::PVDK_Reset;
957 }
958 }
959
960
Reid Klecknera4b3b2d2014-02-13 00:44:34 +0000961 uint64_t Value = 0;
Reid Klecknerc0dca6d2014-02-12 23:50:26 +0000962 if (Kind == Sema::PVDK_Push || Kind == Sema::PVDK_Set) {
963 const IdentifierInfo *II = Tok.getIdentifierInfo();
964 if (II && II->isStr("off")) {
965 PP.Lex(Tok);
966 Value = 0;
967 } else if (II && II->isStr("on")) {
968 PP.Lex(Tok);
969 Value = 1;
970 } else if (Tok.is(tok::numeric_constant) &&
971 PP.parseSimpleIntegerLiteral(Tok, Value)) {
972 if (Value > 2) {
973 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_integer)
974 << 0 << 2 << "vtordisp";
975 return;
976 }
977 } else {
978 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action)
979 << "vtordisp";
980 return;
981 }
982 }
983
984 // Finish the pragma: ')' $
985 if (Tok.isNot(tok::r_paren)) {
986 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_rparen) << "vtordisp";
987 return;
988 }
989 PP.Lex(Tok);
990 if (Tok.isNot(tok::eod)) {
991 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
992 << "vtordisp";
993 return;
994 }
995
996 // Enter the annotation.
997 Token AnnotTok;
998 AnnotTok.startToken();
999 AnnotTok.setKind(tok::annot_pragma_ms_vtordisp);
1000 AnnotTok.setLocation(VtorDispLoc);
Reid Klecknera4b3b2d2014-02-13 00:44:34 +00001001 AnnotTok.setAnnotationValue(reinterpret_cast<void *>(
1002 static_cast<uintptr_t>((Kind << 16) | (Value & 0xFFFF))));
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00001003 PP.EnterToken(AnnotTok);
1004}
1005
Aaron Ballman5d041be2013-06-04 02:07:14 +00001006/// \brief Handle the Microsoft \#pragma detect_mismatch extension.
1007///
1008/// The syntax is:
1009/// \code
1010/// #pragma detect_mismatch("name", "value")
1011/// \endcode
1012/// Where 'name' and 'value' are quoted strings. The values are embedded in
1013/// the object file and passed along to the linker. If the linker detects a
1014/// mismatch in the object file's values for the given name, a LNK2038 error
1015/// is emitted. See MSDN for more details.
1016void PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP,
1017 PragmaIntroducerKind Introducer,
1018 Token &Tok) {
1019 SourceLocation CommentLoc = Tok.getLocation();
1020 PP.Lex(Tok);
1021 if (Tok.isNot(tok::l_paren)) {
Alp Tokerec543272013-12-24 09:48:30 +00001022 PP.Diag(CommentLoc, diag::err_expected) << tok::l_paren;
Aaron Ballman5d041be2013-06-04 02:07:14 +00001023 return;
1024 }
1025
1026 // Read the name to embed, which must be a string literal.
1027 std::string NameString;
1028 if (!PP.LexStringLiteral(Tok, NameString,
1029 "pragma detect_mismatch",
1030 /*MacroExpansion=*/true))
1031 return;
1032
1033 // Read the comma followed by a second string literal.
1034 std::string ValueString;
1035 if (Tok.isNot(tok::comma)) {
1036 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
1037 return;
1038 }
1039
1040 if (!PP.LexStringLiteral(Tok, ValueString, "pragma detect_mismatch",
1041 /*MacroExpansion=*/true))
1042 return;
1043
1044 if (Tok.isNot(tok::r_paren)) {
Alp Tokerec543272013-12-24 09:48:30 +00001045 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
Aaron Ballman5d041be2013-06-04 02:07:14 +00001046 return;
1047 }
1048 PP.Lex(Tok); // Eat the r_paren.
1049
1050 if (Tok.isNot(tok::eod)) {
1051 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
1052 return;
1053 }
1054
1055 // If the pragma is lexically sound, notify any interested PPCallbacks.
1056 if (PP.getPPCallbacks())
1057 PP.getPPCallbacks()->PragmaDetectMismatch(CommentLoc, NameString,
1058 ValueString);
1059
1060 Actions.ActOnPragmaDetectMismatch(NameString, ValueString);
1061}
1062
Reid Kleckner002562a2013-05-06 21:02:12 +00001063/// \brief Handle the microsoft \#pragma comment extension.
1064///
1065/// The syntax is:
1066/// \code
1067/// #pragma comment(linker, "foo")
1068/// \endcode
1069/// 'linker' is one of five identifiers: compiler, exestr, lib, linker, user.
1070/// "foo" is a string, which is fully macro expanded, and permits string
1071/// concatenation, embedded escape characters etc. See MSDN for more details.
1072void PragmaCommentHandler::HandlePragma(Preprocessor &PP,
1073 PragmaIntroducerKind Introducer,
1074 Token &Tok) {
1075 SourceLocation CommentLoc = Tok.getLocation();
1076 PP.Lex(Tok);
1077 if (Tok.isNot(tok::l_paren)) {
1078 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
1079 return;
1080 }
1081
1082 // Read the identifier.
1083 PP.Lex(Tok);
1084 if (Tok.isNot(tok::identifier)) {
1085 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
1086 return;
1087 }
1088
1089 // Verify that this is one of the 5 whitelisted options.
Reid Klecknere43f0fe2013-05-08 13:44:39 +00001090 IdentifierInfo *II = Tok.getIdentifierInfo();
1091 Sema::PragmaMSCommentKind Kind =
1092 llvm::StringSwitch<Sema::PragmaMSCommentKind>(II->getName())
1093 .Case("linker", Sema::PCK_Linker)
1094 .Case("lib", Sema::PCK_Lib)
1095 .Case("compiler", Sema::PCK_Compiler)
1096 .Case("exestr", Sema::PCK_ExeStr)
1097 .Case("user", Sema::PCK_User)
1098 .Default(Sema::PCK_Unknown);
1099 if (Kind == Sema::PCK_Unknown) {
Reid Kleckner002562a2013-05-06 21:02:12 +00001100 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_unknown_kind);
1101 return;
1102 }
1103
1104 // Read the optional string if present.
1105 PP.Lex(Tok);
1106 std::string ArgumentString;
1107 if (Tok.is(tok::comma) && !PP.LexStringLiteral(Tok, ArgumentString,
1108 "pragma comment",
1109 /*MacroExpansion=*/true))
1110 return;
1111
Reid Klecknere43f0fe2013-05-08 13:44:39 +00001112 // FIXME: warn that 'exestr' is deprecated.
Reid Kleckner002562a2013-05-06 21:02:12 +00001113 // FIXME: If the kind is "compiler" warn if the string is present (it is
1114 // ignored).
Reid Klecknere43f0fe2013-05-08 13:44:39 +00001115 // The MSDN docs say that "lib" and "linker" require a string and have a short
1116 // whitelist of linker options they support, but in practice MSVC doesn't
1117 // issue a diagnostic. Therefore neither does clang.
Reid Kleckner002562a2013-05-06 21:02:12 +00001118
1119 if (Tok.isNot(tok::r_paren)) {
1120 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
1121 return;
1122 }
1123 PP.Lex(Tok); // eat the r_paren.
1124
1125 if (Tok.isNot(tok::eod)) {
1126 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
1127 return;
1128 }
1129
1130 // If the pragma is lexically sound, notify any interested PPCallbacks.
1131 if (PP.getPPCallbacks())
1132 PP.getPPCallbacks()->PragmaComment(CommentLoc, II, ArgumentString);
Reid Klecknere43f0fe2013-05-08 13:44:39 +00001133
1134 Actions.ActOnPragmaMSComment(Kind, ArgumentString);
Reid Kleckner002562a2013-05-06 21:02:12 +00001135}