blob: 787d3f0bdf4a062e59ee338365a17ad354cfd7a1 [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
Stephen Hines6bcf27b2014-05-29 04:14:42 -070014#include "RAIIObjectsForParser.h"
Chandler Carruth55fc8732012-12-04 09:13:33 +000015#include "clang/Lex/Preprocessor.h"
Chris Lattner500d3292009-01-29 05:15:15 +000016#include "clang/Parse/ParseDiagnostic.h"
Ted Kremenek4726d032009-03-23 22:28:25 +000017#include "clang/Parse/Parser.h"
Tareq A. Siraj6afcf882013-04-16 19:37:38 +000018#include "clang/Sema/Scope.h"
Reid Kleckner7adf79a2013-05-06 21:02:12 +000019#include "llvm/ADT/StringSwitch.h"
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000020using namespace clang;
21
Stephen Hines651f13c2014-04-23 16:59:28 -070022namespace {
23
24struct PragmaAlignHandler : public PragmaHandler {
25 explicit PragmaAlignHandler() : PragmaHandler("align") {}
26 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
27 Token &FirstToken) override;
28};
29
30struct PragmaGCCVisibilityHandler : public PragmaHandler {
31 explicit PragmaGCCVisibilityHandler() : PragmaHandler("visibility") {}
32 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
33 Token &FirstToken) override;
34};
35
36struct PragmaOptionsHandler : public PragmaHandler {
37 explicit PragmaOptionsHandler() : PragmaHandler("options") {}
38 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
39 Token &FirstToken) override;
40};
41
42struct PragmaPackHandler : public PragmaHandler {
43 explicit PragmaPackHandler() : PragmaHandler("pack") {}
44 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
45 Token &FirstToken) override;
46};
47
48struct PragmaMSStructHandler : public PragmaHandler {
49 explicit PragmaMSStructHandler() : PragmaHandler("ms_struct") {}
50 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
51 Token &FirstToken) override;
52};
53
54struct PragmaUnusedHandler : public PragmaHandler {
55 PragmaUnusedHandler() : PragmaHandler("unused") {}
56 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
57 Token &FirstToken) override;
58};
59
60struct PragmaWeakHandler : public PragmaHandler {
61 explicit PragmaWeakHandler() : PragmaHandler("weak") {}
62 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
63 Token &FirstToken) override;
64};
65
66struct PragmaRedefineExtnameHandler : public PragmaHandler {
67 explicit PragmaRedefineExtnameHandler() : PragmaHandler("redefine_extname") {}
68 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
69 Token &FirstToken) override;
70};
71
72struct PragmaOpenCLExtensionHandler : public PragmaHandler {
73 PragmaOpenCLExtensionHandler() : PragmaHandler("EXTENSION") {}
74 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
75 Token &FirstToken) override;
76};
77
78
79struct PragmaFPContractHandler : public PragmaHandler {
80 PragmaFPContractHandler() : PragmaHandler("FP_CONTRACT") {}
81 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
82 Token &FirstToken) override;
83};
84
85struct PragmaNoOpenMPHandler : public PragmaHandler {
86 PragmaNoOpenMPHandler() : PragmaHandler("omp") { }
87 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
88 Token &FirstToken) override;
89};
90
91struct PragmaOpenMPHandler : public PragmaHandler {
92 PragmaOpenMPHandler() : PragmaHandler("omp") { }
93 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
94 Token &FirstToken) override;
95};
96
97/// PragmaCommentHandler - "\#pragma comment ...".
98struct PragmaCommentHandler : public PragmaHandler {
99 PragmaCommentHandler(Sema &Actions)
100 : PragmaHandler("comment"), Actions(Actions) {}
101 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
102 Token &FirstToken) override;
103private:
104 Sema &Actions;
105};
106
107struct PragmaDetectMismatchHandler : public PragmaHandler {
108 PragmaDetectMismatchHandler(Sema &Actions)
109 : PragmaHandler("detect_mismatch"), Actions(Actions) {}
110 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
111 Token &FirstToken) override;
112private:
113 Sema &Actions;
114};
115
116struct PragmaMSPointersToMembers : public PragmaHandler {
117 explicit PragmaMSPointersToMembers() : PragmaHandler("pointers_to_members") {}
118 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
119 Token &FirstToken) override;
120};
121
122struct PragmaMSVtorDisp : public PragmaHandler {
123 explicit PragmaMSVtorDisp() : PragmaHandler("vtordisp") {}
124 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
125 Token &FirstToken) override;
126};
127
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700128struct PragmaMSPragma : public PragmaHandler {
129 explicit PragmaMSPragma(const char *name) : PragmaHandler(name) {}
130 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
131 Token &FirstToken) override;
132};
133
134/// PragmaOptimizeHandler - "\#pragma clang optimize on/off".
135struct PragmaOptimizeHandler : public PragmaHandler {
136 PragmaOptimizeHandler(Sema &S)
137 : PragmaHandler("optimize"), Actions(S) {}
138 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
139 Token &FirstToken) override;
140private:
141 Sema &Actions;
142};
143
Stephen Hines651f13c2014-04-23 16:59:28 -0700144} // end namespace
145
146void Parser::initializePragmaHandlers() {
147 AlignHandler.reset(new PragmaAlignHandler());
148 PP.AddPragmaHandler(AlignHandler.get());
149
150 GCCVisibilityHandler.reset(new PragmaGCCVisibilityHandler());
151 PP.AddPragmaHandler("GCC", GCCVisibilityHandler.get());
152
153 OptionsHandler.reset(new PragmaOptionsHandler());
154 PP.AddPragmaHandler(OptionsHandler.get());
155
156 PackHandler.reset(new PragmaPackHandler());
157 PP.AddPragmaHandler(PackHandler.get());
158
159 MSStructHandler.reset(new PragmaMSStructHandler());
160 PP.AddPragmaHandler(MSStructHandler.get());
161
162 UnusedHandler.reset(new PragmaUnusedHandler());
163 PP.AddPragmaHandler(UnusedHandler.get());
164
165 WeakHandler.reset(new PragmaWeakHandler());
166 PP.AddPragmaHandler(WeakHandler.get());
167
168 RedefineExtnameHandler.reset(new PragmaRedefineExtnameHandler());
169 PP.AddPragmaHandler(RedefineExtnameHandler.get());
170
171 FPContractHandler.reset(new PragmaFPContractHandler());
172 PP.AddPragmaHandler("STDC", FPContractHandler.get());
173
174 if (getLangOpts().OpenCL) {
175 OpenCLExtensionHandler.reset(new PragmaOpenCLExtensionHandler());
176 PP.AddPragmaHandler("OPENCL", OpenCLExtensionHandler.get());
177
178 PP.AddPragmaHandler("OPENCL", FPContractHandler.get());
179 }
180 if (getLangOpts().OpenMP)
181 OpenMPHandler.reset(new PragmaOpenMPHandler());
182 else
183 OpenMPHandler.reset(new PragmaNoOpenMPHandler());
184 PP.AddPragmaHandler(OpenMPHandler.get());
185
186 if (getLangOpts().MicrosoftExt) {
187 MSCommentHandler.reset(new PragmaCommentHandler(Actions));
188 PP.AddPragmaHandler(MSCommentHandler.get());
189 MSDetectMismatchHandler.reset(new PragmaDetectMismatchHandler(Actions));
190 PP.AddPragmaHandler(MSDetectMismatchHandler.get());
191 MSPointersToMembers.reset(new PragmaMSPointersToMembers());
192 PP.AddPragmaHandler(MSPointersToMembers.get());
193 MSVtorDisp.reset(new PragmaMSVtorDisp());
194 PP.AddPragmaHandler(MSVtorDisp.get());
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700195 MSInitSeg.reset(new PragmaMSPragma("init_seg"));
196 PP.AddPragmaHandler(MSInitSeg.get());
197 MSDataSeg.reset(new PragmaMSPragma("data_seg"));
198 PP.AddPragmaHandler(MSDataSeg.get());
199 MSBSSSeg.reset(new PragmaMSPragma("bss_seg"));
200 PP.AddPragmaHandler(MSBSSSeg.get());
201 MSConstSeg.reset(new PragmaMSPragma("const_seg"));
202 PP.AddPragmaHandler(MSConstSeg.get());
203 MSCodeSeg.reset(new PragmaMSPragma("code_seg"));
204 PP.AddPragmaHandler(MSCodeSeg.get());
205 MSSection.reset(new PragmaMSPragma("section"));
206 PP.AddPragmaHandler(MSSection.get());
Stephen Hines651f13c2014-04-23 16:59:28 -0700207 }
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700208
209 OptimizeHandler.reset(new PragmaOptimizeHandler(Actions));
210 PP.AddPragmaHandler("clang", OptimizeHandler.get());
Stephen Hines651f13c2014-04-23 16:59:28 -0700211}
212
213void Parser::resetPragmaHandlers() {
214 // Remove the pragma handlers we installed.
215 PP.RemovePragmaHandler(AlignHandler.get());
216 AlignHandler.reset();
217 PP.RemovePragmaHandler("GCC", GCCVisibilityHandler.get());
218 GCCVisibilityHandler.reset();
219 PP.RemovePragmaHandler(OptionsHandler.get());
220 OptionsHandler.reset();
221 PP.RemovePragmaHandler(PackHandler.get());
222 PackHandler.reset();
223 PP.RemovePragmaHandler(MSStructHandler.get());
224 MSStructHandler.reset();
225 PP.RemovePragmaHandler(UnusedHandler.get());
226 UnusedHandler.reset();
227 PP.RemovePragmaHandler(WeakHandler.get());
228 WeakHandler.reset();
229 PP.RemovePragmaHandler(RedefineExtnameHandler.get());
230 RedefineExtnameHandler.reset();
231
232 if (getLangOpts().OpenCL) {
233 PP.RemovePragmaHandler("OPENCL", OpenCLExtensionHandler.get());
234 OpenCLExtensionHandler.reset();
235 PP.RemovePragmaHandler("OPENCL", FPContractHandler.get());
236 }
237 PP.RemovePragmaHandler(OpenMPHandler.get());
238 OpenMPHandler.reset();
239
240 if (getLangOpts().MicrosoftExt) {
241 PP.RemovePragmaHandler(MSCommentHandler.get());
242 MSCommentHandler.reset();
243 PP.RemovePragmaHandler(MSDetectMismatchHandler.get());
244 MSDetectMismatchHandler.reset();
245 PP.RemovePragmaHandler(MSPointersToMembers.get());
246 MSPointersToMembers.reset();
247 PP.RemovePragmaHandler(MSVtorDisp.get());
248 MSVtorDisp.reset();
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700249 PP.RemovePragmaHandler(MSInitSeg.get());
250 MSInitSeg.reset();
251 PP.RemovePragmaHandler(MSDataSeg.get());
252 MSDataSeg.reset();
253 PP.RemovePragmaHandler(MSBSSSeg.get());
254 MSBSSSeg.reset();
255 PP.RemovePragmaHandler(MSConstSeg.get());
256 MSConstSeg.reset();
257 PP.RemovePragmaHandler(MSCodeSeg.get());
258 MSCodeSeg.reset();
259 PP.RemovePragmaHandler(MSSection.get());
260 MSSection.reset();
Stephen Hines651f13c2014-04-23 16:59:28 -0700261 }
262
263 PP.RemovePragmaHandler("STDC", FPContractHandler.get());
264 FPContractHandler.reset();
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700265
266 PP.RemovePragmaHandler("clang", OptimizeHandler.get());
267 OptimizeHandler.reset();
Stephen Hines651f13c2014-04-23 16:59:28 -0700268}
269
Argyrios Kyrtzidisb918d0f2011-01-17 18:58:44 +0000270/// \brief Handle the annotation token produced for #pragma unused(...)
271///
272/// Each annot_pragma_unused is followed by the argument token so e.g.
273/// "#pragma unused(x,y)" becomes:
274/// annot_pragma_unused 'x' annot_pragma_unused 'y'
275void Parser::HandlePragmaUnused() {
276 assert(Tok.is(tok::annot_pragma_unused));
277 SourceLocation UnusedLoc = ConsumeToken();
278 Actions.ActOnPragmaUnused(Tok, getCurScope(), UnusedLoc);
279 ConsumeToken(); // The argument token.
280}
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000281
Rafael Espindola426fc942012-01-26 02:02:57 +0000282void Parser::HandlePragmaVisibility() {
283 assert(Tok.is(tok::annot_pragma_vis));
284 const IdentifierInfo *VisType =
285 static_cast<IdentifierInfo *>(Tok.getAnnotationValue());
286 SourceLocation VisLoc = ConsumeToken();
287 Actions.ActOnPragmaVisibility(VisType, VisLoc);
288}
289
Eli Friedmanaa5ab262012-02-23 23:47:16 +0000290struct PragmaPackInfo {
291 Sema::PragmaPackKind Kind;
292 IdentifierInfo *Name;
Eli Friedman9595c7e2012-10-04 02:36:51 +0000293 Token Alignment;
Eli Friedmanaa5ab262012-02-23 23:47:16 +0000294 SourceLocation LParenLoc;
295 SourceLocation RParenLoc;
296};
297
298void Parser::HandlePragmaPack() {
299 assert(Tok.is(tok::annot_pragma_pack));
300 PragmaPackInfo *Info =
301 static_cast<PragmaPackInfo *>(Tok.getAnnotationValue());
302 SourceLocation PragmaLoc = ConsumeToken();
Eli Friedman9595c7e2012-10-04 02:36:51 +0000303 ExprResult Alignment;
304 if (Info->Alignment.is(tok::numeric_constant)) {
305 Alignment = Actions.ActOnNumericConstant(Info->Alignment);
306 if (Alignment.isInvalid())
307 return;
308 }
309 Actions.ActOnPragmaPack(Info->Kind, Info->Name, Alignment.get(), PragmaLoc,
Eli Friedmanaa5ab262012-02-23 23:47:16 +0000310 Info->LParenLoc, Info->RParenLoc);
Eli Friedmanaa5ab262012-02-23 23:47:16 +0000311}
312
Eli Friedman9595c7e2012-10-04 02:36:51 +0000313void Parser::HandlePragmaMSStruct() {
314 assert(Tok.is(tok::annot_pragma_msstruct));
315 Sema::PragmaMSStructKind Kind =
316 static_cast<Sema::PragmaMSStructKind>(
317 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
318 Actions.ActOnPragmaMSStruct(Kind);
319 ConsumeToken(); // The annotation token.
320}
321
322void Parser::HandlePragmaAlign() {
323 assert(Tok.is(tok::annot_pragma_align));
324 Sema::PragmaOptionsAlignKind Kind =
325 static_cast<Sema::PragmaOptionsAlignKind>(
326 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
327 SourceLocation PragmaLoc = ConsumeToken();
328 Actions.ActOnPragmaOptionsAlign(Kind, PragmaLoc);
329}
330
331void Parser::HandlePragmaWeak() {
332 assert(Tok.is(tok::annot_pragma_weak));
333 SourceLocation PragmaLoc = ConsumeToken();
334 Actions.ActOnPragmaWeakID(Tok.getIdentifierInfo(), PragmaLoc,
335 Tok.getLocation());
336 ConsumeToken(); // The weak name.
337}
338
339void Parser::HandlePragmaWeakAlias() {
340 assert(Tok.is(tok::annot_pragma_weakalias));
341 SourceLocation PragmaLoc = ConsumeToken();
342 IdentifierInfo *WeakName = Tok.getIdentifierInfo();
343 SourceLocation WeakNameLoc = Tok.getLocation();
344 ConsumeToken();
345 IdentifierInfo *AliasName = Tok.getIdentifierInfo();
346 SourceLocation AliasNameLoc = Tok.getLocation();
347 ConsumeToken();
348 Actions.ActOnPragmaWeakAlias(WeakName, AliasName, PragmaLoc,
349 WeakNameLoc, AliasNameLoc);
350
351}
352
353void Parser::HandlePragmaRedefineExtname() {
354 assert(Tok.is(tok::annot_pragma_redefine_extname));
355 SourceLocation RedefLoc = ConsumeToken();
356 IdentifierInfo *RedefName = Tok.getIdentifierInfo();
357 SourceLocation RedefNameLoc = Tok.getLocation();
358 ConsumeToken();
359 IdentifierInfo *AliasName = Tok.getIdentifierInfo();
360 SourceLocation AliasNameLoc = Tok.getLocation();
361 ConsumeToken();
362 Actions.ActOnPragmaRedefineExtname(RedefName, AliasName, RedefLoc,
363 RedefNameLoc, AliasNameLoc);
364}
365
366void Parser::HandlePragmaFPContract() {
367 assert(Tok.is(tok::annot_pragma_fp_contract));
368 tok::OnOffSwitch OOS =
369 static_cast<tok::OnOffSwitch>(
370 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
371 Actions.ActOnPragmaFPContract(OOS);
372 ConsumeToken(); // The annotation token.
373}
374
Tareq A. Siraj85192c72013-04-16 18:41:26 +0000375StmtResult Parser::HandlePragmaCaptured()
376{
377 assert(Tok.is(tok::annot_pragma_captured));
378 ConsumeToken();
379
380 if (Tok.isNot(tok::l_brace)) {
Stephen Hines651f13c2014-04-23 16:59:28 -0700381 PP.Diag(Tok, diag::err_expected) << tok::l_brace;
Tareq A. Siraj85192c72013-04-16 18:41:26 +0000382 return StmtError();
383 }
384
Tareq A. Siraj6afcf882013-04-16 19:37:38 +0000385 SourceLocation Loc = Tok.getLocation();
386
387 ParseScope CapturedRegionScope(this, Scope::FnScope | Scope::DeclScope);
Ben Langmuir8c045ac2013-05-03 19:00:33 +0000388 Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_Default,
389 /*NumParams=*/1);
Tareq A. Siraj6afcf882013-04-16 19:37:38 +0000390
391 StmtResult R = ParseCompoundStatement();
392 CapturedRegionScope.Exit();
393
394 if (R.isInvalid()) {
395 Actions.ActOnCapturedRegionError();
396 return StmtError();
397 }
398
399 return Actions.ActOnCapturedRegionEnd(R.get());
Tareq A. Siraj85192c72013-04-16 18:41:26 +0000400}
401
Eli Friedman9595c7e2012-10-04 02:36:51 +0000402namespace {
403 typedef llvm::PointerIntPair<IdentifierInfo *, 1, bool> OpenCLExtData;
404}
405
406void Parser::HandlePragmaOpenCLExtension() {
407 assert(Tok.is(tok::annot_pragma_opencl_extension));
408 OpenCLExtData data =
409 OpenCLExtData::getFromOpaqueValue(Tok.getAnnotationValue());
410 unsigned state = data.getInt();
411 IdentifierInfo *ename = data.getPointer();
412 SourceLocation NameLoc = Tok.getLocation();
413 ConsumeToken(); // The annotation token.
414
415 OpenCLOptions &f = Actions.getOpenCLOptions();
416 // OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions,
417 // overriding all previously issued extension directives, but only if the
418 // behavior is set to disable."
419 if (state == 0 && ename->isStr("all")) {
420#define OPENCLEXT(nm) f.nm = 0;
421#include "clang/Basic/OpenCLExtensions.def"
422 }
423#define OPENCLEXT(nm) else if (ename->isStr(#nm)) { f.nm = state; }
424#include "clang/Basic/OpenCLExtensions.def"
425 else {
426 PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << ename;
427 return;
428 }
429}
430
Stephen Hines651f13c2014-04-23 16:59:28 -0700431void Parser::HandlePragmaMSPointersToMembers() {
432 assert(Tok.is(tok::annot_pragma_ms_pointers_to_members));
433 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod =
434 static_cast<LangOptions::PragmaMSPointersToMembersKind>(
435 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
436 SourceLocation PragmaLoc = ConsumeToken(); // The annotation token.
437 Actions.ActOnPragmaMSPointersToMembers(RepresentationMethod, PragmaLoc);
438}
Tareq A. Siraj85192c72013-04-16 18:41:26 +0000439
Stephen Hines651f13c2014-04-23 16:59:28 -0700440void Parser::HandlePragmaMSVtorDisp() {
441 assert(Tok.is(tok::annot_pragma_ms_vtordisp));
442 uintptr_t Value = reinterpret_cast<uintptr_t>(Tok.getAnnotationValue());
443 Sema::PragmaVtorDispKind Kind =
444 static_cast<Sema::PragmaVtorDispKind>((Value >> 16) & 0xFFFF);
445 MSVtorDispAttr::Mode Mode = MSVtorDispAttr::Mode(Value & 0xFFFF);
446 SourceLocation PragmaLoc = ConsumeToken(); // The annotation token.
447 Actions.ActOnPragmaMSVtorDisp(Kind, PragmaLoc, Mode);
448}
Tareq A. Siraj85192c72013-04-16 18:41:26 +0000449
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700450void Parser::HandlePragmaMSPragma() {
451 assert(Tok.is(tok::annot_pragma_ms_pragma));
452 // Grab the tokens out of the annotation and enter them into the stream.
453 auto TheTokens = (std::pair<Token*, size_t> *)Tok.getAnnotationValue();
454 PP.EnterTokenStream(TheTokens->first, TheTokens->second, true, true);
455 SourceLocation PragmaLocation = ConsumeToken(); // The annotation token.
456 assert(Tok.isAnyIdentifier());
457 llvm::StringRef PragmaName = Tok.getIdentifierInfo()->getName();
458 PP.Lex(Tok); // pragma kind
459 // Figure out which #pragma we're dealing with. The switch has no default
460 // because lex shouldn't emit the annotation token for unrecognized pragmas.
461 typedef unsigned (Parser::*PragmaHandler)(llvm::StringRef, SourceLocation);
462 PragmaHandler Handler = llvm::StringSwitch<PragmaHandler>(PragmaName)
463 .Case("data_seg", &Parser::HandlePragmaMSSegment)
464 .Case("bss_seg", &Parser::HandlePragmaMSSegment)
465 .Case("const_seg", &Parser::HandlePragmaMSSegment)
466 .Case("code_seg", &Parser::HandlePragmaMSSegment)
467 .Case("section", &Parser::HandlePragmaMSSection)
468 .Case("init_seg", &Parser::HandlePragmaMSInitSeg);
469 if (auto DiagID = (this->*Handler)(PragmaName, PragmaLocation)) {
470 PP.Diag(PragmaLocation, DiagID) << PragmaName;
471 while (Tok.isNot(tok::eof))
472 PP.Lex(Tok);
473 PP.Lex(Tok);
474 }
475}
476
477unsigned Parser::HandlePragmaMSSection(llvm::StringRef PragmaName,
478 SourceLocation PragmaLocation) {
479 if (Tok.isNot(tok::l_paren))
480 return diag::warn_pragma_expected_lparen;
481 PP.Lex(Tok); // (
482 // Parsing code for pragma section
483 if (Tok.isNot(tok::string_literal))
484 return diag::warn_pragma_expected_section_name;
485 StringLiteral *SegmentName =
486 cast<StringLiteral>(ParseStringLiteralExpression().get());
487 int SectionFlags = 0;
488 while (Tok.is(tok::comma)) {
489 PP.Lex(Tok); // ,
490 if (!Tok.isAnyIdentifier())
491 return diag::warn_pragma_expected_action_or_r_paren;
492 Sema::PragmaSectionFlag Flag =
493 llvm::StringSwitch<Sema::PragmaSectionFlag>(
494 Tok.getIdentifierInfo()->getName())
495 .Case("read", Sema::PSF_Read)
496 .Case("write", Sema::PSF_Write)
497 .Case("execute", Sema::PSF_Execute)
498 .Case("shared", Sema::PSF_Invalid)
499 .Case("nopage", Sema::PSF_Invalid)
500 .Case("nocache", Sema::PSF_Invalid)
501 .Case("discard", Sema::PSF_Invalid)
502 .Case("remove", Sema::PSF_Invalid)
503 .Default(Sema::PSF_None);
504 if (Flag == Sema::PSF_None || Flag == Sema::PSF_Invalid) {
505 PP.Diag(PragmaLocation, Flag == Sema::PSF_None ?
506 diag::warn_pragma_invalid_specific_action :
507 diag::warn_pragma_unsupported_action)
508 << PragmaName << Tok.getIdentifierInfo()->getName();
509 while (Tok.isNot(tok::eof))
510 PP.Lex(Tok);
511 PP.Lex(Tok);
512 return 0;
513 }
514 SectionFlags |= Flag;
515 PP.Lex(Tok); // Identifier
516 }
517 if (Tok.isNot(tok::r_paren))
518 return diag::warn_pragma_expected_rparen;
519 PP.Lex(Tok); // )
520 if (Tok.isNot(tok::eof))
521 return diag::warn_pragma_extra_tokens_at_eol;
522 PP.Lex(Tok); // eof
523 Actions.ActOnPragmaMSSection(PragmaLocation, SectionFlags, SegmentName);
524 return 0;
525}
526
527unsigned Parser::HandlePragmaMSSegment(llvm::StringRef PragmaName,
528 SourceLocation PragmaLocation) {
529 if (Tok.isNot(tok::l_paren))
530 return diag::warn_pragma_expected_lparen;
531 PP.Lex(Tok); // (
532 Sema::PragmaMsStackAction Action = Sema::PSK_Reset;
533 llvm::StringRef SlotLabel;
534 if (Tok.isAnyIdentifier()) {
535 llvm::StringRef PushPop = Tok.getIdentifierInfo()->getName();
536 if (PushPop == "push")
537 Action = Sema::PSK_Push;
538 else if (PushPop == "pop")
539 Action = Sema::PSK_Pop;
540 else
541 return diag::warn_pragma_expected_section_push_pop_or_name;
542 if (Action != Sema::PSK_Reset) {
543 PP.Lex(Tok); // push | pop
544 if (Tok.is(tok::comma)) {
545 PP.Lex(Tok); // ,
546 // If we've got a comma, we either need a label or a string.
547 if (Tok.isAnyIdentifier()) {
548 SlotLabel = Tok.getIdentifierInfo()->getName();
549 PP.Lex(Tok); // identifier
550 if (Tok.is(tok::comma))
551 PP.Lex(Tok);
552 else if (Tok.isNot(tok::r_paren))
553 return diag::warn_pragma_expected_punc;
554 }
555 } else if (Tok.isNot(tok::r_paren))
556 return diag::warn_pragma_expected_punc;
557 }
558 }
559 // Grab the string literal for our section name.
560 StringLiteral *SegmentName = nullptr;
561 if (Tok.isNot(tok::r_paren)) {
562 if (Tok.isNot(tok::string_literal))
563 return Action != Sema::PSK_Reset ? !SlotLabel.empty() ?
564 diag::warn_pragma_expected_section_name :
565 diag::warn_pragma_expected_section_label_or_name :
566 diag::warn_pragma_expected_section_push_pop_or_name;
567 SegmentName = cast<StringLiteral>(ParseStringLiteralExpression().get());
568 // Setting section "" has no effect
569 if (SegmentName->getLength())
570 Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
571 }
572 if (Tok.isNot(tok::r_paren))
573 return diag::warn_pragma_expected_rparen;
574 PP.Lex(Tok); // )
575 if (Tok.isNot(tok::eof))
576 return diag::warn_pragma_extra_tokens_at_eol;
577 PP.Lex(Tok); // eof
578 Actions.ActOnPragmaMSSeg(PragmaLocation, Action, SlotLabel,
579 SegmentName, PragmaName);
580 return 0;
581}
582
583unsigned Parser::HandlePragmaMSInitSeg(llvm::StringRef PragmaName,
584 SourceLocation PragmaLocation) {
585 return PP.getDiagnostics().getCustomDiagID(
586 DiagnosticsEngine::Error, "'#pragma %0' not implemented.");
587}
588
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000589// #pragma GCC visibility comes in two variants:
590// 'push' '(' [visibility] ')'
591// 'pop'
Douglas Gregor80c60f72010-09-09 22:45:38 +0000592void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,
593 PragmaIntroducerKind Introducer,
594 Token &VisTok) {
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000595 SourceLocation VisLoc = VisTok.getLocation();
596
597 Token Tok;
Joerg Sonnenbergere23af2a2011-07-20 01:03:50 +0000598 PP.LexUnexpandedToken(Tok);
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000599
600 const IdentifierInfo *PushPop = Tok.getIdentifierInfo();
601
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000602 const IdentifierInfo *VisType;
603 if (PushPop && PushPop->isStr("pop")) {
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700604 VisType = nullptr;
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000605 } else if (PushPop && PushPop->isStr("push")) {
Joerg Sonnenbergere23af2a2011-07-20 01:03:50 +0000606 PP.LexUnexpandedToken(Tok);
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000607 if (Tok.isNot(tok::l_paren)) {
608 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
609 << "visibility";
610 return;
611 }
Joerg Sonnenbergere23af2a2011-07-20 01:03:50 +0000612 PP.LexUnexpandedToken(Tok);
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000613 VisType = Tok.getIdentifierInfo();
614 if (!VisType) {
615 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
616 << "visibility";
617 return;
618 }
Joerg Sonnenbergere23af2a2011-07-20 01:03:50 +0000619 PP.LexUnexpandedToken(Tok);
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000620 if (Tok.isNot(tok::r_paren)) {
621 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
622 << "visibility";
623 return;
624 }
625 } else {
626 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
627 << "visibility";
628 return;
629 }
Joerg Sonnenbergere23af2a2011-07-20 01:03:50 +0000630 PP.LexUnexpandedToken(Tok);
Peter Collingbourne84021552011-02-28 02:37:51 +0000631 if (Tok.isNot(tok::eod)) {
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000632 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
633 << "visibility";
634 return;
635 }
636
Rafael Espindola426fc942012-01-26 02:02:57 +0000637 Token *Toks = new Token[1];
638 Toks[0].startToken();
639 Toks[0].setKind(tok::annot_pragma_vis);
640 Toks[0].setLocation(VisLoc);
641 Toks[0].setAnnotationValue(
642 const_cast<void*>(static_cast<const void*>(VisType)));
643 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
644 /*OwnsTokens=*/true);
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000645}
646
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000647// #pragma pack(...) comes in the following delicious flavors:
648// pack '(' [integer] ')'
649// pack '(' 'show' ')'
650// pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'
Douglas Gregor80c60f72010-09-09 22:45:38 +0000651void PragmaPackHandler::HandlePragma(Preprocessor &PP,
652 PragmaIntroducerKind Introducer,
653 Token &PackTok) {
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000654 SourceLocation PackLoc = PackTok.getLocation();
655
656 Token Tok;
657 PP.Lex(Tok);
658 if (Tok.isNot(tok::l_paren)) {
Ted Kremenek4726d032009-03-23 22:28:25 +0000659 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack";
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000660 return;
661 }
662
John McCallf312b1e2010-08-26 23:41:50 +0000663 Sema::PragmaPackKind Kind = Sema::PPK_Default;
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700664 IdentifierInfo *Name = nullptr;
Eli Friedman9595c7e2012-10-04 02:36:51 +0000665 Token Alignment;
666 Alignment.startToken();
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000667 SourceLocation LParenLoc = Tok.getLocation();
Mike Stump1eb44332009-09-09 15:08:12 +0000668 PP.Lex(Tok);
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000669 if (Tok.is(tok::numeric_constant)) {
Eli Friedman9595c7e2012-10-04 02:36:51 +0000670 Alignment = Tok;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000671
672 PP.Lex(Tok);
Eli Friedman19bda3a2011-11-02 01:53:16 +0000673
674 // In MSVC/gcc, #pragma pack(4) sets the alignment without affecting
675 // the push/pop stack.
676 // In Apple gcc, #pragma pack(4) is equivalent to #pragma pack(push, 4)
David Blaikie4e4d0842012-03-11 07:00:24 +0000677 if (PP.getLangOpts().ApplePragmaPack)
Eli Friedman19bda3a2011-11-02 01:53:16 +0000678 Kind = Sema::PPK_Push;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000679 } else if (Tok.is(tok::identifier)) {
680 const IdentifierInfo *II = Tok.getIdentifierInfo();
Chris Lattner08631c52008-11-23 21:45:46 +0000681 if (II->isStr("show")) {
John McCallf312b1e2010-08-26 23:41:50 +0000682 Kind = Sema::PPK_Show;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000683 PP.Lex(Tok);
684 } else {
Chris Lattner08631c52008-11-23 21:45:46 +0000685 if (II->isStr("push")) {
John McCallf312b1e2010-08-26 23:41:50 +0000686 Kind = Sema::PPK_Push;
Chris Lattner08631c52008-11-23 21:45:46 +0000687 } else if (II->isStr("pop")) {
John McCallf312b1e2010-08-26 23:41:50 +0000688 Kind = Sema::PPK_Pop;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000689 } else {
Stephen Hines651f13c2014-04-23 16:59:28 -0700690 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action) << "pack";
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000691 return;
Mike Stump1eb44332009-09-09 15:08:12 +0000692 }
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000693 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000694
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000695 if (Tok.is(tok::comma)) {
696 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000697
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000698 if (Tok.is(tok::numeric_constant)) {
Eli Friedman9595c7e2012-10-04 02:36:51 +0000699 Alignment = Tok;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000700
701 PP.Lex(Tok);
702 } else if (Tok.is(tok::identifier)) {
703 Name = Tok.getIdentifierInfo();
704 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000705
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000706 if (Tok.is(tok::comma)) {
707 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000708
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000709 if (Tok.isNot(tok::numeric_constant)) {
Chris Lattner08631c52008-11-23 21:45:46 +0000710 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000711 return;
712 }
Mike Stump1eb44332009-09-09 15:08:12 +0000713
Eli Friedman9595c7e2012-10-04 02:36:51 +0000714 Alignment = Tok;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000715
716 PP.Lex(Tok);
717 }
718 } else {
Chris Lattner08631c52008-11-23 21:45:46 +0000719 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000720 return;
721 }
722 }
723 }
David Blaikie4e4d0842012-03-11 07:00:24 +0000724 } else if (PP.getLangOpts().ApplePragmaPack) {
Eli Friedman19bda3a2011-11-02 01:53:16 +0000725 // In MSVC/gcc, #pragma pack() resets the alignment without affecting
726 // the push/pop stack.
727 // In Apple gcc #pragma pack() is equivalent to #pragma pack(pop).
728 Kind = Sema::PPK_Pop;
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000729 }
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000730
731 if (Tok.isNot(tok::r_paren)) {
Ted Kremenek4726d032009-03-23 22:28:25 +0000732 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack";
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000733 return;
734 }
735
Daniel Dunbar861800c2010-05-26 23:29:06 +0000736 SourceLocation RParenLoc = Tok.getLocation();
Eli Friedman99914792009-06-05 00:49:58 +0000737 PP.Lex(Tok);
Peter Collingbourne84021552011-02-28 02:37:51 +0000738 if (Tok.isNot(tok::eod)) {
Eli Friedman99914792009-06-05 00:49:58 +0000739 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack";
740 return;
741 }
742
Daniel Dunbarb0939552012-02-29 01:38:22 +0000743 PragmaPackInfo *Info =
744 (PragmaPackInfo*) PP.getPreprocessorAllocator().Allocate(
745 sizeof(PragmaPackInfo), llvm::alignOf<PragmaPackInfo>());
746 new (Info) PragmaPackInfo();
Eli Friedmanaa5ab262012-02-23 23:47:16 +0000747 Info->Kind = Kind;
748 Info->Name = Name;
Eli Friedman9595c7e2012-10-04 02:36:51 +0000749 Info->Alignment = Alignment;
Eli Friedmanaa5ab262012-02-23 23:47:16 +0000750 Info->LParenLoc = LParenLoc;
751 Info->RParenLoc = RParenLoc;
752
Daniel Dunbarb0939552012-02-29 01:38:22 +0000753 Token *Toks =
754 (Token*) PP.getPreprocessorAllocator().Allocate(
755 sizeof(Token) * 1, llvm::alignOf<Token>());
756 new (Toks) Token();
Eli Friedmanaa5ab262012-02-23 23:47:16 +0000757 Toks[0].startToken();
758 Toks[0].setKind(tok::annot_pragma_pack);
759 Toks[0].setLocation(PackLoc);
760 Toks[0].setAnnotationValue(static_cast<void*>(Info));
761 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
Daniel Dunbarb0939552012-02-29 01:38:22 +0000762 /*OwnsTokens=*/false);
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000763}
764
Fariborz Jahanian62c92582011-04-25 18:49:15 +0000765// #pragma ms_struct on
766// #pragma ms_struct off
767void PragmaMSStructHandler::HandlePragma(Preprocessor &PP,
768 PragmaIntroducerKind Introducer,
769 Token &MSStructTok) {
770 Sema::PragmaMSStructKind Kind = Sema::PMSST_OFF;
771
772 Token Tok;
773 PP.Lex(Tok);
774 if (Tok.isNot(tok::identifier)) {
775 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
776 return;
777 }
778 const IdentifierInfo *II = Tok.getIdentifierInfo();
779 if (II->isStr("on")) {
780 Kind = Sema::PMSST_ON;
781 PP.Lex(Tok);
782 }
783 else if (II->isStr("off") || II->isStr("reset"))
784 PP.Lex(Tok);
785 else {
786 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
787 return;
788 }
789
790 if (Tok.isNot(tok::eod)) {
Daniel Dunbarb0939552012-02-29 01:38:22 +0000791 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
792 << "ms_struct";
Fariborz Jahanian62c92582011-04-25 18:49:15 +0000793 return;
794 }
Eli Friedman9595c7e2012-10-04 02:36:51 +0000795
796 Token *Toks =
797 (Token*) PP.getPreprocessorAllocator().Allocate(
798 sizeof(Token) * 1, llvm::alignOf<Token>());
799 new (Toks) Token();
800 Toks[0].startToken();
801 Toks[0].setKind(tok::annot_pragma_msstruct);
802 Toks[0].setLocation(MSStructTok.getLocation());
803 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
804 static_cast<uintptr_t>(Kind)));
805 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
806 /*OwnsTokens=*/false);
Fariborz Jahanian62c92582011-04-25 18:49:15 +0000807}
808
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000809// #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
810// #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
Eli Friedman9595c7e2012-10-04 02:36:51 +0000811static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok,
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000812 bool IsOptions) {
Daniel Dunbar861800c2010-05-26 23:29:06 +0000813 Token Tok;
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000814
815 if (IsOptions) {
816 PP.Lex(Tok);
817 if (Tok.isNot(tok::identifier) ||
818 !Tok.getIdentifierInfo()->isStr("align")) {
819 PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align);
820 return;
821 }
Daniel Dunbar861800c2010-05-26 23:29:06 +0000822 }
Daniel Dunbar638e7cf2010-05-27 18:42:09 +0000823
Daniel Dunbar861800c2010-05-26 23:29:06 +0000824 PP.Lex(Tok);
825 if (Tok.isNot(tok::equal)) {
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000826 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal)
827 << IsOptions;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000828 return;
829 }
830
831 PP.Lex(Tok);
832 if (Tok.isNot(tok::identifier)) {
833 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000834 << (IsOptions ? "options" : "align");
Daniel Dunbar861800c2010-05-26 23:29:06 +0000835 return;
836 }
837
John McCallf312b1e2010-08-26 23:41:50 +0000838 Sema::PragmaOptionsAlignKind Kind = Sema::POAK_Natural;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000839 const IdentifierInfo *II = Tok.getIdentifierInfo();
Daniel Dunbar638e7cf2010-05-27 18:42:09 +0000840 if (II->isStr("native"))
John McCallf312b1e2010-08-26 23:41:50 +0000841 Kind = Sema::POAK_Native;
Daniel Dunbar638e7cf2010-05-27 18:42:09 +0000842 else if (II->isStr("natural"))
John McCallf312b1e2010-08-26 23:41:50 +0000843 Kind = Sema::POAK_Natural;
Daniel Dunbar6f739142010-05-27 18:42:17 +0000844 else if (II->isStr("packed"))
John McCallf312b1e2010-08-26 23:41:50 +0000845 Kind = Sema::POAK_Packed;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000846 else if (II->isStr("power"))
John McCallf312b1e2010-08-26 23:41:50 +0000847 Kind = Sema::POAK_Power;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000848 else if (II->isStr("mac68k"))
John McCallf312b1e2010-08-26 23:41:50 +0000849 Kind = Sema::POAK_Mac68k;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000850 else if (II->isStr("reset"))
John McCallf312b1e2010-08-26 23:41:50 +0000851 Kind = Sema::POAK_Reset;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000852 else {
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000853 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option)
854 << IsOptions;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000855 return;
856 }
857
Daniel Dunbar861800c2010-05-26 23:29:06 +0000858 PP.Lex(Tok);
Peter Collingbourne84021552011-02-28 02:37:51 +0000859 if (Tok.isNot(tok::eod)) {
Daniel Dunbar861800c2010-05-26 23:29:06 +0000860 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000861 << (IsOptions ? "options" : "align");
Daniel Dunbar861800c2010-05-26 23:29:06 +0000862 return;
863 }
864
Eli Friedman9595c7e2012-10-04 02:36:51 +0000865 Token *Toks =
866 (Token*) PP.getPreprocessorAllocator().Allocate(
867 sizeof(Token) * 1, llvm::alignOf<Token>());
868 new (Toks) Token();
869 Toks[0].startToken();
870 Toks[0].setKind(tok::annot_pragma_align);
871 Toks[0].setLocation(FirstTok.getLocation());
872 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
873 static_cast<uintptr_t>(Kind)));
874 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
875 /*OwnsTokens=*/false);
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000876}
877
Douglas Gregor80c60f72010-09-09 22:45:38 +0000878void PragmaAlignHandler::HandlePragma(Preprocessor &PP,
879 PragmaIntroducerKind Introducer,
880 Token &AlignTok) {
Eli Friedman9595c7e2012-10-04 02:36:51 +0000881 ParseAlignPragma(PP, AlignTok, /*IsOptions=*/false);
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000882}
883
Douglas Gregor80c60f72010-09-09 22:45:38 +0000884void PragmaOptionsHandler::HandlePragma(Preprocessor &PP,
885 PragmaIntroducerKind Introducer,
886 Token &OptionsTok) {
Eli Friedman9595c7e2012-10-04 02:36:51 +0000887 ParseAlignPragma(PP, OptionsTok, /*IsOptions=*/true);
Daniel Dunbar861800c2010-05-26 23:29:06 +0000888}
889
Ted Kremenek4726d032009-03-23 22:28:25 +0000890// #pragma unused(identifier)
Douglas Gregor80c60f72010-09-09 22:45:38 +0000891void PragmaUnusedHandler::HandlePragma(Preprocessor &PP,
892 PragmaIntroducerKind Introducer,
893 Token &UnusedTok) {
Ted Kremenek4726d032009-03-23 22:28:25 +0000894 // FIXME: Should we be expanding macros here? My guess is no.
895 SourceLocation UnusedLoc = UnusedTok.getLocation();
Mike Stump1eb44332009-09-09 15:08:12 +0000896
Ted Kremenek4726d032009-03-23 22:28:25 +0000897 // Lex the left '('.
898 Token Tok;
899 PP.Lex(Tok);
900 if (Tok.isNot(tok::l_paren)) {
901 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
902 return;
903 }
Mike Stump1eb44332009-09-09 15:08:12 +0000904
Ted Kremenek4726d032009-03-23 22:28:25 +0000905 // Lex the declaration reference(s).
Chris Lattner5f9e2722011-07-23 10:55:15 +0000906 SmallVector<Token, 5> Identifiers;
Ted Kremenek4726d032009-03-23 22:28:25 +0000907 SourceLocation RParenLoc;
908 bool LexID = true;
Mike Stump1eb44332009-09-09 15:08:12 +0000909
Ted Kremenek4726d032009-03-23 22:28:25 +0000910 while (true) {
911 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000912
Ted Kremenek4726d032009-03-23 22:28:25 +0000913 if (LexID) {
Mike Stump1eb44332009-09-09 15:08:12 +0000914 if (Tok.is(tok::identifier)) {
Ted Kremenek7a02a372009-08-03 23:24:57 +0000915 Identifiers.push_back(Tok);
Ted Kremenek4726d032009-03-23 22:28:25 +0000916 LexID = false;
917 continue;
918 }
919
Ted Kremenek7a02a372009-08-03 23:24:57 +0000920 // Illegal token!
Ted Kremenek4726d032009-03-23 22:28:25 +0000921 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
922 return;
923 }
Mike Stump1eb44332009-09-09 15:08:12 +0000924
Ted Kremenek4726d032009-03-23 22:28:25 +0000925 // We are execting a ')' or a ','.
926 if (Tok.is(tok::comma)) {
927 LexID = true;
928 continue;
929 }
Mike Stump1eb44332009-09-09 15:08:12 +0000930
Ted Kremenek4726d032009-03-23 22:28:25 +0000931 if (Tok.is(tok::r_paren)) {
932 RParenLoc = Tok.getLocation();
933 break;
934 }
Mike Stump1eb44332009-09-09 15:08:12 +0000935
Ted Kremenek7a02a372009-08-03 23:24:57 +0000936 // Illegal token!
Stephen Hines651f13c2014-04-23 16:59:28 -0700937 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_punc) << "unused";
Ted Kremenek4726d032009-03-23 22:28:25 +0000938 return;
939 }
Eli Friedman99914792009-06-05 00:49:58 +0000940
941 PP.Lex(Tok);
Peter Collingbourne84021552011-02-28 02:37:51 +0000942 if (Tok.isNot(tok::eod)) {
Eli Friedman99914792009-06-05 00:49:58 +0000943 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
944 "unused";
945 return;
946 }
947
Ted Kremenek4726d032009-03-23 22:28:25 +0000948 // Verify that we have a location for the right parenthesis.
949 assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
Ted Kremenek7a02a372009-08-03 23:24:57 +0000950 assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
Ted Kremenek4726d032009-03-23 22:28:25 +0000951
Argyrios Kyrtzidisb918d0f2011-01-17 18:58:44 +0000952 // For each identifier token, insert into the token stream a
953 // annot_pragma_unused token followed by the identifier token.
954 // This allows us to cache a "#pragma unused" that occurs inside an inline
955 // C++ member function.
956
Daniel Dunbarb0939552012-02-29 01:38:22 +0000957 Token *Toks =
958 (Token*) PP.getPreprocessorAllocator().Allocate(
959 sizeof(Token) * 2 * Identifiers.size(), llvm::alignOf<Token>());
Argyrios Kyrtzidisb918d0f2011-01-17 18:58:44 +0000960 for (unsigned i=0; i != Identifiers.size(); i++) {
961 Token &pragmaUnusedTok = Toks[2*i], &idTok = Toks[2*i+1];
962 pragmaUnusedTok.startToken();
963 pragmaUnusedTok.setKind(tok::annot_pragma_unused);
964 pragmaUnusedTok.setLocation(UnusedLoc);
965 idTok = Identifiers[i];
966 }
Daniel Dunbarb0939552012-02-29 01:38:22 +0000967 PP.EnterTokenStream(Toks, 2*Identifiers.size(),
968 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
Ted Kremenek4726d032009-03-23 22:28:25 +0000969}
Eli Friedman99914792009-06-05 00:49:58 +0000970
971// #pragma weak identifier
972// #pragma weak identifier '=' identifier
Douglas Gregor80c60f72010-09-09 22:45:38 +0000973void PragmaWeakHandler::HandlePragma(Preprocessor &PP,
974 PragmaIntroducerKind Introducer,
975 Token &WeakTok) {
Eli Friedman99914792009-06-05 00:49:58 +0000976 SourceLocation WeakLoc = WeakTok.getLocation();
977
978 Token Tok;
979 PP.Lex(Tok);
980 if (Tok.isNot(tok::identifier)) {
981 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";
982 return;
983 }
984
Eli Friedman9595c7e2012-10-04 02:36:51 +0000985 Token WeakName = Tok;
986 bool HasAlias = false;
987 Token AliasName;
Eli Friedman99914792009-06-05 00:49:58 +0000988
989 PP.Lex(Tok);
990 if (Tok.is(tok::equal)) {
Eli Friedman9595c7e2012-10-04 02:36:51 +0000991 HasAlias = true;
Eli Friedman99914792009-06-05 00:49:58 +0000992 PP.Lex(Tok);
993 if (Tok.isNot(tok::identifier)) {
Mike Stump1eb44332009-09-09 15:08:12 +0000994 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Eli Friedman99914792009-06-05 00:49:58 +0000995 << "weak";
996 return;
997 }
Eli Friedman9595c7e2012-10-04 02:36:51 +0000998 AliasName = Tok;
Eli Friedman99914792009-06-05 00:49:58 +0000999 PP.Lex(Tok);
1000 }
1001
Peter Collingbourne84021552011-02-28 02:37:51 +00001002 if (Tok.isNot(tok::eod)) {
Eli Friedman99914792009-06-05 00:49:58 +00001003 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";
1004 return;
1005 }
1006
Eli Friedman9595c7e2012-10-04 02:36:51 +00001007 if (HasAlias) {
1008 Token *Toks =
1009 (Token*) PP.getPreprocessorAllocator().Allocate(
1010 sizeof(Token) * 3, llvm::alignOf<Token>());
1011 Token &pragmaUnusedTok = Toks[0];
1012 pragmaUnusedTok.startToken();
1013 pragmaUnusedTok.setKind(tok::annot_pragma_weakalias);
1014 pragmaUnusedTok.setLocation(WeakLoc);
1015 Toks[1] = WeakName;
1016 Toks[2] = AliasName;
1017 PP.EnterTokenStream(Toks, 3,
1018 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
Eli Friedman99914792009-06-05 00:49:58 +00001019 } else {
Eli Friedman9595c7e2012-10-04 02:36:51 +00001020 Token *Toks =
1021 (Token*) PP.getPreprocessorAllocator().Allocate(
1022 sizeof(Token) * 2, llvm::alignOf<Token>());
1023 Token &pragmaUnusedTok = Toks[0];
1024 pragmaUnusedTok.startToken();
1025 pragmaUnusedTok.setKind(tok::annot_pragma_weak);
1026 pragmaUnusedTok.setLocation(WeakLoc);
1027 Toks[1] = WeakName;
1028 PP.EnterTokenStream(Toks, 2,
1029 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
Eli Friedman99914792009-06-05 00:49:58 +00001030 }
1031}
Peter Collingbourne321b8172011-02-14 01:42:35 +00001032
David Chisnall5f3c1632012-02-18 16:12:34 +00001033// #pragma redefine_extname identifier identifier
1034void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP,
1035 PragmaIntroducerKind Introducer,
1036 Token &RedefToken) {
1037 SourceLocation RedefLoc = RedefToken.getLocation();
1038
1039 Token Tok;
1040 PP.Lex(Tok);
1041 if (Tok.isNot(tok::identifier)) {
1042 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
1043 "redefine_extname";
1044 return;
1045 }
1046
Eli Friedman9595c7e2012-10-04 02:36:51 +00001047 Token RedefName = Tok;
David Chisnall5f3c1632012-02-18 16:12:34 +00001048 PP.Lex(Tok);
Eli Friedman9595c7e2012-10-04 02:36:51 +00001049
David Chisnall5f3c1632012-02-18 16:12:34 +00001050 if (Tok.isNot(tok::identifier)) {
1051 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1052 << "redefine_extname";
1053 return;
1054 }
Eli Friedman9595c7e2012-10-04 02:36:51 +00001055
1056 Token AliasName = Tok;
David Chisnall5f3c1632012-02-18 16:12:34 +00001057 PP.Lex(Tok);
1058
1059 if (Tok.isNot(tok::eod)) {
1060 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
1061 "redefine_extname";
1062 return;
1063 }
1064
Eli Friedman9595c7e2012-10-04 02:36:51 +00001065 Token *Toks =
1066 (Token*) PP.getPreprocessorAllocator().Allocate(
1067 sizeof(Token) * 3, llvm::alignOf<Token>());
1068 Token &pragmaRedefTok = Toks[0];
1069 pragmaRedefTok.startToken();
1070 pragmaRedefTok.setKind(tok::annot_pragma_redefine_extname);
1071 pragmaRedefTok.setLocation(RedefLoc);
1072 Toks[1] = RedefName;
1073 Toks[2] = AliasName;
1074 PP.EnterTokenStream(Toks, 3,
1075 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
David Chisnall5f3c1632012-02-18 16:12:34 +00001076}
1077
1078
Peter Collingbourne321b8172011-02-14 01:42:35 +00001079void
1080PragmaFPContractHandler::HandlePragma(Preprocessor &PP,
1081 PragmaIntroducerKind Introducer,
1082 Token &Tok) {
1083 tok::OnOffSwitch OOS;
1084 if (PP.LexOnOffSwitch(OOS))
1085 return;
1086
Eli Friedman9595c7e2012-10-04 02:36:51 +00001087 Token *Toks =
1088 (Token*) PP.getPreprocessorAllocator().Allocate(
1089 sizeof(Token) * 1, llvm::alignOf<Token>());
1090 new (Toks) Token();
1091 Toks[0].startToken();
1092 Toks[0].setKind(tok::annot_pragma_fp_contract);
1093 Toks[0].setLocation(Tok.getLocation());
1094 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
1095 static_cast<uintptr_t>(OOS)));
1096 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
1097 /*OwnsTokens=*/false);
Peter Collingbourne321b8172011-02-14 01:42:35 +00001098}
Peter Collingbournef315fa82011-02-14 01:42:53 +00001099
1100void
1101PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
1102 PragmaIntroducerKind Introducer,
1103 Token &Tok) {
Tanya Lattnerb38b6a72011-04-14 23:35:31 +00001104 PP.LexUnexpandedToken(Tok);
Peter Collingbournef315fa82011-02-14 01:42:53 +00001105 if (Tok.isNot(tok::identifier)) {
1106 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
1107 "OPENCL";
1108 return;
1109 }
1110 IdentifierInfo *ename = Tok.getIdentifierInfo();
1111 SourceLocation NameLoc = Tok.getLocation();
1112
1113 PP.Lex(Tok);
1114 if (Tok.isNot(tok::colon)) {
1115 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << ename;
1116 return;
1117 }
1118
1119 PP.Lex(Tok);
1120 if (Tok.isNot(tok::identifier)) {
1121 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
1122 return;
1123 }
1124 IdentifierInfo *op = Tok.getIdentifierInfo();
1125
1126 unsigned state;
1127 if (op->isStr("enable")) {
1128 state = 1;
1129 } else if (op->isStr("disable")) {
1130 state = 0;
1131 } else {
1132 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
1133 return;
1134 }
Pekka Jaaskelainena0950e82013-10-12 09:29:48 +00001135 SourceLocation StateLoc = Tok.getLocation();
Peter Collingbournef315fa82011-02-14 01:42:53 +00001136
Eli Friedman9595c7e2012-10-04 02:36:51 +00001137 PP.Lex(Tok);
1138 if (Tok.isNot(tok::eod)) {
1139 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
1140 "OPENCL EXTENSION";
Peter Collingbournef315fa82011-02-14 01:42:53 +00001141 return;
1142 }
Eli Friedman9595c7e2012-10-04 02:36:51 +00001143
1144 OpenCLExtData data(ename, state);
1145 Token *Toks =
1146 (Token*) PP.getPreprocessorAllocator().Allocate(
1147 sizeof(Token) * 1, llvm::alignOf<Token>());
1148 new (Toks) Token();
1149 Toks[0].startToken();
1150 Toks[0].setKind(tok::annot_pragma_opencl_extension);
1151 Toks[0].setLocation(NameLoc);
1152 Toks[0].setAnnotationValue(data.getOpaqueValue());
1153 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
1154 /*OwnsTokens=*/false);
Pekka Jaaskelainena0950e82013-10-12 09:29:48 +00001155
1156 if (PP.getPPCallbacks())
1157 PP.getPPCallbacks()->PragmaOpenCLExtension(NameLoc, ename,
1158 StateLoc, state);
Peter Collingbournef315fa82011-02-14 01:42:53 +00001159}
1160
Alexey Bataevc6400582013-03-22 06:34:35 +00001161/// \brief Handle '#pragma omp ...' when OpenMP is disabled.
1162///
1163void
1164PragmaNoOpenMPHandler::HandlePragma(Preprocessor &PP,
1165 PragmaIntroducerKind Introducer,
1166 Token &FirstTok) {
1167 if (PP.getDiagnostics().getDiagnosticLevel(diag::warn_pragma_omp_ignored,
1168 FirstTok.getLocation()) !=
1169 DiagnosticsEngine::Ignored) {
1170 PP.Diag(FirstTok, diag::warn_pragma_omp_ignored);
1171 PP.getDiagnostics().setDiagnosticMapping(diag::warn_pragma_omp_ignored,
1172 diag::MAP_IGNORE,
1173 SourceLocation());
1174 }
1175 PP.DiscardUntilEndOfDirective();
1176}
1177
1178/// \brief Handle '#pragma omp ...' when OpenMP is enabled.
1179///
1180void
1181PragmaOpenMPHandler::HandlePragma(Preprocessor &PP,
1182 PragmaIntroducerKind Introducer,
1183 Token &FirstTok) {
1184 SmallVector<Token, 16> Pragma;
1185 Token Tok;
1186 Tok.startToken();
1187 Tok.setKind(tok::annot_pragma_openmp);
1188 Tok.setLocation(FirstTok.getLocation());
1189
1190 while (Tok.isNot(tok::eod)) {
1191 Pragma.push_back(Tok);
1192 PP.Lex(Tok);
1193 }
1194 SourceLocation EodLoc = Tok.getLocation();
1195 Tok.startToken();
1196 Tok.setKind(tok::annot_pragma_openmp_end);
1197 Tok.setLocation(EodLoc);
1198 Pragma.push_back(Tok);
1199
1200 Token *Toks = new Token[Pragma.size()];
1201 std::copy(Pragma.begin(), Pragma.end(), Toks);
1202 PP.EnterTokenStream(Toks, Pragma.size(),
1203 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/true);
1204}
Reid Kleckner7adf79a2013-05-06 21:02:12 +00001205
Stephen Hines651f13c2014-04-23 16:59:28 -07001206/// \brief Handle '#pragma pointers_to_members'
1207// The grammar for this pragma is as follows:
1208//
1209// <inheritance model> ::= ('single' | 'multiple' | 'virtual') '_inheritance'
1210//
1211// #pragma pointers_to_members '(' 'best_case' ')'
1212// #pragma pointers_to_members '(' 'full_generality' [',' inheritance-model] ')'
1213// #pragma pointers_to_members '(' inheritance-model ')'
1214void PragmaMSPointersToMembers::HandlePragma(Preprocessor &PP,
1215 PragmaIntroducerKind Introducer,
1216 Token &Tok) {
1217 SourceLocation PointersToMembersLoc = Tok.getLocation();
1218 PP.Lex(Tok);
1219 if (Tok.isNot(tok::l_paren)) {
1220 PP.Diag(PointersToMembersLoc, diag::warn_pragma_expected_lparen)
1221 << "pointers_to_members";
1222 return;
1223 }
1224 PP.Lex(Tok);
1225 const IdentifierInfo *Arg = Tok.getIdentifierInfo();
1226 if (!Arg) {
1227 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1228 << "pointers_to_members";
1229 return;
1230 }
1231 PP.Lex(Tok);
1232
1233 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod;
1234 if (Arg->isStr("best_case")) {
1235 RepresentationMethod = LangOptions::PPTMK_BestCase;
1236 } else {
1237 if (Arg->isStr("full_generality")) {
1238 if (Tok.is(tok::comma)) {
1239 PP.Lex(Tok);
1240
1241 Arg = Tok.getIdentifierInfo();
1242 if (!Arg) {
1243 PP.Diag(Tok.getLocation(),
1244 diag::err_pragma_pointers_to_members_unknown_kind)
1245 << Tok.getKind() << /*OnlyInheritanceModels*/ 0;
1246 return;
1247 }
1248 PP.Lex(Tok);
1249 } else if (Tok.is(tok::r_paren)) {
1250 // #pragma pointers_to_members(full_generality) implicitly specifies
1251 // virtual_inheritance.
Stephen Hines6bcf27b2014-05-29 04:14:42 -07001252 Arg = nullptr;
Stephen Hines651f13c2014-04-23 16:59:28 -07001253 RepresentationMethod = LangOptions::PPTMK_FullGeneralityVirtualInheritance;
1254 } else {
1255 PP.Diag(Tok.getLocation(), diag::err_expected_punc)
1256 << "full_generality";
1257 return;
1258 }
1259 }
1260
1261 if (Arg) {
1262 if (Arg->isStr("single_inheritance")) {
1263 RepresentationMethod =
1264 LangOptions::PPTMK_FullGeneralitySingleInheritance;
1265 } else if (Arg->isStr("multiple_inheritance")) {
1266 RepresentationMethod =
1267 LangOptions::PPTMK_FullGeneralityMultipleInheritance;
1268 } else if (Arg->isStr("virtual_inheritance")) {
1269 RepresentationMethod =
1270 LangOptions::PPTMK_FullGeneralityVirtualInheritance;
1271 } else {
1272 PP.Diag(Tok.getLocation(),
1273 diag::err_pragma_pointers_to_members_unknown_kind)
1274 << Arg << /*HasPointerDeclaration*/ 1;
1275 return;
1276 }
1277 }
1278 }
1279
1280 if (Tok.isNot(tok::r_paren)) {
1281 PP.Diag(Tok.getLocation(), diag::err_expected_rparen_after)
1282 << (Arg ? Arg->getName() : "full_generality");
1283 return;
1284 }
1285
1286 PP.Lex(Tok);
1287 if (Tok.isNot(tok::eod)) {
1288 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1289 << "pointers_to_members";
1290 return;
1291 }
1292
1293 Token AnnotTok;
1294 AnnotTok.startToken();
1295 AnnotTok.setKind(tok::annot_pragma_ms_pointers_to_members);
1296 AnnotTok.setLocation(PointersToMembersLoc);
1297 AnnotTok.setAnnotationValue(
1298 reinterpret_cast<void *>(static_cast<uintptr_t>(RepresentationMethod)));
1299 PP.EnterToken(AnnotTok);
1300}
1301
1302/// \brief Handle '#pragma vtordisp'
1303// The grammar for this pragma is as follows:
1304//
1305// <vtordisp-mode> ::= ('off' | 'on' | '0' | '1' | '2' )
1306//
1307// #pragma vtordisp '(' ['push' ','] vtordisp-mode ')'
1308// #pragma vtordisp '(' 'pop' ')'
1309// #pragma vtordisp '(' ')'
1310void PragmaMSVtorDisp::HandlePragma(Preprocessor &PP,
1311 PragmaIntroducerKind Introducer,
1312 Token &Tok) {
1313 SourceLocation VtorDispLoc = Tok.getLocation();
1314 PP.Lex(Tok);
1315 if (Tok.isNot(tok::l_paren)) {
1316 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_lparen) << "vtordisp";
1317 return;
1318 }
1319 PP.Lex(Tok);
1320
1321 Sema::PragmaVtorDispKind Kind = Sema::PVDK_Set;
1322 const IdentifierInfo *II = Tok.getIdentifierInfo();
1323 if (II) {
1324 if (II->isStr("push")) {
1325 // #pragma vtordisp(push, mode)
1326 PP.Lex(Tok);
1327 if (Tok.isNot(tok::comma)) {
1328 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_punc) << "vtordisp";
1329 return;
1330 }
1331 PP.Lex(Tok);
1332 Kind = Sema::PVDK_Push;
1333 // not push, could be on/off
1334 } else if (II->isStr("pop")) {
1335 // #pragma vtordisp(pop)
1336 PP.Lex(Tok);
1337 Kind = Sema::PVDK_Pop;
1338 }
1339 // not push or pop, could be on/off
1340 } else {
1341 if (Tok.is(tok::r_paren)) {
1342 // #pragma vtordisp()
1343 Kind = Sema::PVDK_Reset;
1344 }
1345 }
1346
1347
1348 uint64_t Value = 0;
1349 if (Kind == Sema::PVDK_Push || Kind == Sema::PVDK_Set) {
1350 const IdentifierInfo *II = Tok.getIdentifierInfo();
1351 if (II && II->isStr("off")) {
1352 PP.Lex(Tok);
1353 Value = 0;
1354 } else if (II && II->isStr("on")) {
1355 PP.Lex(Tok);
1356 Value = 1;
1357 } else if (Tok.is(tok::numeric_constant) &&
1358 PP.parseSimpleIntegerLiteral(Tok, Value)) {
1359 if (Value > 2) {
1360 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_integer)
1361 << 0 << 2 << "vtordisp";
1362 return;
1363 }
1364 } else {
1365 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action)
1366 << "vtordisp";
1367 return;
1368 }
1369 }
1370
1371 // Finish the pragma: ')' $
1372 if (Tok.isNot(tok::r_paren)) {
1373 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_rparen) << "vtordisp";
1374 return;
1375 }
1376 PP.Lex(Tok);
1377 if (Tok.isNot(tok::eod)) {
1378 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1379 << "vtordisp";
1380 return;
1381 }
1382
1383 // Enter the annotation.
1384 Token AnnotTok;
1385 AnnotTok.startToken();
1386 AnnotTok.setKind(tok::annot_pragma_ms_vtordisp);
1387 AnnotTok.setLocation(VtorDispLoc);
1388 AnnotTok.setAnnotationValue(reinterpret_cast<void *>(
1389 static_cast<uintptr_t>((Kind << 16) | (Value & 0xFFFF))));
1390 PP.EnterToken(AnnotTok);
1391}
1392
Stephen Hines6bcf27b2014-05-29 04:14:42 -07001393/// \brief Handle all MS pragmas. Simply forwards the tokens after inserting
1394/// an annotation token.
1395void PragmaMSPragma::HandlePragma(Preprocessor &PP,
1396 PragmaIntroducerKind Introducer,
1397 Token &Tok) {
1398 Token EoF, AnnotTok;
1399 EoF.startToken();
1400 EoF.setKind(tok::eof);
1401 AnnotTok.startToken();
1402 AnnotTok.setKind(tok::annot_pragma_ms_pragma);
1403 AnnotTok.setLocation(Tok.getLocation());
1404 SmallVector<Token, 8> TokenVector;
1405 // Suck up all of the tokens before the eod.
1406 for (; Tok.isNot(tok::eod); PP.Lex(Tok))
1407 TokenVector.push_back(Tok);
1408 // Add a sentinal EoF token to the end of the list.
1409 TokenVector.push_back(EoF);
1410 // We must allocate this array with new because EnterTokenStream is going to
1411 // delete it later.
1412 Token *TokenArray = new Token[TokenVector.size()];
1413 std::copy(TokenVector.begin(), TokenVector.end(), TokenArray);
1414 auto Value = new (PP.getPreprocessorAllocator())
1415 std::pair<Token*, size_t>(std::make_pair(TokenArray, TokenVector.size()));
1416 AnnotTok.setAnnotationValue(Value);
1417 PP.EnterToken(AnnotTok);
1418}
1419
Aaron Ballmana7ff62f2013-06-04 02:07:14 +00001420/// \brief Handle the Microsoft \#pragma detect_mismatch extension.
1421///
1422/// The syntax is:
1423/// \code
1424/// #pragma detect_mismatch("name", "value")
1425/// \endcode
1426/// Where 'name' and 'value' are quoted strings. The values are embedded in
1427/// the object file and passed along to the linker. If the linker detects a
1428/// mismatch in the object file's values for the given name, a LNK2038 error
1429/// is emitted. See MSDN for more details.
1430void PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP,
1431 PragmaIntroducerKind Introducer,
1432 Token &Tok) {
1433 SourceLocation CommentLoc = Tok.getLocation();
1434 PP.Lex(Tok);
1435 if (Tok.isNot(tok::l_paren)) {
Stephen Hines651f13c2014-04-23 16:59:28 -07001436 PP.Diag(CommentLoc, diag::err_expected) << tok::l_paren;
Aaron Ballmana7ff62f2013-06-04 02:07:14 +00001437 return;
1438 }
1439
1440 // Read the name to embed, which must be a string literal.
1441 std::string NameString;
1442 if (!PP.LexStringLiteral(Tok, NameString,
1443 "pragma detect_mismatch",
1444 /*MacroExpansion=*/true))
1445 return;
1446
1447 // Read the comma followed by a second string literal.
1448 std::string ValueString;
1449 if (Tok.isNot(tok::comma)) {
1450 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
1451 return;
1452 }
1453
1454 if (!PP.LexStringLiteral(Tok, ValueString, "pragma detect_mismatch",
1455 /*MacroExpansion=*/true))
1456 return;
1457
1458 if (Tok.isNot(tok::r_paren)) {
Stephen Hines651f13c2014-04-23 16:59:28 -07001459 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
Aaron Ballmana7ff62f2013-06-04 02:07:14 +00001460 return;
1461 }
1462 PP.Lex(Tok); // Eat the r_paren.
1463
1464 if (Tok.isNot(tok::eod)) {
1465 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
1466 return;
1467 }
1468
1469 // If the pragma is lexically sound, notify any interested PPCallbacks.
1470 if (PP.getPPCallbacks())
1471 PP.getPPCallbacks()->PragmaDetectMismatch(CommentLoc, NameString,
1472 ValueString);
1473
1474 Actions.ActOnPragmaDetectMismatch(NameString, ValueString);
1475}
1476
Reid Kleckner7adf79a2013-05-06 21:02:12 +00001477/// \brief Handle the microsoft \#pragma comment extension.
1478///
1479/// The syntax is:
1480/// \code
1481/// #pragma comment(linker, "foo")
1482/// \endcode
1483/// 'linker' is one of five identifiers: compiler, exestr, lib, linker, user.
1484/// "foo" is a string, which is fully macro expanded, and permits string
1485/// concatenation, embedded escape characters etc. See MSDN for more details.
1486void PragmaCommentHandler::HandlePragma(Preprocessor &PP,
1487 PragmaIntroducerKind Introducer,
1488 Token &Tok) {
1489 SourceLocation CommentLoc = Tok.getLocation();
1490 PP.Lex(Tok);
1491 if (Tok.isNot(tok::l_paren)) {
1492 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
1493 return;
1494 }
1495
1496 // Read the identifier.
1497 PP.Lex(Tok);
1498 if (Tok.isNot(tok::identifier)) {
1499 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
1500 return;
1501 }
1502
1503 // Verify that this is one of the 5 whitelisted options.
Reid Kleckner3190ca92013-05-08 13:44:39 +00001504 IdentifierInfo *II = Tok.getIdentifierInfo();
1505 Sema::PragmaMSCommentKind Kind =
1506 llvm::StringSwitch<Sema::PragmaMSCommentKind>(II->getName())
1507 .Case("linker", Sema::PCK_Linker)
1508 .Case("lib", Sema::PCK_Lib)
1509 .Case("compiler", Sema::PCK_Compiler)
1510 .Case("exestr", Sema::PCK_ExeStr)
1511 .Case("user", Sema::PCK_User)
1512 .Default(Sema::PCK_Unknown);
1513 if (Kind == Sema::PCK_Unknown) {
Reid Kleckner7adf79a2013-05-06 21:02:12 +00001514 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_unknown_kind);
1515 return;
1516 }
1517
1518 // Read the optional string if present.
1519 PP.Lex(Tok);
1520 std::string ArgumentString;
1521 if (Tok.is(tok::comma) && !PP.LexStringLiteral(Tok, ArgumentString,
1522 "pragma comment",
1523 /*MacroExpansion=*/true))
1524 return;
1525
Reid Kleckner3190ca92013-05-08 13:44:39 +00001526 // FIXME: warn that 'exestr' is deprecated.
Reid Kleckner7adf79a2013-05-06 21:02:12 +00001527 // FIXME: If the kind is "compiler" warn if the string is present (it is
1528 // ignored).
Reid Kleckner3190ca92013-05-08 13:44:39 +00001529 // The MSDN docs say that "lib" and "linker" require a string and have a short
1530 // whitelist of linker options they support, but in practice MSVC doesn't
1531 // issue a diagnostic. Therefore neither does clang.
Reid Kleckner7adf79a2013-05-06 21:02:12 +00001532
1533 if (Tok.isNot(tok::r_paren)) {
1534 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
1535 return;
1536 }
1537 PP.Lex(Tok); // eat the r_paren.
1538
1539 if (Tok.isNot(tok::eod)) {
1540 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
1541 return;
1542 }
1543
1544 // If the pragma is lexically sound, notify any interested PPCallbacks.
1545 if (PP.getPPCallbacks())
1546 PP.getPPCallbacks()->PragmaComment(CommentLoc, II, ArgumentString);
Reid Kleckner3190ca92013-05-08 13:44:39 +00001547
1548 Actions.ActOnPragmaMSComment(Kind, ArgumentString);
Reid Kleckner7adf79a2013-05-06 21:02:12 +00001549}
Stephen Hines6bcf27b2014-05-29 04:14:42 -07001550
1551// #pragma clang optimize off
1552// #pragma clang optimize on
1553void PragmaOptimizeHandler::HandlePragma(Preprocessor &PP,
1554 PragmaIntroducerKind Introducer,
1555 Token &FirstToken) {
1556 Token Tok;
1557 PP.Lex(Tok);
1558 if (Tok.is(tok::eod)) {
1559 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_missing_argument);
1560 return;
1561 }
1562 if (Tok.isNot(tok::identifier)) {
1563 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
1564 << PP.getSpelling(Tok);
1565 return;
1566 }
1567 const IdentifierInfo *II = Tok.getIdentifierInfo();
1568 // The only accepted values are 'on' or 'off'.
1569 bool IsOn = false;
1570 if (II->isStr("on")) {
1571 IsOn = true;
1572 } else if (!II->isStr("off")) {
1573 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
1574 << PP.getSpelling(Tok);
1575 return;
1576 }
1577 PP.Lex(Tok);
1578
1579 if (Tok.isNot(tok::eod)) {
1580 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_extra_argument)
1581 << PP.getSpelling(Tok);
1582 return;
1583 }
1584
1585 Actions.ActOnPragmaOptimize(IsOn, FirstToken.getLocation());
1586}