blob: 29e17715b3b11fe59e58a8605822c141e841ac53 [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
Chandler Carruth55fc8732012-12-04 09:13:33 +000014#include "clang/Lex/Preprocessor.h"
Chris Lattner500d3292009-01-29 05:15:15 +000015#include "clang/Parse/ParseDiagnostic.h"
Ted Kremenek4726d032009-03-23 22:28:25 +000016#include "clang/Parse/Parser.h"
Tareq A. Siraj6afcf882013-04-16 19:37:38 +000017#include "clang/Sema/Scope.h"
Reid Kleckner7adf79a2013-05-06 21:02:12 +000018#include "llvm/ADT/StringSwitch.h"
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000019using namespace clang;
20
Stephen Hines651f13c2014-04-23 16:59:28 -070021namespace {
22
23struct PragmaAlignHandler : public PragmaHandler {
24 explicit PragmaAlignHandler() : PragmaHandler("align") {}
25 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
26 Token &FirstToken) override;
27};
28
29struct PragmaGCCVisibilityHandler : public PragmaHandler {
30 explicit PragmaGCCVisibilityHandler() : PragmaHandler("visibility") {}
31 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
32 Token &FirstToken) override;
33};
34
35struct PragmaOptionsHandler : public PragmaHandler {
36 explicit PragmaOptionsHandler() : PragmaHandler("options") {}
37 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
38 Token &FirstToken) override;
39};
40
41struct PragmaPackHandler : public PragmaHandler {
42 explicit PragmaPackHandler() : PragmaHandler("pack") {}
43 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
44 Token &FirstToken) override;
45};
46
47struct PragmaMSStructHandler : public PragmaHandler {
48 explicit PragmaMSStructHandler() : PragmaHandler("ms_struct") {}
49 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
50 Token &FirstToken) override;
51};
52
53struct PragmaUnusedHandler : public PragmaHandler {
54 PragmaUnusedHandler() : PragmaHandler("unused") {}
55 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
56 Token &FirstToken) override;
57};
58
59struct PragmaWeakHandler : public PragmaHandler {
60 explicit PragmaWeakHandler() : PragmaHandler("weak") {}
61 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
62 Token &FirstToken) override;
63};
64
65struct PragmaRedefineExtnameHandler : public PragmaHandler {
66 explicit PragmaRedefineExtnameHandler() : PragmaHandler("redefine_extname") {}
67 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
68 Token &FirstToken) override;
69};
70
71struct PragmaOpenCLExtensionHandler : public PragmaHandler {
72 PragmaOpenCLExtensionHandler() : PragmaHandler("EXTENSION") {}
73 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
74 Token &FirstToken) override;
75};
76
77
78struct PragmaFPContractHandler : public PragmaHandler {
79 PragmaFPContractHandler() : PragmaHandler("FP_CONTRACT") {}
80 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
81 Token &FirstToken) override;
82};
83
84struct PragmaNoOpenMPHandler : public PragmaHandler {
85 PragmaNoOpenMPHandler() : PragmaHandler("omp") { }
86 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
87 Token &FirstToken) override;
88};
89
90struct PragmaOpenMPHandler : public PragmaHandler {
91 PragmaOpenMPHandler() : PragmaHandler("omp") { }
92 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
93 Token &FirstToken) override;
94};
95
96/// PragmaCommentHandler - "\#pragma comment ...".
97struct PragmaCommentHandler : public PragmaHandler {
98 PragmaCommentHandler(Sema &Actions)
99 : PragmaHandler("comment"), Actions(Actions) {}
100 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
101 Token &FirstToken) override;
102private:
103 Sema &Actions;
104};
105
106struct PragmaDetectMismatchHandler : public PragmaHandler {
107 PragmaDetectMismatchHandler(Sema &Actions)
108 : PragmaHandler("detect_mismatch"), Actions(Actions) {}
109 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
110 Token &FirstToken) override;
111private:
112 Sema &Actions;
113};
114
115struct PragmaMSPointersToMembers : public PragmaHandler {
116 explicit PragmaMSPointersToMembers() : PragmaHandler("pointers_to_members") {}
117 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
118 Token &FirstToken) override;
119};
120
121struct PragmaMSVtorDisp : public PragmaHandler {
122 explicit PragmaMSVtorDisp() : PragmaHandler("vtordisp") {}
123 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
124 Token &FirstToken) override;
125};
126
127} // end namespace
128
129void Parser::initializePragmaHandlers() {
130 AlignHandler.reset(new PragmaAlignHandler());
131 PP.AddPragmaHandler(AlignHandler.get());
132
133 GCCVisibilityHandler.reset(new PragmaGCCVisibilityHandler());
134 PP.AddPragmaHandler("GCC", GCCVisibilityHandler.get());
135
136 OptionsHandler.reset(new PragmaOptionsHandler());
137 PP.AddPragmaHandler(OptionsHandler.get());
138
139 PackHandler.reset(new PragmaPackHandler());
140 PP.AddPragmaHandler(PackHandler.get());
141
142 MSStructHandler.reset(new PragmaMSStructHandler());
143 PP.AddPragmaHandler(MSStructHandler.get());
144
145 UnusedHandler.reset(new PragmaUnusedHandler());
146 PP.AddPragmaHandler(UnusedHandler.get());
147
148 WeakHandler.reset(new PragmaWeakHandler());
149 PP.AddPragmaHandler(WeakHandler.get());
150
151 RedefineExtnameHandler.reset(new PragmaRedefineExtnameHandler());
152 PP.AddPragmaHandler(RedefineExtnameHandler.get());
153
154 FPContractHandler.reset(new PragmaFPContractHandler());
155 PP.AddPragmaHandler("STDC", FPContractHandler.get());
156
157 if (getLangOpts().OpenCL) {
158 OpenCLExtensionHandler.reset(new PragmaOpenCLExtensionHandler());
159 PP.AddPragmaHandler("OPENCL", OpenCLExtensionHandler.get());
160
161 PP.AddPragmaHandler("OPENCL", FPContractHandler.get());
162 }
163 if (getLangOpts().OpenMP)
164 OpenMPHandler.reset(new PragmaOpenMPHandler());
165 else
166 OpenMPHandler.reset(new PragmaNoOpenMPHandler());
167 PP.AddPragmaHandler(OpenMPHandler.get());
168
169 if (getLangOpts().MicrosoftExt) {
170 MSCommentHandler.reset(new PragmaCommentHandler(Actions));
171 PP.AddPragmaHandler(MSCommentHandler.get());
172 MSDetectMismatchHandler.reset(new PragmaDetectMismatchHandler(Actions));
173 PP.AddPragmaHandler(MSDetectMismatchHandler.get());
174 MSPointersToMembers.reset(new PragmaMSPointersToMembers());
175 PP.AddPragmaHandler(MSPointersToMembers.get());
176 MSVtorDisp.reset(new PragmaMSVtorDisp());
177 PP.AddPragmaHandler(MSVtorDisp.get());
178 }
179}
180
181void Parser::resetPragmaHandlers() {
182 // Remove the pragma handlers we installed.
183 PP.RemovePragmaHandler(AlignHandler.get());
184 AlignHandler.reset();
185 PP.RemovePragmaHandler("GCC", GCCVisibilityHandler.get());
186 GCCVisibilityHandler.reset();
187 PP.RemovePragmaHandler(OptionsHandler.get());
188 OptionsHandler.reset();
189 PP.RemovePragmaHandler(PackHandler.get());
190 PackHandler.reset();
191 PP.RemovePragmaHandler(MSStructHandler.get());
192 MSStructHandler.reset();
193 PP.RemovePragmaHandler(UnusedHandler.get());
194 UnusedHandler.reset();
195 PP.RemovePragmaHandler(WeakHandler.get());
196 WeakHandler.reset();
197 PP.RemovePragmaHandler(RedefineExtnameHandler.get());
198 RedefineExtnameHandler.reset();
199
200 if (getLangOpts().OpenCL) {
201 PP.RemovePragmaHandler("OPENCL", OpenCLExtensionHandler.get());
202 OpenCLExtensionHandler.reset();
203 PP.RemovePragmaHandler("OPENCL", FPContractHandler.get());
204 }
205 PP.RemovePragmaHandler(OpenMPHandler.get());
206 OpenMPHandler.reset();
207
208 if (getLangOpts().MicrosoftExt) {
209 PP.RemovePragmaHandler(MSCommentHandler.get());
210 MSCommentHandler.reset();
211 PP.RemovePragmaHandler(MSDetectMismatchHandler.get());
212 MSDetectMismatchHandler.reset();
213 PP.RemovePragmaHandler(MSPointersToMembers.get());
214 MSPointersToMembers.reset();
215 PP.RemovePragmaHandler(MSVtorDisp.get());
216 MSVtorDisp.reset();
217 }
218
219 PP.RemovePragmaHandler("STDC", FPContractHandler.get());
220 FPContractHandler.reset();
221}
222
Argyrios Kyrtzidisb918d0f2011-01-17 18:58:44 +0000223/// \brief Handle the annotation token produced for #pragma unused(...)
224///
225/// Each annot_pragma_unused is followed by the argument token so e.g.
226/// "#pragma unused(x,y)" becomes:
227/// annot_pragma_unused 'x' annot_pragma_unused 'y'
228void Parser::HandlePragmaUnused() {
229 assert(Tok.is(tok::annot_pragma_unused));
230 SourceLocation UnusedLoc = ConsumeToken();
231 Actions.ActOnPragmaUnused(Tok, getCurScope(), UnusedLoc);
232 ConsumeToken(); // The argument token.
233}
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000234
Rafael Espindola426fc942012-01-26 02:02:57 +0000235void Parser::HandlePragmaVisibility() {
236 assert(Tok.is(tok::annot_pragma_vis));
237 const IdentifierInfo *VisType =
238 static_cast<IdentifierInfo *>(Tok.getAnnotationValue());
239 SourceLocation VisLoc = ConsumeToken();
240 Actions.ActOnPragmaVisibility(VisType, VisLoc);
241}
242
Eli Friedmanaa5ab262012-02-23 23:47:16 +0000243struct PragmaPackInfo {
244 Sema::PragmaPackKind Kind;
245 IdentifierInfo *Name;
Eli Friedman9595c7e2012-10-04 02:36:51 +0000246 Token Alignment;
Eli Friedmanaa5ab262012-02-23 23:47:16 +0000247 SourceLocation LParenLoc;
248 SourceLocation RParenLoc;
249};
250
251void Parser::HandlePragmaPack() {
252 assert(Tok.is(tok::annot_pragma_pack));
253 PragmaPackInfo *Info =
254 static_cast<PragmaPackInfo *>(Tok.getAnnotationValue());
255 SourceLocation PragmaLoc = ConsumeToken();
Eli Friedman9595c7e2012-10-04 02:36:51 +0000256 ExprResult Alignment;
257 if (Info->Alignment.is(tok::numeric_constant)) {
258 Alignment = Actions.ActOnNumericConstant(Info->Alignment);
259 if (Alignment.isInvalid())
260 return;
261 }
262 Actions.ActOnPragmaPack(Info->Kind, Info->Name, Alignment.get(), PragmaLoc,
Eli Friedmanaa5ab262012-02-23 23:47:16 +0000263 Info->LParenLoc, Info->RParenLoc);
Eli Friedmanaa5ab262012-02-23 23:47:16 +0000264}
265
Eli Friedman9595c7e2012-10-04 02:36:51 +0000266void Parser::HandlePragmaMSStruct() {
267 assert(Tok.is(tok::annot_pragma_msstruct));
268 Sema::PragmaMSStructKind Kind =
269 static_cast<Sema::PragmaMSStructKind>(
270 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
271 Actions.ActOnPragmaMSStruct(Kind);
272 ConsumeToken(); // The annotation token.
273}
274
275void Parser::HandlePragmaAlign() {
276 assert(Tok.is(tok::annot_pragma_align));
277 Sema::PragmaOptionsAlignKind Kind =
278 static_cast<Sema::PragmaOptionsAlignKind>(
279 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
280 SourceLocation PragmaLoc = ConsumeToken();
281 Actions.ActOnPragmaOptionsAlign(Kind, PragmaLoc);
282}
283
284void Parser::HandlePragmaWeak() {
285 assert(Tok.is(tok::annot_pragma_weak));
286 SourceLocation PragmaLoc = ConsumeToken();
287 Actions.ActOnPragmaWeakID(Tok.getIdentifierInfo(), PragmaLoc,
288 Tok.getLocation());
289 ConsumeToken(); // The weak name.
290}
291
292void Parser::HandlePragmaWeakAlias() {
293 assert(Tok.is(tok::annot_pragma_weakalias));
294 SourceLocation PragmaLoc = ConsumeToken();
295 IdentifierInfo *WeakName = Tok.getIdentifierInfo();
296 SourceLocation WeakNameLoc = Tok.getLocation();
297 ConsumeToken();
298 IdentifierInfo *AliasName = Tok.getIdentifierInfo();
299 SourceLocation AliasNameLoc = Tok.getLocation();
300 ConsumeToken();
301 Actions.ActOnPragmaWeakAlias(WeakName, AliasName, PragmaLoc,
302 WeakNameLoc, AliasNameLoc);
303
304}
305
306void Parser::HandlePragmaRedefineExtname() {
307 assert(Tok.is(tok::annot_pragma_redefine_extname));
308 SourceLocation RedefLoc = ConsumeToken();
309 IdentifierInfo *RedefName = Tok.getIdentifierInfo();
310 SourceLocation RedefNameLoc = Tok.getLocation();
311 ConsumeToken();
312 IdentifierInfo *AliasName = Tok.getIdentifierInfo();
313 SourceLocation AliasNameLoc = Tok.getLocation();
314 ConsumeToken();
315 Actions.ActOnPragmaRedefineExtname(RedefName, AliasName, RedefLoc,
316 RedefNameLoc, AliasNameLoc);
317}
318
319void Parser::HandlePragmaFPContract() {
320 assert(Tok.is(tok::annot_pragma_fp_contract));
321 tok::OnOffSwitch OOS =
322 static_cast<tok::OnOffSwitch>(
323 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
324 Actions.ActOnPragmaFPContract(OOS);
325 ConsumeToken(); // The annotation token.
326}
327
Tareq A. Siraj85192c72013-04-16 18:41:26 +0000328StmtResult Parser::HandlePragmaCaptured()
329{
330 assert(Tok.is(tok::annot_pragma_captured));
331 ConsumeToken();
332
333 if (Tok.isNot(tok::l_brace)) {
Stephen Hines651f13c2014-04-23 16:59:28 -0700334 PP.Diag(Tok, diag::err_expected) << tok::l_brace;
Tareq A. Siraj85192c72013-04-16 18:41:26 +0000335 return StmtError();
336 }
337
Tareq A. Siraj6afcf882013-04-16 19:37:38 +0000338 SourceLocation Loc = Tok.getLocation();
339
340 ParseScope CapturedRegionScope(this, Scope::FnScope | Scope::DeclScope);
Ben Langmuir8c045ac2013-05-03 19:00:33 +0000341 Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_Default,
342 /*NumParams=*/1);
Tareq A. Siraj6afcf882013-04-16 19:37:38 +0000343
344 StmtResult R = ParseCompoundStatement();
345 CapturedRegionScope.Exit();
346
347 if (R.isInvalid()) {
348 Actions.ActOnCapturedRegionError();
349 return StmtError();
350 }
351
352 return Actions.ActOnCapturedRegionEnd(R.get());
Tareq A. Siraj85192c72013-04-16 18:41:26 +0000353}
354
Eli Friedman9595c7e2012-10-04 02:36:51 +0000355namespace {
356 typedef llvm::PointerIntPair<IdentifierInfo *, 1, bool> OpenCLExtData;
357}
358
359void Parser::HandlePragmaOpenCLExtension() {
360 assert(Tok.is(tok::annot_pragma_opencl_extension));
361 OpenCLExtData data =
362 OpenCLExtData::getFromOpaqueValue(Tok.getAnnotationValue());
363 unsigned state = data.getInt();
364 IdentifierInfo *ename = data.getPointer();
365 SourceLocation NameLoc = Tok.getLocation();
366 ConsumeToken(); // The annotation token.
367
368 OpenCLOptions &f = Actions.getOpenCLOptions();
369 // OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions,
370 // overriding all previously issued extension directives, but only if the
371 // behavior is set to disable."
372 if (state == 0 && ename->isStr("all")) {
373#define OPENCLEXT(nm) f.nm = 0;
374#include "clang/Basic/OpenCLExtensions.def"
375 }
376#define OPENCLEXT(nm) else if (ename->isStr(#nm)) { f.nm = state; }
377#include "clang/Basic/OpenCLExtensions.def"
378 else {
379 PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << ename;
380 return;
381 }
382}
383
Stephen Hines651f13c2014-04-23 16:59:28 -0700384void Parser::HandlePragmaMSPointersToMembers() {
385 assert(Tok.is(tok::annot_pragma_ms_pointers_to_members));
386 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod =
387 static_cast<LangOptions::PragmaMSPointersToMembersKind>(
388 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
389 SourceLocation PragmaLoc = ConsumeToken(); // The annotation token.
390 Actions.ActOnPragmaMSPointersToMembers(RepresentationMethod, PragmaLoc);
391}
Tareq A. Siraj85192c72013-04-16 18:41:26 +0000392
Stephen Hines651f13c2014-04-23 16:59:28 -0700393void Parser::HandlePragmaMSVtorDisp() {
394 assert(Tok.is(tok::annot_pragma_ms_vtordisp));
395 uintptr_t Value = reinterpret_cast<uintptr_t>(Tok.getAnnotationValue());
396 Sema::PragmaVtorDispKind Kind =
397 static_cast<Sema::PragmaVtorDispKind>((Value >> 16) & 0xFFFF);
398 MSVtorDispAttr::Mode Mode = MSVtorDispAttr::Mode(Value & 0xFFFF);
399 SourceLocation PragmaLoc = ConsumeToken(); // The annotation token.
400 Actions.ActOnPragmaMSVtorDisp(Kind, PragmaLoc, Mode);
401}
Tareq A. Siraj85192c72013-04-16 18:41:26 +0000402
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000403// #pragma GCC visibility comes in two variants:
404// 'push' '(' [visibility] ')'
405// 'pop'
Douglas Gregor80c60f72010-09-09 22:45:38 +0000406void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,
407 PragmaIntroducerKind Introducer,
408 Token &VisTok) {
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000409 SourceLocation VisLoc = VisTok.getLocation();
410
411 Token Tok;
Joerg Sonnenbergere23af2a2011-07-20 01:03:50 +0000412 PP.LexUnexpandedToken(Tok);
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000413
414 const IdentifierInfo *PushPop = Tok.getIdentifierInfo();
415
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000416 const IdentifierInfo *VisType;
417 if (PushPop && PushPop->isStr("pop")) {
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000418 VisType = 0;
419 } else if (PushPop && PushPop->isStr("push")) {
Joerg Sonnenbergere23af2a2011-07-20 01:03:50 +0000420 PP.LexUnexpandedToken(Tok);
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000421 if (Tok.isNot(tok::l_paren)) {
422 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
423 << "visibility";
424 return;
425 }
Joerg Sonnenbergere23af2a2011-07-20 01:03:50 +0000426 PP.LexUnexpandedToken(Tok);
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000427 VisType = Tok.getIdentifierInfo();
428 if (!VisType) {
429 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
430 << "visibility";
431 return;
432 }
Joerg Sonnenbergere23af2a2011-07-20 01:03:50 +0000433 PP.LexUnexpandedToken(Tok);
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000434 if (Tok.isNot(tok::r_paren)) {
435 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
436 << "visibility";
437 return;
438 }
439 } else {
440 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
441 << "visibility";
442 return;
443 }
Joerg Sonnenbergere23af2a2011-07-20 01:03:50 +0000444 PP.LexUnexpandedToken(Tok);
Peter Collingbourne84021552011-02-28 02:37:51 +0000445 if (Tok.isNot(tok::eod)) {
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000446 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
447 << "visibility";
448 return;
449 }
450
Rafael Espindola426fc942012-01-26 02:02:57 +0000451 Token *Toks = new Token[1];
452 Toks[0].startToken();
453 Toks[0].setKind(tok::annot_pragma_vis);
454 Toks[0].setLocation(VisLoc);
455 Toks[0].setAnnotationValue(
456 const_cast<void*>(static_cast<const void*>(VisType)));
457 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
458 /*OwnsTokens=*/true);
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000459}
460
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000461// #pragma pack(...) comes in the following delicious flavors:
462// pack '(' [integer] ')'
463// pack '(' 'show' ')'
464// pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'
Douglas Gregor80c60f72010-09-09 22:45:38 +0000465void PragmaPackHandler::HandlePragma(Preprocessor &PP,
466 PragmaIntroducerKind Introducer,
467 Token &PackTok) {
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000468 SourceLocation PackLoc = PackTok.getLocation();
469
470 Token Tok;
471 PP.Lex(Tok);
472 if (Tok.isNot(tok::l_paren)) {
Ted Kremenek4726d032009-03-23 22:28:25 +0000473 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack";
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000474 return;
475 }
476
John McCallf312b1e2010-08-26 23:41:50 +0000477 Sema::PragmaPackKind Kind = Sema::PPK_Default;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000478 IdentifierInfo *Name = 0;
Eli Friedman9595c7e2012-10-04 02:36:51 +0000479 Token Alignment;
480 Alignment.startToken();
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000481 SourceLocation LParenLoc = Tok.getLocation();
Mike Stump1eb44332009-09-09 15:08:12 +0000482 PP.Lex(Tok);
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000483 if (Tok.is(tok::numeric_constant)) {
Eli Friedman9595c7e2012-10-04 02:36:51 +0000484 Alignment = Tok;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000485
486 PP.Lex(Tok);
Eli Friedman19bda3a2011-11-02 01:53:16 +0000487
488 // In MSVC/gcc, #pragma pack(4) sets the alignment without affecting
489 // the push/pop stack.
490 // In Apple gcc, #pragma pack(4) is equivalent to #pragma pack(push, 4)
David Blaikie4e4d0842012-03-11 07:00:24 +0000491 if (PP.getLangOpts().ApplePragmaPack)
Eli Friedman19bda3a2011-11-02 01:53:16 +0000492 Kind = Sema::PPK_Push;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000493 } else if (Tok.is(tok::identifier)) {
494 const IdentifierInfo *II = Tok.getIdentifierInfo();
Chris Lattner08631c52008-11-23 21:45:46 +0000495 if (II->isStr("show")) {
John McCallf312b1e2010-08-26 23:41:50 +0000496 Kind = Sema::PPK_Show;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000497 PP.Lex(Tok);
498 } else {
Chris Lattner08631c52008-11-23 21:45:46 +0000499 if (II->isStr("push")) {
John McCallf312b1e2010-08-26 23:41:50 +0000500 Kind = Sema::PPK_Push;
Chris Lattner08631c52008-11-23 21:45:46 +0000501 } else if (II->isStr("pop")) {
John McCallf312b1e2010-08-26 23:41:50 +0000502 Kind = Sema::PPK_Pop;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000503 } else {
Stephen Hines651f13c2014-04-23 16:59:28 -0700504 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action) << "pack";
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000505 return;
Mike Stump1eb44332009-09-09 15:08:12 +0000506 }
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000507 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000508
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000509 if (Tok.is(tok::comma)) {
510 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000511
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000512 if (Tok.is(tok::numeric_constant)) {
Eli Friedman9595c7e2012-10-04 02:36:51 +0000513 Alignment = Tok;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000514
515 PP.Lex(Tok);
516 } else if (Tok.is(tok::identifier)) {
517 Name = Tok.getIdentifierInfo();
518 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000519
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000520 if (Tok.is(tok::comma)) {
521 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000522
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000523 if (Tok.isNot(tok::numeric_constant)) {
Chris Lattner08631c52008-11-23 21:45:46 +0000524 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000525 return;
526 }
Mike Stump1eb44332009-09-09 15:08:12 +0000527
Eli Friedman9595c7e2012-10-04 02:36:51 +0000528 Alignment = Tok;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000529
530 PP.Lex(Tok);
531 }
532 } else {
Chris Lattner08631c52008-11-23 21:45:46 +0000533 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000534 return;
535 }
536 }
537 }
David Blaikie4e4d0842012-03-11 07:00:24 +0000538 } else if (PP.getLangOpts().ApplePragmaPack) {
Eli Friedman19bda3a2011-11-02 01:53:16 +0000539 // In MSVC/gcc, #pragma pack() resets the alignment without affecting
540 // the push/pop stack.
541 // In Apple gcc #pragma pack() is equivalent to #pragma pack(pop).
542 Kind = Sema::PPK_Pop;
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000543 }
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000544
545 if (Tok.isNot(tok::r_paren)) {
Ted Kremenek4726d032009-03-23 22:28:25 +0000546 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack";
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000547 return;
548 }
549
Daniel Dunbar861800c2010-05-26 23:29:06 +0000550 SourceLocation RParenLoc = Tok.getLocation();
Eli Friedman99914792009-06-05 00:49:58 +0000551 PP.Lex(Tok);
Peter Collingbourne84021552011-02-28 02:37:51 +0000552 if (Tok.isNot(tok::eod)) {
Eli Friedman99914792009-06-05 00:49:58 +0000553 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack";
554 return;
555 }
556
Daniel Dunbarb0939552012-02-29 01:38:22 +0000557 PragmaPackInfo *Info =
558 (PragmaPackInfo*) PP.getPreprocessorAllocator().Allocate(
559 sizeof(PragmaPackInfo), llvm::alignOf<PragmaPackInfo>());
560 new (Info) PragmaPackInfo();
Eli Friedmanaa5ab262012-02-23 23:47:16 +0000561 Info->Kind = Kind;
562 Info->Name = Name;
Eli Friedman9595c7e2012-10-04 02:36:51 +0000563 Info->Alignment = Alignment;
Eli Friedmanaa5ab262012-02-23 23:47:16 +0000564 Info->LParenLoc = LParenLoc;
565 Info->RParenLoc = RParenLoc;
566
Daniel Dunbarb0939552012-02-29 01:38:22 +0000567 Token *Toks =
568 (Token*) PP.getPreprocessorAllocator().Allocate(
569 sizeof(Token) * 1, llvm::alignOf<Token>());
570 new (Toks) Token();
Eli Friedmanaa5ab262012-02-23 23:47:16 +0000571 Toks[0].startToken();
572 Toks[0].setKind(tok::annot_pragma_pack);
573 Toks[0].setLocation(PackLoc);
574 Toks[0].setAnnotationValue(static_cast<void*>(Info));
575 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
Daniel Dunbarb0939552012-02-29 01:38:22 +0000576 /*OwnsTokens=*/false);
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000577}
578
Fariborz Jahanian62c92582011-04-25 18:49:15 +0000579// #pragma ms_struct on
580// #pragma ms_struct off
581void PragmaMSStructHandler::HandlePragma(Preprocessor &PP,
582 PragmaIntroducerKind Introducer,
583 Token &MSStructTok) {
584 Sema::PragmaMSStructKind Kind = Sema::PMSST_OFF;
585
586 Token Tok;
587 PP.Lex(Tok);
588 if (Tok.isNot(tok::identifier)) {
589 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
590 return;
591 }
592 const IdentifierInfo *II = Tok.getIdentifierInfo();
593 if (II->isStr("on")) {
594 Kind = Sema::PMSST_ON;
595 PP.Lex(Tok);
596 }
597 else if (II->isStr("off") || II->isStr("reset"))
598 PP.Lex(Tok);
599 else {
600 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
601 return;
602 }
603
604 if (Tok.isNot(tok::eod)) {
Daniel Dunbarb0939552012-02-29 01:38:22 +0000605 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
606 << "ms_struct";
Fariborz Jahanian62c92582011-04-25 18:49:15 +0000607 return;
608 }
Eli Friedman9595c7e2012-10-04 02:36:51 +0000609
610 Token *Toks =
611 (Token*) PP.getPreprocessorAllocator().Allocate(
612 sizeof(Token) * 1, llvm::alignOf<Token>());
613 new (Toks) Token();
614 Toks[0].startToken();
615 Toks[0].setKind(tok::annot_pragma_msstruct);
616 Toks[0].setLocation(MSStructTok.getLocation());
617 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
618 static_cast<uintptr_t>(Kind)));
619 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
620 /*OwnsTokens=*/false);
Fariborz Jahanian62c92582011-04-25 18:49:15 +0000621}
622
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000623// #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
624// #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
Eli Friedman9595c7e2012-10-04 02:36:51 +0000625static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok,
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000626 bool IsOptions) {
Daniel Dunbar861800c2010-05-26 23:29:06 +0000627 Token Tok;
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000628
629 if (IsOptions) {
630 PP.Lex(Tok);
631 if (Tok.isNot(tok::identifier) ||
632 !Tok.getIdentifierInfo()->isStr("align")) {
633 PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align);
634 return;
635 }
Daniel Dunbar861800c2010-05-26 23:29:06 +0000636 }
Daniel Dunbar638e7cf2010-05-27 18:42:09 +0000637
Daniel Dunbar861800c2010-05-26 23:29:06 +0000638 PP.Lex(Tok);
639 if (Tok.isNot(tok::equal)) {
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000640 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal)
641 << IsOptions;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000642 return;
643 }
644
645 PP.Lex(Tok);
646 if (Tok.isNot(tok::identifier)) {
647 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000648 << (IsOptions ? "options" : "align");
Daniel Dunbar861800c2010-05-26 23:29:06 +0000649 return;
650 }
651
John McCallf312b1e2010-08-26 23:41:50 +0000652 Sema::PragmaOptionsAlignKind Kind = Sema::POAK_Natural;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000653 const IdentifierInfo *II = Tok.getIdentifierInfo();
Daniel Dunbar638e7cf2010-05-27 18:42:09 +0000654 if (II->isStr("native"))
John McCallf312b1e2010-08-26 23:41:50 +0000655 Kind = Sema::POAK_Native;
Daniel Dunbar638e7cf2010-05-27 18:42:09 +0000656 else if (II->isStr("natural"))
John McCallf312b1e2010-08-26 23:41:50 +0000657 Kind = Sema::POAK_Natural;
Daniel Dunbar6f739142010-05-27 18:42:17 +0000658 else if (II->isStr("packed"))
John McCallf312b1e2010-08-26 23:41:50 +0000659 Kind = Sema::POAK_Packed;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000660 else if (II->isStr("power"))
John McCallf312b1e2010-08-26 23:41:50 +0000661 Kind = Sema::POAK_Power;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000662 else if (II->isStr("mac68k"))
John McCallf312b1e2010-08-26 23:41:50 +0000663 Kind = Sema::POAK_Mac68k;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000664 else if (II->isStr("reset"))
John McCallf312b1e2010-08-26 23:41:50 +0000665 Kind = Sema::POAK_Reset;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000666 else {
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000667 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option)
668 << IsOptions;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000669 return;
670 }
671
Daniel Dunbar861800c2010-05-26 23:29:06 +0000672 PP.Lex(Tok);
Peter Collingbourne84021552011-02-28 02:37:51 +0000673 if (Tok.isNot(tok::eod)) {
Daniel Dunbar861800c2010-05-26 23:29:06 +0000674 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000675 << (IsOptions ? "options" : "align");
Daniel Dunbar861800c2010-05-26 23:29:06 +0000676 return;
677 }
678
Eli Friedman9595c7e2012-10-04 02:36:51 +0000679 Token *Toks =
680 (Token*) PP.getPreprocessorAllocator().Allocate(
681 sizeof(Token) * 1, llvm::alignOf<Token>());
682 new (Toks) Token();
683 Toks[0].startToken();
684 Toks[0].setKind(tok::annot_pragma_align);
685 Toks[0].setLocation(FirstTok.getLocation());
686 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
687 static_cast<uintptr_t>(Kind)));
688 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
689 /*OwnsTokens=*/false);
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000690}
691
Douglas Gregor80c60f72010-09-09 22:45:38 +0000692void PragmaAlignHandler::HandlePragma(Preprocessor &PP,
693 PragmaIntroducerKind Introducer,
694 Token &AlignTok) {
Eli Friedman9595c7e2012-10-04 02:36:51 +0000695 ParseAlignPragma(PP, AlignTok, /*IsOptions=*/false);
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000696}
697
Douglas Gregor80c60f72010-09-09 22:45:38 +0000698void PragmaOptionsHandler::HandlePragma(Preprocessor &PP,
699 PragmaIntroducerKind Introducer,
700 Token &OptionsTok) {
Eli Friedman9595c7e2012-10-04 02:36:51 +0000701 ParseAlignPragma(PP, OptionsTok, /*IsOptions=*/true);
Daniel Dunbar861800c2010-05-26 23:29:06 +0000702}
703
Ted Kremenek4726d032009-03-23 22:28:25 +0000704// #pragma unused(identifier)
Douglas Gregor80c60f72010-09-09 22:45:38 +0000705void PragmaUnusedHandler::HandlePragma(Preprocessor &PP,
706 PragmaIntroducerKind Introducer,
707 Token &UnusedTok) {
Ted Kremenek4726d032009-03-23 22:28:25 +0000708 // FIXME: Should we be expanding macros here? My guess is no.
709 SourceLocation UnusedLoc = UnusedTok.getLocation();
Mike Stump1eb44332009-09-09 15:08:12 +0000710
Ted Kremenek4726d032009-03-23 22:28:25 +0000711 // Lex the left '('.
712 Token Tok;
713 PP.Lex(Tok);
714 if (Tok.isNot(tok::l_paren)) {
715 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
716 return;
717 }
Mike Stump1eb44332009-09-09 15:08:12 +0000718
Ted Kremenek4726d032009-03-23 22:28:25 +0000719 // Lex the declaration reference(s).
Chris Lattner5f9e2722011-07-23 10:55:15 +0000720 SmallVector<Token, 5> Identifiers;
Ted Kremenek4726d032009-03-23 22:28:25 +0000721 SourceLocation RParenLoc;
722 bool LexID = true;
Mike Stump1eb44332009-09-09 15:08:12 +0000723
Ted Kremenek4726d032009-03-23 22:28:25 +0000724 while (true) {
725 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000726
Ted Kremenek4726d032009-03-23 22:28:25 +0000727 if (LexID) {
Mike Stump1eb44332009-09-09 15:08:12 +0000728 if (Tok.is(tok::identifier)) {
Ted Kremenek7a02a372009-08-03 23:24:57 +0000729 Identifiers.push_back(Tok);
Ted Kremenek4726d032009-03-23 22:28:25 +0000730 LexID = false;
731 continue;
732 }
733
Ted Kremenek7a02a372009-08-03 23:24:57 +0000734 // Illegal token!
Ted Kremenek4726d032009-03-23 22:28:25 +0000735 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
736 return;
737 }
Mike Stump1eb44332009-09-09 15:08:12 +0000738
Ted Kremenek4726d032009-03-23 22:28:25 +0000739 // We are execting a ')' or a ','.
740 if (Tok.is(tok::comma)) {
741 LexID = true;
742 continue;
743 }
Mike Stump1eb44332009-09-09 15:08:12 +0000744
Ted Kremenek4726d032009-03-23 22:28:25 +0000745 if (Tok.is(tok::r_paren)) {
746 RParenLoc = Tok.getLocation();
747 break;
748 }
Mike Stump1eb44332009-09-09 15:08:12 +0000749
Ted Kremenek7a02a372009-08-03 23:24:57 +0000750 // Illegal token!
Stephen Hines651f13c2014-04-23 16:59:28 -0700751 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_punc) << "unused";
Ted Kremenek4726d032009-03-23 22:28:25 +0000752 return;
753 }
Eli Friedman99914792009-06-05 00:49:58 +0000754
755 PP.Lex(Tok);
Peter Collingbourne84021552011-02-28 02:37:51 +0000756 if (Tok.isNot(tok::eod)) {
Eli Friedman99914792009-06-05 00:49:58 +0000757 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
758 "unused";
759 return;
760 }
761
Ted Kremenek4726d032009-03-23 22:28:25 +0000762 // Verify that we have a location for the right parenthesis.
763 assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
Ted Kremenek7a02a372009-08-03 23:24:57 +0000764 assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
Ted Kremenek4726d032009-03-23 22:28:25 +0000765
Argyrios Kyrtzidisb918d0f2011-01-17 18:58:44 +0000766 // For each identifier token, insert into the token stream a
767 // annot_pragma_unused token followed by the identifier token.
768 // This allows us to cache a "#pragma unused" that occurs inside an inline
769 // C++ member function.
770
Daniel Dunbarb0939552012-02-29 01:38:22 +0000771 Token *Toks =
772 (Token*) PP.getPreprocessorAllocator().Allocate(
773 sizeof(Token) * 2 * Identifiers.size(), llvm::alignOf<Token>());
Argyrios Kyrtzidisb918d0f2011-01-17 18:58:44 +0000774 for (unsigned i=0; i != Identifiers.size(); i++) {
775 Token &pragmaUnusedTok = Toks[2*i], &idTok = Toks[2*i+1];
776 pragmaUnusedTok.startToken();
777 pragmaUnusedTok.setKind(tok::annot_pragma_unused);
778 pragmaUnusedTok.setLocation(UnusedLoc);
779 idTok = Identifiers[i];
780 }
Daniel Dunbarb0939552012-02-29 01:38:22 +0000781 PP.EnterTokenStream(Toks, 2*Identifiers.size(),
782 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
Ted Kremenek4726d032009-03-23 22:28:25 +0000783}
Eli Friedman99914792009-06-05 00:49:58 +0000784
785// #pragma weak identifier
786// #pragma weak identifier '=' identifier
Douglas Gregor80c60f72010-09-09 22:45:38 +0000787void PragmaWeakHandler::HandlePragma(Preprocessor &PP,
788 PragmaIntroducerKind Introducer,
789 Token &WeakTok) {
Eli Friedman99914792009-06-05 00:49:58 +0000790 SourceLocation WeakLoc = WeakTok.getLocation();
791
792 Token Tok;
793 PP.Lex(Tok);
794 if (Tok.isNot(tok::identifier)) {
795 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";
796 return;
797 }
798
Eli Friedman9595c7e2012-10-04 02:36:51 +0000799 Token WeakName = Tok;
800 bool HasAlias = false;
801 Token AliasName;
Eli Friedman99914792009-06-05 00:49:58 +0000802
803 PP.Lex(Tok);
804 if (Tok.is(tok::equal)) {
Eli Friedman9595c7e2012-10-04 02:36:51 +0000805 HasAlias = true;
Eli Friedman99914792009-06-05 00:49:58 +0000806 PP.Lex(Tok);
807 if (Tok.isNot(tok::identifier)) {
Mike Stump1eb44332009-09-09 15:08:12 +0000808 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Eli Friedman99914792009-06-05 00:49:58 +0000809 << "weak";
810 return;
811 }
Eli Friedman9595c7e2012-10-04 02:36:51 +0000812 AliasName = Tok;
Eli Friedman99914792009-06-05 00:49:58 +0000813 PP.Lex(Tok);
814 }
815
Peter Collingbourne84021552011-02-28 02:37:51 +0000816 if (Tok.isNot(tok::eod)) {
Eli Friedman99914792009-06-05 00:49:58 +0000817 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";
818 return;
819 }
820
Eli Friedman9595c7e2012-10-04 02:36:51 +0000821 if (HasAlias) {
822 Token *Toks =
823 (Token*) PP.getPreprocessorAllocator().Allocate(
824 sizeof(Token) * 3, llvm::alignOf<Token>());
825 Token &pragmaUnusedTok = Toks[0];
826 pragmaUnusedTok.startToken();
827 pragmaUnusedTok.setKind(tok::annot_pragma_weakalias);
828 pragmaUnusedTok.setLocation(WeakLoc);
829 Toks[1] = WeakName;
830 Toks[2] = AliasName;
831 PP.EnterTokenStream(Toks, 3,
832 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
Eli Friedman99914792009-06-05 00:49:58 +0000833 } else {
Eli Friedman9595c7e2012-10-04 02:36:51 +0000834 Token *Toks =
835 (Token*) PP.getPreprocessorAllocator().Allocate(
836 sizeof(Token) * 2, llvm::alignOf<Token>());
837 Token &pragmaUnusedTok = Toks[0];
838 pragmaUnusedTok.startToken();
839 pragmaUnusedTok.setKind(tok::annot_pragma_weak);
840 pragmaUnusedTok.setLocation(WeakLoc);
841 Toks[1] = WeakName;
842 PP.EnterTokenStream(Toks, 2,
843 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
Eli Friedman99914792009-06-05 00:49:58 +0000844 }
845}
Peter Collingbourne321b8172011-02-14 01:42:35 +0000846
David Chisnall5f3c1632012-02-18 16:12:34 +0000847// #pragma redefine_extname identifier identifier
848void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP,
849 PragmaIntroducerKind Introducer,
850 Token &RedefToken) {
851 SourceLocation RedefLoc = RedefToken.getLocation();
852
853 Token Tok;
854 PP.Lex(Tok);
855 if (Tok.isNot(tok::identifier)) {
856 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
857 "redefine_extname";
858 return;
859 }
860
Eli Friedman9595c7e2012-10-04 02:36:51 +0000861 Token RedefName = Tok;
David Chisnall5f3c1632012-02-18 16:12:34 +0000862 PP.Lex(Tok);
Eli Friedman9595c7e2012-10-04 02:36:51 +0000863
David Chisnall5f3c1632012-02-18 16:12:34 +0000864 if (Tok.isNot(tok::identifier)) {
865 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
866 << "redefine_extname";
867 return;
868 }
Eli Friedman9595c7e2012-10-04 02:36:51 +0000869
870 Token AliasName = Tok;
David Chisnall5f3c1632012-02-18 16:12:34 +0000871 PP.Lex(Tok);
872
873 if (Tok.isNot(tok::eod)) {
874 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
875 "redefine_extname";
876 return;
877 }
878
Eli Friedman9595c7e2012-10-04 02:36:51 +0000879 Token *Toks =
880 (Token*) PP.getPreprocessorAllocator().Allocate(
881 sizeof(Token) * 3, llvm::alignOf<Token>());
882 Token &pragmaRedefTok = Toks[0];
883 pragmaRedefTok.startToken();
884 pragmaRedefTok.setKind(tok::annot_pragma_redefine_extname);
885 pragmaRedefTok.setLocation(RedefLoc);
886 Toks[1] = RedefName;
887 Toks[2] = AliasName;
888 PP.EnterTokenStream(Toks, 3,
889 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
David Chisnall5f3c1632012-02-18 16:12:34 +0000890}
891
892
Peter Collingbourne321b8172011-02-14 01:42:35 +0000893void
894PragmaFPContractHandler::HandlePragma(Preprocessor &PP,
895 PragmaIntroducerKind Introducer,
896 Token &Tok) {
897 tok::OnOffSwitch OOS;
898 if (PP.LexOnOffSwitch(OOS))
899 return;
900
Eli Friedman9595c7e2012-10-04 02:36:51 +0000901 Token *Toks =
902 (Token*) PP.getPreprocessorAllocator().Allocate(
903 sizeof(Token) * 1, llvm::alignOf<Token>());
904 new (Toks) Token();
905 Toks[0].startToken();
906 Toks[0].setKind(tok::annot_pragma_fp_contract);
907 Toks[0].setLocation(Tok.getLocation());
908 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
909 static_cast<uintptr_t>(OOS)));
910 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
911 /*OwnsTokens=*/false);
Peter Collingbourne321b8172011-02-14 01:42:35 +0000912}
Peter Collingbournef315fa82011-02-14 01:42:53 +0000913
914void
915PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
916 PragmaIntroducerKind Introducer,
917 Token &Tok) {
Tanya Lattnerb38b6a72011-04-14 23:35:31 +0000918 PP.LexUnexpandedToken(Tok);
Peter Collingbournef315fa82011-02-14 01:42:53 +0000919 if (Tok.isNot(tok::identifier)) {
920 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
921 "OPENCL";
922 return;
923 }
924 IdentifierInfo *ename = Tok.getIdentifierInfo();
925 SourceLocation NameLoc = Tok.getLocation();
926
927 PP.Lex(Tok);
928 if (Tok.isNot(tok::colon)) {
929 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << ename;
930 return;
931 }
932
933 PP.Lex(Tok);
934 if (Tok.isNot(tok::identifier)) {
935 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
936 return;
937 }
938 IdentifierInfo *op = Tok.getIdentifierInfo();
939
940 unsigned state;
941 if (op->isStr("enable")) {
942 state = 1;
943 } else if (op->isStr("disable")) {
944 state = 0;
945 } else {
946 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
947 return;
948 }
Pekka Jaaskelainena0950e82013-10-12 09:29:48 +0000949 SourceLocation StateLoc = Tok.getLocation();
Peter Collingbournef315fa82011-02-14 01:42:53 +0000950
Eli Friedman9595c7e2012-10-04 02:36:51 +0000951 PP.Lex(Tok);
952 if (Tok.isNot(tok::eod)) {
953 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
954 "OPENCL EXTENSION";
Peter Collingbournef315fa82011-02-14 01:42:53 +0000955 return;
956 }
Eli Friedman9595c7e2012-10-04 02:36:51 +0000957
958 OpenCLExtData data(ename, state);
959 Token *Toks =
960 (Token*) PP.getPreprocessorAllocator().Allocate(
961 sizeof(Token) * 1, llvm::alignOf<Token>());
962 new (Toks) Token();
963 Toks[0].startToken();
964 Toks[0].setKind(tok::annot_pragma_opencl_extension);
965 Toks[0].setLocation(NameLoc);
966 Toks[0].setAnnotationValue(data.getOpaqueValue());
967 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
968 /*OwnsTokens=*/false);
Pekka Jaaskelainena0950e82013-10-12 09:29:48 +0000969
970 if (PP.getPPCallbacks())
971 PP.getPPCallbacks()->PragmaOpenCLExtension(NameLoc, ename,
972 StateLoc, state);
Peter Collingbournef315fa82011-02-14 01:42:53 +0000973}
974
Alexey Bataevc6400582013-03-22 06:34:35 +0000975/// \brief Handle '#pragma omp ...' when OpenMP is disabled.
976///
977void
978PragmaNoOpenMPHandler::HandlePragma(Preprocessor &PP,
979 PragmaIntroducerKind Introducer,
980 Token &FirstTok) {
981 if (PP.getDiagnostics().getDiagnosticLevel(diag::warn_pragma_omp_ignored,
982 FirstTok.getLocation()) !=
983 DiagnosticsEngine::Ignored) {
984 PP.Diag(FirstTok, diag::warn_pragma_omp_ignored);
985 PP.getDiagnostics().setDiagnosticMapping(diag::warn_pragma_omp_ignored,
986 diag::MAP_IGNORE,
987 SourceLocation());
988 }
989 PP.DiscardUntilEndOfDirective();
990}
991
992/// \brief Handle '#pragma omp ...' when OpenMP is enabled.
993///
994void
995PragmaOpenMPHandler::HandlePragma(Preprocessor &PP,
996 PragmaIntroducerKind Introducer,
997 Token &FirstTok) {
998 SmallVector<Token, 16> Pragma;
999 Token Tok;
1000 Tok.startToken();
1001 Tok.setKind(tok::annot_pragma_openmp);
1002 Tok.setLocation(FirstTok.getLocation());
1003
1004 while (Tok.isNot(tok::eod)) {
1005 Pragma.push_back(Tok);
1006 PP.Lex(Tok);
1007 }
1008 SourceLocation EodLoc = Tok.getLocation();
1009 Tok.startToken();
1010 Tok.setKind(tok::annot_pragma_openmp_end);
1011 Tok.setLocation(EodLoc);
1012 Pragma.push_back(Tok);
1013
1014 Token *Toks = new Token[Pragma.size()];
1015 std::copy(Pragma.begin(), Pragma.end(), Toks);
1016 PP.EnterTokenStream(Toks, Pragma.size(),
1017 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/true);
1018}
Reid Kleckner7adf79a2013-05-06 21:02:12 +00001019
Stephen Hines651f13c2014-04-23 16:59:28 -07001020/// \brief Handle '#pragma pointers_to_members'
1021// The grammar for this pragma is as follows:
1022//
1023// <inheritance model> ::= ('single' | 'multiple' | 'virtual') '_inheritance'
1024//
1025// #pragma pointers_to_members '(' 'best_case' ')'
1026// #pragma pointers_to_members '(' 'full_generality' [',' inheritance-model] ')'
1027// #pragma pointers_to_members '(' inheritance-model ')'
1028void PragmaMSPointersToMembers::HandlePragma(Preprocessor &PP,
1029 PragmaIntroducerKind Introducer,
1030 Token &Tok) {
1031 SourceLocation PointersToMembersLoc = Tok.getLocation();
1032 PP.Lex(Tok);
1033 if (Tok.isNot(tok::l_paren)) {
1034 PP.Diag(PointersToMembersLoc, diag::warn_pragma_expected_lparen)
1035 << "pointers_to_members";
1036 return;
1037 }
1038 PP.Lex(Tok);
1039 const IdentifierInfo *Arg = Tok.getIdentifierInfo();
1040 if (!Arg) {
1041 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1042 << "pointers_to_members";
1043 return;
1044 }
1045 PP.Lex(Tok);
1046
1047 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod;
1048 if (Arg->isStr("best_case")) {
1049 RepresentationMethod = LangOptions::PPTMK_BestCase;
1050 } else {
1051 if (Arg->isStr("full_generality")) {
1052 if (Tok.is(tok::comma)) {
1053 PP.Lex(Tok);
1054
1055 Arg = Tok.getIdentifierInfo();
1056 if (!Arg) {
1057 PP.Diag(Tok.getLocation(),
1058 diag::err_pragma_pointers_to_members_unknown_kind)
1059 << Tok.getKind() << /*OnlyInheritanceModels*/ 0;
1060 return;
1061 }
1062 PP.Lex(Tok);
1063 } else if (Tok.is(tok::r_paren)) {
1064 // #pragma pointers_to_members(full_generality) implicitly specifies
1065 // virtual_inheritance.
1066 Arg = 0;
1067 RepresentationMethod = LangOptions::PPTMK_FullGeneralityVirtualInheritance;
1068 } else {
1069 PP.Diag(Tok.getLocation(), diag::err_expected_punc)
1070 << "full_generality";
1071 return;
1072 }
1073 }
1074
1075 if (Arg) {
1076 if (Arg->isStr("single_inheritance")) {
1077 RepresentationMethod =
1078 LangOptions::PPTMK_FullGeneralitySingleInheritance;
1079 } else if (Arg->isStr("multiple_inheritance")) {
1080 RepresentationMethod =
1081 LangOptions::PPTMK_FullGeneralityMultipleInheritance;
1082 } else if (Arg->isStr("virtual_inheritance")) {
1083 RepresentationMethod =
1084 LangOptions::PPTMK_FullGeneralityVirtualInheritance;
1085 } else {
1086 PP.Diag(Tok.getLocation(),
1087 diag::err_pragma_pointers_to_members_unknown_kind)
1088 << Arg << /*HasPointerDeclaration*/ 1;
1089 return;
1090 }
1091 }
1092 }
1093
1094 if (Tok.isNot(tok::r_paren)) {
1095 PP.Diag(Tok.getLocation(), diag::err_expected_rparen_after)
1096 << (Arg ? Arg->getName() : "full_generality");
1097 return;
1098 }
1099
1100 PP.Lex(Tok);
1101 if (Tok.isNot(tok::eod)) {
1102 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1103 << "pointers_to_members";
1104 return;
1105 }
1106
1107 Token AnnotTok;
1108 AnnotTok.startToken();
1109 AnnotTok.setKind(tok::annot_pragma_ms_pointers_to_members);
1110 AnnotTok.setLocation(PointersToMembersLoc);
1111 AnnotTok.setAnnotationValue(
1112 reinterpret_cast<void *>(static_cast<uintptr_t>(RepresentationMethod)));
1113 PP.EnterToken(AnnotTok);
1114}
1115
1116/// \brief Handle '#pragma vtordisp'
1117// The grammar for this pragma is as follows:
1118//
1119// <vtordisp-mode> ::= ('off' | 'on' | '0' | '1' | '2' )
1120//
1121// #pragma vtordisp '(' ['push' ','] vtordisp-mode ')'
1122// #pragma vtordisp '(' 'pop' ')'
1123// #pragma vtordisp '(' ')'
1124void PragmaMSVtorDisp::HandlePragma(Preprocessor &PP,
1125 PragmaIntroducerKind Introducer,
1126 Token &Tok) {
1127 SourceLocation VtorDispLoc = Tok.getLocation();
1128 PP.Lex(Tok);
1129 if (Tok.isNot(tok::l_paren)) {
1130 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_lparen) << "vtordisp";
1131 return;
1132 }
1133 PP.Lex(Tok);
1134
1135 Sema::PragmaVtorDispKind Kind = Sema::PVDK_Set;
1136 const IdentifierInfo *II = Tok.getIdentifierInfo();
1137 if (II) {
1138 if (II->isStr("push")) {
1139 // #pragma vtordisp(push, mode)
1140 PP.Lex(Tok);
1141 if (Tok.isNot(tok::comma)) {
1142 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_punc) << "vtordisp";
1143 return;
1144 }
1145 PP.Lex(Tok);
1146 Kind = Sema::PVDK_Push;
1147 // not push, could be on/off
1148 } else if (II->isStr("pop")) {
1149 // #pragma vtordisp(pop)
1150 PP.Lex(Tok);
1151 Kind = Sema::PVDK_Pop;
1152 }
1153 // not push or pop, could be on/off
1154 } else {
1155 if (Tok.is(tok::r_paren)) {
1156 // #pragma vtordisp()
1157 Kind = Sema::PVDK_Reset;
1158 }
1159 }
1160
1161
1162 uint64_t Value = 0;
1163 if (Kind == Sema::PVDK_Push || Kind == Sema::PVDK_Set) {
1164 const IdentifierInfo *II = Tok.getIdentifierInfo();
1165 if (II && II->isStr("off")) {
1166 PP.Lex(Tok);
1167 Value = 0;
1168 } else if (II && II->isStr("on")) {
1169 PP.Lex(Tok);
1170 Value = 1;
1171 } else if (Tok.is(tok::numeric_constant) &&
1172 PP.parseSimpleIntegerLiteral(Tok, Value)) {
1173 if (Value > 2) {
1174 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_integer)
1175 << 0 << 2 << "vtordisp";
1176 return;
1177 }
1178 } else {
1179 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action)
1180 << "vtordisp";
1181 return;
1182 }
1183 }
1184
1185 // Finish the pragma: ')' $
1186 if (Tok.isNot(tok::r_paren)) {
1187 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_rparen) << "vtordisp";
1188 return;
1189 }
1190 PP.Lex(Tok);
1191 if (Tok.isNot(tok::eod)) {
1192 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1193 << "vtordisp";
1194 return;
1195 }
1196
1197 // Enter the annotation.
1198 Token AnnotTok;
1199 AnnotTok.startToken();
1200 AnnotTok.setKind(tok::annot_pragma_ms_vtordisp);
1201 AnnotTok.setLocation(VtorDispLoc);
1202 AnnotTok.setAnnotationValue(reinterpret_cast<void *>(
1203 static_cast<uintptr_t>((Kind << 16) | (Value & 0xFFFF))));
1204 PP.EnterToken(AnnotTok);
1205}
1206
Aaron Ballmana7ff62f2013-06-04 02:07:14 +00001207/// \brief Handle the Microsoft \#pragma detect_mismatch extension.
1208///
1209/// The syntax is:
1210/// \code
1211/// #pragma detect_mismatch("name", "value")
1212/// \endcode
1213/// Where 'name' and 'value' are quoted strings. The values are embedded in
1214/// the object file and passed along to the linker. If the linker detects a
1215/// mismatch in the object file's values for the given name, a LNK2038 error
1216/// is emitted. See MSDN for more details.
1217void PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP,
1218 PragmaIntroducerKind Introducer,
1219 Token &Tok) {
1220 SourceLocation CommentLoc = Tok.getLocation();
1221 PP.Lex(Tok);
1222 if (Tok.isNot(tok::l_paren)) {
Stephen Hines651f13c2014-04-23 16:59:28 -07001223 PP.Diag(CommentLoc, diag::err_expected) << tok::l_paren;
Aaron Ballmana7ff62f2013-06-04 02:07:14 +00001224 return;
1225 }
1226
1227 // Read the name to embed, which must be a string literal.
1228 std::string NameString;
1229 if (!PP.LexStringLiteral(Tok, NameString,
1230 "pragma detect_mismatch",
1231 /*MacroExpansion=*/true))
1232 return;
1233
1234 // Read the comma followed by a second string literal.
1235 std::string ValueString;
1236 if (Tok.isNot(tok::comma)) {
1237 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
1238 return;
1239 }
1240
1241 if (!PP.LexStringLiteral(Tok, ValueString, "pragma detect_mismatch",
1242 /*MacroExpansion=*/true))
1243 return;
1244
1245 if (Tok.isNot(tok::r_paren)) {
Stephen Hines651f13c2014-04-23 16:59:28 -07001246 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
Aaron Ballmana7ff62f2013-06-04 02:07:14 +00001247 return;
1248 }
1249 PP.Lex(Tok); // Eat the r_paren.
1250
1251 if (Tok.isNot(tok::eod)) {
1252 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
1253 return;
1254 }
1255
1256 // If the pragma is lexically sound, notify any interested PPCallbacks.
1257 if (PP.getPPCallbacks())
1258 PP.getPPCallbacks()->PragmaDetectMismatch(CommentLoc, NameString,
1259 ValueString);
1260
1261 Actions.ActOnPragmaDetectMismatch(NameString, ValueString);
1262}
1263
Reid Kleckner7adf79a2013-05-06 21:02:12 +00001264/// \brief Handle the microsoft \#pragma comment extension.
1265///
1266/// The syntax is:
1267/// \code
1268/// #pragma comment(linker, "foo")
1269/// \endcode
1270/// 'linker' is one of five identifiers: compiler, exestr, lib, linker, user.
1271/// "foo" is a string, which is fully macro expanded, and permits string
1272/// concatenation, embedded escape characters etc. See MSDN for more details.
1273void PragmaCommentHandler::HandlePragma(Preprocessor &PP,
1274 PragmaIntroducerKind Introducer,
1275 Token &Tok) {
1276 SourceLocation CommentLoc = Tok.getLocation();
1277 PP.Lex(Tok);
1278 if (Tok.isNot(tok::l_paren)) {
1279 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
1280 return;
1281 }
1282
1283 // Read the identifier.
1284 PP.Lex(Tok);
1285 if (Tok.isNot(tok::identifier)) {
1286 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
1287 return;
1288 }
1289
1290 // Verify that this is one of the 5 whitelisted options.
Reid Kleckner3190ca92013-05-08 13:44:39 +00001291 IdentifierInfo *II = Tok.getIdentifierInfo();
1292 Sema::PragmaMSCommentKind Kind =
1293 llvm::StringSwitch<Sema::PragmaMSCommentKind>(II->getName())
1294 .Case("linker", Sema::PCK_Linker)
1295 .Case("lib", Sema::PCK_Lib)
1296 .Case("compiler", Sema::PCK_Compiler)
1297 .Case("exestr", Sema::PCK_ExeStr)
1298 .Case("user", Sema::PCK_User)
1299 .Default(Sema::PCK_Unknown);
1300 if (Kind == Sema::PCK_Unknown) {
Reid Kleckner7adf79a2013-05-06 21:02:12 +00001301 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_unknown_kind);
1302 return;
1303 }
1304
1305 // Read the optional string if present.
1306 PP.Lex(Tok);
1307 std::string ArgumentString;
1308 if (Tok.is(tok::comma) && !PP.LexStringLiteral(Tok, ArgumentString,
1309 "pragma comment",
1310 /*MacroExpansion=*/true))
1311 return;
1312
Reid Kleckner3190ca92013-05-08 13:44:39 +00001313 // FIXME: warn that 'exestr' is deprecated.
Reid Kleckner7adf79a2013-05-06 21:02:12 +00001314 // FIXME: If the kind is "compiler" warn if the string is present (it is
1315 // ignored).
Reid Kleckner3190ca92013-05-08 13:44:39 +00001316 // The MSDN docs say that "lib" and "linker" require a string and have a short
1317 // whitelist of linker options they support, but in practice MSVC doesn't
1318 // issue a diagnostic. Therefore neither does clang.
Reid Kleckner7adf79a2013-05-06 21:02:12 +00001319
1320 if (Tok.isNot(tok::r_paren)) {
1321 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
1322 return;
1323 }
1324 PP.Lex(Tok); // eat the r_paren.
1325
1326 if (Tok.isNot(tok::eod)) {
1327 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
1328 return;
1329 }
1330
1331 // If the pragma is lexically sound, notify any interested PPCallbacks.
1332 if (PP.getPPCallbacks())
1333 PP.getPPCallbacks()->PragmaComment(CommentLoc, II, ArgumentString);
Reid Kleckner3190ca92013-05-08 13:44:39 +00001334
1335 Actions.ActOnPragmaMSComment(Kind, ArgumentString);
Reid Kleckner7adf79a2013-05-06 21:02:12 +00001336}